diff --git a/internal/explainer/explainer.go b/internal/explainer/explainer.go index 3a1ecb7..bc70da0 100644 --- a/internal/explainer/explainer.go +++ b/internal/explainer/explainer.go @@ -19,9 +19,23 @@ import ( "maunium.net/go/mautrix/id" ) -// QuestionEmoji is the reaction key that triggers a summary. Matrix delivers -// the reaction key verbatim — Element sends "❓" (U+2753). -const QuestionEmoji = "❓" +// questionReactions is the set of reaction keys that trigger a summary. +// Matrix delivers the key verbatim; we accept several question-y glyphs plus +// plain "?" so users don't have to hunt for the exact red question mark. +var questionReactions = map[string]bool{ + "❓": true, // U+2753 red question mark + "❔": true, // U+2754 white question mark + "⁉": true, // U+2049 exclamation question mark + "⁉️": true, // U+2049 + VS16 (emoji presentation) + "🤔": true, // U+1F914 thinking face + "?": true, // plain ascii + "?": true, // U+FF1F fullwidth question mark +} + +// IsQuestionReaction reports whether a reaction key should trigger a summary. +func IsQuestionReaction(key string) bool { + return questionReactions[key] +} // cooldown for repeat-explain on the same story (per process). const explainCooldown = 5 * time.Minute @@ -47,7 +61,7 @@ func New(mx *matrix.Client, ollama *classifier.OllamaClient) *Explainer { // Handle is the entry point used as a callback from poster.HandleReaction. // It runs synchronously — callers should invoke it in a goroutine. func (e *Explainer) Handle(roomID id.RoomID, rootEventID id.EventID, guid, channel, emoji string) { - if emoji != QuestionEmoji { + if !IsQuestionReaction(emoji) { return } if !e.acquire(guid) {