add code notes
This commit is contained in:
parent
61a1313bd9
commit
6475fe6bfc
24
bot.go
24
bot.go
@ -17,6 +17,7 @@ type Bot struct {
|
|||||||
exit chan bool
|
exit chan bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断当前用户是否正常在线
|
||||||
func (b *Bot) Alive() bool {
|
func (b *Bot) Alive() bool {
|
||||||
if b.self == nil {
|
if b.self == nil {
|
||||||
return false
|
return false
|
||||||
@ -29,6 +30,7 @@ func (b *Bot) Alive() bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前的用户
|
||||||
func (b *Bot) GetCurrentUser() (*Self, error) {
|
func (b *Bot) GetCurrentUser() (*Self, error) {
|
||||||
if b.self == nil {
|
if b.self == nil {
|
||||||
return nil, errors.New("user not login")
|
return nil, errors.New("user not login")
|
||||||
@ -36,6 +38,8 @@ func (b *Bot) GetCurrentUser() (*Self, error) {
|
|||||||
return b.self, nil
|
return b.self, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户登录
|
||||||
|
// 该方法会一直阻塞,直到用户扫码登录,或者二维码过期
|
||||||
func (b *Bot) Login() error {
|
func (b *Bot) Login() error {
|
||||||
b.prepare()
|
b.prepare()
|
||||||
uuid, err := b.Caller.GetLoginUUID()
|
uuid, err := b.Caller.GetLoginUUID()
|
||||||
@ -65,17 +69,22 @@ func (b *Bot) Login() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 登录逻辑
|
||||||
func (b *Bot) login(data []byte) error {
|
func (b *Bot) login(data []byte) error {
|
||||||
|
// 判断是否有登录回调,如果有执行它
|
||||||
if b.LoginCallBack != nil {
|
if b.LoginCallBack != nil {
|
||||||
b.LoginCallBack(data)
|
b.LoginCallBack(data)
|
||||||
}
|
}
|
||||||
|
// 获取登录的一些基本的信息
|
||||||
info, err := b.Caller.GetLoginInfo(data)
|
info, err := b.Caller.GetLoginInfo(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将LoginInfo存到storage里面
|
||||||
b.storage.SetLoginInfo(*info)
|
b.storage.SetLoginInfo(*info)
|
||||||
|
|
||||||
|
// 构建BaseRequest
|
||||||
request := BaseRequest{
|
request := BaseRequest{
|
||||||
Uin: info.WxUin,
|
Uin: info.WxUin,
|
||||||
Sid: info.WxSid,
|
Sid: info.WxSid,
|
||||||
@ -83,23 +92,30 @@ func (b *Bot) login(data []byte) error {
|
|||||||
DeviceID: GetRandomDeviceId(),
|
DeviceID: GetRandomDeviceId(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 将BaseRequest存到storage里面方便后续调用
|
||||||
b.storage.SetBaseRequest(request)
|
b.storage.SetBaseRequest(request)
|
||||||
|
// 获取初始化的用户信息和一些必要的参数
|
||||||
resp, err := b.Caller.WebInit(request)
|
resp, err := b.Caller.WebInit(request)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// 设置当前的用户
|
||||||
b.self = &Self{Bot: b, User: &resp.User}
|
b.self = &Self{Bot: b, User: &resp.User}
|
||||||
b.storage.SetWebInitResponse(*resp)
|
b.storage.SetWebInitResponse(*resp)
|
||||||
|
|
||||||
|
// 通知手机客户端已经登录
|
||||||
if err = b.Caller.WebWxStatusNotify(request, *resp, *info); err != nil {
|
if err = b.Caller.WebWxStatusNotify(request, *resp, *info); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// 开启协程,轮训获取是否有新的消息返回
|
||||||
go func() {
|
go func() {
|
||||||
b.stopAsyncCALL(b.asyncCall())
|
b.stopAsyncCALL(b.asyncCall())
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 轮训请求
|
||||||
|
// 根据状态码判断是否有新的请求
|
||||||
func (b *Bot) asyncCall() error {
|
func (b *Bot) asyncCall() error {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
@ -112,9 +128,11 @@ func (b *Bot) asyncCall() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// 如果不是正常的状态码返回,发生了错误,直接退出
|
||||||
if !resp.Success() {
|
if !resp.Success() {
|
||||||
return fmt.Errorf("unknow code got %s", resp.RetCode)
|
return fmt.Errorf("unknow code got %s", resp.RetCode)
|
||||||
}
|
}
|
||||||
|
// 如果Selector不为0,则获取消息
|
||||||
if !resp.NorMal() {
|
if !resp.NorMal() {
|
||||||
if err = b.getMessage(); err != nil {
|
if err = b.getMessage(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -130,6 +148,8 @@ func (b *Bot) stopAsyncCALL(err error) {
|
|||||||
b.err = err
|
b.err = err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取新的消息
|
||||||
func (b *Bot) getMessage() error {
|
func (b *Bot) getMessage() error {
|
||||||
info := b.storage.GetLoginInfo()
|
info := b.storage.GetLoginInfo()
|
||||||
response := b.storage.GetWebInitResponse()
|
response := b.storage.GetWebInitResponse()
|
||||||
@ -138,10 +158,14 @@ func (b *Bot) getMessage() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// 更新SyncKey并且重新存入storage
|
||||||
response.SyncKey = resp.SyncKey
|
response.SyncKey = resp.SyncKey
|
||||||
b.storage.SetWebInitResponse(response)
|
b.storage.SetWebInitResponse(response)
|
||||||
|
// 遍历所有的新的消息,依次处理
|
||||||
for _, message := range resp.AddMsgList {
|
for _, message := range resp.AddMsgList {
|
||||||
|
// 根据不同的消息类型来进行处理,方便后续统一调用
|
||||||
processMessage(message, b)
|
processMessage(message, b)
|
||||||
|
// 调用自定义的处理方法
|
||||||
b.messageHandlerGroups.ProcessMessage(message)
|
b.messageHandlerGroups.ProcessMessage(message)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
30
caller.go
30
caller.go
@ -2,22 +2,26 @@ package openwechat
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 调用请求和解析请求
|
||||||
|
// 上层模块可以直接获取封装后的请求结果
|
||||||
type Caller struct {
|
type Caller struct {
|
||||||
Client *Client
|
Client *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructor for Caller
|
||||||
func NewCaller(client *Client) *Caller {
|
func NewCaller(client *Client) *Caller {
|
||||||
return &Caller{Client: client}
|
return &Caller{Client: client}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default Constructor for Caller
|
||||||
func DefaultCaller() *Caller {
|
func DefaultCaller() *Caller {
|
||||||
return NewCaller(DefaultClient())
|
return NewCaller(DefaultClient())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取登录的uuid
|
||||||
func (c *Caller) GetLoginUUID() (string, error) {
|
func (c *Caller) GetLoginUUID() (string, error) {
|
||||||
resp := NewReturnResponse(c.Client.GetLoginUUID())
|
resp := NewReturnResponse(c.Client.GetLoginUUID())
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -28,13 +32,16 @@ func (c *Caller) GetLoginUUID() (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
// 正则匹配uuid字符串
|
||||||
results := uuidRegexp.FindSubmatch(data)
|
results := uuidRegexp.FindSubmatch(data)
|
||||||
if len(results) != 2 {
|
if len(results) != 2 {
|
||||||
|
// 如果没有匹配到,可能微信的接口做了修改,或者当前机器的ip被加入了黑名单
|
||||||
return "", errors.New("uuid does not match")
|
return "", errors.New("uuid does not match")
|
||||||
}
|
}
|
||||||
return string(results[1]), nil
|
return string(results[1]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否登录成功
|
||||||
func (c *Caller) CheckLogin(uuid string) (*CheckLoginResponse, error) {
|
func (c *Caller) CheckLogin(uuid string) (*CheckLoginResponse, error) {
|
||||||
resp := NewReturnResponse(c.Client.CheckLogin(uuid))
|
resp := NewReturnResponse(c.Client.CheckLogin(uuid))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -45,6 +52,8 @@ func (c *Caller) CheckLogin(uuid string) (*CheckLoginResponse, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// 正则匹配检测的code
|
||||||
|
// 具体code参考
|
||||||
results := statusCodeRegexp.FindSubmatch(data)
|
results := statusCodeRegexp.FindSubmatch(data)
|
||||||
if len(results) != 2 {
|
if len(results) != 2 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
@ -53,7 +62,9 @@ func (c *Caller) CheckLogin(uuid string) (*CheckLoginResponse, error) {
|
|||||||
return &CheckLoginResponse{Code: code, Raw: data}, nil
|
return &CheckLoginResponse{Code: code, Raw: data}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取登录信息
|
||||||
func (c *Caller) GetLoginInfo(body []byte) (*LoginInfo, error) {
|
func (c *Caller) GetLoginInfo(body []byte) (*LoginInfo, error) {
|
||||||
|
// 从响应体里面获取需要跳转的url
|
||||||
results := redirectUriRegexp.FindSubmatch(body)
|
results := redirectUriRegexp.FindSubmatch(body)
|
||||||
if len(results) != 2 {
|
if len(results) != 2 {
|
||||||
return nil, errors.New("redirect url does not match")
|
return nil, errors.New("redirect url does not match")
|
||||||
@ -65,12 +76,14 @@ func (c *Caller) GetLoginInfo(body []byte) (*LoginInfo, error) {
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var loginInfo LoginInfo
|
var loginInfo LoginInfo
|
||||||
|
// xml结构体序列化储存
|
||||||
if err := resp.ScanXML(&loginInfo); err != nil {
|
if err := resp.ScanXML(&loginInfo); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &loginInfo, nil
|
return &loginInfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取初始化信息
|
||||||
func (c *Caller) WebInit(request BaseRequest) (*WebInitResponse, error) {
|
func (c *Caller) WebInit(request BaseRequest) (*WebInitResponse, error) {
|
||||||
resp := NewReturnResponse(c.Client.WebInit(request))
|
resp := NewReturnResponse(c.Client.WebInit(request))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -84,6 +97,7 @@ func (c *Caller) WebInit(request BaseRequest) (*WebInitResponse, error) {
|
|||||||
return &webInitResponse, nil
|
return &webInitResponse, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知手机已登录
|
||||||
func (c *Caller) WebWxStatusNotify(request BaseRequest, response WebInitResponse, info LoginInfo) error {
|
func (c *Caller) WebWxStatusNotify(request BaseRequest, response WebInitResponse, info LoginInfo) error {
|
||||||
resp := NewReturnResponse(c.Client.WebWxStatusNotify(request, response, info))
|
resp := NewReturnResponse(c.Client.WebWxStatusNotify(request, response, info))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -100,6 +114,7 @@ func (c *Caller) WebWxStatusNotify(request BaseRequest, response WebInitResponse
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 异步获取是否有新的消息
|
||||||
func (c *Caller) SyncCheck(info LoginInfo, response WebInitResponse) (*SyncCheckResponse, error) {
|
func (c *Caller) SyncCheck(info LoginInfo, response WebInitResponse) (*SyncCheckResponse, error) {
|
||||||
resp := NewReturnResponse(c.Client.SyncCheck(info, response))
|
resp := NewReturnResponse(c.Client.SyncCheck(info, response))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -107,7 +122,6 @@ func (c *Caller) SyncCheck(info LoginInfo, response WebInitResponse) (*SyncCheck
|
|||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err := resp.ReadAll()
|
data, err := resp.ReadAll()
|
||||||
fmt.Println(string(data))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -120,6 +134,7 @@ func (c *Caller) SyncCheck(info LoginInfo, response WebInitResponse) (*SyncCheck
|
|||||||
return syncCheckResponse, nil
|
return syncCheckResponse, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取所有的联系人
|
||||||
func (c *Caller) WebWxGetContact(info LoginInfo) (Members, error) {
|
func (c *Caller) WebWxGetContact(info LoginInfo) (Members, error) {
|
||||||
resp := NewReturnResponse(c.Client.WebWxGetContact(info))
|
resp := NewReturnResponse(c.Client.WebWxGetContact(info))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -136,6 +151,8 @@ func (c *Caller) WebWxGetContact(info LoginInfo) (Members, error) {
|
|||||||
return item.MemberList, nil
|
return item.MemberList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取联系人的详情
|
||||||
|
// 注: Members参数的长度不要大于50
|
||||||
func (c *Caller) WebWxBatchGetContact(members Members, request BaseRequest) (Members, error) {
|
func (c *Caller) WebWxBatchGetContact(members Members, request BaseRequest) (Members, error) {
|
||||||
resp := NewReturnResponse(c.Client.WebWxBatchGetContact(members, request))
|
resp := NewReturnResponse(c.Client.WebWxBatchGetContact(members, request))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -152,6 +169,7 @@ func (c *Caller) WebWxBatchGetContact(members Members, request BaseRequest) (Mem
|
|||||||
return item.ContactList, nil
|
return item.ContactList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取新的消息接口
|
||||||
func (c *Caller) WebWxSync(request BaseRequest, response WebInitResponse, info LoginInfo) (*WebWxSyncResponse, error) {
|
func (c *Caller) WebWxSync(request BaseRequest, response WebInitResponse, info LoginInfo) (*WebWxSyncResponse, error) {
|
||||||
resp := NewReturnResponse(c.Client.WebWxSync(request, response, info))
|
resp := NewReturnResponse(c.Client.WebWxSync(request, response, info))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
@ -165,18 +183,23 @@ func (c *Caller) WebWxSync(request BaseRequest, response WebInitResponse, info L
|
|||||||
return &webWxSyncResponse, nil
|
return &webWxSyncResponse, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送消息接口
|
||||||
func (c *Caller) WebWxSendMsg(msg *SendMessage, info LoginInfo, request BaseRequest) error {
|
func (c *Caller) WebWxSendMsg(msg *SendMessage, info LoginInfo, request BaseRequest) error {
|
||||||
resp := NewReturnResponse(c.Client.WebWxSendMsg(msg, info, request))
|
resp := NewReturnResponse(c.Client.WebWxSendMsg(msg, info, request))
|
||||||
return parseBaseResponseError(resp)
|
return parseBaseResponseError(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 修改用户备注接口
|
||||||
func (c *Caller) WebWxOplog(request BaseRequest, remarkName, toUserName string) error {
|
func (c *Caller) WebWxOplog(request BaseRequest, remarkName, toUserName string) error {
|
||||||
resp := NewReturnResponse(c.Client.WebWxOplog(request, remarkName, toUserName))
|
resp := NewReturnResponse(c.Client.WebWxOplog(request, remarkName, toUserName))
|
||||||
return parseBaseResponseError(resp)
|
return parseBaseResponseError(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送图片消息接口
|
||||||
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) error {
|
||||||
|
// 首先尝试上传图片
|
||||||
resp := NewReturnResponse(c.Client.WebWxUploadMedia(file, request, info, fromUserName, toUserName, "image/jpeg", "pic"))
|
resp := NewReturnResponse(c.Client.WebWxUploadMedia(file, request, info, fromUserName, toUserName, "image/jpeg", "pic"))
|
||||||
|
// 无错误上传成功之后获取请求结果,判断结果是否正常
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
return resp.Err()
|
return resp.Err()
|
||||||
}
|
}
|
||||||
@ -191,11 +214,14 @@ func (c *Caller) WebWxSendImageMsg(file *os.File, request BaseRequest, info Logi
|
|||||||
if !item.BaseResponse.Ok() {
|
if !item.BaseResponse.Ok() {
|
||||||
return item.BaseResponse
|
return item.BaseResponse
|
||||||
}
|
}
|
||||||
|
// 构造新的图片类型的信息
|
||||||
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))
|
||||||
return parseBaseResponseError(resp)
|
return parseBaseResponseError(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理响应返回的结果是否正常
|
||||||
func parseBaseResponseError(resp *ReturnResponse) error {
|
func parseBaseResponseError(resp *ReturnResponse) error {
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
return resp.Err()
|
return resp.Err()
|
||||||
|
29
client.go
29
client.go
@ -16,14 +16,17 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client struct {
|
// http请求客户端
|
||||||
*http.Client
|
// 客户端需要维持Session会话
|
||||||
}
|
// 并且客户端不允许跳转
|
||||||
|
type Client struct{ *http.Client }
|
||||||
|
|
||||||
func NewClient(client *http.Client) *Client {
|
func NewClient(client *http.Client) *Client {
|
||||||
return &Client{Client: client}
|
return &Client{Client: client}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自动存储cookie
|
||||||
|
// 设置客户端不自动跳转
|
||||||
func DefaultClient() *Client {
|
func DefaultClient() *Client {
|
||||||
jar, _ := cookiejar.New(nil)
|
jar, _ := cookiejar.New(nil)
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
@ -35,6 +38,7 @@ func DefaultClient() *Client {
|
|||||||
return NewClient(client)
|
return NewClient(client)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取登录的uuid
|
||||||
func (c *Client) GetLoginUUID() (*http.Response, error) {
|
func (c *Client) GetLoginUUID() (*http.Response, error) {
|
||||||
path, _ := url.Parse(jsLoginUrl)
|
path, _ := url.Parse(jsLoginUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -47,11 +51,13 @@ func (c *Client) GetLoginUUID() (*http.Response, error) {
|
|||||||
return c.Get(path.String())
|
return c.Get(path.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取登录的二维吗
|
||||||
func (c *Client) GetLoginQrcode(uuid string) (*http.Response, error) {
|
func (c *Client) GetLoginQrcode(uuid string) (*http.Response, error) {
|
||||||
path := qrcodeUrl + uuid
|
path := qrcodeUrl + uuid
|
||||||
return c.Get(path)
|
return c.Get(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 检查是否登录
|
||||||
func (c *Client) CheckLogin(uuid string) (*http.Response, error) {
|
func (c *Client) CheckLogin(uuid string) (*http.Response, error) {
|
||||||
path, _ := url.Parse(loginUrl)
|
path, _ := url.Parse(loginUrl)
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
@ -65,10 +71,12 @@ func (c *Client) CheckLogin(uuid string) (*http.Response, error) {
|
|||||||
return c.Get(path.String())
|
return c.Get(path.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 请求获取LoginInfo
|
||||||
func (c *Client) GetLoginInfo(path string) (*http.Response, error) {
|
func (c *Client) GetLoginInfo(path string) (*http.Response, error) {
|
||||||
return c.Get(path)
|
return c.Get(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 请求获取初始化信息
|
||||||
func (c *Client) WebInit(request BaseRequest) (*http.Response, error) {
|
func (c *Client) WebInit(request BaseRequest) (*http.Response, error) {
|
||||||
path, _ := url.Parse(webWxInitUrl)
|
path, _ := url.Parse(webWxInitUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -82,6 +90,7 @@ func (c *Client) WebInit(request BaseRequest) (*http.Response, error) {
|
|||||||
return c.Post(path.String(), jsonContentType, body)
|
return c.Post(path.String(), jsonContentType, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 通知手机已登录
|
||||||
func (c *Client) WebWxStatusNotify(request BaseRequest, response WebInitResponse, info LoginInfo) (*http.Response, error) {
|
func (c *Client) WebWxStatusNotify(request BaseRequest, response WebInitResponse, info LoginInfo) (*http.Response, error) {
|
||||||
path, _ := url.Parse(webWxStatusNotifyUrl)
|
path, _ := url.Parse(webWxStatusNotifyUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -102,6 +111,7 @@ func (c *Client) WebWxStatusNotify(request BaseRequest, response WebInitResponse
|
|||||||
return c.Do(req)
|
return c.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 异步检查是否有新的消息返回
|
||||||
func (c *Client) SyncCheck(info LoginInfo, response WebInitResponse) (*http.Response, error) {
|
func (c *Client) SyncCheck(info LoginInfo, response WebInitResponse) (*http.Response, error) {
|
||||||
path, _ := url.Parse(syncCheckUrl)
|
path, _ := url.Parse(syncCheckUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -124,6 +134,7 @@ func (c *Client) SyncCheck(info LoginInfo, response WebInitResponse) (*http.Resp
|
|||||||
return c.Do(req)
|
return c.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取联系人信息
|
||||||
func (c *Client) WebWxGetContact(info LoginInfo) (*http.Response, error) {
|
func (c *Client) WebWxGetContact(info LoginInfo) (*http.Response, error) {
|
||||||
path, _ := url.Parse(webWxGetContactUrl)
|
path, _ := url.Parse(webWxGetContactUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -134,6 +145,7 @@ func (c *Client) WebWxGetContact(info LoginInfo) (*http.Response, error) {
|
|||||||
return c.Get(path.String())
|
return c.Get(path.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取联系人详情
|
||||||
func (c *Client) WebWxBatchGetContact(members Members, request BaseRequest) (*http.Response, error) {
|
func (c *Client) WebWxBatchGetContact(members Members, request BaseRequest) (*http.Response, error) {
|
||||||
path, _ := url.Parse(webWxBatchGetContactUrl)
|
path, _ := url.Parse(webWxBatchGetContactUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -152,6 +164,7 @@ func (c *Client) WebWxBatchGetContact(members Members, request BaseRequest) (*ht
|
|||||||
return c.Do(req)
|
return c.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取消息接口
|
||||||
func (c *Client) WebWxSync(request BaseRequest, response WebInitResponse, info LoginInfo) (*http.Response, error) {
|
func (c *Client) WebWxSync(request BaseRequest, response WebInitResponse, info LoginInfo) (*http.Response, error) {
|
||||||
path, _ := url.Parse(webWxSyncUrl)
|
path, _ := url.Parse(webWxSyncUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -171,6 +184,7 @@ func (c *Client) WebWxSync(request BaseRequest, response WebInitResponse, info L
|
|||||||
return c.Do(req)
|
return c.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送消息
|
||||||
func (c *Client) sendMessage(request BaseRequest, url string, msg *SendMessage) (*http.Response, error) {
|
func (c *Client) sendMessage(request BaseRequest, url string, msg *SendMessage) (*http.Response, error) {
|
||||||
content := map[string]interface{}{
|
content := map[string]interface{}{
|
||||||
"BaseRequest": request,
|
"BaseRequest": request,
|
||||||
@ -183,6 +197,7 @@ func (c *Client) sendMessage(request BaseRequest, url string, msg *SendMessage)
|
|||||||
return c.Do(req)
|
return c.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送文本消息
|
||||||
func (c *Client) WebWxSendMsg(msg *SendMessage, info LoginInfo, request BaseRequest) (*http.Response, error) {
|
func (c *Client) WebWxSendMsg(msg *SendMessage, info LoginInfo, request BaseRequest) (*http.Response, error) {
|
||||||
msg.Type = TextMessage
|
msg.Type = TextMessage
|
||||||
path, _ := url.Parse(webWxSendMsgUrl)
|
path, _ := url.Parse(webWxSendMsgUrl)
|
||||||
@ -193,11 +208,13 @@ func (c *Client) WebWxSendMsg(msg *SendMessage, info LoginInfo, request BaseRequ
|
|||||||
return c.sendMessage(request, path.String(), msg)
|
return c.sendMessage(request, path.String(), msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取用户的头像
|
||||||
func (c *Client) WebWxGetHeadImg(headImageUrl string) (*http.Response, error) {
|
func (c *Client) WebWxGetHeadImg(headImageUrl string) (*http.Response, error) {
|
||||||
path := baseUrl + headImageUrl
|
path := baseUrl + headImageUrl
|
||||||
return c.Get(path)
|
return c.Get(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
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, contentType, mediaType string) (*http.Response, error) {
|
||||||
path, _ := url.Parse(webWxUpLoadMediaUrl)
|
path, _ := url.Parse(webWxUpLoadMediaUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -261,6 +278,9 @@ func (c *Client) WebWxUploadMedia(file *os.File, request BaseRequest, info Login
|
|||||||
return c.Post(path.String(), ct, body)
|
return c.Post(path.String(), ct, body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送图片
|
||||||
|
// 这个接口依赖上传文件的接口
|
||||||
|
// 发送的图片必须是已经成功上传的图片
|
||||||
func (c *Client) WebWxSendMsgImg(msg *SendMessage, request BaseRequest, info LoginInfo) (*http.Response, error) {
|
func (c *Client) WebWxSendMsgImg(msg *SendMessage, request BaseRequest, info LoginInfo) (*http.Response, error) {
|
||||||
msg.Type = ImageMessage
|
msg.Type = ImageMessage
|
||||||
path, _ := url.Parse(webWxSendMsgImgUrl)
|
path, _ := url.Parse(webWxSendMsgImgUrl)
|
||||||
@ -273,6 +293,7 @@ func (c *Client) WebWxSendMsgImg(msg *SendMessage, request BaseRequest, info Log
|
|||||||
return c.sendMessage(request, path.String(), msg)
|
return c.sendMessage(request, path.String(), msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 发送文件信息
|
||||||
func (c *Client) WebWxSendAppMsg(msg *SendMessage, request BaseRequest) (*http.Response, error) {
|
func (c *Client) WebWxSendAppMsg(msg *SendMessage, request BaseRequest) (*http.Response, error) {
|
||||||
msg.Type = AppMessage
|
msg.Type = AppMessage
|
||||||
path, _ := url.Parse(webWxSendAppMsgUrl)
|
path, _ := url.Parse(webWxSendAppMsgUrl)
|
||||||
@ -283,6 +304,7 @@ func (c *Client) WebWxSendAppMsg(msg *SendMessage, request BaseRequest) (*http.R
|
|||||||
return c.sendMessage(request, path.String(), msg)
|
return c.sendMessage(request, path.String(), msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 用户重命名接口
|
||||||
func (c *Client) WebWxOplog(request BaseRequest, remarkName, userName string, ) (*http.Response, error) {
|
func (c *Client) WebWxOplog(request BaseRequest, remarkName, userName string, ) (*http.Response, error) {
|
||||||
path, _ := url.Parse(webWxOplogUrl)
|
path, _ := url.Parse(webWxOplogUrl)
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
@ -300,6 +322,7 @@ func (c *Client) WebWxOplog(request BaseRequest, remarkName, userName string, )
|
|||||||
return c.Do(req)
|
return c.Do(req)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加用户为好友接口
|
||||||
func (c *Client) WebWxVerifyUser(storage WechatStorage, info RecommendInfo, verifyContent string) (*http.Response, error) {
|
func (c *Client) WebWxVerifyUser(storage WechatStorage, info RecommendInfo, verifyContent string) (*http.Response, error) {
|
||||||
loginInfo := storage.GetLoginInfo()
|
loginInfo := storage.GetLoginInfo()
|
||||||
path, _ := url.Parse(webWxVerifyUserUrl)
|
path, _ := url.Parse(webWxVerifyUserUrl)
|
||||||
|
@ -33,12 +33,14 @@ const (
|
|||||||
jsonContentType = "application/json; charset=utf-8"
|
jsonContentType = "application/json; charset=utf-8"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 消息类型
|
||||||
const (
|
const (
|
||||||
TextMessage = 1
|
TextMessage = 1
|
||||||
ImageMessage = 3
|
ImageMessage = 3
|
||||||
AppMessage = 6
|
AppMessage = 6
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// 登录状态
|
||||||
const (
|
const (
|
||||||
statusSuccess = "200"
|
statusSuccess = "200"
|
||||||
statusScanned = "201"
|
statusScanned = "201"
|
||||||
|
6
http.go
6
http.go
@ -7,19 +7,23 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Http请求的响应结构体封装
|
||||||
type ReturnResponse struct {
|
type ReturnResponse struct {
|
||||||
*http.Response
|
*http.Response
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constructor for ReturnResponse
|
||||||
func NewReturnResponse(response *http.Response, err error) *ReturnResponse {
|
func NewReturnResponse(response *http.Response, err error) *ReturnResponse {
|
||||||
return &ReturnResponse{Response: response, err: err}
|
return &ReturnResponse{Response: response, err: err}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取当前请求的错误
|
||||||
func (r *ReturnResponse) Err() error {
|
func (r *ReturnResponse) Err() error {
|
||||||
return r.err
|
return r.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// json序列化
|
||||||
func (r *ReturnResponse) ScanJSON(v interface{}) error {
|
func (r *ReturnResponse) ScanJSON(v interface{}) error {
|
||||||
if data, err := r.ReadAll(); err != nil {
|
if data, err := r.ReadAll(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -28,6 +32,7 @@ func (r *ReturnResponse) ScanJSON(v interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// xml序列化
|
||||||
func (r *ReturnResponse) ScanXML(v interface{}) error {
|
func (r *ReturnResponse) ScanXML(v interface{}) error {
|
||||||
if data, err := r.ReadAll(); err != nil {
|
if data, err := r.ReadAll(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -36,6 +41,7 @@ func (r *ReturnResponse) ScanXML(v interface{}) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 读取请求体
|
||||||
func (r *ReturnResponse) ReadAll() ([]byte, error) {
|
func (r *ReturnResponse) ReadAll() ([]byte, error) {
|
||||||
if r.Err() != nil {
|
if r.Err() != nil {
|
||||||
return nil, r.Err()
|
return nil, r.Err()
|
||||||
|
1
items.go
1
items.go
@ -26,6 +26,7 @@ func (b BaseResponse) Ok() bool {
|
|||||||
return b.Ret == 0
|
return b.Ret == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 实现error接口
|
||||||
func (b BaseResponse) Error() string {
|
func (b BaseResponse) Error() string {
|
||||||
switch b.Ret {
|
switch b.Ret {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -43,6 +43,7 @@ type Message struct {
|
|||||||
senderInGroupUserName string
|
senderInGroupUserName string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取消息的发送者
|
||||||
func (m *Message) Sender() (*User, error) {
|
func (m *Message) Sender() (*User, error) {
|
||||||
members, err := m.Bot.self.Members(true)
|
members, err := m.Bot.self.Members(true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -59,6 +60,7 @@ func (m *Message) Sender() (*User, error) {
|
|||||||
return nil, errors.New("no such user found")
|
return nil, errors.New("no such user found")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取消息在群里面的发送者
|
||||||
func (m *Message) SenderInGroup() (*User, error) {
|
func (m *Message) SenderInGroup() (*User, error) {
|
||||||
if !m.IsSendByGroup() {
|
if !m.IsSendByGroup() {
|
||||||
return nil, errors.New("message is not from group")
|
return nil, errors.New("message is not from group")
|
||||||
@ -79,19 +81,22 @@ func (m *Message) SenderInGroup() (*User, error) {
|
|||||||
return nil, errors.New("no such user found")
|
return nil, errors.New("no such user found")
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
// 判断消息是否由自己发送
|
||||||
func (m *Message) IsSendBySelf() bool {
|
func (m *Message) IsSendBySelf() bool {
|
||||||
return m.FromUserName == m.Bot.self.User.UserName
|
return m.FromUserName == m.Bot.self.User.UserName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断消息是否由好友发送
|
||||||
func (m *Message) IsSendByFriend() bool {
|
func (m *Message) IsSendByFriend() bool {
|
||||||
return !m.IsSendByGroup() && strings.HasPrefix(m.FromUserName, "@")
|
return !m.IsSendByGroup() && strings.HasPrefix(m.FromUserName, "@")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 判断消息是否由群组发送
|
||||||
func (m *Message) IsSendByGroup() bool {
|
func (m *Message) IsSendByGroup() bool {
|
||||||
return strings.HasPrefix(m.FromUserName, "@@")
|
return strings.HasPrefix(m.FromUserName, "@@")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 回复消息
|
||||||
func (m *Message) Reply(msgType int, content, mediaId string) error {
|
func (m *Message) Reply(msgType int, content, mediaId string) error {
|
||||||
msg := NewSendMessage(msgType, content, m.Bot.self.User.UserName, m.FromUserName, mediaId)
|
msg := NewSendMessage(msgType, content, m.Bot.self.User.UserName, m.FromUserName, mediaId)
|
||||||
info := m.Bot.storage.GetLoginInfo()
|
info := m.Bot.storage.GetLoginInfo()
|
||||||
@ -99,10 +104,12 @@ func (m *Message) Reply(msgType int, content, mediaId string) error {
|
|||||||
return m.Bot.Caller.WebWxSendMsg(msg, info, request)
|
return m.Bot.Caller.WebWxSendMsg(msg, info, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 回复文本消息
|
||||||
func (m *Message) ReplyText(content string) error {
|
func (m *Message) ReplyText(content string) error {
|
||||||
return m.Reply(TextMessage, content, "")
|
return m.Reply(TextMessage, content, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 回复图片消息
|
||||||
func (m *Message) ReplyImage(file *os.File) error {
|
func (m *Message) ReplyImage(file *os.File) error {
|
||||||
info := m.Bot.storage.GetLoginInfo()
|
info := m.Bot.storage.GetLoginInfo()
|
||||||
request := m.Bot.storage.GetBaseRequest()
|
request := m.Bot.storage.GetBaseRequest()
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package openwechat
|
package openwechat
|
||||||
|
|
||||||
|
// WechatStorage
|
||||||
|
// 可以根据自己的情况来实现该接口
|
||||||
type WechatStorage interface {
|
type WechatStorage interface {
|
||||||
SetLoginInfo(loginInfo LoginInfo)
|
SetLoginInfo(loginInfo LoginInfo)
|
||||||
SetBaseRequest(baseRequest BaseRequest)
|
SetBaseRequest(baseRequest BaseRequest)
|
||||||
@ -10,6 +12,7 @@ type WechatStorage interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// implement WechatStorage
|
// implement WechatStorage
|
||||||
|
// WechatStorage接口的实现
|
||||||
type SimpleWechatStorage struct {
|
type SimpleWechatStorage struct {
|
||||||
loginInfo LoginInfo
|
loginInfo LoginInfo
|
||||||
baseRequest BaseRequest
|
baseRequest BaseRequest
|
||||||
|
Loading…
x
Reference in New Issue
Block a user