message.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. package hook
  2. import (
  3. "encoding/base64"
  4. "encoding/json"
  5. "fmt"
  6. "github.com/gorilla/websocket"
  7. "path/filepath"
  8. "strings"
  9. "wechat-api/workphone"
  10. )
  11. // 开启/关闭实时消息接收功能
  12. func (h *Hook) ConfigureMsgRecive(isEnable string, url string) (err error) {
  13. resp, err := h.Client.R().SetBody(&ConfigureMsgReciveReq{
  14. IsEnable: isEnable,
  15. URL: url,
  16. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/ConfigureMsgRecive")
  17. if err != nil {
  18. return
  19. }
  20. if !resp.IsSuccessState() {
  21. err = fmt.Errorf("ConfigureMsgRecive failed with status code %d", resp.StatusCode)
  22. return
  23. }
  24. return
  25. }
  26. // 发送微信文本消息
  27. func (h *Hook) SendTextMsg(wxid, msg, wxWxid string) error {
  28. if h.ServerIp == "" {
  29. conn, err := h.connWorkPhone()
  30. if err != nil {
  31. err = fmt.Errorf("SendTextMsg failed")
  32. return err
  33. }
  34. defer func(conn *websocket.Conn) {
  35. err = conn.Close()
  36. if err != nil {
  37. err = fmt.Errorf("SendTextMsg failed")
  38. }
  39. }(conn)
  40. encodedString := base64.StdEncoding.EncodeToString([]byte(msg))
  41. //sendMsg := &workphone.TalkToFriendTaskMessage{
  42. // WeChatId: wxWxid,
  43. // FriendId: wxid,
  44. // ContentType: workphone.EnumContentType_Text,
  45. // Content: []byte(encodedString),
  46. //}
  47. //content, err := anypb.New(sendMsg) <-- 这里有坑,会增加字段 "@type": "type.googleapis.com/Jubo.JuLiao.IM.Wx.Proto.TalkToFriendTaskMessage",
  48. //if err != nil {
  49. // return fmt.Errorf("failed to pack message: %v", err)
  50. //}
  51. //transportMessage := &workphone.TransportMessage{
  52. // MsgType: workphone.EnumMsgType_TalkToFriendTask,
  53. // Content: content,
  54. //}
  55. // 将 TransportMessage 转换为 JSON
  56. //transportMessageJSON, err := protojson.MarshalOptions{
  57. // UseProtoNames: true,
  58. //}.Marshal(transportMessage)
  59. //if err != nil {
  60. // return fmt.Errorf("failed to marshal transport message: %v", err)
  61. //}
  62. message := map[string]interface{}{
  63. "MsgType": "TalkToFriendTask",
  64. "Content": map[string]interface{}{
  65. "WeChatId": wxWxid,
  66. "FriendId": wxid,
  67. "ContentType": "Text",
  68. "Content": encodedString,
  69. },
  70. }
  71. transportMessageJSON, err := json.Marshal(message)
  72. if err != nil {
  73. return err
  74. }
  75. // 发送 JSON 消息
  76. err = conn.WriteMessage(websocket.TextMessage, transportMessageJSON)
  77. if err != nil {
  78. return fmt.Errorf("failed to send message: %v", err)
  79. }
  80. // 读取回复消息
  81. _, replyMessage, err := conn.ReadMessage()
  82. if err != nil {
  83. return fmt.Errorf("failed to read message: %v", err)
  84. }
  85. var replyMessageData map[string]interface{}
  86. err = json.Unmarshal([]byte(replyMessage), &replyMessageData)
  87. if err != nil {
  88. return fmt.Errorf("failed to send message: %v", err)
  89. }
  90. if replyMessageData["msgType"] == nil || replyMessageData["msgType"] != "MsgReceivedAck" {
  91. return fmt.Errorf("failed to send message: %v")
  92. }
  93. return nil
  94. } else {
  95. resp, err := h.Client.R().SetBody(&SendTextMsgReq{
  96. Wxid: wxid,
  97. Msg: msg,
  98. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendTextMsg")
  99. if err != nil {
  100. return err
  101. }
  102. if !resp.IsSuccessState() {
  103. err = fmt.Errorf("SendTextMsg failed with status code %d", resp.StatusCode)
  104. return err
  105. }
  106. return nil
  107. }
  108. }
  109. // 发送微信图片
  110. func (h *Hook) SendPicMsg(wxid, picpath, diyfilename, wxWxid string) (err error) {
  111. if h.ServerIp == "" {
  112. conn, err := h.connWorkPhone()
  113. if err != nil {
  114. err = fmt.Errorf("SendTextMsg failed")
  115. return err
  116. }
  117. defer func(conn *websocket.Conn) {
  118. err = conn.Close()
  119. if err != nil {
  120. err = fmt.Errorf("SendTextMsg failed")
  121. }
  122. }(conn)
  123. encodedString := base64.StdEncoding.EncodeToString([]byte(picpath))
  124. contentType := "File"
  125. if isImageFile(diyfilename) {
  126. contentType = "Picture"
  127. }
  128. message := map[string]interface{}{
  129. "MsgType": "TalkToFriendTask",
  130. "Content": map[string]interface{}{
  131. "WeChatId": wxWxid,
  132. "FriendId": wxid,
  133. "ContentType": contentType,
  134. "Content": encodedString,
  135. },
  136. }
  137. transportMessageJSON, err := json.Marshal(message)
  138. if err != nil {
  139. return err
  140. }
  141. // 发送 JSON 消息
  142. err = conn.WriteMessage(websocket.TextMessage, transportMessageJSON)
  143. if err != nil {
  144. return fmt.Errorf("failed to send message: %v", err)
  145. }
  146. // 读取回复消息
  147. _, replyMessage, err := conn.ReadMessage()
  148. if err != nil {
  149. return fmt.Errorf("failed to read message: %v", err)
  150. }
  151. var replyMessageData map[string]interface{}
  152. err = json.Unmarshal([]byte(replyMessage), &replyMessageData)
  153. if err != nil {
  154. return fmt.Errorf("failed to send message: %v", err)
  155. }
  156. if replyMessageData["msgType"] == nil || replyMessageData["msgType"] != workphone.EnumMsgType_name[int32(workphone.EnumMsgType_MsgReceivedAck)] {
  157. return fmt.Errorf("failed to send message: %v")
  158. }
  159. return nil
  160. } else {
  161. resp, err := h.Client.R().SetBody(&SendPicMsgReq{
  162. Wxid: wxid,
  163. Picpath: picpath,
  164. Diyfilename: diyfilename,
  165. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
  166. if err != nil {
  167. return err
  168. }
  169. if !resp.IsSuccessState() {
  170. err = fmt.Errorf("SendPicMsg failed with status code %d", resp.StatusCode)
  171. return err
  172. }
  173. return nil
  174. }
  175. }
  176. // 发送微信图片(本地测试)
  177. func (h *Hook) SendPicMsgLocal(wxid, picpath string) (err error) {
  178. resp, err := h.Client.R().SetBody(&SendPicMsgLocalReq{
  179. Wxid: wxid,
  180. Picpath: picpath,
  181. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
  182. if err != nil {
  183. return
  184. }
  185. if !resp.IsSuccessState() {
  186. err = fmt.Errorf("SendPicMsgLocal failed with status code %d", resp.StatusCode)
  187. return
  188. }
  189. return
  190. }
  191. func isImageFile(filename string) bool {
  192. ext := strings.ToLower(filepath.Ext(filename))
  193. imageExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp"}
  194. for _, extToCheck := range imageExtensions {
  195. if ext == extToCheck {
  196. return true
  197. }
  198. }
  199. return false
  200. }