white-zone-bot/bot/handlers/start_handler.go
2025-05-24 09:16:47 +06:00

188 lines
4.8 KiB
Go
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handlers
import (
"errors"
"fmt"
"log/slog"
"strconv"
"strings"
"github.com/theorift/white-zone-bot/bot"
"github.com/theorift/white-zone-bot/repositories"
"github.com/theorift/white-zone-bot/services"
"gopkg.in/telebot.v4"
)
const (
genericErrorMsg = "⚠️ Oops! Something went wrong. Please try again later."
welcomeMessage = "Welcome to VIP Group Portal!\n\nExplore using the buttons below:"
welcomeBackMessage = "Welcome back! Your options:"
inviteButtonText = "🔗 Get Invite Link"
pointsButtonText = "💰 Check Points"
)
func HandleStart(b bot.Bot, userRepo repositories.UserRepository) {
instance := b.GetInstance()
instance.Handle("/start", func(ctx telebot.Context) error {
sender := ctx.Sender()
msg := ctx.Message()
slog.Info("User started bot",
"userID", sender.ID,
"payload", msg.Payload,
"chatID", msg.Chat.ID,
)
referrerID, parseErr := parseReferrerID(msg.Payload)
if parseErr != nil {
sendParseError(ctx, sender.ID)
return nil
}
userService := services.NewUserService(sender.ID, userRepo)
err := userService.ProcessStart(referrerID)
if err != nil {
return handleStartError(ctx, err, sender.ID, referrerID)
}
slog.Info("Start processed successfully",
"userID", sender.ID,
"referrerID", referrerID)
return sendWelcomeMessage(ctx, false)
})
}
func parseReferrerID(payload string) (int64, error) {
trimmed := strings.TrimSpace(payload)
if trimmed == "" {
return 0, nil
}
id, err := strconv.ParseInt(trimmed, 10, 64)
if err != nil {
return 0, fmt.Errorf("invalid referrer format: %w", err)
}
return id, nil
}
func sendParseError(ctx telebot.Context, userID int64) {
msg := "❌ Invalid referral code format! Please use numeric codes."
if err := ctx.Send(msg); err != nil {
slog.Error("Failed to send parse error",
"userID", userID,
"error", err)
}
}
func handleStartError(ctx telebot.Context, err error, userID, referrerID int64) error {
var userMsg string
switch {
case errors.Is(err, services.ErrSelfReferral):
userMsg = "❌ Self-referrals are not allowed!"
slog.Warn("Self-referral blocked",
"userID", userID,
"referrerID", referrerID)
case errors.Is(err, services.ErrInvalidReferrer):
userMsg = "❌ Invalid referral code! Please check and try again."
slog.Warn("Invalid referral attempt",
"userID", userID,
"referrerID", referrerID)
case errors.Is(err, services.ErrAlreadyReferred):
userMsg = " You already have an active referral!"
slog.Info("Duplicate referral ignored",
"userID", userID,
"referrerID", referrerID)
case errors.Is(err, services.ErrLateReferralAttempt):
userMsg = " Referrals must happen during first use!"
slog.Info("Late attempt referral blocked",
"userID", userID,
"referrerID", referrerID)
case errors.Is(err, services.ErrCircularReference):
userMsg = "❌ Circular referrals are not allowed!"
slog.Info("Circular referral blocked",
"userID", userID,
"referrerID", referrerID)
case errors.Is(err, services.ErrDuplicateUser):
slog.Info("Duplicate user creation attempt", "userID", userID)
if sendErr := sendWelcomeMessage(ctx, true); sendErr != nil {
// Attempt fallback message
if backupErr := ctx.Send("Welcome back! Please use the menu buttons."); backupErr != nil {
slog.Error("Failed to send welcome messages",
"userID", userID,
"welcomeError", sendErr,
"fallbackError", backupErr)
}
}
return nil
case errors.Is(err, services.ErrReferralChainTooLong):
userMsg = "❌ Invalid referral chain detected!"
slog.Warn("Long referral chain blocked",
"userID", userID,
"referrerID", referrerID)
default:
userMsg = genericErrorMsg
slog.Error("Start handler failed",
"userID", userID,
"referrerID", referrerID,
"error", err)
}
if sendErr := ctx.Send(userMsg); sendErr != nil {
slog.Error("Failed to send error message",
"userID", userID,
"originalError", err,
"sendError", sendErr)
}
return nil
}
func sendWelcomeMessage(ctx telebot.Context, isReturning bool) error {
msg := welcomeMessage
if isReturning {
msg = welcomeBackMessage
}
markup := &telebot.ReplyMarkup{
InlineKeyboard: [][]telebot.InlineButton{
{
{
Text: inviteButtonText,
InlineQueryChosenChat: &telebot.SwitchInlineQuery{
Query: "invite",
AllowUserChats: true,
AllowBotChats: false,
AllowGroupChats: true,
AllowChannelChats: true,
},
},
},
{
{
Unique: "check_points",
Text: pointsButtonText,
},
},
},
}
err := ctx.Send(msg, markup)
if err != nil {
slog.Error("Failed to send welcome message",
"userID", ctx.Sender().ID,
"error", err)
return err
}
return nil
}