message.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. var message map[string]interface{}
  63. if h.Ctype == uint64(3) {
  64. message = map[string]interface{}{
  65. "MsgType": "TalkToFriendTask",
  66. "Content": map[string]interface{}{
  67. "WxId": wxWxid,
  68. "ConvId": wxid,
  69. "ContentType": "Text",
  70. "Content": encodedString,
  71. },
  72. }
  73. } else {
  74. message = map[string]interface{}{
  75. "MsgType": "TalkToFriendTask",
  76. "Content": map[string]interface{}{
  77. "WeChatId": wxWxid,
  78. "FriendId": wxid,
  79. "ContentType": "Text",
  80. "Content": encodedString,
  81. },
  82. }
  83. }
  84. transportMessageJSON, err := json.Marshal(message)
  85. if err != nil {
  86. return err
  87. }
  88. // 发送 JSON 消息
  89. err = conn.WriteMessage(websocket.TextMessage, transportMessageJSON)
  90. if err != nil {
  91. return fmt.Errorf("failed to send message: %v", err)
  92. }
  93. // 读取回复消息
  94. _, replyMessage, err := conn.ReadMessage()
  95. if err != nil {
  96. return fmt.Errorf("failed to read message: %v", err)
  97. }
  98. var replyMessageData map[string]interface{}
  99. err = json.Unmarshal([]byte(replyMessage), &replyMessageData)
  100. if err != nil {
  101. return fmt.Errorf("failed to send message: %v", err)
  102. }
  103. if replyMessageData["msgType"] == nil || replyMessageData["msgType"] != "MsgReceivedAck" {
  104. return fmt.Errorf("failed to send message: %v")
  105. }
  106. return nil
  107. } else {
  108. resp, err := h.Client.R().SetBody(&SendTextMsgReq{
  109. Wxid: wxid,
  110. Msg: msg,
  111. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendTextMsg")
  112. if err != nil {
  113. return err
  114. }
  115. if !resp.IsSuccessState() {
  116. err = fmt.Errorf("SendTextMsg failed with status code %d", resp.StatusCode)
  117. return err
  118. }
  119. return nil
  120. }
  121. }
  122. // 发送微信图片
  123. func (h *Hook) SendPicMsg(wxid, picpath, diyfilename, wxWxid string) (err error) {
  124. if h.ServerIp == "" {
  125. conn, err := h.connWorkPhone()
  126. if err != nil {
  127. err = fmt.Errorf("SendTextMsg failed")
  128. return err
  129. }
  130. defer func(conn *websocket.Conn) {
  131. err = conn.Close()
  132. if err != nil {
  133. err = fmt.Errorf("SendTextMsg failed")
  134. }
  135. }(conn)
  136. encodedString := base64.StdEncoding.EncodeToString([]byte(picpath))
  137. contentType := "File"
  138. if isImageFile(diyfilename) {
  139. contentType = "Picture"
  140. }
  141. message := map[string]interface{}{
  142. "MsgType": "TalkToFriendTask",
  143. "Content": map[string]interface{}{
  144. "WeChatId": wxWxid,
  145. "FriendId": wxid,
  146. "ContentType": contentType,
  147. "Content": encodedString,
  148. },
  149. }
  150. transportMessageJSON, err := json.Marshal(message)
  151. if err != nil {
  152. return err
  153. }
  154. // 发送 JSON 消息
  155. err = conn.WriteMessage(websocket.TextMessage, transportMessageJSON)
  156. if err != nil {
  157. return fmt.Errorf("failed to send message: %v", err)
  158. }
  159. // 读取回复消息
  160. _, replyMessage, err := conn.ReadMessage()
  161. if err != nil {
  162. return fmt.Errorf("failed to read message: %v", err)
  163. }
  164. var replyMessageData map[string]interface{}
  165. err = json.Unmarshal([]byte(replyMessage), &replyMessageData)
  166. if err != nil {
  167. return fmt.Errorf("failed to send message: %v", err)
  168. }
  169. if replyMessageData["msgType"] == nil || replyMessageData["msgType"] != workphone.EnumMsgType_name[int32(workphone.EnumMsgType_MsgReceivedAck)] {
  170. return fmt.Errorf("failed to send message: %v")
  171. }
  172. return nil
  173. } else {
  174. resp, err := h.Client.R().SetBody(&SendPicMsgReq{
  175. Wxid: wxid,
  176. Picpath: picpath,
  177. Diyfilename: diyfilename,
  178. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
  179. if err != nil {
  180. return err
  181. }
  182. if !resp.IsSuccessState() {
  183. err = fmt.Errorf("SendPicMsg failed with status code %d", resp.StatusCode)
  184. return err
  185. }
  186. return nil
  187. }
  188. }
  189. // 发送微信图片(本地测试)
  190. func (h *Hook) SendPicMsgLocal(wxid, picpath string) (err error) {
  191. resp, err := h.Client.R().SetBody(&SendPicMsgLocalReq{
  192. Wxid: wxid,
  193. Picpath: picpath,
  194. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
  195. if err != nil {
  196. return
  197. }
  198. if !resp.IsSuccessState() {
  199. err = fmt.Errorf("SendPicMsgLocal failed with status code %d", resp.StatusCode)
  200. return
  201. }
  202. return
  203. }
  204. func isImageFile(filename string) bool {
  205. ext := strings.ToLower(filepath.Ext(filename))
  206. imageExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp"}
  207. for _, extToCheck := range imageExtensions {
  208. if ext == extToCheck {
  209. return true
  210. }
  211. }
  212. return false
  213. }