Add /config trial VPN generation for users (1 day default)

Users get Remnawave subscription via /config or inline button; TRIAL_USER_DAYS and panel lookup by Telegram ID.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
tgvpn
2026-05-21 01:29:55 +03:00
parent 30866bb244
commit cbb2133991
9 changed files with 278 additions and 24 deletions
+49 -13
View File
@@ -35,17 +35,18 @@ func NewHandler(cfg *config.Config, api *tgbotapi.BotAPI, database *db.DB) *Hand
}
func (h *Handler) RegisterCommands() {
commands := []tgbotapi.BotCommand{
public := []tgbotapi.BotCommand{
{Command: "start", Description: "Начать"},
{Command: "admin", Description: "Админ-меню Remnawave (панель 1)"},
{Command: "config", Description: "Получить VPN-конфиг"},
}
if _, err := h.api.Request(tgbotapi.NewSetMyCommands(public...)); err != nil {
log.Printf("команды (все пользователи): %v", err)
}
admin := append(public, tgbotapi.BotCommand{Command: "admin", Description: "Админ-меню"})
scope := tgbotapi.BotCommandScope{Type: "chat", ChatID: h.admin}
cfg := tgbotapi.SetMyCommandsConfig{
Commands: commands,
Scope: &scope,
}
if _, err := h.api.Request(cfg); err != nil {
log.Printf("не удалось зарегистрировать команды для админа: %v", err)
if _, err := h.api.Request(tgbotapi.SetMyCommandsConfig{Commands: admin, Scope: &scope}); err != nil {
log.Printf("команды (админ): %v", err)
}
}
@@ -65,6 +66,8 @@ func (h *Handler) HandleUpdate(update tgbotapi.Update) {
switch {
case text == "/start":
h.sendStart(chatID, userID, update.Message.From.FirstName, update.Message.From.UserName)
case text == "/config", text == "/getconfig":
h.handleUserConfig(chatID, userID)
case strings.HasPrefix(text, "/admin"):
h.handleAdminCommand(chatID, userID, text)
case strings.HasPrefix(text, "/"):
@@ -73,6 +76,10 @@ func (h *Handler) HandleUpdate(update tgbotapi.Update) {
if h.isAdmin(userID) && h.handleWizardMessage(chatID, userID, text) {
return
}
if text == "📲 Получить конфиг (1 день)" || strings.HasPrefix(text, "📲 Получить конфиг") {
h.handleUserConfig(chatID, userID)
return
}
if h.isAdmin(userID) {
switch text {
case "📋 Конфиг панели":
@@ -131,6 +138,11 @@ func (h *Handler) handleCallback(cq *tgbotapi.CallbackQuery) {
return
}
if cq.Data == "user:config" {
h.handleUserConfig(cq.Message.Chat.ID, cq.From.ID)
return
}
if h.handleWizardCallback(cq) {
return
}
@@ -163,17 +175,41 @@ func (h *Handler) sendStart(chatID, userID int64, firstName, tgUsername string)
if name == "" {
name = "друг"
}
text := fmt.Sprintf("Привет, %s!\n\nЯ VPN-бот на базе панели Remnawave.", name)
days := h.cfg.TrialUserDays
if days <= 0 {
days = 1
}
text := fmt.Sprintf("Привет, %s!\n\nЯ VPN-бот. Нажмите кнопку ниже — получите конфиг на %d дн.\nИли команда /config", name, days)
if h.isAdmin(userID) {
text += "\n\n/admin — админ-меню\n/admin user — создать пользователя\n/admin squads — сквады"
text += "\n\n/admin — админ-меню"
}
msg := tgbotapi.NewMessage(chatID, text)
if h.isAdmin(userID) {
msg.ReplyMarkup = adminReplyKeyboard()
}
msg.ReplyMarkup = h.startInlineKeyboard(userID)
h.send(msg)
}
func (h *Handler) startInlineKeyboard(userID int64) tgbotapi.InlineKeyboardMarkup {
rows := [][]tgbotapi.InlineKeyboardButton{
tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData(h.userConfigButtonLabel(), "user:config"),
),
}
if h.isAdmin(userID) {
rows = append(rows, tgbotapi.NewInlineKeyboardRow(
tgbotapi.NewInlineKeyboardButtonData("🛠 Админ-меню", "admin:menu"),
))
}
return tgbotapi.NewInlineKeyboardMarkup(rows...)
}
func (h *Handler) userConfigButtonLabel() string {
days := h.cfg.TrialUserDays
if days <= 0 {
days = 1
}
return fmt.Sprintf("📲 Получить конфиг (%d дн.)", days)
}
func (h *Handler) sendAdminMenu(chatID int64) {
text := fmt.Sprintf(
"🛠 *Админ-меню* — %s\n\n"+