添加同意好友请求支持
This commit is contained in:
parent
72338d99bb
commit
2d4d7e7d78
17
bot_test.go
17
bot_test.go
@ -196,3 +196,20 @@ func TestSendMessage(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAgreeFriendsAdd(t *testing.T) {
|
||||||
|
bot := defaultBot()
|
||||||
|
bot.MessageHandler = func(msg *Message) {
|
||||||
|
if msg.IsFriendAdd() {
|
||||||
|
if err := msg.Agree(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
bot.Logout()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := bot.Login(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
bot.Block()
|
||||||
|
}
|
||||||
|
366
caller.go
366
caller.go
@ -1,262 +1,268 @@
|
|||||||
package openwechat
|
package openwechat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 调用请求和解析请求
|
// 调用请求和解析请求
|
||||||
// 上层模块可以直接获取封装后的请求结果
|
// 上层模块可以直接获取封装后的请求结果
|
||||||
type Caller struct {
|
type Caller struct {
|
||||||
Client *Client
|
Client *Client
|
||||||
}
|
}
|
||||||
|
|
||||||
// Constructor for Caller
|
// 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
|
// Default Constructor for Caller
|
||||||
func DefaultCaller(urlManager UrlManager) *Caller {
|
func DefaultCaller(urlManager UrlManager) *Caller {
|
||||||
return NewCaller(DefaultClient(urlManager))
|
return NewCaller(DefaultClient(urlManager))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取登录的uuid
|
// 获取登录的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 {
|
||||||
return "", resp.Err()
|
return "", resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err := resp.ReadAll()
|
data, err := resp.ReadAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
// 正则匹配uuid字符串
|
// 正则匹配uuid字符串
|
||||||
results := uuidRegexp.FindSubmatch(data)
|
results := uuidRegexp.FindSubmatch(data)
|
||||||
if len(results) != 2 {
|
if len(results) != 2 {
|
||||||
// 如果没有匹配到,可能微信的接口做了修改,或者当前机器的ip被加入了黑名单
|
// 如果没有匹配到,可能微信的接口做了修改,或者当前机器的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 {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err := resp.ReadAll()
|
data, err := resp.ReadAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// 正则匹配检测的code
|
// 正则匹配检测的code
|
||||||
// 具体code参考global.go
|
// 具体code参考global.go
|
||||||
results := statusCodeRegexp.FindSubmatch(data)
|
results := statusCodeRegexp.FindSubmatch(data)
|
||||||
if len(results) != 2 {
|
if len(results) != 2 {
|
||||||
return nil, errors.New("error status code match")
|
return nil, errors.New("error status code match")
|
||||||
}
|
}
|
||||||
code := string(results[1])
|
code := string(results[1])
|
||||||
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
|
// 从响应体里面获取需要跳转的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")
|
||||||
}
|
}
|
||||||
path := string(results[1])
|
path := string(results[1])
|
||||||
resp := NewReturnResponse(c.Client.GetLoginInfo(path))
|
resp := NewReturnResponse(c.Client.GetLoginInfo(path))
|
||||||
if resp.Err() != nil {
|
if resp.Err() != nil {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var loginInfo LoginInfo
|
var loginInfo LoginInfo
|
||||||
// xml结构体序列化储存
|
// 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 {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
var webInitResponse WebInitResponse
|
var webInitResponse WebInitResponse
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
if err := resp.ScanJSON(&webInitResponse); err != nil {
|
if err := resp.ScanJSON(&webInitResponse); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
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 {
|
||||||
return resp.Err()
|
return resp.Err()
|
||||||
}
|
}
|
||||||
var item struct{ BaseResponse BaseResponse }
|
var item struct{ BaseResponse BaseResponse }
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
if err := resp.ScanJSON(&item); err != nil {
|
if err := resp.ScanJSON(&item); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !item.BaseResponse.Ok() {
|
if !item.BaseResponse.Ok() {
|
||||||
return item.BaseResponse
|
return item.BaseResponse
|
||||||
}
|
}
|
||||||
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 {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
data, err := resp.ReadAll()
|
data, err := resp.ReadAll()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
results := syncCheckRegexp.FindSubmatch(data)
|
results := syncCheckRegexp.FindSubmatch(data)
|
||||||
if len(results) != 3 {
|
if len(results) != 3 {
|
||||||
return nil, errors.New("parse sync key failed")
|
return nil, errors.New("parse sync key failed")
|
||||||
}
|
}
|
||||||
retCode, selector := string(results[1]), string(results[2])
|
retCode, selector := string(results[1]), string(results[2])
|
||||||
syncCheckResponse := &SyncCheckResponse{RetCode: retCode, Selector: selector}
|
syncCheckResponse := &SyncCheckResponse{RetCode: retCode, Selector: selector}
|
||||||
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 {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var item WebWxContactResponse
|
var item WebWxContactResponse
|
||||||
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
|
||||||
}
|
}
|
||||||
return item.MemberList, nil
|
return item.MemberList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取联系人的详情
|
// 获取联系人的详情
|
||||||
// 注: Members参数的长度不要大于50
|
// 注: 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 {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var item WebWxBatchContactResponse
|
var item WebWxBatchContactResponse
|
||||||
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
|
||||||
}
|
}
|
||||||
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 {
|
||||||
return nil, resp.Err()
|
return nil, resp.Err()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var webWxSyncResponse WebWxSyncResponse
|
var webWxSyncResponse WebWxSyncResponse
|
||||||
if err := resp.ScanJSON(&webWxSyncResponse); err != nil {
|
if err := resp.ScanJSON(&webWxSyncResponse); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
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()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
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 err
|
return err
|
||||||
}
|
}
|
||||||
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 (c *Caller) Logout(info *LoginInfo) error {
|
func (c *Caller) Logout(info *LoginInfo) error {
|
||||||
resp := NewReturnResponse(c.Client.Logout(info))
|
resp := NewReturnResponse(c.Client.Logout(info))
|
||||||
return parseBaseResponseError(resp)
|
return parseBaseResponseError(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 拉好友入群
|
// 拉好友入群
|
||||||
func (c *Caller) AddFriendIntoChatRoom(req *BaseRequest, info *LoginInfo, group *Group, friends ...*Friend) error {
|
func (c *Caller) AddFriendIntoChatRoom(req *BaseRequest, info *LoginInfo, group *Group, friends ...*Friend) error {
|
||||||
if len(friends) == 0 {
|
if len(friends) == 0 {
|
||||||
return errors.New("no friends found")
|
return errors.New("no friends found")
|
||||||
}
|
}
|
||||||
resp := NewReturnResponse(c.Client.AddMemberIntoChatRoom(req, info, group, friends...))
|
resp := NewReturnResponse(c.Client.AddMemberIntoChatRoom(req, info, group, friends...))
|
||||||
return parseBaseResponseError(resp)
|
return parseBaseResponseError(resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从群聊中移除用户
|
// 从群聊中移除用户
|
||||||
func (c *Caller) RemoveFriendFromChatRoom(req *BaseRequest, info *LoginInfo, group *Group, users ...*User) error {
|
func (c *Caller) RemoveFriendFromChatRoom(req *BaseRequest, info *LoginInfo, group *Group, users ...*User) error {
|
||||||
if len(users) == 0 {
|
if len(users) == 0 {
|
||||||
return errors.New("no users found")
|
return errors.New("no users found")
|
||||||
}
|
}
|
||||||
resp := NewReturnResponse(c.Client.RemoveMemberFromChatRoom(req, info, group, users...))
|
resp := NewReturnResponse(c.Client.RemoveMemberFromChatRoom(req, info, group, users...))
|
||||||
return parseBaseResponseError(resp)
|
return parseBaseResponseError(resp)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同意加好友请求
|
||||||
|
func (c *Caller) WebWxVerifyUser(storage *Storage, info RecommendInfo, verifyContent string) error {
|
||||||
|
resp := NewReturnResponse(c.Client.WebWxVerifyUser(storage, info, verifyContent))
|
||||||
|
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()
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var item struct{ BaseResponse BaseResponse }
|
var item struct{ BaseResponse BaseResponse }
|
||||||
if err := resp.ScanJSON(&item); err != nil {
|
if err := resp.ScanJSON(&item); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if !item.BaseResponse.Ok() {
|
if !item.BaseResponse.Ok() {
|
||||||
return item.BaseResponse
|
return item.BaseResponse
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -340,7 +340,7 @@ func (c *Client) WebWxVerifyUser(storage *Storage, info RecommendInfo, verifyCon
|
|||||||
content := map[string]interface{}{
|
content := map[string]interface{}{
|
||||||
"BaseRequest": storage.Request,
|
"BaseRequest": storage.Request,
|
||||||
"Opcode": 3,
|
"Opcode": 3,
|
||||||
"SceneList": []int{33},
|
"SceneList": [1]int{33},
|
||||||
"SceneListCount": 1,
|
"SceneListCount": 1,
|
||||||
"VerifyContent": verifyContent,
|
"VerifyContent": verifyContent,
|
||||||
"VerifyUserList": []interface{}{map[string]string{
|
"VerifyUserList": []interface{}{map[string]string{
|
||||||
|
514
message.go
514
message.go
@ -1,353 +1,413 @@
|
|||||||
package openwechat
|
package openwechat
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"fmt"
|
||||||
"os"
|
"net/http"
|
||||||
"strconv"
|
"os"
|
||||||
"strings"
|
"strconv"
|
||||||
"sync"
|
"strings"
|
||||||
"time"
|
"sync"
|
||||||
"unicode"
|
"time"
|
||||||
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Message struct {
|
type Message struct {
|
||||||
IsAt bool
|
IsAt bool
|
||||||
AppInfo struct {
|
AppInfo struct {
|
||||||
Type int
|
Type int
|
||||||
AppID string
|
AppID string
|
||||||
}
|
}
|
||||||
AppMsgType int
|
AppMsgType int
|
||||||
HasProductId int
|
HasProductId int
|
||||||
ImgHeight int
|
ImgHeight int
|
||||||
ImgStatus int
|
ImgStatus int
|
||||||
ImgWidth int
|
ImgWidth int
|
||||||
ForwardFlag int
|
ForwardFlag int
|
||||||
MsgType int
|
MsgType int
|
||||||
Status int
|
Status int
|
||||||
StatusNotifyCode int
|
StatusNotifyCode int
|
||||||
SubMsgType int
|
SubMsgType int
|
||||||
VoiceLength int
|
VoiceLength int
|
||||||
CreateTime int64
|
CreateTime int64
|
||||||
NewMsgId int64
|
NewMsgId int64
|
||||||
PlayLength int64
|
PlayLength int64
|
||||||
MediaId string
|
MediaId string
|
||||||
MsgId string
|
MsgId string
|
||||||
EncryFileName string
|
EncryFileName string
|
||||||
FileName string
|
FileName string
|
||||||
FileSize string
|
FileSize string
|
||||||
Content string
|
Content string
|
||||||
FromUserName string
|
FromUserName string
|
||||||
OriContent string
|
OriContent string
|
||||||
StatusNotifyUserName string
|
StatusNotifyUserName string
|
||||||
Ticket string
|
Ticket string
|
||||||
ToUserName string
|
ToUserName string
|
||||||
Url string
|
Url string
|
||||||
senderInGroupUserName string
|
senderInGroupUserName string
|
||||||
RecommendInfo RecommendInfo
|
RecommendInfo RecommendInfo
|
||||||
Bot *Bot
|
Bot *Bot
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
Context context.Context
|
Context context.Context
|
||||||
item map[string]interface{}
|
item map[string]interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取消息的发送者
|
// 获取消息的发送者
|
||||||
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 {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if m.FromUserName == m.Bot.self.User.UserName {
|
if m.FromUserName == m.Bot.self.User.UserName {
|
||||||
return m.Bot.self.User, nil
|
return m.Bot.self.User, nil
|
||||||
}
|
}
|
||||||
user := members.SearchByUserName(1, m.FromUserName)
|
user := members.SearchByUserName(1, m.FromUserName)
|
||||||
if user == nil {
|
if user == nil {
|
||||||
return nil, noSuchUserFoundError
|
return nil, noSuchUserFoundError
|
||||||
}
|
}
|
||||||
return user.First().Detail()
|
return user.First().Detail()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取消息在群里面的发送者
|
// 获取消息在群里面的发送者
|
||||||
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")
|
||||||
}
|
}
|
||||||
group, err := m.Sender()
|
group, err := m.Sender()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
group, err = group.Detail()
|
group, err = group.Detail()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
users := group.MemberList.SearchByUserName(1, m.senderInGroupUserName)
|
users := group.MemberList.SearchByUserName(1, m.senderInGroupUserName)
|
||||||
if users == nil {
|
if users == nil {
|
||||||
return nil, noSuchUserFoundError
|
return nil, noSuchUserFoundError
|
||||||
}
|
}
|
||||||
return users.First(), nil
|
return users.First(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取消息的接收者
|
// 获取消息的接收者
|
||||||
func (m *Message) Receiver() (*User, error) {
|
func (m *Message) Receiver() (*User, error) {
|
||||||
if m.IsSendByGroup() {
|
if m.IsSendByGroup() {
|
||||||
if sender, err := m.Sender(); err != nil {
|
if sender, err := m.Sender(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
} else {
|
} else {
|
||||||
users := sender.MemberList.SearchByUserName(1, m.ToUserName)
|
users := sender.MemberList.SearchByUserName(1, m.ToUserName)
|
||||||
if users == nil {
|
if users == nil {
|
||||||
return nil, noSuchUserFoundError
|
return nil, noSuchUserFoundError
|
||||||
}
|
}
|
||||||
return users.First(), nil
|
return users.First(), nil
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
users := m.Bot.self.MemberList.SearchByUserName(1, m.ToUserName)
|
users := m.Bot.self.MemberList.SearchByUserName(1, m.ToUserName)
|
||||||
if users == nil {
|
if users == nil {
|
||||||
return nil, noSuchUserFoundError
|
return nil, noSuchUserFoundError
|
||||||
}
|
}
|
||||||
return users.First(), nil
|
return users.First(), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断消息是否由自己发送
|
// 判断消息是否由自己发送
|
||||||
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.LoginInfo
|
info := m.Bot.storage.LoginInfo
|
||||||
request := m.Bot.storage.Request
|
request := m.Bot.storage.Request
|
||||||
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.LoginInfo
|
info := m.Bot.storage.LoginInfo
|
||||||
request := m.Bot.storage.Request
|
request := m.Bot.storage.Request
|
||||||
return m.Bot.Caller.WebWxSendImageMsg(file, request, info, m.Bot.self.UserName, m.FromUserName)
|
return m.Bot.Caller.WebWxSendImageMsg(file, request, info, m.Bot.self.UserName, m.FromUserName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsText() bool {
|
func (m *Message) IsText() bool {
|
||||||
return m.MsgType == 1 && m.Url == ""
|
return m.MsgType == 1 && m.Url == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsMap() bool {
|
func (m *Message) IsMap() bool {
|
||||||
return m.MsgType == 1 && m.Url != ""
|
return m.MsgType == 1 && m.Url != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsPicture() bool {
|
func (m *Message) IsPicture() bool {
|
||||||
return m.MsgType == 3 || m.MsgType == 47
|
return m.MsgType == 3 || m.MsgType == 47
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsVoice() bool {
|
func (m *Message) IsVoice() bool {
|
||||||
return m.MsgType == 34
|
return m.MsgType == 34
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsFriendAdd() bool {
|
func (m *Message) IsFriendAdd() bool {
|
||||||
return m.MsgType == 37
|
return m.MsgType == 37 && m.FromUserName == "fmessage"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsCard() bool {
|
func (m *Message) IsCard() bool {
|
||||||
return m.MsgType == 42
|
return m.MsgType == 42
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsVideo() bool {
|
func (m *Message) IsVideo() bool {
|
||||||
return m.MsgType == 43 || m.MsgType == 62
|
return m.MsgType == 43 || m.MsgType == 62
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsMedia() bool {
|
func (m *Message) IsMedia() bool {
|
||||||
return m.MsgType == 49
|
return m.MsgType == 49
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsRecalled() bool {
|
func (m *Message) IsRecalled() bool {
|
||||||
return m.MsgType == 10002
|
return m.MsgType == 10002
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsSystem() bool {
|
func (m *Message) IsSystem() bool {
|
||||||
return m.MsgType == 10000
|
return m.MsgType == 10000
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Message) IsNotify() bool {
|
func (m *Message) IsNotify() bool {
|
||||||
return m.MsgType == 51 && m.StatusNotifyCode != 0
|
return m.MsgType == 51 && m.StatusNotifyCode != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// 判断消息是否为文件类型的消息
|
// 判断消息是否为文件类型的消息
|
||||||
func (m *Message) HasFile() bool {
|
func (m *Message) HasFile() bool {
|
||||||
return m.IsPicture() || m.IsVoice() || m.IsVideo() || m.IsMedia()
|
return m.IsPicture() || m.IsVoice() || m.IsVideo() || m.IsMedia()
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取文件消息的文件
|
// 获取文件消息的文件
|
||||||
func (m *Message) GetFile() (*http.Response, error) {
|
func (m *Message) GetFile() (*http.Response, error) {
|
||||||
if !m.HasFile() {
|
if !m.HasFile() {
|
||||||
return nil, errors.New("invalid message type")
|
return nil, errors.New("invalid message type")
|
||||||
}
|
}
|
||||||
if m.IsPicture() {
|
if m.IsPicture() {
|
||||||
return m.Bot.Caller.Client.WebWxGetMsgImg(m, m.Bot.storage.LoginInfo)
|
return m.Bot.Caller.Client.WebWxGetMsgImg(m, m.Bot.storage.LoginInfo)
|
||||||
}
|
}
|
||||||
if m.IsVoice() {
|
if m.IsVoice() {
|
||||||
return m.Bot.Caller.Client.WebWxGetVoice(m, m.Bot.storage.LoginInfo)
|
return m.Bot.Caller.Client.WebWxGetVoice(m, m.Bot.storage.LoginInfo)
|
||||||
}
|
}
|
||||||
if m.IsVideo() {
|
if m.IsVideo() {
|
||||||
return m.Bot.Caller.Client.WebWxGetVideo(m, m.Bot.storage.LoginInfo)
|
return m.Bot.Caller.Client.WebWxGetVideo(m, m.Bot.storage.LoginInfo)
|
||||||
}
|
}
|
||||||
if m.IsMedia() {
|
if m.IsMedia() {
|
||||||
return m.Bot.Caller.Client.WebWxGetMedia(m, m.Bot.storage.LoginInfo)
|
return m.Bot.Caller.Client.WebWxGetMedia(m, m.Bot.storage.LoginInfo)
|
||||||
}
|
}
|
||||||
return nil, errors.New("unsupported type")
|
return nil, errors.New("unsupported type")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取card类型
|
// 获取card类型
|
||||||
func (m *Message) Card() (*Card, error) {
|
func (m *Message) Card() (*Card, error) {
|
||||||
if !m.IsCard() {
|
if !m.IsCard() {
|
||||||
return nil, errors.New("card message required")
|
return nil, errors.New("card message required")
|
||||||
}
|
}
|
||||||
var card Card
|
var card Card
|
||||||
content := XmlFormString(m.Content)
|
content := XmlFormString(m.Content)
|
||||||
err := xml.Unmarshal([]byte(content), &card)
|
err := xml.Unmarshal([]byte(content), &card)
|
||||||
return &card, err
|
return &card, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取FriendAddMessageContent内容
|
||||||
|
func (m *Message) FriendAddMessageContent() (*FriendAddMessageContent, error) {
|
||||||
|
if !m.IsFriendAdd() {
|
||||||
|
return nil, errors.New("friend add message required")
|
||||||
|
}
|
||||||
|
var f FriendAddMessageContent
|
||||||
|
content := XmlFormString(m.Content)
|
||||||
|
err := xml.Unmarshal([]byte(content), &f)
|
||||||
|
return &f, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 同意好友的请求
|
||||||
|
func (m *Message) Agree(verifyContents ...string) error {
|
||||||
|
if !m.IsFriendAdd() {
|
||||||
|
return fmt.Errorf("friend add message required")
|
||||||
|
}
|
||||||
|
var builder strings.Builder
|
||||||
|
for _, v := range verifyContents {
|
||||||
|
builder.WriteString(v)
|
||||||
|
}
|
||||||
|
return m.Bot.Caller.WebWxVerifyUser(m.Bot.storage, m.RecommendInfo, builder.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 往消息上下文中设置值
|
// 往消息上下文中设置值
|
||||||
// goroutine safe
|
// goroutine safe
|
||||||
func (m *Message) Set(key string, value interface{}) {
|
func (m *Message) Set(key string, value interface{}) {
|
||||||
m.mu.Lock()
|
m.mu.Lock()
|
||||||
defer m.mu.Unlock()
|
defer m.mu.Unlock()
|
||||||
if m.item == nil {
|
if m.item == nil {
|
||||||
m.item = make(map[string]interface{})
|
m.item = make(map[string]interface{})
|
||||||
}
|
}
|
||||||
m.item[key] = value
|
m.item[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 从消息上下文中获取值
|
// 从消息上下文中获取值
|
||||||
// goroutine safe
|
// goroutine safe
|
||||||
func (m *Message) Get(key string) (value interface{}, exist bool) {
|
func (m *Message) Get(key string) (value interface{}, exist bool) {
|
||||||
m.mu.RLock()
|
m.mu.RLock()
|
||||||
defer m.mu.RUnlock()
|
defer m.mu.RUnlock()
|
||||||
value, exist = m.item[key]
|
value, exist = m.item[key]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消息初始化,根据不同的消息作出不同的处理
|
// 消息初始化,根据不同的消息作出不同的处理
|
||||||
func (m *Message) init(bot *Bot) {
|
func (m *Message) init(bot *Bot) {
|
||||||
m.Bot = bot
|
m.Bot = bot
|
||||||
if m.IsSendByGroup() {
|
if m.IsSendByGroup() {
|
||||||
data := strings.Split(m.Content, ":<br/>")
|
data := strings.Split(m.Content, ":<br/>")
|
||||||
m.Content = strings.Join(data[1:], "")
|
m.Content = strings.Join(data[1:], "")
|
||||||
m.senderInGroupUserName = data[0]
|
m.senderInGroupUserName = data[0]
|
||||||
receiver, err := m.Receiver()
|
receiver, err := m.Receiver()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
displayName := receiver.DisplayName
|
displayName := receiver.DisplayName
|
||||||
if displayName == "" {
|
if displayName == "" {
|
||||||
displayName = receiver.NickName
|
displayName = receiver.NickName
|
||||||
}
|
}
|
||||||
atFlag := "@" + displayName
|
atFlag := "@" + displayName
|
||||||
index := len(atFlag) + 1 + 1
|
index := len(atFlag) + 1 + 1
|
||||||
if strings.HasPrefix(m.Content, atFlag) && unicode.IsSpace(rune(m.Content[index])) {
|
if strings.HasPrefix(m.Content, atFlag) && unicode.IsSpace(rune(m.Content[index])) {
|
||||||
m.IsAt = true
|
m.IsAt = true
|
||||||
m.Content = m.Content[index+1:]
|
m.Content = m.Content[index+1:]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (m *Message) Agree() error {
|
|
||||||
// if !m.IsFriendAdd() {
|
|
||||||
// return fmt.Errorf("the excepted message type is 37, but got %d", m.MsgType)
|
|
||||||
// }
|
|
||||||
// return m.Bot.Caller.Client.WebWxVerifyUser(m.Bot.storage, m.RecommendInfo, "")
|
|
||||||
//}
|
|
||||||
|
|
||||||
// 发送消息的结构体
|
// 发送消息的结构体
|
||||||
type SendMessage struct {
|
type SendMessage struct {
|
||||||
Type int
|
Type int
|
||||||
Content string
|
Content string
|
||||||
FromUserName string
|
FromUserName string
|
||||||
ToUserName string
|
ToUserName string
|
||||||
LocalID string
|
LocalID string
|
||||||
ClientMsgId string
|
ClientMsgId string
|
||||||
MediaId string
|
MediaId string
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendMessage的构造方法
|
// SendMessage的构造方法
|
||||||
func NewSendMessage(msgType int, content, fromUserName, toUserName, mediaId string) *SendMessage {
|
func NewSendMessage(msgType int, content, fromUserName, toUserName, mediaId string) *SendMessage {
|
||||||
id := strconv.FormatInt(time.Now().Unix()*1e4, 10)
|
id := strconv.FormatInt(time.Now().Unix()*1e4, 10)
|
||||||
return &SendMessage{
|
return &SendMessage{
|
||||||
Type: msgType,
|
Type: msgType,
|
||||||
Content: content,
|
Content: content,
|
||||||
FromUserName: fromUserName,
|
FromUserName: fromUserName,
|
||||||
ToUserName: toUserName,
|
ToUserName: toUserName,
|
||||||
LocalID: id,
|
LocalID: id,
|
||||||
ClientMsgId: id,
|
ClientMsgId: id,
|
||||||
MediaId: mediaId,
|
MediaId: mediaId,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 文本消息的构造方法
|
// 文本消息的构造方法
|
||||||
func NewTextSendMessage(content, fromUserName, toUserName string) *SendMessage {
|
func NewTextSendMessage(content, fromUserName, toUserName string) *SendMessage {
|
||||||
return NewSendMessage(TextMessage, content, fromUserName, toUserName, "")
|
return NewSendMessage(TextMessage, content, fromUserName, toUserName, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 媒体消息的构造方法
|
// 媒体消息的构造方法
|
||||||
func NewMediaSendMessage(msgType int, fromUserName, toUserName, mediaId string) *SendMessage {
|
func NewMediaSendMessage(msgType int, fromUserName, toUserName, mediaId string) *SendMessage {
|
||||||
return NewSendMessage(msgType, "", fromUserName, toUserName, mediaId)
|
return NewSendMessage(msgType, "", fromUserName, toUserName, mediaId)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 一些特殊类型的消息会携带该结构体信息
|
// 一些特殊类型的消息会携带该结构体信息
|
||||||
type RecommendInfo struct {
|
type RecommendInfo struct {
|
||||||
OpCode int
|
OpCode int
|
||||||
Scene int
|
Scene int
|
||||||
Sex int
|
Sex int
|
||||||
VerifyFlag int
|
VerifyFlag int
|
||||||
AttrStatus int64
|
AttrStatus int64
|
||||||
QQNum int64
|
QQNum int64
|
||||||
Alias string
|
Alias string
|
||||||
City string
|
City string
|
||||||
Content string
|
Content string
|
||||||
NickName string
|
NickName string
|
||||||
Province string
|
Province string
|
||||||
Signature string
|
Signature string
|
||||||
Ticket string
|
Ticket string
|
||||||
UserName string
|
UserName string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 名片消息内容
|
// 名片消息内容
|
||||||
type Card struct {
|
type Card struct {
|
||||||
XMLName xml.Name `xml:"msg"`
|
XMLName xml.Name `xml:"msg"`
|
||||||
ImageStatus int `xml:"imagestatus,attr"`
|
ImageStatus int `xml:"imagestatus,attr"`
|
||||||
Scene int `xml:"scene,attr"`
|
Scene int `xml:"scene,attr"`
|
||||||
Sex int `xml:"sex,attr"`
|
Sex int `xml:"sex,attr"`
|
||||||
Certflag int `xml:"certflag,attr"`
|
Certflag int `xml:"certflag,attr"`
|
||||||
BigHeadImgUrl string `xml:"bigheadimgurl,attr"`
|
BigHeadImgUrl string `xml:"bigheadimgurl,attr"`
|
||||||
SmallHeadImgUrl string `xml:"smallheadimgurl,attr"`
|
SmallHeadImgUrl string `xml:"smallheadimgurl,attr"`
|
||||||
UserName string `xml:"username,attr"`
|
UserName string `xml:"username,attr"`
|
||||||
NickName string `xml:"nickname,attr"`
|
NickName string `xml:"nickname,attr"`
|
||||||
ShortPy string `xml:"shortpy,attr"`
|
ShortPy string `xml:"shortpy,attr"`
|
||||||
Alias string `xml:"alias,attr"` // Note: 这个是名片用户的微信号
|
Alias string `xml:"alias,attr"` // Note: 这个是名片用户的微信号
|
||||||
Province string `xml:"province,attr"`
|
Province string `xml:"province,attr"`
|
||||||
City string `xml:"city,attr"`
|
City string `xml:"city,attr"`
|
||||||
Sign string `xml:"sign,attr"`
|
Sign string `xml:"sign,attr"`
|
||||||
Certinfo string `xml:"certinfo,attr"`
|
Certinfo string `xml:"certinfo,attr"`
|
||||||
BrandIconUrl string `xml:"brandIconUrl,attr"`
|
BrandIconUrl string `xml:"brandIconUrl,attr"`
|
||||||
BrandHomeUr string `xml:"brandHomeUr,attr"`
|
BrandHomeUr string `xml:"brandHomeUr,attr"`
|
||||||
BrandSubscriptConfigUrl string `xml:"brandSubscriptConfigUrl,attr"`
|
BrandSubscriptConfigUrl string `xml:"brandSubscriptConfigUrl,attr"`
|
||||||
BrandFlags string `xml:"brandFlags,attr"`
|
BrandFlags string `xml:"brandFlags,attr"`
|
||||||
RegionCode string `xml:"regionCode,attr"`
|
RegionCode string `xml:"regionCode,attr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 好友添加消息信息内容
|
||||||
|
type FriendAddMessageContent struct {
|
||||||
|
XMLName xml.Name `xml:"msg"`
|
||||||
|
Shortpy int `xml:"shortpy,attr"`
|
||||||
|
ImageStatus int `xml:"imagestatus,attr"`
|
||||||
|
Scene int `xml:"scene,attr"`
|
||||||
|
PerCard int `xml:"percard,attr"`
|
||||||
|
Sex int `xml:"sex,attr"`
|
||||||
|
AlbumFlag int `xml:"albumflag,attr"`
|
||||||
|
AlbumStyle int `xml:"albumstyle,attr"`
|
||||||
|
SnsFlag int `xml:"snsflag,attr"`
|
||||||
|
Opcode int `xml:"opcode,attr"`
|
||||||
|
FromUserName string `xml:"fromusername,attr"`
|
||||||
|
EncryptUserName string `xml:"encryptusername,attr"`
|
||||||
|
FromNickName string `xml:"fromnickname,attr"`
|
||||||
|
Content string `xml:"content,attr"`
|
||||||
|
Country string `xml:"country,attr"`
|
||||||
|
Province string `xml:"province,attr"`
|
||||||
|
City string `xml:"city,attr"`
|
||||||
|
Sign string `xml:"sign,attr"`
|
||||||
|
Alias string `xml:"alias,attr"`
|
||||||
|
WeiBo string `xml:"weibo,attr"`
|
||||||
|
AlbumBgImgId string `xml:"albumbgimgid,attr"`
|
||||||
|
SnsBgImgId string `xml:"snsbgimgid,attr"`
|
||||||
|
SnsBgObjectId string `xml:"snsbgobjectid,attr"`
|
||||||
|
MHash string `xml:"mhash,attr"`
|
||||||
|
MFullHash string `xml:"mfullhash,attr"`
|
||||||
|
BigHeadImgUrl string `xml:"bigheadimgurl,attr"`
|
||||||
|
SmallHeadImgUrl string `xml:"smallheadimgurl,attr"`
|
||||||
|
Ticket string `xml:"ticket,attr"`
|
||||||
|
GoogleContact string `xml:"googlecontact,attr"`
|
||||||
|
QrTicket string `xml:"qrticket,attr"`
|
||||||
|
ChatRoomUserName string `xml:"chatroomusername,attr"`
|
||||||
|
SourceUserName string `xml:"sourceusername,attr"`
|
||||||
|
ShareCardUserName string `xml:"sharecardusername,attr"`
|
||||||
|
ShareCardNickName string `xml:"sharecardnickname,attr"`
|
||||||
|
CardVersion string `xml:"cardversion,attr"`
|
||||||
|
BrandList struct {
|
||||||
|
Count int `xml:"count,attr"`
|
||||||
|
Ver int64 `xml:"ver,attr"`
|
||||||
|
} `xml:"brandlist"`
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user