When a user reacts ❓ on one of Pete's posts, fetch the article body,
ask Ollama for a 3-bullet summary, and post it as a threaded reply
rooted at the original story event. Per-process cooldown of 5min per
story keeps repeated reactions from re-summarizing.
- ingestion.FetchArticleBody: visible <p> text capped at 8000 chars
- classifier.OllamaClient.GenerateText: non-JSON variant
- storage.GetStoryByGUID: full row lookup
- matrix.PostThreadedReply: m.thread + m.in_reply_to fallback
- poster.SetReactionCallback: optional hook fired after recording
- New package: internal/explainer
54 lines
1.4 KiB
Go
54 lines
1.4 KiB
Go
package poster
|
|
|
|
import (
|
|
"log/slog"
|
|
"sync"
|
|
"time"
|
|
|
|
"pete/internal/storage"
|
|
|
|
"maunium.net/go/mautrix/id"
|
|
)
|
|
|
|
// ReactionCallback is an optional hook fired after a reaction is recorded.
|
|
// Used to wire reaction-driven features (e.g. ❓ → summary) without coupling
|
|
// poster to those packages.
|
|
type ReactionCallback func(roomID id.RoomID, targetEventID id.EventID, guid, channel, emoji string)
|
|
|
|
var (
|
|
reactionCallbackMu sync.RWMutex
|
|
reactionCallback ReactionCallback
|
|
)
|
|
|
|
// SetReactionCallback installs a hook called after every recorded reaction.
|
|
// Pass nil to clear. Safe to call before or after the matrix client starts.
|
|
func SetReactionCallback(fn ReactionCallback) {
|
|
reactionCallbackMu.Lock()
|
|
reactionCallback = fn
|
|
reactionCallbackMu.Unlock()
|
|
}
|
|
|
|
// HandleReaction processes a reaction event by mapping it back to the story GUID.
|
|
func HandleReaction(roomID id.RoomID, eventID id.EventID, targetEventID id.EventID, emoji string, userID id.UserID) {
|
|
guid, channel, found := storage.LookupPostGUID(string(targetEventID))
|
|
if !found {
|
|
// Reaction on a message we didn't post — ignore
|
|
return
|
|
}
|
|
|
|
storage.InsertReaction(guid, channel, string(eventID), emoji, string(userID), time.Now().Unix())
|
|
slog.Debug("reaction recorded",
|
|
"guid", guid,
|
|
"channel", channel,
|
|
"emoji", emoji,
|
|
"user", userID,
|
|
)
|
|
|
|
reactionCallbackMu.RLock()
|
|
cb := reactionCallback
|
|
reactionCallbackMu.RUnlock()
|
|
if cb != nil {
|
|
go cb(roomID, targetEventID, guid, channel, emoji)
|
|
}
|
|
}
|