优化对象的字段的排列

This commit is contained in:
eatMoreApple 2021-04-27 11:13:09 +08:00
parent d84fbe1681
commit 291010997f

View File

@ -1,270 +1,270 @@
package openwechat package openwechat
import ( import (
"context" "context"
"encoding/xml" "encoding/xml"
"errors" "errors"
"net/http" "net/http"
"os" "os"
"strings" "strings"
"sync" "sync"
"time" "time"
"unicode" "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
} }
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
} }
// 往消息上下文中设置值 // 往消息上下文中设置值
// 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 { //func (m *Message) Agree() error {
@ -276,76 +276,76 @@ func (m *Message) init(bot *Bot) {
// 发送消息的结构体 // 发送消息的结构体
type SendMessage struct { type SendMessage struct {
Type int Type int
Content string Content string
FromUserName string FromUserName string
ToUserName string ToUserName string
LocalID int64 LocalID int64
ClientMsgId int64 ClientMsgId int64
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 {
return &SendMessage{ return &SendMessage{
Type: msgType, Type: msgType,
Content: content, Content: content,
FromUserName: fromUserName, FromUserName: fromUserName,
ToUserName: toUserName, ToUserName: toUserName,
LocalID: time.Now().Unix() * 1e4, LocalID: time.Now().Unix() * 1e4,
ClientMsgId: time.Now().Unix() * 1e4, ClientMsgId: time.Now().Unix() * 1e4,
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 {
Alias string Alias string
AttrStatus int64 AttrStatus int64
City string City string
Content string Content string
NickName string NickName string
OpCode int OpCode int
Province string Province string
QQNum int64 QQNum int64
Scene int Scene int
Sex int Sex int
Signature string Signature string
Ticket string Ticket string
UserName string UserName string
VerifyFlag int VerifyFlag int
} }
// 名片消息内容 // 名片消息内容
type Card struct { type Card struct {
XMLName xml.Name `xml:"msg"` XMLName xml.Name `xml:"msg"`
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: 这个是名片用户的微信号
ImageStatus int `xml:"imagestatus,attr"` ImageStatus int `xml:"imagestatus,attr"`
Scene int `xml:"scene,attr"` Scene int `xml:"scene,attr"`
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"`
Sex int `xml:"sex,attr"` Sex int `xml:"sex,attr"`
Certflag int `xml:"certflag,attr"` Certflag int `xml:"certflag,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"`
} }