message.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  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. // SendTextMsg 发送微信文本消息
  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. // SendPicMsg 发送微信图片
  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("SendPicMsg failed")
  128. return err
  129. }
  130. defer func(conn *websocket.Conn) {
  131. err = conn.Close()
  132. if err != nil {
  133. err = fmt.Errorf("SendPicMsg failed")
  134. }
  135. }(conn)
  136. encodedString := base64.StdEncoding.EncodeToString([]byte(picpath))
  137. contentType := "File"
  138. if isImageFile(diyfilename) {
  139. contentType = "Picture"
  140. }
  141. var message map[string]interface{}
  142. if h.Ctype == uint64(3) {
  143. message = map[string]interface{}{
  144. "MsgType": "TalkToFriendTask",
  145. "Content": map[string]interface{}{
  146. "WxId": wxWxid,
  147. "ConvId": wxid,
  148. "ContentType": contentType,
  149. "Content": encodedString,
  150. },
  151. }
  152. } else {
  153. message = map[string]interface{}{
  154. "MsgType": "TalkToFriendTask",
  155. "Content": map[string]interface{}{
  156. "WeChatId": wxWxid,
  157. "FriendId": wxid,
  158. "ContentType": contentType,
  159. "Content": encodedString,
  160. },
  161. }
  162. }
  163. transportMessageJSON, err := json.Marshal(message)
  164. if err != nil {
  165. return err
  166. }
  167. // 发送 JSON 消息
  168. err = conn.WriteMessage(websocket.TextMessage, transportMessageJSON)
  169. if err != nil {
  170. return fmt.Errorf("failed to send message: %v", err)
  171. }
  172. // 读取回复消息
  173. _, replyMessage, err := conn.ReadMessage()
  174. if err != nil {
  175. return fmt.Errorf("failed to read message: %v", err)
  176. }
  177. var replyMessageData map[string]interface{}
  178. err = json.Unmarshal([]byte(replyMessage), &replyMessageData)
  179. if err != nil {
  180. return fmt.Errorf("failed to send message: %v", err)
  181. }
  182. if replyMessageData["msgType"] == nil || replyMessageData["msgType"] != workphone.EnumMsgType_name[int32(workphone.EnumMsgType_MsgReceivedAck)] {
  183. return fmt.Errorf("failed to send message: %v")
  184. }
  185. return nil
  186. } else {
  187. resp, err := h.Client.R().SetBody(&SendPicMsgReq{
  188. Wxid: wxid,
  189. Picpath: picpath,
  190. Diyfilename: diyfilename,
  191. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
  192. if err != nil {
  193. return err
  194. }
  195. if !resp.IsSuccessState() {
  196. err = fmt.Errorf("SendPicMsg failed with status code %d", resp.StatusCode)
  197. return err
  198. }
  199. return nil
  200. }
  201. }
  202. // 发送微信图片(本地测试)
  203. func (h *Hook) SendPicMsgLocal(wxid, picpath string) (err error) {
  204. resp, err := h.Client.R().SetBody(&SendPicMsgLocalReq{
  205. Wxid: wxid,
  206. Picpath: picpath,
  207. }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg")
  208. if err != nil {
  209. return
  210. }
  211. if !resp.IsSuccessState() {
  212. err = fmt.Errorf("SendPicMsgLocal failed with status code %d", resp.StatusCode)
  213. return
  214. }
  215. return
  216. }
  217. func isImageFile(filename string) bool {
  218. ext := strings.ToLower(filepath.Ext(filename))
  219. imageExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp"}
  220. for _, extToCheck := range imageExtensions {
  221. if ext == extToCheck {
  222. return true
  223. }
  224. }
  225. return false
  226. }