优化对象的字段的排列
This commit is contained in:
parent
7ddcde9ab6
commit
d84fbe1681
322
bot.go
322
bot.go
@ -1,223 +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
|
||||
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
|
||||
}
|
||||
|
||||
// 判断当前用户是否正常在线
|
||||
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(modes ...mode) *Bot {
|
||||
var m mode
|
||||
if len(modes) == 0 {
|
||||
m = Normal
|
||||
} else {
|
||||
m = modes[0]
|
||||
}
|
||||
urlManager := GetUrlManagerByMode(m)
|
||||
return NewBot(DefaultCaller(urlManager))
|
||||
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))
|
||||
}
|
||||
|
220
items.go
220
items.go
@ -8,173 +8,173 @@ import "fmt"
|
||||
|
||||
// 登录信息
|
||||
type LoginInfo struct {
|
||||
Ret int `xml:"ret"`
|
||||
Message string `xml:"message"`
|
||||
SKey string `xml:"skey"`
|
||||
WxSid string `xml:"wxsid"`
|
||||
WxUin int `xml:"wxuin"`
|
||||
PassTicket string `xml:"pass_ticket"`
|
||||
IsGrayScale int `xml:"isgrayscale"`
|
||||
Ret int `xml:"ret"`
|
||||
WxUin int `xml:"wxuin"`
|
||||
IsGrayScale int `xml:"isgrayscale"`
|
||||
Message string `xml:"message"`
|
||||
SKey string `xml:"skey"`
|
||||
WxSid string `xml:"wxsid"`
|
||||
PassTicket string `xml:"pass_ticket"`
|
||||
}
|
||||
|
||||
// 初始的请求信息
|
||||
// 几乎所有的请求都要携带该参数
|
||||
type BaseRequest struct {
|
||||
Uin int
|
||||
Sid, Skey, DeviceID string
|
||||
Uin int
|
||||
Sid, Skey, DeviceID string
|
||||
}
|
||||
|
||||
// 大部分返回对象都携带该信息
|
||||
type BaseResponse struct {
|
||||
ErrMsg string
|
||||
Ret int
|
||||
Ret int
|
||||
ErrMsg string
|
||||
}
|
||||
|
||||
func (b BaseResponse) Ok() bool {
|
||||
return b.Ret == 0
|
||||
return b.Ret == 0
|
||||
}
|
||||
|
||||
func (b BaseResponse) Error() string {
|
||||
switch b.Ret {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return "param error"
|
||||
case -14:
|
||||
return "ticket error"
|
||||
case 1100:
|
||||
return "not login warn"
|
||||
case 1101:
|
||||
return "not login check"
|
||||
case 1102:
|
||||
return "cookie invalid error"
|
||||
case 1203:
|
||||
return "login env error"
|
||||
case 1205:
|
||||
return "opt too often"
|
||||
default:
|
||||
return fmt.Sprintf("base response ret code %d", b.Ret)
|
||||
}
|
||||
switch b.Ret {
|
||||
case 0:
|
||||
return ""
|
||||
case 1:
|
||||
return "param error"
|
||||
case -14:
|
||||
return "ticket error"
|
||||
case 1100:
|
||||
return "not login warn"
|
||||
case 1101:
|
||||
return "not login check"
|
||||
case 1102:
|
||||
return "cookie invalid error"
|
||||
case 1203:
|
||||
return "login env error"
|
||||
case 1205:
|
||||
return "opt too often"
|
||||
default:
|
||||
return fmt.Sprintf("base response ret code %d", b.Ret)
|
||||
}
|
||||
}
|
||||
|
||||
type SyncKey struct {
|
||||
Count int
|
||||
List []struct{ Key, Val int64 }
|
||||
Count int
|
||||
List []struct{ Key, Val int64 }
|
||||
}
|
||||
|
||||
// 初始化的相应信息
|
||||
type WebInitResponse struct {
|
||||
BaseResponse BaseResponse
|
||||
Count int
|
||||
ChatSet string
|
||||
SKey string
|
||||
SyncKey SyncKey
|
||||
User User
|
||||
ClientVersion int
|
||||
SystemTime int64
|
||||
GrayScale int
|
||||
InviteStartCount int
|
||||
MPSubscribeMsgCount int
|
||||
MPSubscribeMsgList []MPSubscribeMsg
|
||||
ClickReportInterval int
|
||||
ContactList []User
|
||||
Count int
|
||||
ClientVersion int
|
||||
GrayScale int
|
||||
InviteStartCount int
|
||||
MPSubscribeMsgCount int
|
||||
ClickReportInterval int
|
||||
SystemTime int64
|
||||
ChatSet string
|
||||
SKey string
|
||||
BaseResponse BaseResponse
|
||||
SyncKey SyncKey
|
||||
User User
|
||||
MPSubscribeMsgList []MPSubscribeMsg
|
||||
ContactList []User
|
||||
}
|
||||
|
||||
// 公众号的订阅信息
|
||||
type MPSubscribeMsg struct {
|
||||
UserName string
|
||||
Time int64
|
||||
NickName string
|
||||
MPArticleCount int
|
||||
MPArticleList []struct {
|
||||
Title string
|
||||
Cover string
|
||||
Digest string
|
||||
Url string
|
||||
}
|
||||
MPArticleCount int
|
||||
Time int64
|
||||
UserName string
|
||||
NickName string
|
||||
MPArticleList []struct {
|
||||
Title string
|
||||
Cover string
|
||||
Digest string
|
||||
Url string
|
||||
}
|
||||
}
|
||||
|
||||
type UserDetailItem struct {
|
||||
UserName string
|
||||
EncryChatRoomId string
|
||||
UserName string
|
||||
EncryChatRoomId string
|
||||
}
|
||||
|
||||
type UserDetailItemList []UserDetailItem
|
||||
|
||||
func NewUserDetailItemList(members Members) UserDetailItemList {
|
||||
var list UserDetailItemList
|
||||
for _, member := range members {
|
||||
item := UserDetailItem{UserName: member.UserName, EncryChatRoomId: member.EncryChatRoomId}
|
||||
list = append(list, item)
|
||||
}
|
||||
return list
|
||||
var list UserDetailItemList
|
||||
for _, member := range members {
|
||||
item := UserDetailItem{UserName: member.UserName, EncryChatRoomId: member.EncryChatRoomId}
|
||||
list = append(list, item)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
type SyncCheckResponse struct {
|
||||
RetCode string
|
||||
Selector string
|
||||
RetCode string
|
||||
Selector string
|
||||
}
|
||||
|
||||
func (s *SyncCheckResponse) Success() bool {
|
||||
return s.RetCode == "0"
|
||||
return s.RetCode == "0"
|
||||
}
|
||||
|
||||
func (s *SyncCheckResponse) NorMal() bool {
|
||||
return s.Success() && s.Selector == "0"
|
||||
return s.Success() && s.Selector == "0"
|
||||
}
|
||||
|
||||
// 实现error接口
|
||||
func (s *SyncCheckResponse) Error() string {
|
||||
switch s.RetCode {
|
||||
case "0":
|
||||
return ""
|
||||
case "1":
|
||||
return "param error"
|
||||
case "-14":
|
||||
return "ticker error"
|
||||
case "1100":
|
||||
return "not login warn"
|
||||
case "1101":
|
||||
return "not login check"
|
||||
case "1102":
|
||||
return "cookie invalid error"
|
||||
case "1203":
|
||||
return "login env error"
|
||||
case "1205":
|
||||
return "opt too often"
|
||||
default:
|
||||
return fmt.Sprintf("sync check response error code %s", s.RetCode)
|
||||
}
|
||||
switch s.RetCode {
|
||||
case "0":
|
||||
return ""
|
||||
case "1":
|
||||
return "param error"
|
||||
case "-14":
|
||||
return "ticker error"
|
||||
case "1100":
|
||||
return "not login warn"
|
||||
case "1101":
|
||||
return "not login check"
|
||||
case "1102":
|
||||
return "cookie invalid error"
|
||||
case "1203":
|
||||
return "login env error"
|
||||
case "1205":
|
||||
return "opt too often"
|
||||
default:
|
||||
return fmt.Sprintf("sync check response error code %s", s.RetCode)
|
||||
}
|
||||
}
|
||||
|
||||
type WebWxSyncResponse struct {
|
||||
AddMsgCount int
|
||||
AddMsgList []*Message
|
||||
BaseResponse BaseResponse
|
||||
ContinueFlag int
|
||||
DelContactCount int
|
||||
ModChatRoomMemberCount int
|
||||
ModChatRoomMemberList Members
|
||||
ModContactCount int
|
||||
Skey string
|
||||
SyncCheckKey SyncKey
|
||||
SyncKey SyncKey
|
||||
AddMsgCount int
|
||||
ContinueFlag int
|
||||
DelContactCount int
|
||||
ModChatRoomMemberCount int
|
||||
ModContactCount int
|
||||
Skey string
|
||||
SyncCheckKey SyncKey
|
||||
SyncKey SyncKey
|
||||
BaseResponse BaseResponse
|
||||
ModChatRoomMemberList Members
|
||||
AddMsgList []*Message
|
||||
}
|
||||
|
||||
type WebWxContactResponse struct {
|
||||
BaseResponse BaseResponse
|
||||
MemberCount int
|
||||
MemberList []*User
|
||||
Seq int
|
||||
MemberCount int
|
||||
Seq int
|
||||
BaseResponse BaseResponse
|
||||
MemberList []*User
|
||||
}
|
||||
|
||||
type WebWxBatchContactResponse struct {
|
||||
BaseResponse BaseResponse
|
||||
ContactList []*User
|
||||
Count int
|
||||
Count int
|
||||
BaseResponse BaseResponse
|
||||
ContactList []*User
|
||||
}
|
||||
|
||||
type CheckLoginResponse struct {
|
||||
Code string
|
||||
Raw []byte
|
||||
Code string
|
||||
Raw []byte
|
||||
}
|
||||
|
63
message.go
63
message.go
@ -13,44 +13,43 @@ import (
|
||||
)
|
||||
|
||||
type Message struct {
|
||||
IsAt bool
|
||||
AppInfo struct {
|
||||
AppID string
|
||||
Type int
|
||||
AppID string
|
||||
}
|
||||
AppMsgType int
|
||||
Content string
|
||||
CreateTime int64
|
||||
EncryFileName string
|
||||
FileName string
|
||||
FileSize string
|
||||
ForwardFlag int
|
||||
FromUserName string
|
||||
HasProductId int
|
||||
ImgHeight int
|
||||
ImgStatus int
|
||||
ImgWidth int
|
||||
MediaId string
|
||||
MsgId string
|
||||
MsgType int
|
||||
NewMsgId int64
|
||||
OriContent string
|
||||
PlayLength int64
|
||||
RecommendInfo RecommendInfo
|
||||
Status int
|
||||
StatusNotifyCode int
|
||||
StatusNotifyUserName string
|
||||
SubMsgType int
|
||||
Ticket string
|
||||
ToUserName string
|
||||
Url string
|
||||
VoiceLength int
|
||||
|
||||
IsAt bool
|
||||
Bot *Bot
|
||||
AppMsgType int
|
||||
HasProductId int
|
||||
ImgHeight int
|
||||
ImgStatus int
|
||||
ImgWidth int
|
||||
ForwardFlag int
|
||||
MsgType int
|
||||
Status int
|
||||
StatusNotifyCode int
|
||||
SubMsgType int
|
||||
VoiceLength int
|
||||
CreateTime int64
|
||||
NewMsgId int64
|
||||
PlayLength int64
|
||||
MediaId string
|
||||
MsgId string
|
||||
EncryFileName string
|
||||
FileName string
|
||||
FileSize string
|
||||
Content string
|
||||
FromUserName string
|
||||
OriContent string
|
||||
StatusNotifyUserName string
|
||||
Ticket string
|
||||
ToUserName string
|
||||
Url string
|
||||
senderInGroupUserName string
|
||||
RecommendInfo RecommendInfo
|
||||
Bot *Bot
|
||||
mu sync.RWMutex
|
||||
item map[string]interface{}
|
||||
Context context.Context
|
||||
item map[string]interface{}
|
||||
}
|
||||
|
||||
// 获取消息的发送者
|
||||
|
Loading…
x
Reference in New Issue
Block a user