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 }