67 lines
2.1 KiB
Go
67 lines
2.1 KiB
Go
package main
|
|
|
|
import "strings"
|
|
|
|
// serverOf returns the homeserver part of an mxid (`@ai:vojo.chat` → `vojo.chat`).
|
|
func serverOf(mxid string) string {
|
|
if i := strings.IndexByte(mxid, ':'); i >= 0 {
|
|
return mxid[i+1:]
|
|
}
|
|
return ""
|
|
}
|
|
|
|
// localpartOf returns the localpart of an mxid (`@ai:vojo.chat` → `ai`).
|
|
func localpartOf(mxid string) string {
|
|
s := strings.TrimPrefix(mxid, "@")
|
|
if i := strings.IndexByte(s, ':'); i >= 0 {
|
|
return s[:i]
|
|
}
|
|
return s
|
|
}
|
|
|
|
// mentionsBot decides whether a message intentionally addresses the bot.
|
|
//
|
|
// Canonical path (MSC3952): the sender's client lists mentioned mxids in
|
|
// content["m.mentions"].user_ids. cinny ALWAYS writes this (RoomInput.tsx:491-492),
|
|
// and the presence of m.mentions suppresses legacy body-keyword push rules — so a
|
|
// plain-text "@ai" with no pill is intentionally NOT a trigger (F30).
|
|
//
|
|
// Fallbacks for non-cinny senders (Element/FluffyChat/bridges) that still pill:
|
|
// - a matrix.to / matrix: pill href targeting the bot mxid in formatted_body;
|
|
// - a reply whose parent we sent (resolved by the caller via replyParentIsBot).
|
|
//
|
|
// We deliberately do NOT scan body for the bot's localpart — that would re-create
|
|
// the unintentional-mention problem MSC3952 removed.
|
|
func mentionsBot(mc *MessageContent, botMXID string, replyParentIsBot bool) bool {
|
|
if mc.Mentions != nil {
|
|
for _, uid := range mc.Mentions.UserIDs { // UserIDs may be nil — range is safe (F29)
|
|
if uid == botMXID {
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
if replyParentIsBot {
|
|
return true
|
|
}
|
|
return pillTargetsBot(mc.FormattedBody, botMXID)
|
|
}
|
|
|
|
// pillTargetsBot looks for an <a href> mention pill addressing the bot in the
|
|
// HTML body. Matrix pills use either matrix.to/#/<mxid> or a matrix: URI.
|
|
func pillTargetsBot(formattedBody, botMXID string) bool {
|
|
if formattedBody == "" {
|
|
return false
|
|
}
|
|
// matrix.to URLs URL-encode the leading '@' as %40; cover both forms.
|
|
needles := []string{
|
|
"matrix.to/#/" + botMXID,
|
|
"matrix.to/#/%40" + strings.TrimPrefix(botMXID, "@"),
|
|
"matrix:u/" + strings.TrimPrefix(botMXID, "@"),
|
|
}
|
|
for _, n := range needles {
|
|
if strings.Contains(formattedBody, n) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|