From d671695f65b8ceaa208ef8c512b58f5c3f20e49b Mon Sep 17 00:00:00 2001 From: salvacybersec Date: Mon, 6 Apr 2026 17:32:18 +0300 Subject: [PATCH] feat(17-04): implement /subscribe and /unsubscribe handlers - handleSubscribe checks IsSubscribed, calls AddSubscriber with chat ID and username - handleUnsubscribe calls RemoveSubscriber, reports rows affected - Both use storage layer from Plan 17-02 - Removed stub implementations from bot.go Co-Authored-By: Claude Opus 4.6 (1M context) --- pkg/bot/bot.go | 8 +----- pkg/bot/subscribe.go | 59 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 pkg/bot/subscribe.go diff --git a/pkg/bot/bot.go b/pkg/bot/bot.go index b369276..2dd95c3 100644 --- a/pkg/bot/bot.go +++ b/pkg/bot/bot.go @@ -250,10 +250,4 @@ func (b *Bot) handleKey(ctx context.Context, msg *telego.Message) { _ = b.replyPlain(ctx, msg.Chat.ID, "Not yet implemented: /key") } -func (b *Bot) handleSubscribe(ctx context.Context, msg *telego.Message) { - _ = b.replyPlain(ctx, msg.Chat.ID, "Not yet implemented: /subscribe") -} - -func (b *Bot) handleUnsubscribe(ctx context.Context, msg *telego.Message) { - _ = b.replyPlain(ctx, msg.Chat.ID, "Not yet implemented: /unsubscribe") -} +// handleSubscribe and handleUnsubscribe are implemented in subscribe.go. diff --git a/pkg/bot/subscribe.go b/pkg/bot/subscribe.go new file mode 100644 index 0000000..69cc905 --- /dev/null +++ b/pkg/bot/subscribe.go @@ -0,0 +1,59 @@ +package bot + +import ( + "context" + "fmt" + "log" + + "github.com/mymmrac/telego" +) + +// handleSubscribe adds the requesting chat to the subscribers table. +// If the chat is already subscribed, it informs the user without error. +func (b *Bot) handleSubscribe(ctx context.Context, msg *telego.Message) { + chatID := msg.Chat.ID + var username string + if msg.From != nil { + username = msg.From.Username + } + + subscribed, err := b.cfg.DB.IsSubscribed(chatID) + if err != nil { + log.Printf("subscribe: checking subscription for chat %d: %v", chatID, err) + _ = b.replyPlain(ctx, chatID, "Error checking subscription status. Please try again.") + return + } + + if subscribed { + _ = b.replyPlain(ctx, chatID, "You are already subscribed to notifications.") + return + } + + if err := b.cfg.DB.AddSubscriber(chatID, username); err != nil { + log.Printf("subscribe: adding subscriber chat %d: %v", chatID, err) + _ = b.replyPlain(ctx, chatID, fmt.Sprintf("Error subscribing: %v", err)) + return + } + + _ = b.replyPlain(ctx, chatID, "Subscribed! You will receive notifications when new API keys are found.") +} + +// handleUnsubscribe removes the requesting chat from the subscribers table. +// If the chat was not subscribed, it informs the user without error. +func (b *Bot) handleUnsubscribe(ctx context.Context, msg *telego.Message) { + chatID := msg.Chat.ID + + rows, err := b.cfg.DB.RemoveSubscriber(chatID) + if err != nil { + log.Printf("unsubscribe: removing subscriber chat %d: %v", chatID, err) + _ = b.replyPlain(ctx, chatID, fmt.Sprintf("Error unsubscribing: %v", err)) + return + } + + if rows == 0 { + _ = b.replyPlain(ctx, chatID, "You are not subscribed.") + return + } + + _ = b.replyPlain(ctx, chatID, "Unsubscribed. You will no longer receive notifications.") +}