package bot import ( "context" "fmt" "log" "time" "telegramvpn/internal/db" "telegramvpn/internal/remnawave" tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5" ) func (h *Handler) handleUserConfig(chatID, telegramID int64) { ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second) defer cancel() days := h.cfg.TrialUserDays if days <= 0 { days = 1 } existing, err := h.database.GetVPNByTelegramID(ctx, telegramID) if err != nil { h.sendText(chatID, "Ошибка базы данных. Попробуйте позже.") return } if existing != nil && existing.ExpireAt != nil && existing.ExpireAt.After(time.Now()) { link := h.resolveSubscriptionLink(ctx, existing.RemnawaveUsername, telegramID) h.sendConfigMessage(chatID, telegramID, days, existing.RemnawaveUsername, *existing.ExpireAt, link) return } panelUser, err := h.panel.GetUserByTelegramID(ctx, telegramID) if err == nil && panelUser != nil && panelUser.ExpireAt.After(time.Now()) { link := panelUser.SubscriptionURL if link == "" { link = h.subscriptionLink(panelUser.ShortUUID) } _ = h.saveVPNFromPanel(ctx, telegramID, panelUser) h.sendConfigMessage(chatID, telegramID, days, panelUser.Username, panelUser.ExpireAt, link) return } username := fmt.Sprintf("u%d", telegramID) var extPtr *string if h.cfg.DefaultExternalSquadUUID != "" { e := h.cfg.DefaultExternalSquadUUID extPtr = &e } ints := h.cfg.DefaultInternalSquadUUIDs tgID := telegramID u, err := h.panel.CreateUser(ctx, remnawave.CreateUserInput{ Username: username, ExpireAt: db.DefaultExpireAt(days), TelegramID: &tgID, ExternalSquadUUID: extPtr, ActiveInternalSquads: ints, Description: fmt.Sprintf("trial %d day via tgvpn bot", days), }) if err != nil { h.sendText(chatID, "Не удалось создать доступ: "+err.Error()+"\n\nПопробуйте позже или напишите администратору.") return } if err := h.saveVPNFromPanel(ctx, telegramID, u); err != nil { log.Printf("save vpn user: %v", err) } link := u.SubscriptionURL if link == "" { link = h.subscriptionLink(u.ShortUUID) } h.sendConfigMessage(chatID, telegramID, days, u.Username, u.ExpireAt, link) } func (h *Handler) saveVPNFromPanel(ctx context.Context, telegramID int64, u *remnawave.PanelUser) error { if u == nil { return nil } var ext *string if h.cfg.DefaultExternalSquadUUID != "" { e := h.cfg.DefaultExternalSquadUUID ext = &e } return h.database.SaveVPNUser(ctx, db.VPNUser{ TelegramID: &telegramID, RemnawaveUUID: u.UUID, RemnawaveUsername: u.Username, ExternalSquadUUID: ext, InternalSquadUUIDs: h.cfg.DefaultInternalSquadUUIDs, ExpireAt: &u.ExpireAt, }) } func (h *Handler) resolveSubscriptionLink(ctx context.Context, username string, telegramID int64) string { if u, err := h.panel.GetUserByUsername(ctx, username); err == nil && u != nil { if u.SubscriptionURL != "" { return u.SubscriptionURL } return h.subscriptionLink(u.ShortUUID) } if u, err := h.panel.GetUserByTelegramID(ctx, telegramID); err == nil && u != nil { if u.SubscriptionURL != "" { return u.SubscriptionURL } return h.subscriptionLink(u.ShortUUID) } return "" } func (h *Handler) subscriptionLink(shortUUID string) string { if shortUUID != "" && h.cfg.RemnawaveSubscription != "" { return h.cfg.RemnawaveSubscription + "/" + shortUUID } return "" } func (h *Handler) sendConfigMessage(chatID, telegramID int64, days int, username string, expireAt time.Time, link string) { text := fmt.Sprintf( "✅ VPN готов\n\n"+ "⏱ Срок: %d дн. (до %s)\n"+ "👤 Логин: %s\n", days, expireAt.Local().Format("02.01.2006 15:04"), username, ) if link != "" { text += "\n🔗 Ссылка подписки — кнопка ниже или:\n" + link } else { text += "\n\n⚠️ Ссылка не настроена — REMNAWAVE_SUBSCRIPTION_URL в .env" } msg := tgbotapi.NewMessage(chatID, text) msg.ReplyMarkup = configResultKeyboard(h.cfg, telegramID, h.admin, link) h.send(msg) }