From 40991fb1a5ee02bc8650713514a6e961f55e0b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=9A=E5=90=83=E7=82=B9=E8=8B=B9=E6=9E=9C?= Date: Fri, 23 Feb 2024 10:48:45 +0800 Subject: [PATCH] add message observer (#457) --- bot.go | 29 +-------- message.go | 47 +-------------- message_observer.go | 139 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 143 insertions(+), 72 deletions(-) create mode 100644 message_observer.go diff --git a/bot.go b/bot.go index cc19caf..d4d938a 100644 --- a/bot.go +++ b/bot.go @@ -192,27 +192,6 @@ func (b *Bot) webInit() error { return nil } -func (b *Bot) updateGroups(msg *Message) { - if msg.IsSendByGroup() { - if msg.FromUserName == msg.bot.self.User.UserName { - return - } - // 首先尝试从缓存里面查找, 如果没有找到则从服务器获取 - members, err := msg.bot.self.Members() - if err != nil { - return - } - _, exist := members.GetByUserName(msg.FromUserName) - if !exist { - // 找不到, 从服务器获取 - user := newUser(msg.Owner(), msg.FromUserName) - _ = user.Detail() - b.self.members = b.self.members.Append(user) - b.self.groups = b.self.members.Groups() - } - } -} - // 轮询请求 // 根据状态码判断是否有新的请求 func (b *Bot) syncCheck() error { @@ -253,17 +232,15 @@ func (b *Bot) syncCheck() error { // todo 将这个错误处理交给用户 _ = b.DumpHotReloadStorage() - if b.MessageHandler == nil { - continue - } for _, message := range messages { message.init(b) // 默认同步调用 // 如果异步调用则需自行处理 // 如配合 openwechat.MessageMatchDispatcher 使用 // NOTE: 请确保 MessageHandler 不会阻塞,否则会导致收不到后续的消息 - b.updateGroups(message) - b.MessageHandler(message) + if b.MessageHandler != nil { + b.MessageHandler(message) + } } } } diff --git a/message.go b/message.go index 8351f38..a00541f 100644 --- a/message.go +++ b/message.go @@ -2,11 +2,9 @@ package openwechat import ( "context" - "encoding/json" "encoding/xml" "errors" "fmt" - "html" "io" "net/http" "os" @@ -484,50 +482,7 @@ func (m *Message) Get(key string) (value interface{}, exist bool) { // 消息初始化,根据不同的消息作出不同的处理 func (m *Message) init(bot *Bot) { m.bot = bot - raw, _ := json.Marshal(m) - m.Raw = raw - m.RawContent = m.Content - // 如果是群消息 - if m.IsSendByGroup() { - if !m.IsSystem() { - // 将Username和正文分开 - if !m.IsSendBySelf() { - data := strings.Split(m.Content, ":
") - m.Content = strings.Join(data[1:], "") - m.senderUserNameInGroup = data[0] - if strings.Contains(m.Content, "@") { - sender, err := m.Sender() - if err == nil { - receiver := sender.MemberList.SearchByUserName(1, m.ToUserName) - if receiver != nil { - displayName := receiver.First().DisplayName - if displayName == "" { - displayName = receiver.First().NickName - } - var atFlag string - msgContent := FormatEmoji(m.Content) - atName := FormatEmoji(displayName) - if strings.Contains(msgContent, "\u2005") { - atFlag = "@" + atName + "\u2005" - } else { - atFlag = "@" + atName - } - m.isAt = strings.Contains(msgContent, atFlag) || strings.HasSuffix(msgContent, atFlag) - } - } - } - } else { - // 这块不严谨,但是只能这么干了 - m.isAt = strings.Contains(m.Content, "@") || strings.Contains(m.Content, "\u2005") - } - } - } - // 处理消息中的换行 - m.Content = strings.Replace(m.Content, `
`, "\n", -1) - // 处理html转义字符 - m.Content = html.UnescapeString(m.Content) - // 处理消息中的emoji表情 - m.Content = FormatEmoji(m.Content) + defaultMessageObserver.OnMessageReceive(m) } // SendMessage 发送消息的结构体 diff --git a/message_observer.go b/message_observer.go new file mode 100644 index 0000000..d8efd0a --- /dev/null +++ b/message_observer.go @@ -0,0 +1,139 @@ +package openwechat + +import ( + "encoding/json" + "html" + "strings" +) + +type MessageObserver interface { + OnMessageReceive(msg *Message) +} + +type MessageObserverGroup []MessageObserver + +func (g MessageObserverGroup) OnMessageReceive(msg *Message) { + for _, observer := range g { + observer.OnMessageReceive(msg) + } +} + +// 保存消息原始内容 +type messageRowContentObserver struct{} + +func (m *messageRowContentObserver) OnMessageReceive(msg *Message) { + raw, _ := json.Marshal(msg) + msg.Raw = raw + msg.RawContent = msg.Content +} + +// 保存发送者在群里的用户名 +type senderInGroupObserver struct{} + +func (s *senderInGroupObserver) OnMessageReceive(msg *Message) { + if !msg.IsSendByGroup() || msg.IsSystem() || msg.IsSendBySelf() { + return + } + data := strings.Split(msg.Content, ":
") + if len(data) < 2 { + return + } + msg.Content = strings.Join(data[1:], "") + msg.senderUserNameInGroup = data[0] +} + +// 检查消息是否被@了, 不是特别严谨 +type atMessageObserver struct{} + +func (g *atMessageObserver) OnMessageReceive(msg *Message) { + if !msg.IsSendByGroup() { + return + } + if msg.IsSystem() { + return + } + if msg.IsSendBySelf() { + // 这块不严谨,但是只能这么干了 + msg.isAt = strings.Contains(msg.Content, "@") || strings.Contains(msg.Content, "\u2005") + return + } + if strings.Contains(msg.Content, "@") { + sender, err := msg.Sender() + if err == nil { + receiver := sender.MemberList.SearchByUserName(1, msg.ToUserName) + if receiver != nil { + displayName := receiver.First().DisplayName + if displayName == "" { + displayName = receiver.First().NickName + } + var atFlag string + msgContent := FormatEmoji(msg.Content) + atName := FormatEmoji(displayName) + if strings.Contains(msgContent, "\u2005") { + atFlag = "@" + atName + "\u2005" + } else { + atFlag = "@" + atName + } + msg.isAt = strings.Contains(msgContent, atFlag) || strings.HasSuffix(msgContent, atFlag) + } + } + } +} + +// 处理消息中的换行符 +type wrapLineMessageObserver struct{} + +func (w *wrapLineMessageObserver) OnMessageReceive(msg *Message) { + msg.Content = strings.Replace(msg.Content, `
`, "\n", -1) +} + +// 处理消息中的html转义字符 +type unescapeHTMLMessageObserver struct{} + +func (u *unescapeHTMLMessageObserver) OnMessageReceive(msg *Message) { + msg.Content = html.UnescapeString(msg.Content) +} + +// 处理消息中的emoji表情 +type emojiMessageObserver struct{} + +func (e *emojiMessageObserver) OnMessageReceive(msg *Message) { + msg.Content = FormatEmoji(msg.Content) +} + +// 尝试获取群聊中的消息的发送者 +type tryToFindGroupMemberObserver struct{} + +func (t *tryToFindGroupMemberObserver) OnMessageReceive(msg *Message) { + if msg.IsSendByGroup() { + if msg.FromUserName == msg.Owner().UserName { + return + } + // 首先尝试从缓存里面查找, 如果没有找到则从服务器获取 + members, err := msg.Owner().Members() + if err != nil { + return + } + _, exist := members.GetByUserName(msg.FromUserName) + if !exist { + owner := msg.Owner() + // 找不到, 从服务器获取 + user := newUser(owner, msg.FromUserName) + _ = user.Detail() + owner.members = owner.members.Append(user) + owner.groups = owner.members.Groups() + } + } +} + +var ( + defaultMessageObserver MessageObserver = MessageObserverGroup{ + &messageRowContentObserver{}, + &senderInGroupObserver{}, + &atMessageObserver{}, + &wrapLineMessageObserver{}, + &unescapeHTMLMessageObserver{}, + &emojiMessageObserver{}, + &tryToFindGroupMemberObserver{}, + } +)