pushrules: fix word boundary matching and case sensitivity
Some checks failed
Go / Lint (latest) (push) Has been cancelled
Go / Build (old, libolm) (push) Has been cancelled
Go / Build (latest, libolm) (push) Has been cancelled
Go / Build (old, goolm) (push) Has been cancelled
Go / Build (latest, goolm) (push) Has been cancelled

This commit is contained in:
Tulir Asokan 2025-02-08 16:17:54 +02:00
commit 29319ccfd5
4 changed files with 46 additions and 8 deletions

2
go.mod
View file

@ -18,7 +18,7 @@ require (
github.com/tidwall/gjson v1.18.0
github.com/tidwall/sjson v1.2.5
github.com/yuin/goldmark v1.7.8
go.mau.fi/util v0.8.5-0.20250203220331-1c0d19ea6003
go.mau.fi/util v0.8.5-0.20250208141401-fde0c0c733f1
go.mau.fi/zeroconfig v0.1.3
golang.org/x/crypto v0.32.0
golang.org/x/exp v0.0.0-20250128182459-e0ece0dbea4c

4
go.sum
View file

@ -54,8 +54,8 @@ github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic=
github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
go.mau.fi/util v0.8.5-0.20250203220331-1c0d19ea6003 h1:ye5l+QpYW5CpGVMedb3EHlmflGMQsMtw8mC4K/U8hIw=
go.mau.fi/util v0.8.5-0.20250203220331-1c0d19ea6003/go.mod h1:MOfGTs1CBuK6ERTcSL4lb5YU7/ujz09eOPVEDckuazY=
go.mau.fi/util v0.8.5-0.20250208141401-fde0c0c733f1 h1:XQ47o9cbYOCtohOkxXIzIM3xnSsR/8lggdgLEZm8PHU=
go.mau.fi/util v0.8.5-0.20250208141401-fde0c0c733f1/go.mod h1:MOfGTs1CBuK6ERTcSL4lb5YU7/ujz09eOPVEDckuazY=
go.mau.fi/zeroconfig v0.1.3 h1:As9wYDKmktjmNZW5i1vn8zvJlmGKHeVxHVIBMXsm4kM=
go.mau.fi/zeroconfig v0.1.3/go.mod h1:NcSJkf180JT+1IId76PcMuLTNa1CzsFFZ0nBygIQM70=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=

View file

@ -8,7 +8,10 @@ package pushrules
import (
"encoding/gob"
"regexp"
"strings"
"go.mau.fi/util/exerrors"
"go.mau.fi/util/glob"
"maunium.net/go/mautrix/event"
@ -165,13 +168,20 @@ func (rule *PushRule) matchConditions(room Room, evt *event.Event) bool {
}
func (rule *PushRule) matchPattern(room Room, evt *event.Event) bool {
pattern := glob.CompileWithImplicitContains(rule.Pattern)
if pattern == nil {
return false
}
msg, ok := evt.Content.Raw["body"].(string)
if !ok {
return false
}
return pattern.Match(msg)
var buf strings.Builder
// As per https://spec.matrix.org/unstable/client-server-api/#push-rules, content rules are case-insensitive
// and must match whole words, so wrap the converted glob in (?i) and \b.
buf.WriteString(`(?i)\b`)
// strings.Builder will never return errors
exerrors.PanicIfNotNil(glob.ToRegexPattern(rule.Pattern, &buf))
buf.WriteString(`\b`)
pattern, err := regexp.Compile(buf.String())
if err != nil {
return false
}
return pattern.MatchString(msg)
}

View file

@ -186,6 +186,34 @@ func TestPushRule_Match_Content(t *testing.T) {
assert.True(t, rule.Match(blankTestRoom, evt))
}
func TestPushRule_Match_WordBoundary(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.ContentRule,
Enabled: true,
Pattern: "test",
}
evt := newFakeEvent(event.EventMessage, &event.MessageEventContent{
MsgType: event.MsgEmote,
Body: "is testing pushrules",
})
assert.False(t, rule.Match(blankTestRoom, evt))
}
func TestPushRule_Match_CaseInsensitive(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.ContentRule,
Enabled: true,
Pattern: "test",
}
evt := newFakeEvent(event.EventMessage, &event.MessageEventContent{
MsgType: event.MsgEmote,
Body: "is TeSt-InG pushrules",
})
assert.True(t, rule.Match(blankTestRoom, evt))
}
func TestPushRule_Match_Content_Fail(t *testing.T) {
rule := &pushrules.PushRule{
Type: pushrules.ContentRule,