diff --git a/cmd/sojuboy/main.go b/cmd/sojuboy/main.go index 2bda330..66eb654 100644 --- a/cmd/sojuboy/main.go +++ b/cmd/sojuboy/main.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "os/signal" + "strings" "sync" "sync/atomic" "syscall" @@ -136,8 +137,15 @@ func main() { } alert := func(channel, author, text, msgid string, at time.Time) { logger.Debug("ingest", "ts", at.UTC(), "channel", channel, "author", author, "body", text, "msgid", msgid) + // Determine storage channel: for DMs to me, store under sender nick + storeChan := channel + isChannel := strings.HasPrefix(channel, "#") || strings.HasPrefix(channel, "&") + isDMToMe := !isChannel && strings.EqualFold(channel, cfg.Nick) + if isDMToMe { + storeChan = author + } if err := st.InsertMessage(ctx, store.Message{ - Channel: channel, + Channel: storeChan, Author: author, Body: text, Time: at.UTC(), @@ -147,26 +155,52 @@ func main() { } else { atomic.AddInt64(&metrics.MessagesIngested, 1) } - if mentionChecker(text) && allowedChannel(channel) { + // Notify on direct messages to me (bypass channel allow/deny; respect quiet hours) + if isDMToMe && !strings.EqualFold(author, cfg.Nick) { if nt != nil { if !cfg.NotifyBackfill && time.Since(at) > 5*time.Minute { - logger.Debug("mention suppressed", "reason", "backfill", "channel", channel, "author", author) + logger.Debug("dm suppressed", "reason", "backfill", "from", author) return } if config.WithinQuietHours(at, cfg.QuietHours) && !isUrgent(text) { - logger.Debug("mention suppressed", "reason", "quiet_hours", "channel", channel, "author", author) + logger.Debug("dm suppressed", "reason", "quiet_hours", "from", author) return } - key := channel + "|" + cfg.Nick + key := "dm|" + author if !rl.allow(key, cfg.MentionMinInterval) { - logger.Debug("mention suppressed", "reason", "rate_limit", "channel", channel, "author", author) + logger.Debug("dm suppressed", "reason", "rate_limit", "from", author) return } - if err := nt.Notify(ctx, "IRC mention in "+channel, author+": "+text); err != nil { + if err := nt.Notify(ctx, "Direct message from "+author, text); err != nil { + logger.Error("dm notify", "err", err) + } else { + atomic.AddInt64(&metrics.NotificationsSent, 1) + logger.Debug("dm notified", "from", author) + } + } + return + } + // Mentions in channels + if mentionChecker(text) && allowedChannel(storeChan) { + if nt != nil { + if !cfg.NotifyBackfill && time.Since(at) > 5*time.Minute { + logger.Debug("mention suppressed", "reason", "backfill", "channel", storeChan, "author", author) + return + } + if config.WithinQuietHours(at, cfg.QuietHours) && !isUrgent(text) { + logger.Debug("mention suppressed", "reason", "quiet_hours", "channel", storeChan, "author", author) + return + } + key := storeChan + "|" + cfg.Nick + if !rl.allow(key, cfg.MentionMinInterval) { + logger.Debug("mention suppressed", "reason", "rate_limit", "channel", storeChan, "author", author) + return + } + if err := nt.Notify(ctx, "IRC mention in "+storeChan, author+": "+text); err != nil { logger.Error("mention notify", "err", err) } else { atomic.AddInt64(&metrics.NotificationsSent, 1) - logger.Debug("mention notified", "channel", channel, "author", author) + logger.Debug("mention notified", "channel", storeChan, "author", author) } } }