Skip to content

Commit

Permalink
add message observer (#457)
Browse files Browse the repository at this point in the history
  • Loading branch information
eatmoreapple authored Feb 23, 2024
1 parent bc69e21 commit 40991fb
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 72 deletions.
29 changes: 3 additions & 26 deletions bot.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
}
}
}
Expand Down
47 changes: 1 addition & 46 deletions message.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package openwechat

import (
"context"
"encoding/json"
"encoding/xml"
"errors"
"fmt"
"html"
"io"
"net/http"
"os"
Expand Down Expand Up @@ -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, ":<br/>")
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, `<br/>`, "\n", -1)
// 处理html转义字符
m.Content = html.UnescapeString(m.Content)
// 处理消息中的emoji表情
m.Content = FormatEmoji(m.Content)
defaultMessageObserver.OnMessageReceive(m)
}

// SendMessage 发送消息的结构体
Expand Down
139 changes: 139 additions & 0 deletions message_observer.go
Original file line number Diff line number Diff line change
@@ -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, ":<br/>")
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, `<br/>`, "\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{},
}
)

0 comments on commit 40991fb

Please sign in to comment.