From b967eda0d076ca497563f603c34c24626ac78867 Mon Sep 17 00:00:00 2001 From: eatMoreApple <15055461510@163.com> Date: Wed, 28 Apr 2021 17:26:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=B6=88=E6=81=AF=E6=92=A4?= =?UTF-8?q?=E5=9B=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bot_test.go | 39 ++++++++++++- caller.go | 46 ++++++++++++--- client.go | 14 +++++ emoji_test.go | 2 +- global.go | 133 ++++++++++++++++++++++--------------------- items.go | 6 ++ message.go | 20 +++++-- relations.go | 26 ++++----- url.go | 155 +++++++++++++++++++++++++------------------------- user.go | 120 +++++++++++++++++++++----------------- 10 files changed, 338 insertions(+), 223 deletions(-) diff --git a/bot_test.go b/bot_test.go index 3c484c8..a401dfe 100644 --- a/bot_test.go +++ b/bot_test.go @@ -193,12 +193,12 @@ func TestSendMessage(t *testing.T) { t.Error(err) return } - if err = helper.SendText("test message! received ?"); err != nil { + if _, err = helper.SendText("test message! received ?"); err != nil { t.Error(err) return } time.Sleep(time.Second) - if err = self.SendTextToFriend(helper, "send test message twice ! received?"); err != nil { + if _, err = self.SendTextToFriend(helper, "send test message twice ! received?"); err != nil { t.Error(err) return } @@ -253,5 +253,38 @@ func TestFriendHelper(t *testing.T) { t.Error(err) return } - fh.SendText("test message") + msg, err := fh.SendText("test message") + if err != nil { + t.Error(err) + return + } + t.Log(msg.MsgId) +} + +func TestRevokeMessage(t *testing.T) { + bot := defaultBot(Desktop) + if err := bot.Login(); err != nil { + t.Error(err) + return + } + self, err := bot.GetCurrentUser() + if err != nil { + t.Error(err) + return + } + friends, err := self.Friends() + if err != nil { + t.Error(err) + return + } + fs := friends.SearchByRemarkName(1, "1") + ms, err := fs.First().SendText("test") + if err != nil { + t.Error(err) + return + } + time.Sleep(time.Second) + if err := ms.Revoke(); err != nil { + t.Error(err) + } } diff --git a/caller.go b/caller.go index cd29d14..953d338 100644 --- a/caller.go +++ b/caller.go @@ -187,9 +187,11 @@ func (c *Caller) WebWxSync(request *BaseRequest, response *WebInitResponse, info } // 发送消息接口 -func (c *Caller) WebWxSendMsg(msg *SendMessage, info *LoginInfo, request *BaseRequest) error { +func (c *Caller) WebWxSendMsg(msg *SendMessage, info *LoginInfo, request *BaseRequest) (*SentMessage, error) { resp := NewReturnResponse(c.Client.WebWxSendMsg(msg, info, request)) - return parseBaseResponseError(resp) + sendSuccessMsg := &SentMessage{SendMessage: msg} + err := parseMessageResponseError(resp, sendSuccessMsg) + return sendSuccessMsg, err } // 修改用户备注接口 @@ -199,12 +201,12 @@ func (c *Caller) WebWxOplog(request *BaseRequest, remarkName, toUserName string) } // 发送图片消息接口 -func (c *Caller) WebWxSendImageMsg(file *os.File, request *BaseRequest, info *LoginInfo, fromUserName, toUserName string) error { +func (c *Caller) WebWxSendImageMsg(file *os.File, request *BaseRequest, info *LoginInfo, fromUserName, toUserName string) (*SentMessage, error) { // 首先尝试上传图片 resp := NewReturnResponse(c.Client.WebWxUploadMedia(file, request, info, fromUserName, toUserName, "image/jpeg", "pic")) // 无错误上传成功之后获取请求结果,判断结果是否正常 if resp.Err() != nil { - return resp.Err() + return nil, resp.Err() } defer resp.Body.Close() var item struct { @@ -212,16 +214,19 @@ func (c *Caller) WebWxSendImageMsg(file *os.File, request *BaseRequest, info *Lo MediaId string } if err := resp.ScanJSON(&item); err != nil { - return err + return nil, err } if !item.BaseResponse.Ok() { - return item.BaseResponse + return nil, item.BaseResponse } // 构造新的图片类型的信息 msg := NewMediaSendMessage(ImageMessage, fromUserName, toUserName, item.MediaId) // 发送图片信息 resp = NewReturnResponse(c.Client.WebWxSendMsgImg(msg, request, info)) - return parseBaseResponseError(resp) + + sendSuccessMsg := &SentMessage{SendMessage: msg} + err := parseMessageResponseError(resp, sendSuccessMsg) + return sendSuccessMsg, err } // 用户退出 @@ -254,6 +259,12 @@ func (c *Caller) WebWxVerifyUser(storage *Storage, info RecommendInfo, verifyCon return parseBaseResponseError(resp) } +// 撤回消息操作 +func (c *Caller) WebWxRevokeMsg(msg *SentMessage, request *BaseRequest) error { + resp := NewReturnResponse(c.Client.WebWxRevokeMsg(msg, request)) + return parseBaseResponseError(resp) +} + // 处理响应返回的结果是否正常 func parseBaseResponseError(resp *ReturnResponse) error { if resp.Err() != nil { @@ -269,3 +280,24 @@ func parseBaseResponseError(resp *ReturnResponse) error { } return nil } + +func parseMessageResponseError(resp *ReturnResponse, msg *SentMessage) error { + if resp.Err() != nil { + return resp.Err() + } + + defer resp.Body.Close() + + var messageResp MessageResponse + + if err := resp.ScanJSON(&messageResp); err != nil { + return err + } + + if !messageResp.BaseResponse.Ok() { + return messageResp.BaseResponse + } + //// 发送成功之后将msgId赋值给SendMessage + msg.MsgId = messageResp.MsgID + return nil +} diff --git a/client.go b/client.go index 93c3491..83b47a2 100644 --- a/client.go +++ b/client.go @@ -494,3 +494,17 @@ func (c *Client) RemoveMemberFromChatRoom(req *BaseRequest, info *LoginInfo, gro requ.Header.Set("Content-Type", jsonContentType) return c.Do(requ) } + +// 撤回消息 +func (c *Client) WebWxRevokeMsg(msg *SentMessage, request *BaseRequest) (*http.Response, error) { + content := map[string]interface{}{ + "BaseRequest": request, + "ClientMsgId": msg.ClientMsgId, + "SvrMsgId": msg.MsgId, + "ToUserName": msg.ToUserName, + } + buffer, _ := ToBuffer(content) + req, _ := http.NewRequest(http.MethodPost, c.webWxRevokeMsg, buffer) + req.Header.Set("Content-Type", jsonContentType) + return c.Do(req) +} diff --git a/emoji_test.go b/emoji_test.go index c795b21..fc2595d 100644 --- a/emoji_test.go +++ b/emoji_test.go @@ -17,5 +17,5 @@ func TestSendEmoji(t *testing.T) { t.Error(err) return } - _ = f.SendText(Emoji.Dagger) + _ , _= f.SendText(Emoji.Dagger) } diff --git a/global.go b/global.go index 4632324..08a2cfd 100644 --- a/global.go +++ b/global.go @@ -1,99 +1,100 @@ package openwechat import ( - "errors" - "regexp" + "errors" + "regexp" ) var ( - uuidRegexp = regexp.MustCompile(`uuid = "(.*?)";`) - statusCodeRegexp = regexp.MustCompile(`window.code=(\d+);`) - syncCheckRegexp = regexp.MustCompile(`window.synccheck=\{retcode:"(\d+)",selector:"(\d+)"\}`) - redirectUriRegexp = regexp.MustCompile(`window.redirect_uri="(.*?)"`) + uuidRegexp = regexp.MustCompile(`uuid = "(.*?)";`) + statusCodeRegexp = regexp.MustCompile(`window.code=(\d+);`) + syncCheckRegexp = regexp.MustCompile(`window.synccheck=\{retcode:"(\d+)",selector:"(\d+)"\}`) + redirectUriRegexp = regexp.MustCompile(`window.redirect_uri="(.*?)"`) ) const ( - appId = "wx782c26e4c19acffb" - jsLoginUrl = "https://login.wx.qq.com/jslogin" - qrcodeUrl = "https://login.weixin.qq.com/qrcode/" - loginUrl = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login" + appId = "wx782c26e4c19acffb" + jsLoginUrl = "https://login.wx.qq.com/jslogin" + qrcodeUrl = "https://login.weixin.qq.com/qrcode/" + loginUrl = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login" - // Normal urls + // Normal urls - baseNormalUrl = "https://wx2.qq.com" - webWxNewLoginPageNormalUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage" - webWxInitNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit" - webWxStatusNotifyNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify" - webWxSyncNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync" - webWxSendMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg" - webWxGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact" - webWxSendMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg" - webWxSendAppMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg" - webWxBatchGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact" - webWxOplogNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxoplog" - webWxVerifyUserNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser" - syncCheckNormalUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin/synccheck" - webWxUpLoadMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia" - webWxGetMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg" - webWxGetVoiceNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice" - webWxGetVideoNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo" - webWxLogoutNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxlogout" - webWxGetMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia" - webWxUpdateChatRoomNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom" + baseNormalUrl = "https://wx2.qq.com" + webWxNewLoginPageNormalUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage" + webWxInitNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit" + webWxStatusNotifyNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify" + webWxSyncNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync" + webWxSendMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg" + webWxGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact" + webWxSendMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg" + webWxSendAppMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg" + webWxBatchGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact" + webWxOplogNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxoplog" + webWxVerifyUserNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser" + syncCheckNormalUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin/synccheck" + webWxUpLoadMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia" + webWxGetMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg" + webWxGetVoiceNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice" + webWxGetVideoNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo" + webWxLogoutNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxlogout" + webWxGetMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia" + webWxUpdateChatRoomNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom" + webWxRevokeMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxrevokemsg" - // Desktop urls + // Desktop urls - baseDesktopUrl = "https://wx.qq.com" - webWxNewLoginPageDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?mod=desktop" - webWxInitDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit" - webWxStatusNotifyDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify" - webWxSyncDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync" - webWxSendMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg" - webWxGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact" - webWxSendMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg" - webWxSendAppMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg" - webWxBatchGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact" - webWxOplogDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxoplog" - webWxVerifyUserDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser" - syncCheckDesktopUrl = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck" - webWxUpLoadMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia" - webWxGetMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg" - webWxGetVoiceDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice" - webWxGetVideoDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo" - webWxLogoutDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout" - webWxGetMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia" - webWxUpdateChatRoomDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom" + baseDesktopUrl = "https://wx.qq.com" + webWxNewLoginPageDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?mod=desktop" + webWxInitDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit" + webWxStatusNotifyDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify" + webWxSyncDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync" + webWxSendMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg" + webWxGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact" + webWxSendMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg" + webWxSendAppMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg" + webWxBatchGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact" + webWxOplogDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxoplog" + webWxVerifyUserDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser" + syncCheckDesktopUrl = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck" + webWxUpLoadMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia" + webWxGetMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg" + webWxGetVoiceDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice" + webWxGetVideoDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo" + webWxLogoutDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout" + webWxGetMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia" + webWxUpdateChatRoomDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom" + webWxRevokeMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxrevokemsg" - jsonContentType = "application/json; charset=utf-8" - uosPatchClientVersion = "2.0.0" - uosPatchExtspam = "Gp8ICJkIEpkICggwMDAwMDAwMRAGGoAI1GiJSIpeO1RZTq9QBKsRbPJdi84ropi16EYI10WB6g74sGmRwSNXjPQnYUKYotKkvLGpshucCaeWZMOylnc6o2AgDX9grhQQx7fm2DJRTyuNhUlwmEoWhjoG3F0ySAWUsEbH3bJMsEBwoB//0qmFJob74ffdaslqL+IrSy7LJ76/G5TkvNC+J0VQkpH1u3iJJs0uUYyLDzdBIQ6Ogd8LDQ3VKnJLm4g/uDLe+G7zzzkOPzCjXL+70naaQ9medzqmh+/SmaQ6uFWLDQLcRln++wBwoEibNpG4uOJvqXy+ql50DjlNchSuqLmeadFoo9/mDT0q3G7o/80P15ostktjb7h9bfNc+nZVSnUEJXbCjTeqS5UYuxn+HTS5nZsPVxJA2O5GdKCYK4x8lTTKShRstqPfbQpplfllx2fwXcSljuYi3YipPyS3GCAqf5A7aYYwJ7AvGqUiR2SsVQ9Nbp8MGHET1GxhifC692APj6SJxZD3i1drSYZPMMsS9rKAJTGz2FEupohtpf2tgXm6c16nDk/cw+C7K7me5j5PLHv55DFCS84b06AytZPdkFZLj7FHOkcFGJXitHkX5cgww7vuf6F3p0yM/W73SoXTx6GX4G6Hg2rYx3O/9VU2Uq8lvURB4qIbD9XQpzmyiFMaytMnqxcZJcoXCtfkTJ6pI7a92JpRUvdSitg967VUDUAQnCXCM/m0snRkR9LtoXAO1FUGpwlp1EfIdCZFPKNnXMeqev0j9W9ZrkEs9ZWcUEexSj5z+dKYQBhIICviYUQHVqBTZSNy22PlUIeDeIs11j7q4t8rD8LPvzAKWVqXE+5lS1JPZkjg4y5hfX1Dod3t96clFfwsvDP6xBSe1NBcoKbkyGxYK0UvPGtKQEE0Se2zAymYDv41klYE9s+rxp8e94/H8XhrL9oGm8KWb2RmYnAE7ry9gd6e8ZuBRIsISlJAE/e8y8xFmP031S6Lnaet6YXPsFpuFsdQs535IjcFd75hh6DNMBYhSfjv456cvhsb99+fRw/KVZLC3yzNSCbLSyo9d9BI45Plma6V8akURQA/qsaAzU0VyTIqZJkPDTzhuCl92vD2AD/QOhx6iwRSVPAxcRFZcWjgc2wCKh+uCYkTVbNQpB9B90YlNmI3fWTuUOUjwOzQRxJZj11NsimjOJ50qQwTTFj6qQvQ1a/I+MkTx5UO+yNHl718JWcR3AXGmv/aa9rD1eNP8ioTGlOZwPgmr2sor2iBpKTOrB83QgZXP+xRYkb4zVC+LoAXEoIa1+zArywlgREer7DLePukkU6wHTkuSaF+ge5Of1bXuU4i938WJHj0t3D8uQxkJvoFi/EYN/7u2P1zGRLV4dHVUsZMGCCtnO6BBigFMAA=" + jsonContentType = "application/json; charset=utf-8" + uosPatchClientVersion = "2.0.0" + uosPatchExtspam = "Gp8ICJkIEpkICggwMDAwMDAwMRAGGoAI1GiJSIpeO1RZTq9QBKsRbPJdi84ropi16EYI10WB6g74sGmRwSNXjPQnYUKYotKkvLGpshucCaeWZMOylnc6o2AgDX9grhQQx7fm2DJRTyuNhUlwmEoWhjoG3F0ySAWUsEbH3bJMsEBwoB//0qmFJob74ffdaslqL+IrSy7LJ76/G5TkvNC+J0VQkpH1u3iJJs0uUYyLDzdBIQ6Ogd8LDQ3VKnJLm4g/uDLe+G7zzzkOPzCjXL+70naaQ9medzqmh+/SmaQ6uFWLDQLcRln++wBwoEibNpG4uOJvqXy+ql50DjlNchSuqLmeadFoo9/mDT0q3G7o/80P15ostktjb7h9bfNc+nZVSnUEJXbCjTeqS5UYuxn+HTS5nZsPVxJA2O5GdKCYK4x8lTTKShRstqPfbQpplfllx2fwXcSljuYi3YipPyS3GCAqf5A7aYYwJ7AvGqUiR2SsVQ9Nbp8MGHET1GxhifC692APj6SJxZD3i1drSYZPMMsS9rKAJTGz2FEupohtpf2tgXm6c16nDk/cw+C7K7me5j5PLHv55DFCS84b06AytZPdkFZLj7FHOkcFGJXitHkX5cgww7vuf6F3p0yM/W73SoXTx6GX4G6Hg2rYx3O/9VU2Uq8lvURB4qIbD9XQpzmyiFMaytMnqxcZJcoXCtfkTJ6pI7a92JpRUvdSitg967VUDUAQnCXCM/m0snRkR9LtoXAO1FUGpwlp1EfIdCZFPKNnXMeqev0j9W9ZrkEs9ZWcUEexSj5z+dKYQBhIICviYUQHVqBTZSNy22PlUIeDeIs11j7q4t8rD8LPvzAKWVqXE+5lS1JPZkjg4y5hfX1Dod3t96clFfwsvDP6xBSe1NBcoKbkyGxYK0UvPGtKQEE0Se2zAymYDv41klYE9s+rxp8e94/H8XhrL9oGm8KWb2RmYnAE7ry9gd6e8ZuBRIsISlJAE/e8y8xFmP031S6Lnaet6YXPsFpuFsdQs535IjcFd75hh6DNMBYhSfjv456cvhsb99+fRw/KVZLC3yzNSCbLSyo9d9BI45Plma6V8akURQA/qsaAzU0VyTIqZJkPDTzhuCl92vD2AD/QOhx6iwRSVPAxcRFZcWjgc2wCKh+uCYkTVbNQpB9B90YlNmI3fWTuUOUjwOzQRxJZj11NsimjOJ50qQwTTFj6qQvQ1a/I+MkTx5UO+yNHl718JWcR3AXGmv/aa9rD1eNP8ioTGlOZwPgmr2sor2iBpKTOrB83QgZXP+xRYkb4zVC+LoAXEoIa1+zArywlgREer7DLePukkU6wHTkuSaF+ge5Of1bXuU4i938WJHj0t3D8uQxkJvoFi/EYN/7u2P1zGRLV4dHVUsZMGCCtnO6BBigFMAA=" ) - // 消息类型 const ( - TextMessage = 1 - ImageMessage = 3 - AppMessage = 6 + TextMessage = 1 + ImageMessage = 3 + AppMessage = 6 ) // 登录状态 const ( - statusSuccess = "200" - statusScanned = "201" - statusTimeout = "400" - statusWait = "408" + statusSuccess = "200" + statusScanned = "201" + statusTimeout = "400" + statusWait = "408" ) // errors var ( - noSuchUserFoundError = errors.New("no such user found") + noSuchUserFoundError = errors.New("no such user found") ) const ALL = 0 // sex const ( - MALE = 1 - FEMALE = 2 + MALE = 1 + FEMALE = 2 ) diff --git a/items.go b/items.go index f14400c..d5f8c07 100644 --- a/items.go +++ b/items.go @@ -196,3 +196,9 @@ type CheckLoginResponse struct { Code string Raw []byte } + +type MessageResponse struct { + BaseResponse BaseResponse + LocalID string + MsgID string +} diff --git a/message.go b/message.go index 2ac2542..91b98cd 100644 --- a/message.go +++ b/message.go @@ -127,7 +127,7 @@ func (m *Message) IsSendByGroup() bool { } // 回复消息 -func (m *Message) Reply(msgType int, content, mediaId string) error { +func (m *Message) Reply(msgType int, content, mediaId string) (*SentMessage, error) { msg := NewSendMessage(msgType, content, m.Bot.self.User.UserName, m.FromUserName, mediaId) info := m.Bot.storage.LoginInfo request := m.Bot.storage.Request @@ -135,12 +135,12 @@ func (m *Message) Reply(msgType int, content, mediaId string) error { } // 回复文本消息 -func (m *Message) ReplyText(content string) error { +func (m *Message) ReplyText(content string) (*SentMessage, error) { return m.Reply(TextMessage, content, "") } // 回复图片消息 -func (m *Message) ReplyImage(file *os.File) error { +func (m *Message) ReplyImage(file *os.File) (*SentMessage, error) { info := m.Bot.storage.LoginInfo request := m.Bot.storage.Request return m.Bot.Caller.WebWxSendImageMsg(file, request, info, m.Bot.self.UserName, m.FromUserName) @@ -341,7 +341,7 @@ type SendMessage struct { // SendMessage的构造方法 func NewSendMessage(msgType int, content, fromUserName, toUserName, mediaId string) *SendMessage { - id := strconv.FormatInt(time.Now().Unix()*1e4, 10) + id := strconv.FormatInt(time.Now().UnixNano()/1e2, 10) return &SendMessage{ Type: msgType, Content: content, @@ -459,3 +459,15 @@ type RevokeMsg struct { ReplaceMsg string `xml:"replacemsg"` } `xml:"revokemsg"` } + +// 已发送的信息 +type SentMessage struct { + *SendMessage + Self *Self + MsgId string +} + +// 撤回该消息 +func (s *SentMessage) Revoke() error { + return s.Self.RevokeMessage(s) +} diff --git a/relations.go b/relations.go index 362eec4..cf1140d 100644 --- a/relations.go +++ b/relations.go @@ -19,17 +19,17 @@ func (f *Friend) SetRemarkName(name string) error { } // 发送自定义消息 -func (f *Friend) SendMsg(msg *SendMessage) error { +func (f *Friend) SendMsg(msg *SendMessage) (*SentMessage, error) { return f.Self.SendMessageToFriend(f, msg) } // 发送文本消息 -func (f *Friend) SendText(content string) error { +func (f *Friend) SendText(content string) (*SentMessage, error) { return f.Self.SendTextToFriend(f, content) } // 发送图片消息 -func (f *Friend) SendImage(file *os.File) error { +func (f *Friend) SendImage(file *os.File) (*SentMessage, error) { return f.Self.SendImageToFriend(f, file) } @@ -106,7 +106,7 @@ func (f Friends) SendMsg(msg *SendMessage, delay ...time.Duration) error { total := getTotalDuration(delay...) for _, friend := range f { time.Sleep(total) - if err := friend.SendMsg(msg); err != nil { + if _, err := friend.SendMsg(msg); err != nil { return err } } @@ -118,7 +118,7 @@ func (f Friends) SendText(text string, delay ...time.Duration) error { total := getTotalDuration(delay...) for _, friend := range f { time.Sleep(total) - if err := friend.SendText(text); err != nil { + if _, err := friend.SendText(text); err != nil { return err } } @@ -130,7 +130,7 @@ func (f Friends) SendImage(file *os.File, delay ...time.Duration) error { total := getTotalDuration(delay...) for _, friend := range f { time.Sleep(total) - if err := friend.SendImage(file); err != nil { + if _, err := friend.SendImage(file); err != nil { return err } } @@ -145,17 +145,17 @@ func (g Group) String() string { } // 发行消息给当前的群组 -func (g *Group) SendMsg(msg *SendMessage) error { +func (g *Group) SendMsg(msg *SendMessage) (*SentMessage, error) { return g.Self.SendMessageToGroup(g, msg) } // 发行文本消息给当前的群组 -func (g *Group) SendText(content string) error { +func (g *Group) SendText(content string) (*SentMessage, error) { return g.Self.SendTextToGroup(g, content) } // 发行图片消息给当前的群组 -func (g *Group) SendImage(file *os.File) error { +func (g *Group) SendImage(file *os.File) (*SentMessage, error) { return g.Self.SendImageToGroup(g, file) } @@ -208,7 +208,7 @@ func (g Groups) SendMsg(msg *SendMessage, delay ...time.Duration) error { total := getTotalDuration(delay...) for _, group := range g { time.Sleep(total) - if err := group.SendMsg(msg); err != nil { + if _, err := group.SendMsg(msg); err != nil { return err } } @@ -220,7 +220,7 @@ func (g Groups) SendText(text string, delay ...time.Duration) error { total := getTotalDuration(delay...) for _, group := range g { time.Sleep(total) - if err := group.SendText(text); err != nil { + if _, err := group.SendText(text); err != nil { return err } } @@ -232,7 +232,7 @@ func (g Groups) SendImage(file *os.File, delay ...time.Duration) error { total := getTotalDuration(delay...) for _, group := range g { time.Sleep(total) - if err := group.SendImage(file); err != nil { + if _, err := group.SendImage(file); err != nil { return err } } @@ -334,5 +334,3 @@ func (m Mps) Search(limit int, condFuncList ...func(group *Mp) bool) (results Mp } return } - - diff --git a/url.go b/url.go index 71ad3ae..519670e 100644 --- a/url.go +++ b/url.go @@ -2,76 +2,79 @@ package openwechat // url信息存储 type UrlManager struct { - baseUrl string - webWxNewLoginPageUrl string - webWxInitUrl string - webWxStatusNotifyUrl string - webWxSyncUrl string - webWxSendMsgUrl string - webWxGetContactUrl string - webWxSendMsgImgUrl string - webWxSendAppMsgUrl string - webWxBatchGetContactUrl string - webWxOplogUrl string - webWxVerifyUserUrl string - syncCheckUrl string - webWxUpLoadMediaUrl string - webWxGetMsgImgUrl string - webWxGetVoiceUrl string - webWxGetVideoUrl string - webWxLogoutUrl string - webWxGetMediaUrl string - webWxUpdateChatRoomUrl string + baseUrl string + webWxNewLoginPageUrl string + webWxInitUrl string + webWxStatusNotifyUrl string + webWxSyncUrl string + webWxSendMsgUrl string + webWxGetContactUrl string + webWxSendMsgImgUrl string + webWxSendAppMsgUrl string + webWxBatchGetContactUrl string + webWxOplogUrl string + webWxVerifyUserUrl string + syncCheckUrl string + webWxUpLoadMediaUrl string + webWxGetMsgImgUrl string + webWxGetVoiceUrl string + webWxGetVideoUrl string + webWxLogoutUrl string + webWxGetMediaUrl string + webWxUpdateChatRoomUrl string + webWxRevokeMsg string } var ( - // uos版 - desktop = UrlManager{ - baseUrl: baseDesktopUrl, - webWxNewLoginPageUrl: webWxNewLoginPageDesktopUrl, - webWxInitUrl: webWxInitDesktopUrl, - webWxStatusNotifyUrl: webWxStatusNotifyDesktopUrl, - webWxSyncUrl: webWxSyncDesktopUrl, - webWxSendMsgUrl: webWxSendMsgDesktopUrl, - webWxGetContactUrl: webWxGetContactDesktopUrl, - webWxSendMsgImgUrl: webWxSendMsgImgDesktopUrl, - webWxSendAppMsgUrl: webWxSendAppMsgDesktopUrl, - webWxBatchGetContactUrl: webWxBatchGetContactDesktopUrl, - webWxOplogUrl: webWxOplogDesktopUrl, - webWxVerifyUserUrl: webWxVerifyUserDesktopUrl, - syncCheckUrl: syncCheckDesktopUrl, - webWxUpLoadMediaUrl: webWxUpLoadMediaDesktopUrl, - webWxGetMsgImgUrl: webWxGetMsgImgDesktopUrl, - webWxGetVoiceUrl: webWxGetVoiceDesktopUrl, - webWxGetVideoUrl: webWxGetVideoDesktopUrl, - webWxLogoutUrl: webWxLogoutDesktopUrl, - webWxGetMediaUrl: webWxGetMediaDesktopUrl, - webWxUpdateChatRoomUrl: webWxUpdateChatRoomDesktopUrl, - } + // uos版 + desktop = UrlManager{ + baseUrl: baseDesktopUrl, + webWxNewLoginPageUrl: webWxNewLoginPageDesktopUrl, + webWxInitUrl: webWxInitDesktopUrl, + webWxStatusNotifyUrl: webWxStatusNotifyDesktopUrl, + webWxSyncUrl: webWxSyncDesktopUrl, + webWxSendMsgUrl: webWxSendMsgDesktopUrl, + webWxGetContactUrl: webWxGetContactDesktopUrl, + webWxSendMsgImgUrl: webWxSendMsgImgDesktopUrl, + webWxSendAppMsgUrl: webWxSendAppMsgDesktopUrl, + webWxBatchGetContactUrl: webWxBatchGetContactDesktopUrl, + webWxOplogUrl: webWxOplogDesktopUrl, + webWxVerifyUserUrl: webWxVerifyUserDesktopUrl, + syncCheckUrl: syncCheckDesktopUrl, + webWxUpLoadMediaUrl: webWxUpLoadMediaDesktopUrl, + webWxGetMsgImgUrl: webWxGetMsgImgDesktopUrl, + webWxGetVoiceUrl: webWxGetVoiceDesktopUrl, + webWxGetVideoUrl: webWxGetVideoDesktopUrl, + webWxLogoutUrl: webWxLogoutDesktopUrl, + webWxGetMediaUrl: webWxGetMediaDesktopUrl, + webWxUpdateChatRoomUrl: webWxUpdateChatRoomDesktopUrl, + webWxRevokeMsg: webWxRevokeMsgDesktopUrl, + } - // 网页版 - normal = UrlManager{ - baseUrl: baseNormalUrl, - webWxNewLoginPageUrl: webWxNewLoginPageNormalUrl, - webWxInitUrl: webWxInitNormalUrl, - webWxStatusNotifyUrl: webWxStatusNotifyNormalUrl, - webWxSyncUrl: webWxSyncNormalUrl, - webWxSendMsgUrl: webWxSendMsgNormalUrl, - webWxGetContactUrl: webWxGetContactNormalUrl, - webWxSendMsgImgUrl: webWxSendMsgImgNormalUrl, - webWxSendAppMsgUrl: webWxSendAppMsgNormalUrl, - webWxBatchGetContactUrl: webWxBatchGetContactNormalUrl, - webWxOplogUrl: webWxOplogNormalUrl, - webWxVerifyUserUrl: webWxVerifyUserNormalUrl, - syncCheckUrl: syncCheckNormalUrl, - webWxUpLoadMediaUrl: webWxUpLoadMediaNormalUrl, - webWxGetMsgImgUrl: webWxGetMsgImgNormalUrl, - webWxGetVoiceUrl: webWxGetVoiceNormalUrl, - webWxGetVideoUrl: webWxGetVideoNormalUrl, - webWxLogoutUrl: webWxLogoutNormalUrl, - webWxGetMediaUrl: webWxGetMediaNormalUrl, - webWxUpdateChatRoomUrl: webWxUpdateChatRoomNormalUrl, - } + // 网页版 + normal = UrlManager{ + baseUrl: baseNormalUrl, + webWxNewLoginPageUrl: webWxNewLoginPageNormalUrl, + webWxInitUrl: webWxInitNormalUrl, + webWxStatusNotifyUrl: webWxStatusNotifyNormalUrl, + webWxSyncUrl: webWxSyncNormalUrl, + webWxSendMsgUrl: webWxSendMsgNormalUrl, + webWxGetContactUrl: webWxGetContactNormalUrl, + webWxSendMsgImgUrl: webWxSendMsgImgNormalUrl, + webWxSendAppMsgUrl: webWxSendAppMsgNormalUrl, + webWxBatchGetContactUrl: webWxBatchGetContactNormalUrl, + webWxOplogUrl: webWxOplogNormalUrl, + webWxVerifyUserUrl: webWxVerifyUserNormalUrl, + syncCheckUrl: syncCheckNormalUrl, + webWxUpLoadMediaUrl: webWxUpLoadMediaNormalUrl, + webWxGetMsgImgUrl: webWxGetMsgImgNormalUrl, + webWxGetVoiceUrl: webWxGetVoiceNormalUrl, + webWxGetVideoUrl: webWxGetVideoNormalUrl, + webWxLogoutUrl: webWxLogoutNormalUrl, + webWxGetMediaUrl: webWxGetMediaNormalUrl, + webWxUpdateChatRoomUrl: webWxUpdateChatRoomNormalUrl, + webWxRevokeMsg: webWxRevokeMsgNormalUrl, + } ) // mode 类型限制 @@ -79,17 +82,17 @@ type mode string // 向外暴露2种模式 const ( - Normal mode = "normal" - Desktop mode = "desktop" + Normal mode = "normal" + Desktop mode = "desktop" ) func GetUrlManagerByMode(m mode) UrlManager { - switch m { - case Desktop: - return desktop - case Normal: - return normal - default: - panic("unsupport mode got") - } + switch m { + case Desktop: + return desktop + case Normal: + return normal + default: + panic("unsupport mode got") + } } diff --git a/user.go b/user.go index 3ab7740..8099744 100644 --- a/user.go +++ b/user.go @@ -205,74 +205,36 @@ func (s *Self) UpdateMembersDetail() error { if err != nil { return err } - // 获取他们的数量 - count := members.Count() - // 一次更新50个,分情况讨论 - - // 获取总的需要更新的次数 - var times int - if count < 50 { - times = 1 - } else { - times = count / 50 - } - var newMembers Members - request := s.Bot.storage.Request - var pMembers Members - // 分情况依次更新 - for i := 1; i <= times; i++ { - if times == 1 { - pMembers = members - } else { - pMembers = members[(i-1)*50 : i*50] - } - nMembers, err := s.Bot.Caller.WebWxBatchGetContact(pMembers, request) - if err != nil { - return err - } - newMembers = append(newMembers, nMembers...) - } - // 最后判断是否全部更新完毕 - total := times * 50 - if total < count { - // 将全部剩余的更新完毕 - left := count - total - pMembers = members[total : total+left] - nMembers, err := s.Bot.Caller.WebWxBatchGetContact(pMembers, request) - if err != nil { - return err - } - newMembers = append(newMembers, nMembers...) - } - if len(newMembers) > 0 { - newMembers.SetOwner(s) - s.members = newMembers - } - return nil + return members.detail(s) } // 抽象发送消息接口 -func (s *Self) sendMessageToUser(user *User, msg *SendMessage) error { +func (s *Self) sendMessageToUser(user *User, msg *SendMessage) (*SentMessage, error) { msg.FromUserName = s.UserName msg.ToUserName = user.UserName info := s.Bot.storage.LoginInfo request := s.Bot.storage.Request - return s.Bot.Caller.WebWxSendMsg(msg, info, request) + successSendMessage, err := s.Bot.Caller.WebWxSendMsg(msg, info, request) + if err != nil { + return nil, err + } + successSendMessage.Self = s + return successSendMessage, nil } // 发送消息给好友 -func (s *Self) SendMessageToFriend(friend *Friend, msg *SendMessage) error { +func (s *Self) SendMessageToFriend(friend *Friend, msg *SendMessage) (*SentMessage, error) { return s.sendMessageToUser(friend.User, msg) } // 发送文本消息给好友 -func (s *Self) SendTextToFriend(friend *Friend, text string) error { +func (s *Self) SendTextToFriend(friend *Friend, text string) (*SentMessage, error) { msg := NewTextSendMessage(text, s.UserName, friend.UserName) return s.SendMessageToFriend(friend, msg) } // 发送图片消息给好友 -func (s *Self) SendImageToFriend(friend *Friend, file *os.File) error { +func (s *Self) SendImageToFriend(friend *Friend, file *os.File) (*SentMessage, error) { req := s.Bot.storage.Request info := s.Bot.storage.LoginInfo return s.Bot.Caller.WebWxSendImageMsg(file, req, info, s.UserName, friend.UserName) @@ -351,23 +313,28 @@ func (s *Self) AddFriendIntoManyGroups(friend *Friend, groups ...*Group) error { } // 发送消息给群组 -func (s *Self) SendMessageToGroup(group *Group, msg *SendMessage) error { +func (s *Self) SendMessageToGroup(group *Group, msg *SendMessage) (*SentMessage, error) { return s.sendMessageToUser(group.User, msg) } // 发送文本消息给群组 -func (s *Self) SendTextToGroup(group *Group, text string) error { +func (s *Self) SendTextToGroup(group *Group, text string) (*SentMessage, error) { msg := NewTextSendMessage(text, s.UserName, group.UserName) return s.SendMessageToGroup(group, msg) } // 发送图片消息给群组 -func (s *Self) SendImageToGroup(group *Group, file *os.File) error { +func (s *Self) SendImageToGroup(group *Group, file *os.File) (*SentMessage, error) { req := s.Bot.storage.Request info := s.Bot.storage.LoginInfo return s.Bot.Caller.WebWxSendImageMsg(file, req, info, s.UserName, group.UserName) } +// 撤回消息 +func (s *Self) RevokeMessage(msg *SentMessage) error { + return s.Bot.Caller.WebWxRevokeMsg(msg, s.Bot.storage.Request) +} + // 抽象的用户组 type Members []*User @@ -477,6 +444,55 @@ func (m Members) MPs() Mps { return mps } +func (m Members) detail(self *Self) error { + // 获取他们的数量 + members := m + + count := members.Count() + // 一次更新50个,分情况讨论 + + // 获取总的需要更新的次数 + var times int + if count < 50 { + times = 1 + } else { + times = count / 50 + } + var newMembers Members + request := self.Bot.storage.Request + var pMembers Members + // 分情况依次更新 + for i := 1; i <= times; i++ { + if times == 1 { + pMembers = members + } else { + pMembers = members[(i-1)*50 : i*50] + } + nMembers, err := self.Bot.Caller.WebWxBatchGetContact(pMembers, request) + if err != nil { + return err + } + newMembers = append(newMembers, nMembers...) + } + // 最后判断是否全部更新完毕 + total := times * 50 + if total < count { + // 将全部剩余的更新完毕 + left := count - total + pMembers = members[total : total+left] + nMembers, err := self.Bot.Caller.WebWxBatchGetContact(pMembers, request) + if err != nil { + return err + } + newMembers = append(newMembers, nMembers...) + } + if len(newMembers) > 0 { + newMembers.SetOwner(self) + self.members = newMembers + } + return nil +} + // 这里为了兼容Desktop版本找不到文件传输助手的问题 // 文件传输助手的微信身份标识符永远是filehelper // 这种形式的对象可能缺少一些其他属性