支持网页版和uos版切换
This commit is contained in:
parent
793bb95095
commit
9cfa517518
319
bot.go
319
bot.go
@ -1,216 +1,223 @@
|
||||
package openwechat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Bot struct {
|
||||
Caller *Caller
|
||||
self *Self
|
||||
storage *Storage
|
||||
ScanCallBack func(body []byte)
|
||||
LoginCallBack func(body []byte)
|
||||
UUIDCallback func(uuid string)
|
||||
MessageHandler func(msg *Message)
|
||||
err error
|
||||
exit chan bool
|
||||
Caller *Caller
|
||||
self *Self
|
||||
storage *Storage
|
||||
ScanCallBack func(body []byte)
|
||||
LoginCallBack func(body []byte)
|
||||
UUIDCallback func(uuid string)
|
||||
MessageHandler func(msg *Message)
|
||||
err error
|
||||
exit chan bool
|
||||
}
|
||||
|
||||
// 判断当前用户是否正常在线MessageHandler
|
||||
// 判断当前用户是否正常在线
|
||||
func (b *Bot) Alive() bool {
|
||||
if b.self == nil {
|
||||
return false
|
||||
}
|
||||
select {
|
||||
case <-b.exit:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
if b.self == nil {
|
||||
return false
|
||||
}
|
||||
select {
|
||||
case <-b.exit:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前的用户
|
||||
func (b *Bot) GetCurrentUser() (*Self, error) {
|
||||
if b.self == nil {
|
||||
return nil, errors.New("user not login")
|
||||
}
|
||||
return b.self, nil
|
||||
if b.self == nil {
|
||||
return nil, errors.New("user not login")
|
||||
}
|
||||
return b.self, nil
|
||||
}
|
||||
|
||||
// 用户登录
|
||||
// 该方法会一直阻塞,直到用户扫码登录,或者二维码过期
|
||||
func (b *Bot) Login() error {
|
||||
uuid, err := b.Caller.GetLoginUUID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b.UUIDCallback != nil {
|
||||
b.UUIDCallback(uuid)
|
||||
}
|
||||
for {
|
||||
resp, err := b.Caller.CheckLogin(uuid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch resp.Code {
|
||||
case statusSuccess:
|
||||
return b.login(resp.Raw)
|
||||
case statusScanned:
|
||||
if b.ScanCallBack != nil {
|
||||
b.ScanCallBack(resp.Raw)
|
||||
}
|
||||
case statusTimeout:
|
||||
return errors.New("login time out")
|
||||
case statusWait:
|
||||
continue
|
||||
}
|
||||
}
|
||||
uuid, err := b.Caller.GetLoginUUID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b.UUIDCallback != nil {
|
||||
b.UUIDCallback(uuid)
|
||||
}
|
||||
for {
|
||||
resp, err := b.Caller.CheckLogin(uuid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch resp.Code {
|
||||
case statusSuccess:
|
||||
return b.login(resp.Raw)
|
||||
case statusScanned:
|
||||
if b.ScanCallBack != nil {
|
||||
b.ScanCallBack(resp.Raw)
|
||||
}
|
||||
case statusTimeout:
|
||||
return errors.New("login time out")
|
||||
case statusWait:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Bot) Logout() error {
|
||||
if b.Alive() {
|
||||
info := b.storage.LoginInfo
|
||||
if err := b.Caller.Logout(info); err != nil {
|
||||
return err
|
||||
}
|
||||
b.stopAsyncCALL(errors.New("logout"))
|
||||
return nil
|
||||
}
|
||||
return errors.New("user not login")
|
||||
if b.Alive() {
|
||||
info := b.storage.LoginInfo
|
||||
if err := b.Caller.Logout(info); err != nil {
|
||||
return err
|
||||
}
|
||||
b.stopAsyncCALL(errors.New("logout"))
|
||||
return nil
|
||||
}
|
||||
return errors.New("user not login")
|
||||
}
|
||||
|
||||
// 登录逻辑
|
||||
func (b *Bot) login(data []byte) error {
|
||||
// 判断是否有登录回调,如果有执行它
|
||||
if b.LoginCallBack != nil {
|
||||
b.LoginCallBack(data)
|
||||
}
|
||||
// 获取登录的一些基本的信息
|
||||
info, err := b.Caller.GetLoginInfo(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 判断是否有登录回调,如果有执行它
|
||||
if b.LoginCallBack != nil {
|
||||
b.LoginCallBack(data)
|
||||
}
|
||||
// 获取登录的一些基本的信息
|
||||
info, err := b.Caller.GetLoginInfo(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 将LoginInfo存到storage里面
|
||||
b.storage.LoginInfo = info
|
||||
// 将LoginInfo存到storage里面
|
||||
b.storage.LoginInfo = info
|
||||
|
||||
// 构建BaseRequest
|
||||
request := &BaseRequest{
|
||||
Uin: info.WxUin,
|
||||
Sid: info.WxSid,
|
||||
Skey: info.SKey,
|
||||
DeviceID: GetRandomDeviceId(),
|
||||
}
|
||||
// 构建BaseRequest
|
||||
request := &BaseRequest{
|
||||
Uin: info.WxUin,
|
||||
Sid: info.WxSid,
|
||||
Skey: info.SKey,
|
||||
DeviceID: GetRandomDeviceId(),
|
||||
}
|
||||
|
||||
// 将BaseRequest存到storage里面方便后续调用
|
||||
b.storage.Request = request
|
||||
// 获取初始化的用户信息和一些必要的参数
|
||||
resp, err := b.Caller.WebInit(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 设置当前的用户
|
||||
b.self = &Self{Bot: b, User: &resp.User}
|
||||
b.self.Self = b.self
|
||||
b.storage.Response = resp
|
||||
// 将BaseRequest存到storage里面方便后续调用
|
||||
b.storage.Request = request
|
||||
// 获取初始化的用户信息和一些必要的参数
|
||||
resp, err := b.Caller.WebInit(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 设置当前的用户
|
||||
b.self = &Self{Bot: b, User: &resp.User}
|
||||
b.self.Self = b.self
|
||||
b.storage.Response = resp
|
||||
|
||||
// 通知手机客户端已经登录
|
||||
if err = b.Caller.WebWxStatusNotify(request, resp, info); err != nil {
|
||||
return err
|
||||
}
|
||||
// 开启协程,轮训获取是否有新的消息返回
|
||||
go func() {
|
||||
b.stopAsyncCALL(b.asyncCall())
|
||||
}()
|
||||
return nil
|
||||
// 通知手机客户端已经登录
|
||||
if err = b.Caller.WebWxStatusNotify(request, resp, info); err != nil {
|
||||
return err
|
||||
}
|
||||
// 开启协程,轮训获取是否有新的消息返回
|
||||
go func() {
|
||||
b.stopAsyncCALL(b.asyncCall())
|
||||
}()
|
||||
return nil
|
||||
}
|
||||
|
||||
// 轮训请求
|
||||
// 根据状态码判断是否有新的请求
|
||||
func (b *Bot) asyncCall() error {
|
||||
var (
|
||||
err error
|
||||
resp *SyncCheckResponse
|
||||
)
|
||||
for b.Alive() {
|
||||
info := b.storage.LoginInfo
|
||||
response := b.storage.Response
|
||||
resp, err = b.Caller.SyncCheck(info, response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 如果不是正常的状态码返回,发生了错误,直接退出
|
||||
if !resp.Success() {
|
||||
return fmt.Errorf("unknow code got %s", resp.RetCode)
|
||||
}
|
||||
// 如果Selector不为0,则获取消息
|
||||
if !resp.NorMal() {
|
||||
if err = b.getMessage(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
var (
|
||||
err error
|
||||
resp *SyncCheckResponse
|
||||
)
|
||||
for b.Alive() {
|
||||
info := b.storage.LoginInfo
|
||||
response := b.storage.Response
|
||||
resp, err = b.Caller.SyncCheck(info, response)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 如果不是正常的状态码返回,发生了错误,直接退出
|
||||
if !resp.Success() {
|
||||
return fmt.Errorf("unknow code got %s", resp.RetCode)
|
||||
}
|
||||
// 如果Selector不为0,则获取消息
|
||||
if !resp.NorMal() {
|
||||
if err = b.getMessage(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (b *Bot) stopAsyncCALL(err error) {
|
||||
b.exit <- true
|
||||
b.err = err
|
||||
b.self = nil
|
||||
b.exit <- true
|
||||
b.err = err
|
||||
b.self = nil
|
||||
}
|
||||
|
||||
// 获取新的消息
|
||||
func (b *Bot) getMessage() error {
|
||||
resp, err := b.Caller.WebWxSync(b.storage.Request, b.storage.Response, b.storage.LoginInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 更新SyncKey并且重新存入storage
|
||||
b.storage.Response.SyncKey = resp.SyncKey
|
||||
// 遍历所有的新的消息,依次处理
|
||||
for _, message := range resp.AddMsgList {
|
||||
// 根据不同的消息类型来进行处理,方便后续统一调用
|
||||
message.init(b)
|
||||
// 调用自定义的处理方法
|
||||
if handler := b.MessageHandler; handler != nil {
|
||||
handler(message)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
resp, err := b.Caller.WebWxSync(b.storage.Request, b.storage.Response, b.storage.LoginInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 更新SyncKey并且重新存入storage
|
||||
b.storage.Response.SyncKey = resp.SyncKey
|
||||
// 遍历所有的新的消息,依次处理
|
||||
for _, message := range resp.AddMsgList {
|
||||
// 根据不同的消息类型来进行处理,方便后续统一调用
|
||||
message.init(b)
|
||||
// 调用自定义的处理方法
|
||||
if handler := b.MessageHandler; handler != nil {
|
||||
handler(message)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 当消息同步发生了错误或者用户主动在手机上退出,该方法会立即返回,否则会一直阻塞
|
||||
func (b *Bot) Block() error {
|
||||
if b.self == nil {
|
||||
return errors.New("`Block` must be called after user login")
|
||||
}
|
||||
if _, closed := <-b.exit; !closed {
|
||||
return errors.New("can not call `Block` after user logout")
|
||||
}
|
||||
close(b.exit)
|
||||
return nil
|
||||
if b.self == nil {
|
||||
return errors.New("`Block` must be called after user login")
|
||||
}
|
||||
if _, closed := <-b.exit; !closed {
|
||||
return errors.New("can not call `Block` after user logout")
|
||||
}
|
||||
close(b.exit)
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewBot(caller *Caller) *Bot {
|
||||
return &Bot{Caller: caller, storage: &Storage{}, exit: make(chan bool)}
|
||||
return &Bot{Caller: caller, storage: &Storage{}, exit: make(chan bool)}
|
||||
}
|
||||
|
||||
func DefaultBot() *Bot {
|
||||
return NewBot(DefaultCaller())
|
||||
func DefaultBot(modes ...mode) *Bot {
|
||||
var m mode
|
||||
if len(modes) == 0 {
|
||||
m = Normal
|
||||
} else {
|
||||
m = modes[0]
|
||||
}
|
||||
urlManager := GetUrlManagerByMode(m)
|
||||
return NewBot(DefaultCaller(urlManager))
|
||||
}
|
||||
|
||||
type Storage struct {
|
||||
LoginInfo *LoginInfo
|
||||
Request *BaseRequest
|
||||
Response *WebInitResponse
|
||||
LoginInfo *LoginInfo
|
||||
Request *BaseRequest
|
||||
Response *WebInitResponse
|
||||
}
|
||||
|
||||
func GetQrcodeUrl(uuid string) string {
|
||||
return qrcodeUrl + uuid
|
||||
return qrcodeUrl + uuid
|
||||
}
|
||||
|
||||
func PrintlnQrcodeUrl(uuid string) {
|
||||
println("访问下面网址扫描二维码登录")
|
||||
println(GetQrcodeUrl(uuid))
|
||||
println("访问下面网址扫描二维码登录")
|
||||
println(GetQrcodeUrl(uuid))
|
||||
}
|
||||
|
26
bot_test.go
26
bot_test.go
@ -2,12 +2,20 @@ package openwechat
|
||||
|
||||
import "testing"
|
||||
|
||||
func defaultBot() *Bot {
|
||||
bot := DefaultBot()
|
||||
func defaultBot(modes ...mode) *Bot {
|
||||
bot := DefaultBot(modes...)
|
||||
bot.UUIDCallback = PrintlnQrcodeUrl
|
||||
return bot
|
||||
}
|
||||
|
||||
func getSelf(modes ...mode) (*Self, error) {
|
||||
bot := defaultBot(modes...)
|
||||
if err := bot.Login(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bot.GetCurrentUser()
|
||||
}
|
||||
|
||||
func TestBotLogin(t *testing.T) {
|
||||
bot := defaultBot()
|
||||
if err := bot.Login(); err != nil {
|
||||
@ -21,3 +29,17 @@ func TestBotLogin(t *testing.T) {
|
||||
}
|
||||
t.Log(self.NickName)
|
||||
}
|
||||
|
||||
func TestFriend(t *testing.T) {
|
||||
self, err := getSelf()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
friends, err := self.Friends()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
t.Log(friends)
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ func NewCaller(client *Client) *Caller {
|
||||
}
|
||||
|
||||
// Default Constructor for Caller
|
||||
func DefaultCaller() *Caller {
|
||||
return NewCaller(DefaultClient())
|
||||
func DefaultCaller(urlManager UrlManager) *Caller {
|
||||
return NewCaller(DefaultClient(urlManager))
|
||||
}
|
||||
|
||||
// 获取登录的uuid
|
||||
|
51
client.go
51
client.go
@ -18,15 +18,18 @@ import (
|
||||
// http请求客户端
|
||||
// 客户端需要维持Session会话
|
||||
// 并且客户端不允许跳转
|
||||
type Client struct{ *http.Client }
|
||||
type Client struct {
|
||||
*http.Client
|
||||
UrlManager
|
||||
}
|
||||
|
||||
func NewClient(client *http.Client) *Client {
|
||||
return &Client{Client: client}
|
||||
func NewClient(client *http.Client, urlManager UrlManager) *Client {
|
||||
return &Client{Client: client, UrlManager: urlManager}
|
||||
}
|
||||
|
||||
// 自动存储cookie
|
||||
// 设置客户端不自动跳转
|
||||
func DefaultClient() *Client {
|
||||
func DefaultClient(urlManager UrlManager) *Client {
|
||||
jar, _ := cookiejar.New(nil)
|
||||
client := &http.Client{
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
@ -34,7 +37,7 @@ func DefaultClient() *Client {
|
||||
},
|
||||
Jar: jar,
|
||||
}
|
||||
return NewClient(client)
|
||||
return NewClient(client, urlManager)
|
||||
}
|
||||
|
||||
// 获取登录的uuid
|
||||
@ -42,7 +45,7 @@ func (c *Client) GetLoginUUID() (*http.Response, error) {
|
||||
path, _ := url.Parse(jsLoginUrl)
|
||||
params := url.Values{}
|
||||
params.Add("appid", appId)
|
||||
params.Add("redirect_uri", webWxNewLoginPage)
|
||||
params.Add("redirect_uri", c.webWxNewLoginPageUrl)
|
||||
params.Add("fun", "new")
|
||||
params.Add("lang", "zh_CN")
|
||||
params.Add("_", strconv.FormatInt(time.Now().Unix(), 10))
|
||||
@ -80,7 +83,7 @@ func (c *Client) GetLoginInfo(path string) (*http.Response, error) {
|
||||
|
||||
// 请求获取初始化信息
|
||||
func (c *Client) WebInit(request *BaseRequest) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxInitUrl)
|
||||
path, _ := url.Parse(c.webWxInitUrl)
|
||||
params := url.Values{}
|
||||
params.Add("_", fmt.Sprintf("%d", time.Now().Unix()))
|
||||
path.RawQuery = params.Encode()
|
||||
@ -94,7 +97,7 @@ func (c *Client) WebInit(request *BaseRequest) (*http.Response, error) {
|
||||
|
||||
// 通知手机已登录
|
||||
func (c *Client) WebWxStatusNotify(request *BaseRequest, response *WebInitResponse, info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxStatusNotifyUrl)
|
||||
path, _ := url.Parse(c.webWxStatusNotifyUrl)
|
||||
params := url.Values{}
|
||||
params.Add("lang", "zh_CN")
|
||||
params.Add("pass_ticket", info.PassTicket)
|
||||
@ -115,7 +118,7 @@ func (c *Client) WebWxStatusNotify(request *BaseRequest, response *WebInitRespon
|
||||
|
||||
// 异步检查是否有新的消息返回
|
||||
func (c *Client) SyncCheck(info *LoginInfo, response *WebInitResponse) (*http.Response, error) {
|
||||
path, _ := url.Parse(syncCheckUrl)
|
||||
path, _ := url.Parse(c.syncCheckUrl)
|
||||
params := url.Values{}
|
||||
params.Add("r", strconv.FormatInt(time.Now().Unix(), 10))
|
||||
params.Add("skey", info.SKey)
|
||||
@ -138,7 +141,7 @@ func (c *Client) SyncCheck(info *LoginInfo, response *WebInitResponse) (*http.Re
|
||||
|
||||
// 获取联系人信息
|
||||
func (c *Client) WebWxGetContact(info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxGetContactUrl)
|
||||
path, _ := url.Parse(c.webWxGetContactUrl)
|
||||
params := url.Values{}
|
||||
params.Add("r", strconv.FormatInt(time.Now().Unix(), 10))
|
||||
params.Add("skey", info.SKey)
|
||||
@ -149,7 +152,7 @@ func (c *Client) WebWxGetContact(info *LoginInfo) (*http.Response, error) {
|
||||
|
||||
// 获取联系人详情
|
||||
func (c *Client) WebWxBatchGetContact(members Members, request *BaseRequest) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxBatchGetContactUrl)
|
||||
path, _ := url.Parse(c.webWxBatchGetContactUrl)
|
||||
params := url.Values{}
|
||||
params.Add("type", "ex")
|
||||
params.Add("r", strconv.FormatInt(time.Now().Unix(), 10))
|
||||
@ -168,7 +171,7 @@ func (c *Client) WebWxBatchGetContact(members Members, request *BaseRequest) (*h
|
||||
|
||||
// 获取消息接口
|
||||
func (c *Client) WebWxSync(request *BaseRequest, response *WebInitResponse, info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxSyncUrl)
|
||||
path, _ := url.Parse(c.webWxSyncUrl)
|
||||
params := url.Values{}
|
||||
params.Add("sid", info.WxSid)
|
||||
params.Add("skey", info.SKey)
|
||||
@ -202,7 +205,7 @@ func (c *Client) sendMessage(request *BaseRequest, url string, msg *SendMessage)
|
||||
// 发送文本消息
|
||||
func (c *Client) WebWxSendMsg(msg *SendMessage, info *LoginInfo, request *BaseRequest) (*http.Response, error) {
|
||||
msg.Type = TextMessage
|
||||
path, _ := url.Parse(webWxSendMsgUrl)
|
||||
path, _ := url.Parse(c.webWxSendMsgUrl)
|
||||
params := url.Values{}
|
||||
params.Add("lang", "zh_CN")
|
||||
params.Add("pass_ticket", info.PassTicket)
|
||||
@ -212,13 +215,13 @@ func (c *Client) WebWxSendMsg(msg *SendMessage, info *LoginInfo, request *BaseRe
|
||||
|
||||
// 获取用户的头像
|
||||
func (c *Client) WebWxGetHeadImg(headImageUrl string) (*http.Response, error) {
|
||||
path := baseUrl + headImageUrl
|
||||
path := c.baseUrl + headImageUrl
|
||||
return c.Get(path)
|
||||
}
|
||||
|
||||
// 上传文件
|
||||
func (c *Client) WebWxUploadMedia(file *os.File, request *BaseRequest, info *LoginInfo, forUserName, toUserName, contentType, mediaType string) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxUpLoadMediaUrl)
|
||||
path, _ := url.Parse(c.webWxUpLoadMediaUrl)
|
||||
params := url.Values{}
|
||||
params.Add("f", "json")
|
||||
path.RawQuery = params.Encode()
|
||||
@ -286,7 +289,7 @@ func (c *Client) WebWxUploadMedia(file *os.File, request *BaseRequest, info *Log
|
||||
// 发送的图片必须是已经成功上传的图片
|
||||
func (c *Client) WebWxSendMsgImg(msg *SendMessage, request *BaseRequest, info *LoginInfo) (*http.Response, error) {
|
||||
msg.Type = ImageMessage
|
||||
path, _ := url.Parse(webWxSendMsgImgUrl)
|
||||
path, _ := url.Parse(c.webWxSendMsgImgUrl)
|
||||
params := url.Values{}
|
||||
params.Add("fun", "async")
|
||||
params.Add("f", "json")
|
||||
@ -299,7 +302,7 @@ func (c *Client) WebWxSendMsgImg(msg *SendMessage, request *BaseRequest, info *L
|
||||
// 发送文件信息
|
||||
func (c *Client) WebWxSendAppMsg(msg *SendMessage, request *BaseRequest) (*http.Response, error) {
|
||||
msg.Type = AppMessage
|
||||
path, _ := url.Parse(webWxSendAppMsgUrl)
|
||||
path, _ := url.Parse(c.webWxSendAppMsgUrl)
|
||||
params := url.Values{}
|
||||
params.Add("fun", "async")
|
||||
params.Add("f", "json")
|
||||
@ -309,7 +312,7 @@ func (c *Client) WebWxSendAppMsg(msg *SendMessage, request *BaseRequest) (*http.
|
||||
|
||||
// 用户重命名接口
|
||||
func (c *Client) WebWxOplog(request *BaseRequest, remarkName, userName string) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxOplogUrl)
|
||||
path, _ := url.Parse(c.webWxOplogUrl)
|
||||
params := url.Values{}
|
||||
params.Add("lang", "zh_CN")
|
||||
path.RawQuery = params.Encode()
|
||||
@ -328,7 +331,7 @@ func (c *Client) WebWxOplog(request *BaseRequest, remarkName, userName string) (
|
||||
// 添加用户为好友接口
|
||||
func (c *Client) WebWxVerifyUser(storage *Storage, info RecommendInfo, verifyContent string) (*http.Response, error) {
|
||||
loginInfo := storage.LoginInfo
|
||||
path, _ := url.Parse(webWxVerifyUserUrl)
|
||||
path, _ := url.Parse(c.webWxVerifyUserUrl)
|
||||
params := url.Values{}
|
||||
params.Add("r", strconv.FormatInt(time.Now().Unix(), 10))
|
||||
params.Add("lang", "zh_CN")
|
||||
@ -355,7 +358,7 @@ func (c *Client) WebWxVerifyUser(storage *Storage, info RecommendInfo, verifyCon
|
||||
|
||||
// 获取图片消息的图片响应
|
||||
func (c *Client) WebWxGetMsgImg(msg *Message, info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxGetMsgImgUrl)
|
||||
path, _ := url.Parse(c.webWxGetMsgImgUrl)
|
||||
params := url.Values{}
|
||||
params.Add("MsgID", msg.MsgId)
|
||||
params.Add("skey", info.SKey)
|
||||
@ -366,7 +369,7 @@ func (c *Client) WebWxGetMsgImg(msg *Message, info *LoginInfo) (*http.Response,
|
||||
|
||||
// 获取语音消息的语音响应
|
||||
func (c *Client) WebWxGetVoice(msg *Message, info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxGetVoiceUrl)
|
||||
path, _ := url.Parse(c.webWxGetVoiceUrl)
|
||||
params := url.Values{}
|
||||
params.Add("msgid", msg.MsgId)
|
||||
params.Add("skey", info.SKey)
|
||||
@ -376,7 +379,7 @@ func (c *Client) WebWxGetVoice(msg *Message, info *LoginInfo) (*http.Response, e
|
||||
|
||||
// 获取视频消息的视频响应
|
||||
func (c *Client) WebWxGetVideo(msg *Message, info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxGetVideoUrl)
|
||||
path, _ := url.Parse(c.webWxGetVideoUrl)
|
||||
params := url.Values{}
|
||||
params.Add("msgid", msg.MsgId)
|
||||
params.Add("skey", info.SKey)
|
||||
@ -386,7 +389,7 @@ func (c *Client) WebWxGetVideo(msg *Message, info *LoginInfo) (*http.Response, e
|
||||
|
||||
// 获取文件消息的文件响应
|
||||
func (c *Client) WebWxGetMedia(msg *Message, info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxGetMediaUrl)
|
||||
path, _ := url.Parse(c.webWxGetMediaUrl)
|
||||
params := url.Values{}
|
||||
params.Add("sender", msg.FromUserName)
|
||||
params.Add("mediaid", msg.MediaId)
|
||||
@ -400,7 +403,7 @@ func (c *Client) WebWxGetMedia(msg *Message, info *LoginInfo) (*http.Response, e
|
||||
|
||||
// 用户退出
|
||||
func (c *Client) Logout(info *LoginInfo) (*http.Response, error) {
|
||||
path, _ := url.Parse(webWxLogoutUrl)
|
||||
path, _ := url.Parse(c.webWxLogoutUrl)
|
||||
params := url.Values{}
|
||||
params.Add("redirect", "1")
|
||||
params.Add("type", "1")
|
||||
|
77
global.go
77
global.go
@ -13,30 +13,54 @@ var (
|
||||
)
|
||||
|
||||
const (
|
||||
appId = "wx782c26e4c19acffb"
|
||||
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"
|
||||
|
||||
baseUrl = "https://wx.qq.com"
|
||||
jsLoginUrl = "https://login.wx.qq.com/jslogin"
|
||||
webWxNewLoginPage = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxnewloginpage?mod=desktop"
|
||||
qrcodeUrl = "https://login.weixin.qq.com/qrcode/"
|
||||
loginUrl = "https://login.wx.qq.com/cgi-bin/mmwebwx-bin/login"
|
||||
webWxInitUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxinit"
|
||||
webWxStatusNotifyUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxstatusnotify"
|
||||
webWxSyncUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsync"
|
||||
webWxSendMsgUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsg"
|
||||
webWxGetContactUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetcontact"
|
||||
webWxSendMsgImgUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg"
|
||||
webWxSendAppMsgUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxsendappmsg"
|
||||
webWxBatchGetContactUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxbatchgetcontact"
|
||||
webWxOplogUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxoplog"
|
||||
webWxVerifyUserUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxverifyuser"
|
||||
syncCheckUrl = "https://webpush.wx.qq.com/cgi-bin/mmwebwx-bin/synccheck"
|
||||
webWxUpLoadMediaUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia"
|
||||
webWxGetMsgImgUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmsgimg"
|
||||
webWxGetVoiceUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvoice"
|
||||
webWxGetVideoUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetvideo"
|
||||
webWxLogoutUrl = "https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxlogout"
|
||||
webWxGetMediaUrl = "https://file.wx.qq.com/cgi-bin/mmwebwx-bin/webwxgetmedia"
|
||||
// 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"
|
||||
|
||||
// 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"
|
||||
|
||||
jsonContentType = "application/json; charset=utf-8"
|
||||
uosPatchClientVersion = "2.0.0"
|
||||
@ -70,10 +94,3 @@ const (
|
||||
MALE = 1
|
||||
FEMALE = 2
|
||||
)
|
||||
|
||||
type mode string
|
||||
|
||||
const (
|
||||
normal mode = "normal"
|
||||
desk mode = "desk"
|
||||
)
|
||||
|
92
url.go
Normal file
92
url.go
Normal file
@ -0,0 +1,92 @@
|
||||
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
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
||||
// 网页版
|
||||
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,
|
||||
}
|
||||
)
|
||||
|
||||
// mode 类型限制
|
||||
type mode string
|
||||
|
||||
// 向外暴露2种模式
|
||||
const (
|
||||
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")
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user