增加大文件上传支持
This commit is contained in:
parent
5ff43c4cea
commit
fac0ede488
13
bot_test.go
13
bot_test.go
@ -1,6 +1,7 @@
|
|||||||
package openwechat
|
package openwechat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -238,8 +239,8 @@ func TestHotLogin(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFriendHelper(t *testing.T) {
|
func TestFriendHelper(t *testing.T) {
|
||||||
bot := defaultBot(Desktop)
|
bot := defaultBot()
|
||||||
if err := bot.Login(); err != nil {
|
if err := bot.HotLogin(NewJsonFileHotReloadStorage("2.json"), true); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -253,7 +254,11 @@ func TestFriendHelper(t *testing.T) {
|
|||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
msg, err := fh.SendText("test message")
|
f, _ := os.Open("webwxgetmsgimg.jpeg")
|
||||||
|
//f, _ := os.Open("2.jpeg")
|
||||||
|
defer f.Close()
|
||||||
|
msg, err := fh.SendImage(f)
|
||||||
|
//msg, err := fh.SendText("hh")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
@ -263,7 +268,7 @@ func TestFriendHelper(t *testing.T) {
|
|||||||
|
|
||||||
func TestRevokeMessage(t *testing.T) {
|
func TestRevokeMessage(t *testing.T) {
|
||||||
bot := defaultBot(Desktop)
|
bot := defaultBot(Desktop)
|
||||||
if err := bot.Login(); err != nil {
|
if err := bot.HotLogin(NewJsonFileHotReloadStorage("2.json")); err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
23
caller.go
23
caller.go
@ -2,6 +2,7 @@ package openwechat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -203,29 +204,45 @@ func (c *Caller) WebWxOplog(request *BaseRequest, remarkName, toUserName string)
|
|||||||
// 发送图片消息接口
|
// 发送图片消息接口
|
||||||
func (c *Caller) WebWxSendImageMsg(file *os.File, request *BaseRequest, info *LoginInfo, fromUserName, toUserName string) (*SentMessage, 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"))
|
sate, err := file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp *ReturnResponse
|
||||||
|
if sate.Size() <= chunkSize {
|
||||||
|
resp = NewReturnResponse(c.Client.WebWxUploadMedia(file, request, info, fromUserName, toUserName, "pic"))
|
||||||
|
} else {
|
||||||
|
resp = NewReturnResponse(c.Client.WebWxUploadMediaByChunk(file, request, info, fromUserName, toUserName, "pic"))
|
||||||
|
}
|
||||||
// 无错误上传成功之后获取请求结果,判断结果是否正常
|
// 无错误上传成功之后获取请求结果,判断结果是否正常
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
data, _ := resp.ReadAll()
|
||||||
|
fmt.Println(string(data))
|
||||||
var item struct {
|
var item struct {
|
||||||
BaseResponse BaseResponse
|
BaseResponse BaseResponse
|
||||||
MediaId string
|
MediaId string
|
||||||
}
|
}
|
||||||
if err := resp.ScanJSON(&item); err != nil {
|
|
||||||
|
if err = resp.ScanJSON(&item); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if !item.BaseResponse.Ok() {
|
if !item.BaseResponse.Ok() {
|
||||||
return nil, item.BaseResponse
|
return nil, item.BaseResponse
|
||||||
}
|
}
|
||||||
|
if len(item.MediaId) == 0 {
|
||||||
|
return nil, errors.New("upload failed")
|
||||||
|
}
|
||||||
// 构造新的图片类型的信息
|
// 构造新的图片类型的信息
|
||||||
msg := NewMediaSendMessage(ImageMessage, fromUserName, toUserName, item.MediaId)
|
msg := NewMediaSendMessage(ImageMessage, fromUserName, toUserName, item.MediaId)
|
||||||
// 发送图片信息
|
// 发送图片信息
|
||||||
resp = NewReturnResponse(c.Client.WebWxSendMsgImg(msg, request, info))
|
resp = NewReturnResponse(c.Client.WebWxSendMsgImg(msg, request, info))
|
||||||
|
|
||||||
sendSuccessMsg := &SentMessage{SendMessage: msg}
|
sendSuccessMsg := &SentMessage{SendMessage: msg}
|
||||||
err := parseMessageResponseError(resp, sendSuccessMsg)
|
err = parseMessageResponseError(resp, sendSuccessMsg)
|
||||||
return sendSuccessMsg, err
|
return sendSuccessMsg, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
144
client.go
144
client.go
@ -46,6 +46,7 @@ func DefaultClient(urlManager UrlManager) *Client {
|
|||||||
// 抽象Do方法,将所有的有效的cookie存入Client.cookies
|
// 抽象Do方法,将所有的有效的cookie存入Client.cookies
|
||||||
// 方便热登陆时获取
|
// 方便热登陆时获取
|
||||||
func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
func (c *Client) Do(req *http.Request) (*http.Response, error) {
|
||||||
|
req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36")
|
||||||
resp, err := c.Client.Do(req)
|
resp, err := c.Client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return resp, err
|
return resp, err
|
||||||
@ -251,7 +252,12 @@ func (c *Client) WebWxGetHeadImg(headImageUrl string) (*http.Response, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 上传文件
|
// 上传文件
|
||||||
func (c *Client) WebWxUploadMedia(file *os.File, request *BaseRequest, info *LoginInfo, forUserName, toUserName, contentType, mediaType string) (*http.Response, error) {
|
func (c *Client) WebWxUploadMedia(file *os.File, request *BaseRequest, info *LoginInfo, forUserName, toUserName, mediaType string) (*http.Response, error) {
|
||||||
|
// 获取文件上传的类型
|
||||||
|
contentType, err := GetFileContentType(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
path, _ := url.Parse(c.webWxUpLoadMediaUrl)
|
path, _ := url.Parse(c.webWxUpLoadMediaUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
params.Add("f", "json")
|
params.Add("f", "json")
|
||||||
@ -260,13 +266,21 @@ func (c *Client) WebWxUploadMedia(file *os.File, request *BaseRequest, info *Log
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
cookies := c.Jar.Cookies(path)
|
||||||
|
webWxDataTicket := getWebWxDataTicket(cookies)
|
||||||
|
|
||||||
|
// 文件复位
|
||||||
|
if _, err = file.Seek(0, 0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
buffer := bytes.Buffer{}
|
buffer := bytes.Buffer{}
|
||||||
if _, err := buffer.ReadFrom(file); err != nil {
|
if _, err := buffer.ReadFrom(file); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
data := buffer.Bytes()
|
data := buffer.Bytes()
|
||||||
fileMd5 := fmt.Sprintf("%x", md5.Sum(data))
|
fileMd5 := fmt.Sprintf("%x", md5.Sum(data))
|
||||||
cookies := c.Jar.Cookies(path)
|
|
||||||
uploadMediaRequest := map[string]interface{}{
|
uploadMediaRequest := map[string]interface{}{
|
||||||
"UploadType": 2,
|
"UploadType": 2,
|
||||||
"BaseRequest": request,
|
"BaseRequest": request,
|
||||||
@ -283,14 +297,15 @@ func (c *Client) WebWxUploadMedia(file *os.File, request *BaseRequest, info *Log
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
content := map[string]interface{}{
|
content := map[string]interface{}{
|
||||||
"id": "WU_FILE_0",
|
"id": "WU_FILE_0",
|
||||||
"name": file.Name(),
|
"name": file.Name(),
|
||||||
"type": contentType,
|
"type": contentType,
|
||||||
"lastModifiedDate": time.Now().Format(http.TimeFormat),
|
"lastModifiedDate": sate.ModTime().Format(TimeFormat),
|
||||||
"size": sate.Size(),
|
"size": sate.Size(),
|
||||||
"mediatype": mediaType,
|
"mediatype": mediaType,
|
||||||
"webwx_data_ticket": getWebWxDataTicket(cookies),
|
"webwx_data_ticket": webWxDataTicket,
|
||||||
"pass_ticket": info.PassTicket,
|
"pass_ticket": info.PassTicket,
|
||||||
}
|
}
|
||||||
body, err := ToBuffer(content)
|
body, err := ToBuffer(content)
|
||||||
@ -313,10 +328,131 @@ func (c *Client) WebWxUploadMedia(file *os.File, request *BaseRequest, info *Log
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req, _ := http.NewRequest(http.MethodPost, path.String(), body)
|
req, _ := http.NewRequest(http.MethodPost, path.String(), body)
|
||||||
|
|
||||||
req.Header.Set("Content-Type", ct)
|
req.Header.Set("Content-Type", ct)
|
||||||
return c.Do(req)
|
return c.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) WebWxUploadMediaByChunk(file *os.File, request *BaseRequest, info *LoginInfo, forUserName, toUserName, mediaType string) (*http.Response, error) {
|
||||||
|
// 获取文件上传的类型
|
||||||
|
contentType, err := GetFileContentType(file)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
path, _ := url.Parse(c.webWxUpLoadMediaUrl)
|
||||||
|
params := url.Values{}
|
||||||
|
params.Add("f", "json")
|
||||||
|
path.RawQuery = params.Encode()
|
||||||
|
sate, err := file.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cookies := c.Jar.Cookies(path)
|
||||||
|
webWxDataTicket := getWebWxDataTicket(cookies)
|
||||||
|
|
||||||
|
// 将文件的游标复原到原点
|
||||||
|
// 上面获取文件的类型的时候已经读取了512个字节
|
||||||
|
if _, err = file.Seek(0, 0); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer := bytes.Buffer{}
|
||||||
|
if _, err := buffer.ReadFrom(file); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
data := buffer.Bytes()
|
||||||
|
fileMd5 := fmt.Sprintf("%x", md5.Sum(data))
|
||||||
|
|
||||||
|
uploadMediaRequest := map[string]interface{}{
|
||||||
|
"UploadType": 2,
|
||||||
|
"BaseRequest": request,
|
||||||
|
"ClientMediaId": time.Now().Unix() * 1e4,
|
||||||
|
"TotalLen": sate.Size(),
|
||||||
|
"StartPos": 0,
|
||||||
|
"DataLen": sate.Size(),
|
||||||
|
"MediaType": 4,
|
||||||
|
"FromUserName": forUserName,
|
||||||
|
"ToUserName": toUserName,
|
||||||
|
"FileMd5": fileMd5,
|
||||||
|
}
|
||||||
|
uploadMediaRequestByte, err := json.Marshal(uploadMediaRequest)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
chunks := sate.Size() / chunkSize
|
||||||
|
if chunks*chunkSize < sate.Size() {
|
||||||
|
chunks++
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp *http.Response
|
||||||
|
|
||||||
|
for chunk := 0; int64(chunk) < chunks; chunk++ {
|
||||||
|
content := map[string]interface{}{
|
||||||
|
"id": "WU_FILE_0",
|
||||||
|
"name": file.Name(),
|
||||||
|
"type": contentType,
|
||||||
|
"lastModifiedDate": sate.ModTime().Format(TimeFormat),
|
||||||
|
"size": sate.Size(),
|
||||||
|
"mediatype": mediaType,
|
||||||
|
"webwx_data_ticket": webWxDataTicket,
|
||||||
|
"pass_ticket": info.PassTicket,
|
||||||
|
"chunks": chunks,
|
||||||
|
"chunk": chunk,
|
||||||
|
}
|
||||||
|
body, err := ToBuffer(content)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
writer := multipart.NewWriter(body)
|
||||||
|
if err = writer.WriteField("uploadmediarequest", string(uploadMediaRequestByte)); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var isLastTime bool
|
||||||
|
if int64(chunk)+1 == chunks {
|
||||||
|
isLastTime = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if w, err := writer.CreateFormFile("filename", file.Name()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
} else {
|
||||||
|
var chunkData []byte
|
||||||
|
// 判断是不是最后一次
|
||||||
|
if !isLastTime {
|
||||||
|
chunkData = data[int64(chunk)*chunkSize : (int64(chunk)+1)*chunkSize]
|
||||||
|
} else {
|
||||||
|
chunkData = data[int64(chunk)*chunkSize:]
|
||||||
|
}
|
||||||
|
if _, err = w.Write(chunkData); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ct := writer.FormDataContentType()
|
||||||
|
if err = writer.Close(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req, _ := http.NewRequest(http.MethodPost, path.String(), body)
|
||||||
|
req.Header.Set("Content-Type", ct)
|
||||||
|
//req.Header.Add("Referer", c.baseUrl)
|
||||||
|
//req.Header.Add("Origin", c.baseUrl)
|
||||||
|
//// Host: file.wx2.qq.com
|
||||||
|
//req.Header.Add("Host", "file.wx2.qq.com")
|
||||||
|
// 发送数据
|
||||||
|
resp, err = c.Do(req)
|
||||||
|
|
||||||
|
// 如果不是最后一次, 解析有没有错误
|
||||||
|
if !isLastTime {
|
||||||
|
returnResp := NewReturnResponse(resp, err)
|
||||||
|
if err := parseBaseResponseError(returnResp); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
// 发送图片
|
// 发送图片
|
||||||
// 这个接口依赖上传文件的接口
|
// 这个接口依赖上传文件的接口
|
||||||
// 发送的图片必须是已经成功上传的图片
|
// 发送的图片必须是已经成功上传的图片
|
||||||
|
138
global.go
138
global.go
@ -1,94 +1,94 @@
|
|||||||
package openwechat
|
package openwechat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
uuidRegexp = regexp.MustCompile(`uuid = "(.*?)";`)
|
uuidRegexp = regexp.MustCompile(`uuid = "(.*?)";`)
|
||||||
statusCodeRegexp = regexp.MustCompile(`window.code=(\d+);`)
|
statusCodeRegexp = regexp.MustCompile(`window.code=(\d+);`)
|
||||||
syncCheckRegexp = regexp.MustCompile(`window.synccheck=\{retcode:"(\d+)",selector:"(\d+)"\}`)
|
syncCheckRegexp = regexp.MustCompile(`window.synccheck=\{retcode:"(\d+)",selector:"(\d+)"\}`)
|
||||||
redirectUriRegexp = regexp.MustCompile(`window.redirect_uri="(.*?)"`)
|
redirectUriRegexp = regexp.MustCompile(`window.redirect_uri="(.*?)"`)
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
appId = "wx782c26e4c19acffb"
|
appId = "wx782c26e4c19acffb"
|
||||||
jsLoginUrl = "https://login.wx.qq.com/jslogin"
|
jsLoginUrl = "https://login.wx.qq.com/jslogin"
|
||||||
qrcodeUrl = "https://login.weixin.qq.com/qrcode/"
|
qrcodeUrl = "https://login.weixin.qq.com/qrcode/"
|
||||||
loginUrl = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login"
|
loginUrl = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login"
|
||||||
|
|
||||||
// Normal urls
|
// Normal urls
|
||||||
|
|
||||||
baseNormalUrl = "https://wx2.qq.com"
|
baseNormalUrl = "https://wx2.qq.com"
|
||||||
webWxNewLoginPageNormalUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage"
|
webWxNewLoginPageNormalUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage"
|
||||||
webWxInitNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit"
|
webWxInitNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxinit"
|
||||||
webWxStatusNotifyNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify"
|
webWxStatusNotifyNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify"
|
||||||
webWxSyncNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync"
|
webWxSyncNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsync"
|
||||||
webWxSendMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg"
|
webWxSendMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg"
|
||||||
webWxGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact"
|
webWxGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact"
|
||||||
webWxSendMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg"
|
webWxSendMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg"
|
||||||
webWxSendAppMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg"
|
webWxSendAppMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg"
|
||||||
webWxBatchGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact"
|
webWxBatchGetContactNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact"
|
||||||
webWxOplogNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxoplog"
|
webWxOplogNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxoplog"
|
||||||
webWxVerifyUserNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser"
|
webWxVerifyUserNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser"
|
||||||
syncCheckNormalUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin/synccheck"
|
syncCheckNormalUrl = "https://webpush.wx2.qq.com/cgi-bin/mmwebwx-bin/synccheck"
|
||||||
webWxUpLoadMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia"
|
webWxUpLoadMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia"
|
||||||
webWxGetMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg"
|
webWxGetMsgImgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg"
|
||||||
webWxGetVoiceNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice"
|
webWxGetVoiceNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice"
|
||||||
webWxGetVideoNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo"
|
webWxGetVideoNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo"
|
||||||
webWxLogoutNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxlogout"
|
webWxLogoutNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxlogout"
|
||||||
webWxGetMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia"
|
webWxGetMediaNormalUrl = "https://file.wx2.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia"
|
||||||
webWxUpdateChatRoomNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom"
|
webWxUpdateChatRoomNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom"
|
||||||
webWxRevokeMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxrevokemsg"
|
webWxRevokeMsgNormalUrl = "https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxrevokemsg"
|
||||||
|
|
||||||
// Desktop urls
|
// Desktop urls
|
||||||
|
|
||||||
baseDesktopUrl = "https://wx.qq.com"
|
baseDesktopUrl = "https://wx.qq.com"
|
||||||
webWxNewLoginPageDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?mod=desktop"
|
webWxNewLoginPageDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?mod=desktop"
|
||||||
webWxInitDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit"
|
webWxInitDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit"
|
||||||
webWxStatusNotifyDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify"
|
webWxStatusNotifyDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify"
|
||||||
webWxSyncDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync"
|
webWxSyncDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync"
|
||||||
webWxSendMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg"
|
webWxSendMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg"
|
||||||
webWxGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact"
|
webWxGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact"
|
||||||
webWxSendMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg"
|
webWxSendMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg"
|
||||||
webWxSendAppMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg"
|
webWxSendAppMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg"
|
||||||
webWxBatchGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact"
|
webWxBatchGetContactDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact"
|
||||||
webWxOplogDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxoplog"
|
webWxOplogDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxoplog"
|
||||||
webWxVerifyUserDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser"
|
webWxVerifyUserDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser"
|
||||||
syncCheckDesktopUrl = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck"
|
syncCheckDesktopUrl = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck"
|
||||||
webWxUpLoadMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia"
|
webWxUpLoadMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia"
|
||||||
webWxGetMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg"
|
webWxGetMsgImgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg"
|
||||||
webWxGetVoiceDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice"
|
webWxGetVoiceDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice"
|
||||||
webWxGetVideoDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo"
|
webWxGetVideoDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo"
|
||||||
webWxLogoutDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout"
|
webWxLogoutDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout"
|
||||||
webWxGetMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia"
|
webWxGetMediaDesktopUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia"
|
||||||
webWxUpdateChatRoomDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom"
|
webWxUpdateChatRoomDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxupdatechatroom"
|
||||||
webWxRevokeMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxrevokemsg"
|
webWxRevokeMsgDesktopUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxrevokemsg"
|
||||||
|
|
||||||
jsonContentType = "application/json; charset=utf-8"
|
jsonContentType = "application/json; charset=utf-8"
|
||||||
uosPatchClientVersion = "2.0.0"
|
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="
|
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 (
|
const (
|
||||||
TextMessage = 1
|
TextMessage = 1
|
||||||
ImageMessage = 3
|
ImageMessage = 3
|
||||||
AppMessage = 6
|
AppMessage = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
// 登录状态
|
// 登录状态
|
||||||
const (
|
const (
|
||||||
statusSuccess = "200"
|
statusSuccess = "200"
|
||||||
statusScanned = "201"
|
statusScanned = "201"
|
||||||
statusTimeout = "400"
|
statusTimeout = "400"
|
||||||
statusWait = "408"
|
statusWait = "408"
|
||||||
)
|
)
|
||||||
|
|
||||||
// errors
|
// errors
|
||||||
var (
|
var (
|
||||||
noSuchUserFoundError = errors.New("no such user found")
|
noSuchUserFoundError = errors.New("no such user found")
|
||||||
)
|
)
|
||||||
|
|
||||||
// ALL跟search函数搭配
|
// ALL跟search函数搭配
|
||||||
@ -97,6 +97,10 @@ const ALL = 0
|
|||||||
|
|
||||||
// 性别
|
// 性别
|
||||||
const (
|
const (
|
||||||
MALE = 1
|
MALE = 1
|
||||||
FEMALE = 2
|
FEMALE = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const chunkSize int64 = 512 * 1024
|
||||||
|
|
||||||
|
const TimeFormat = "Mon Jan 02 2006 15:04:05 GMT+0800 (中国标准时间)"
|
||||||
|
12
parser.go
12
parser.go
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"mime/multipart"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -18,6 +19,7 @@ func ToBuffer(v interface{}) (*bytes.Buffer, error) {
|
|||||||
return bytes.NewBuffer(buf), nil
|
return bytes.NewBuffer(buf), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取随机设备id
|
||||||
func GetRandomDeviceId() string {
|
func GetRandomDeviceId() string {
|
||||||
rand.Seed(time.Now().Unix())
|
rand.Seed(time.Now().Unix())
|
||||||
var builder strings.Builder
|
var builder strings.Builder
|
||||||
@ -38,6 +40,7 @@ func getWebWxDataTicket(cookies []*http.Cookie) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Form Xml 格式化
|
||||||
func XmlFormString(text string) string {
|
func XmlFormString(text string) string {
|
||||||
lt := strings.ReplaceAll(text, "<", "<")
|
lt := strings.ReplaceAll(text, "<", "<")
|
||||||
gt := strings.ReplaceAll(lt, ">", ">")
|
gt := strings.ReplaceAll(lt, ">", ">")
|
||||||
@ -52,3 +55,12 @@ func getTotalDuration(delay ...time.Duration) time.Duration {
|
|||||||
}
|
}
|
||||||
return total
|
return total
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取文件上传的类型
|
||||||
|
func GetFileContentType(file multipart.File) (string, error) {
|
||||||
|
data := make([]byte, 512)
|
||||||
|
if _, err := file.Read(data); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return http.DetectContentType(data), nil
|
||||||
|
}
|
||||||
|
3
user.go
3
user.go
@ -9,7 +9,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 抽象的用户结构,包含 好友 群组 公众号
|
// 抽象的用户结构: 好友 群组 公众号
|
||||||
type User struct {
|
type User struct {
|
||||||
Uin int
|
Uin int
|
||||||
HideInputBarFlag int
|
HideInputBarFlag int
|
||||||
@ -451,6 +451,7 @@ func (m Members) MPs() Mps {
|
|||||||
return mps
|
return mps
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前Members的详情
|
||||||
func (m Members) detail(self *Self) error {
|
func (m Members) detail(self *Self) error {
|
||||||
// 获取他们的数量
|
// 获取他们的数量
|
||||||
members := m
|
members := m
|
||||||
|
Loading…
x
Reference in New Issue
Block a user