mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
fix(matrix): improve group mention detection
This commit is contained in:
@@ -3,7 +3,9 @@ package matrix
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"html"
|
||||
"mime"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@@ -29,6 +31,8 @@ const (
|
||||
roomKindCacheTTL = 5 * time.Minute
|
||||
)
|
||||
|
||||
var matrixMentionHrefRegexp = regexp.MustCompile(`(?i)<a[^>]+href=["']([^"']+)["']`)
|
||||
|
||||
type roomKindCacheEntry struct {
|
||||
isGroup bool
|
||||
expiresAt time.Time
|
||||
@@ -469,6 +473,12 @@ func (c *MatrixChannel) handleMessageEvent(ctx context.Context, evt *event.Event
|
||||
}
|
||||
respond, cleaned := c.ShouldRespondInGroup(isMentioned, content)
|
||||
if !respond {
|
||||
logger.DebugCF("matrix", "Ignoring group message by trigger rules", map[string]any{
|
||||
"room_id": roomID,
|
||||
"is_mentioned": isMentioned,
|
||||
"mention_only": c.config.GroupTrigger.MentionOnly,
|
||||
"prefixes": c.config.GroupTrigger.Prefixes,
|
||||
})
|
||||
return
|
||||
}
|
||||
content = cleaned
|
||||
@@ -807,7 +817,10 @@ func (c *MatrixChannel) isBotMentioned(msgEvt *event.MessageEventContent) bool {
|
||||
}
|
||||
|
||||
userID := c.client.UserID.String()
|
||||
if userID != "" && (strings.Contains(msgEvt.Body, userID) || strings.Contains(msgEvt.FormattedBody, userID)) {
|
||||
if userID != "" && strings.Contains(msgEvt.Body, userID) {
|
||||
return true
|
||||
}
|
||||
if mentionsUserInFormattedBody(msgEvt.FormattedBody, c.client.UserID) {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -820,6 +833,63 @@ func (c *MatrixChannel) isBotMentioned(msgEvt *event.MessageEventContent) bool {
|
||||
return re.MatchString(msgEvt.Body) || re.MatchString(msgEvt.FormattedBody)
|
||||
}
|
||||
|
||||
func mentionsUserInFormattedBody(formattedBody string, userID id.UserID) bool {
|
||||
target := strings.ToLower(strings.TrimSpace(userID.String()))
|
||||
if target == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
formattedBody = strings.TrimSpace(formattedBody)
|
||||
if formattedBody == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(formattedBody), target) {
|
||||
return true
|
||||
}
|
||||
|
||||
matches := matrixMentionHrefRegexp.FindAllStringSubmatch(formattedBody, -1)
|
||||
for _, match := range matches {
|
||||
if len(match) < 2 {
|
||||
continue
|
||||
}
|
||||
decoded := decodeMatrixMentionHref(match[1])
|
||||
if strings.Contains(strings.ToLower(decoded), target) {
|
||||
return true
|
||||
}
|
||||
|
||||
u, err := url.Parse(decoded)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.Contains(strings.ToLower(u.Path), target) || strings.Contains(strings.ToLower(u.Fragment), target) {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(strings.ToLower(decodeMatrixMentionHref(u.Fragment)), target) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func decodeMatrixMentionHref(v string) string {
|
||||
decoded := html.UnescapeString(strings.TrimSpace(v))
|
||||
if decoded == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
next, err := url.QueryUnescape(decoded)
|
||||
if err != nil || next == decoded {
|
||||
break
|
||||
}
|
||||
decoded = next
|
||||
}
|
||||
return decoded
|
||||
}
|
||||
|
||||
func (c *MatrixChannel) typingLoop(ctx context.Context, roomID id.RoomID, session *typingSession) {
|
||||
sendTyping := func() {
|
||||
_, err := c.client.UserTyping(ctx, roomID, true, typingServerTTL)
|
||||
|
||||
@@ -91,6 +91,22 @@ func TestIsBotMentioned(t *testing.T) {
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "formatted mention href matrix.to plain",
|
||||
msg: event.MessageEventContent{
|
||||
Body: "hello bot",
|
||||
FormattedBody: `<a href="https://matrix.to/#/@picoclaw:matrix.org">PicoClaw</a> hello`,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "formatted mention href matrix.to encoded",
|
||||
msg: event.MessageEventContent{
|
||||
Body: "hello bot",
|
||||
FormattedBody: `<a href="https://matrix.to/#/%40picoclaw%3Amatrix.org">PicoClaw</a> hello`,
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
Reference in New Issue
Block a user