package bot import ( "context" "database/sql" "encoding/json" "fmt" "strings" "time" ) // ConfessConfig: "channel_id" is where anonymous confessions land. type ConfessConfig struct { ChannelID string `json:"channel_id"` } // parseConfessContent returns the confession body if content is a /confess command. func parseConfessContent(content string) (string, bool) { trimmed := strings.TrimSpace(content) if len(trimmed) < 8 || !strings.EqualFold(trimmed[:8], "/confess") { return "", false } // Require word boundary after the command (space, end, or more text after optional space). rest := strings.TrimSpace(trimmed[8:]) if rest == "" { return "", false } return rest, true } // ConfessBot is a safety-net poller for any /confess that slipped past intercept. // Primary path is Runner.TryConfess at message create (no original ever stored). func ConfessBot(ctx context.Context, db *sql.DB, raw json.RawMessage, send SendMessageFunc) { // Polling path is intentionally inert for normal operation when intercept works. // Keep a lightweight no-op loop so the runner lifecycle stays consistent. // Real cleanup of any leaked /confess rows is handled if deleteMsg is wired later. _ = db _ = raw _ = send ticker := time.NewTicker(30 * time.Second) defer ticker.Stop() for { select { case <-ctx.Done(): return case <-ticker.C: // no-op: intercept handles live confessions } } } // confessFormat is shared with TryConfess. func confessFormat(text string) string { return fmt.Sprintf("🕵️ **anonymous confession:** %s", text) }