优化对象的字段的排列

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
import (
"context"
"encoding/xml"
"errors"
"net/http"
"os"
"strings"
"sync"
"time"
"unicode"
"context"
"encoding/xml"
"errors"
"net/http"
"os"
"strings"
"sync"
"time"
"unicode"
)
type Message struct {
IsAt bool
AppInfo struct {
Type int
AppID string
}
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
Context context.Context
item map[string]interface{}
IsAt bool
AppInfo struct {
Type int
AppID string
}
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
Context context.Context
item map[string]interface{}
}
// 获取消息的发送者
func (m *Message) Sender() (*User, error) {
members, err := m.Bot.self.Members(true)
if err != nil {
return nil, err
}
if m.FromUserName == m.Bot.self.User.UserName {
return m.Bot.self.User, nil
}
user := members.SearchByUserName(1, m.FromUserName)
if user == nil {
return nil, noSuchUserFoundError
}
return user.First().Detail()
members, err := m.Bot.self.Members(true)
if err != nil {
return nil, err
}
if m.FromUserName == m.Bot.self.User.UserName {
return m.Bot.self.User, nil
}
user := members.SearchByUserName(1, m.FromUserName)
if user == nil {
return nil, noSuchUserFoundError
}
return user.First().Detail()
}
// 获取消息在群里面的发送者
func (m *Message) SenderInGroup() (*User, error) {
if !m.IsSendByGroup() {
return nil, errors.New("message is not from group")
}
group, err := m.Sender()
if err != nil {
return nil, err
}
group, err = group.Detail()
if err != nil {
return nil, err
}
users := group.MemberList.SearchByUserName(1, m.senderInGroupUserName)
if users == nil {
return nil, noSuchUserFoundError
}
return users.First(), nil
if !m.IsSendByGroup() {
return nil, errors.New("message is not from group")
}
group, err := m.Sender()
if err != nil {
return nil, err
}
group, err = group.Detail()
if err != nil {
return nil, err
}
users := group.MemberList.SearchByUserName(1, m.senderInGroupUserName)
if users == nil {
return nil, noSuchUserFoundError
}
return users.First(), nil
}
// 获取消息的接收者
func (m *Message) Receiver() (*User, error) {
if m.IsSendByGroup() {
if sender, err := m.Sender(); err != nil {
return nil, err
} else {
users := sender.MemberList.SearchByUserName(1, m.ToUserName)
if users == nil {
return nil, noSuchUserFoundError
}
return users.First(), nil
}
} else {
users := m.Bot.self.MemberList.SearchByUserName(1, m.ToUserName)
if users == nil {
return nil, noSuchUserFoundError
}
return users.First(), nil
}
if m.IsSendByGroup() {
if sender, err := m.Sender(); err != nil {
return nil, err
} else {
users := sender.MemberList.SearchByUserName(1, m.ToUserName)
if users == nil {
return nil, noSuchUserFoundError
}
return users.First(), nil
}
} else {
users := m.Bot.self.MemberList.SearchByUserName(1, m.ToUserName)
if users == nil {
return nil, noSuchUserFoundError
}
return users.First(), nil
}
}
// 判断消息是否由自己发送
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 {
return !m.IsSendByGroup() && strings.HasPrefix(m.FromUserName, "@")
return !m.IsSendByGroup() && strings.HasPrefix(m.FromUserName, "@")
}
// 判断消息是否由群组发送
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 {
msg := NewSendMessage(msgType, content, m.Bot.self.User.UserName, m.FromUserName, mediaId)
info := m.Bot.storage.LoginInfo
request := m.Bot.storage.Request
return m.Bot.Caller.WebWxSendMsg(msg, info, request)
msg := NewSendMessage(msgType, content, m.Bot.self.User.UserName, m.FromUserName, mediaId)
info := m.Bot.storage.LoginInfo
request := m.Bot.storage.Request
return m.Bot.Caller.WebWxSendMsg(msg, info, request)
}
// 回复文本消息
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 {
info := m.Bot.storage.LoginInfo
request := m.Bot.storage.Request
return m.Bot.Caller.WebWxSendImageMsg(file, request, info, m.Bot.self.UserName, m.FromUserName)
info := m.Bot.storage.LoginInfo
request := m.Bot.storage.Request
return m.Bot.Caller.WebWxSendImageMsg(file, request, info, m.Bot.self.UserName, m.FromUserName)
}
func (m *Message) IsText() bool {
return m.MsgType == 1 && m.Url == ""
return m.MsgType == 1 && m.Url == ""
}
func (m *Message) IsMap() bool {
return m.MsgType == 1 && m.Url != ""
return m.MsgType == 1 && m.Url != ""
}
func (m *Message) IsPicture() bool {
return m.MsgType == 3 || m.MsgType == 47
return m.MsgType == 3 || m.MsgType == 47
}
func (m *Message) IsVoice() bool {
return m.MsgType == 34
return m.MsgType == 34
}
func (m *Message) IsFriendAdd() bool {
return m.MsgType == 37
return m.MsgType == 37
}
func (m *Message) IsCard() bool {
return m.MsgType == 42
return m.MsgType == 42
}
func (m *Message) IsVideo() bool {
return m.MsgType == 43 || m.MsgType == 62
return m.MsgType == 43 || m.MsgType == 62
}
func (m *Message) IsMedia() bool {
return m.MsgType == 49
return m.MsgType == 49
}
func (m *Message) IsRecalled() bool {
return m.MsgType == 10002
return m.MsgType == 10002
}
func (m *Message) IsSystem() bool {
return m.MsgType == 10000
return m.MsgType == 10000
}
func (m *Message) IsNotify() bool {
return m.MsgType == 51 && m.StatusNotifyCode != 0
return m.MsgType == 51 && m.StatusNotifyCode != 0
}
// 判断消息是否为文件类型的消息
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) {
if !m.HasFile() {
return nil, errors.New("invalid message type")
}
if m.IsPicture() {
return m.Bot.Caller.Client.WebWxGetMsgImg(m, m.Bot.storage.LoginInfo)
}
if m.IsVoice() {
return m.Bot.Caller.Client.WebWxGetVoice(m, m.Bot.storage.LoginInfo)
}
if m.IsVideo() {
return m.Bot.Caller.Client.WebWxGetVideo(m, m.Bot.storage.LoginInfo)
}
if m.IsMedia() {
return m.Bot.Caller.Client.WebWxGetMedia(m, m.Bot.storage.LoginInfo)
}
return nil, errors.New("unsupported type")
if !m.HasFile() {
return nil, errors.New("invalid message type")
}
if m.IsPicture() {
return m.Bot.Caller.Client.WebWxGetMsgImg(m, m.Bot.storage.LoginInfo)
}
if m.IsVoice() {
return m.Bot.Caller.Client.WebWxGetVoice(m, m.Bot.storage.LoginInfo)
}
if m.IsVideo() {
return m.Bot.Caller.Client.WebWxGetVideo(m, m.Bot.storage.LoginInfo)
}
if m.IsMedia() {
return m.Bot.Caller.Client.WebWxGetMedia(m, m.Bot.storage.LoginInfo)
}
return nil, errors.New("unsupported type")
}
// 获取card类型
func (m *Message) Card() (*Card, error) {
if !m.IsCard() {
return nil, errors.New("card message required")
}
var card Card
content := XmlFormString(m.Content)
err := xml.Unmarshal([]byte(content), &card)
return &card, err
if !m.IsCard() {
return nil, errors.New("card message required")
}
var card Card
content := XmlFormString(m.Content)
err := xml.Unmarshal([]byte(content), &card)
return &card, err
}
// 往消息上下文中设置值
// goroutine safe
func (m *Message) Set(key string, value interface{}) {
m.mu.Lock()
defer m.mu.Unlock()
if m.item == nil {
m.item = make(map[string]interface{})
}
m.item[key] = value
m.mu.Lock()
defer m.mu.Unlock()
if m.item == nil {
m.item = make(map[string]interface{})
}
m.item[key] = value
}
// 从消息上下文中获取值
// goroutine safe
func (m *Message) Get(key string) (value interface{}, exist bool) {
m.mu.RLock()
defer m.mu.RUnlock()
value, exist = m.item[key]
return
m.mu.RLock()
defer m.mu.RUnlock()
value, exist = m.item[key]
return
}
// 消息初始化,根据不同的消息作出不同的处理
func (m *Message) init(bot *Bot) {
m.Bot = bot
if m.IsSendByGroup() {
data := strings.Split(m.Content, ":<br/>")
m.Content = strings.Join(data[1:], "")
m.senderInGroupUserName = data[0]
receiver, err := m.Receiver()
if err == nil {
displayName := receiver.DisplayName
if displayName == "" {
displayName = receiver.NickName
}
atFlag := "@" + displayName
index := len(atFlag) + 1 + 1
if strings.HasPrefix(m.Content, atFlag) && unicode.IsSpace(rune(m.Content[index])) {
m.IsAt = true
m.Content = m.Content[index+1:]
}
}
}
m.Bot = bot
if m.IsSendByGroup() {
data := strings.Split(m.Content, ":<br/>")
m.Content = strings.Join(data[1:], "")
m.senderInGroupUserName = data[0]
receiver, err := m.Receiver()
if err == nil {
displayName := receiver.DisplayName
if displayName == "" {
displayName = receiver.NickName
}
atFlag := "@" + displayName
index := len(atFlag) + 1 + 1
if strings.HasPrefix(m.Content, atFlag) && unicode.IsSpace(rune(m.Content[index])) {
m.IsAt = true
m.Content = m.Content[index+1:]
}
}
}
}
//func (m *Message) Agree() error {
@ -276,76 +276,76 @@ func (m *Message) init(bot *Bot) {
// 发送消息的结构体
type SendMessage struct {
Type int
Content string
FromUserName string
ToUserName string
LocalID int64
ClientMsgId int64
MediaId string
Type int
Content string
FromUserName string
ToUserName string
LocalID int64
ClientMsgId int64
MediaId string
}
// SendMessage的构造方法
func NewSendMessage(msgType int, content, fromUserName, toUserName, mediaId string) *SendMessage {
return &SendMessage{
Type: msgType,
Content: content,
FromUserName: fromUserName,
ToUserName: toUserName,
LocalID: time.Now().Unix() * 1e4,
ClientMsgId: time.Now().Unix() * 1e4,
MediaId: mediaId,
}
return &SendMessage{
Type: msgType,
Content: content,
FromUserName: fromUserName,
ToUserName: toUserName,
LocalID: time.Now().Unix() * 1e4,
ClientMsgId: time.Now().Unix() * 1e4,
MediaId: mediaId,
}
}
// 文本消息的构造方法
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 {
return NewSendMessage(msgType, "", fromUserName, toUserName, mediaId)
return NewSendMessage(msgType, "", fromUserName, toUserName, mediaId)
}
// 一些特殊类型的消息会携带该结构体信息
type RecommendInfo struct {
Alias string
AttrStatus int64
City string
Content string
NickName string
OpCode int
Province string
QQNum int64
Scene int
Sex int
Signature string
Ticket string
UserName string
VerifyFlag int
Alias string
AttrStatus int64
City string
Content string
NickName string
OpCode int
Province string
QQNum int64
Scene int
Sex int
Signature string
Ticket string
UserName string
VerifyFlag int
}
// 名片消息内容
type Card struct {
XMLName xml.Name `xml:"msg"`
BigHeadImgUrl string `xml:"bigheadimgurl,attr"`
SmallHeadImgUrl string `xml:"smallheadimgurl,attr"`
UserName string `xml:"username,attr"`
NickName string `xml:"nickname,attr"`
ShortPy string `xml:"shortpy,attr"`
Alias string `xml:"alias,attr"` // Note: 这个是名片用户的微信号
ImageStatus int `xml:"imagestatus,attr"`
Scene int `xml:"scene,attr"`
Province string `xml:"province,attr"`
City string `xml:"city,attr"`
Sign string `xml:"sign,attr"`
Sex int `xml:"sex,attr"`
Certflag int `xml:"certflag,attr"`
Certinfo string `xml:"certinfo,attr"`
BrandIconUrl string `xml:"brandIconUrl,attr"`
BrandHomeUr string `xml:"brandHomeUr,attr"`
BrandSubscriptConfigUrl string `xml:"brandSubscriptConfigUrl,attr"`
BrandFlags string `xml:"brandFlags,attr"`
RegionCode string `xml:"regionCode,attr"`
XMLName xml.Name `xml:"msg"`
BigHeadImgUrl string `xml:"bigheadimgurl,attr"`
SmallHeadImgUrl string `xml:"smallheadimgurl,attr"`
UserName string `xml:"username,attr"`
NickName string `xml:"nickname,attr"`
ShortPy string `xml:"shortpy,attr"`
Alias string `xml:"alias,attr"` // Note: 这个是名片用户的微信号
ImageStatus int `xml:"imagestatus,attr"`
Scene int `xml:"scene,attr"`
Province string `xml:"province,attr"`
City string `xml:"city,attr"`
Sign string `xml:"sign,attr"`
Sex int `xml:"sex,attr"`
Certflag int `xml:"certflag,attr"`
Certinfo string `xml:"certinfo,attr"`
BrandIconUrl string `xml:"brandIconUrl,attr"`
BrandHomeUr string `xml:"brandHomeUr,attr"`
BrandSubscriptConfigUrl string `xml:"brandSubscriptConfigUrl,attr"`
BrandFlags string `xml:"brandFlags,attr"`
RegionCode string `xml:"regionCode,attr"`
}