package hook import ( "encoding/base64" "encoding/json" "fmt" "github.com/gorilla/websocket" "path/filepath" "strings" "wechat-api/workphone" ) // 开启/关闭实时消息接收功能 func (h *Hook) ConfigureMsgRecive(isEnable string, url string) (err error) { resp, err := h.Client.R().SetBody(&ConfigureMsgReciveReq{ IsEnable: isEnable, URL: url, }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/ConfigureMsgRecive") if err != nil { return } if !resp.IsSuccessState() { err = fmt.Errorf("ConfigureMsgRecive failed with status code %d", resp.StatusCode) return } return } // 发送微信文本消息 func (h *Hook) SendTextMsg(wxid, msg, wxWxid string) error { if h.ServerIp == "" { conn, err := h.connWorkPhone() if err != nil { err = fmt.Errorf("SendTextMsg failed") return err } defer func(conn *websocket.Conn) { err = conn.Close() if err != nil { err = fmt.Errorf("SendTextMsg failed") } }(conn) encodedString := base64.StdEncoding.EncodeToString([]byte(msg)) //sendMsg := &workphone.TalkToFriendTaskMessage{ // WeChatId: wxWxid, // FriendId: wxid, // ContentType: workphone.EnumContentType_Text, // Content: []byte(encodedString), //} //content, err := anypb.New(sendMsg) <-- 这里有坑,会增加字段 "@type": "type.googleapis.com/Jubo.JuLiao.IM.Wx.Proto.TalkToFriendTaskMessage", //if err != nil { // return fmt.Errorf("failed to pack message: %v", err) //} //transportMessage := &workphone.TransportMessage{ // MsgType: workphone.EnumMsgType_TalkToFriendTask, // Content: content, //} // 将 TransportMessage 转换为 JSON //transportMessageJSON, err := protojson.MarshalOptions{ // UseProtoNames: true, //}.Marshal(transportMessage) //if err != nil { // return fmt.Errorf("failed to marshal transport message: %v", err) //} var message map[string]interface{} if h.Ctype == uint64(3) { message = map[string]interface{}{ "MsgType": "TalkToFriendTask", "Content": map[string]interface{}{ "WxId": wxWxid, "ConvId": wxid, "ContentType": "Text", "Content": encodedString, }, } } else { message = map[string]interface{}{ "MsgType": "TalkToFriendTask", "Content": map[string]interface{}{ "WeChatId": wxWxid, "FriendId": wxid, "ContentType": "Text", "Content": encodedString, }, } } transportMessageJSON, err := json.Marshal(message) if err != nil { return err } // 发送 JSON 消息 err = conn.WriteMessage(websocket.TextMessage, transportMessageJSON) if err != nil { return fmt.Errorf("failed to send message: %v", err) } // 读取回复消息 _, replyMessage, err := conn.ReadMessage() if err != nil { return fmt.Errorf("failed to read message: %v", err) } var replyMessageData map[string]interface{} err = json.Unmarshal([]byte(replyMessage), &replyMessageData) if err != nil { return fmt.Errorf("failed to send message: %v", err) } if replyMessageData["msgType"] == nil || replyMessageData["msgType"] != "MsgReceivedAck" { return fmt.Errorf("failed to send message: %v") } return nil } else { resp, err := h.Client.R().SetBody(&SendTextMsgReq{ Wxid: wxid, Msg: msg, }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendTextMsg") if err != nil { return err } if !resp.IsSuccessState() { err = fmt.Errorf("SendTextMsg failed with status code %d", resp.StatusCode) return err } return nil } } // 发送微信图片 func (h *Hook) SendPicMsg(wxid, picpath, diyfilename, wxWxid string) (err error) { if h.ServerIp == "" { conn, err := h.connWorkPhone() if err != nil { err = fmt.Errorf("SendTextMsg failed") return err } defer func(conn *websocket.Conn) { err = conn.Close() if err != nil { err = fmt.Errorf("SendTextMsg failed") } }(conn) encodedString := base64.StdEncoding.EncodeToString([]byte(picpath)) contentType := "File" if isImageFile(diyfilename) { contentType = "Picture" } message := map[string]interface{}{ "MsgType": "TalkToFriendTask", "Content": map[string]interface{}{ "WeChatId": wxWxid, "FriendId": wxid, "ContentType": contentType, "Content": encodedString, }, } transportMessageJSON, err := json.Marshal(message) if err != nil { return err } // 发送 JSON 消息 err = conn.WriteMessage(websocket.TextMessage, transportMessageJSON) if err != nil { return fmt.Errorf("failed to send message: %v", err) } // 读取回复消息 _, replyMessage, err := conn.ReadMessage() if err != nil { return fmt.Errorf("failed to read message: %v", err) } var replyMessageData map[string]interface{} err = json.Unmarshal([]byte(replyMessage), &replyMessageData) if err != nil { return fmt.Errorf("failed to send message: %v", err) } if replyMessageData["msgType"] == nil || replyMessageData["msgType"] != workphone.EnumMsgType_name[int32(workphone.EnumMsgType_MsgReceivedAck)] { return fmt.Errorf("failed to send message: %v") } return nil } else { resp, err := h.Client.R().SetBody(&SendPicMsgReq{ Wxid: wxid, Picpath: picpath, Diyfilename: diyfilename, }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg") if err != nil { return err } if !resp.IsSuccessState() { err = fmt.Errorf("SendPicMsg failed with status code %d", resp.StatusCode) return err } return nil } } // 发送微信图片(本地测试) func (h *Hook) SendPicMsgLocal(wxid, picpath string) (err error) { resp, err := h.Client.R().SetBody(&SendPicMsgLocalReq{ Wxid: wxid, Picpath: picpath, }).Post("http://" + h.ServerIp + ":" + h.WxPort + "/SendPicMsg") if err != nil { return } if !resp.IsSuccessState() { err = fmt.Errorf("SendPicMsgLocal failed with status code %d", resp.StatusCode) return } return } func isImageFile(filename string) bool { ext := strings.ToLower(filepath.Ext(filename)) imageExtensions := []string{".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".webp"} for _, extToCheck := range imageExtensions { if ext == extToCheck { return true } } return false }