From dd324c03177e12f83d9208c4e26b3cac3f19826b Mon Sep 17 00:00:00 2001 From: prosolis <5590409+prosolis@users.noreply.github.com> Date: Fri, 22 May 2026 18:29:32 -0700 Subject: [PATCH] Accept more question-mark reactions as explain triggers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now triggers on ❓ ❔ ⁉ ⁉️ 🤔 ? ? — covers the obvious red/white/thinking variants, the exclamation-question combo (with and without VS16), and plain ascii / fullwidth question marks for keyboard users. --- internal/explainer/explainer.go | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) 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) {