23f5e782f8
Unified inline menus, user callbacks for all users, Home button to exit admin panel. Co-authored-by: Cursor <cursoragent@cursor.com>
140 lines
4.1 KiB
Go
140 lines
4.1 KiB
Go
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)
|
|
}
|
|
|