mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-07-11 07:06:06 +00:00
7d23a2c15b
cron: SkipIfStillRunning stops a slow 5s/10s job from overlapping itself and racing the shared xrayAPI (grpc conn leak) and the StatsLastValues map (fatal concurrent map write). memlimit: auto-detect a Go soft memory limit from XUI_MEMORY_LIMIT, the cgroup limit, or system RAM (about 90 percent); opt-in pprof via XUI_PPROF. tgbot: userStates now goes through a mutex-guarded store with TTL pruning (was raced by worker-pool and delayed-delete goroutines). check_client_ip: prefilter inbounds by settings LIKE limitIp instead of loading and JSON-parsing all of them every scan. minor: prune StatsLastValues, RateLimiter.lastSent, reportedRemoteTagConflict. docker-compose: document the memory knobs.
1517 lines
67 KiB
Go
1517 lines
67 KiB
Go
package tgbot
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"html"
|
|
"slices"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/mhsanaei/3x-ui/v3/internal/logger"
|
|
|
|
"github.com/mymmrac/telego"
|
|
th "github.com/mymmrac/telego/telegohandler"
|
|
tu "github.com/mymmrac/telego/telegoutil"
|
|
)
|
|
|
|
// OnReceive starts the message receiving loop for the Telegram bot.
|
|
func (t *Tgbot) OnReceive() {
|
|
params := telego.GetUpdatesParams{
|
|
Timeout: 20, // Reduced timeout to detect connection issues faster
|
|
}
|
|
// Strict singleton: never start a second long-polling loop.
|
|
tgBotMutex.Lock()
|
|
if botCancel != nil || isRunning {
|
|
tgBotMutex.Unlock()
|
|
logger.Warning("TgBot OnReceive called while already running; ignoring.")
|
|
return
|
|
}
|
|
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
botCancel = cancel
|
|
isRunning = true
|
|
// Add to WaitGroup before releasing the lock so StopBot() can't return
|
|
// before this receiver goroutine is accounted for.
|
|
botWG.Add(1)
|
|
tgBotMutex.Unlock()
|
|
|
|
// Get updates channel using the context with shorter timeout for better error recovery
|
|
updates, _ := bot.UpdatesViaLongPolling(ctx, ¶ms)
|
|
go func() {
|
|
defer botWG.Done()
|
|
h, _ := th.NewBotHandler(bot, updates)
|
|
tgBotMutex.Lock()
|
|
botHandler = h
|
|
tgBotMutex.Unlock()
|
|
|
|
h.HandleMessage(func(ctx *th.Context, message telego.Message) error {
|
|
userStateMgr.clear(message.Chat.ID)
|
|
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove())
|
|
return nil
|
|
}, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard")))
|
|
|
|
h.HandleMessage(func(ctx *th.Context, message telego.Message) error {
|
|
if !t.isCommandForCurrentBot(&message) {
|
|
return nil
|
|
}
|
|
|
|
// Use goroutine with worker pool for concurrent command processing
|
|
go func() {
|
|
messageWorkerPool <- struct{}{} // Acquire worker
|
|
defer func() { <-messageWorkerPool }() // Release worker
|
|
|
|
userStateMgr.clear(message.Chat.ID)
|
|
t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID))
|
|
}()
|
|
return nil
|
|
}, th.AnyCommand())
|
|
|
|
h.HandleCallbackQuery(func(ctx *th.Context, query telego.CallbackQuery) error {
|
|
// Use goroutine with worker pool for concurrent callback processing
|
|
go func() {
|
|
messageWorkerPool <- struct{}{} // Acquire worker
|
|
defer func() { <-messageWorkerPool }() // Release worker
|
|
|
|
userStateMgr.clear(query.Message.GetChat().ID)
|
|
t.answerCallback(&query, checkAdmin(query.From.ID))
|
|
}()
|
|
return nil
|
|
}, th.AnyCallbackQueryWithMessage())
|
|
|
|
h.HandleMessage(func(ctx *th.Context, message telego.Message) error {
|
|
userStateMgr.maybePrune(time.Hour)
|
|
if userState, exists := userStateMgr.get(message.Chat.ID); exists {
|
|
switch userState {
|
|
case "awaiting_email":
|
|
if client_Email == strings.TrimSpace(message.Text) {
|
|
t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
|
|
userStateMgr.clear(message.Chat.ID)
|
|
return nil
|
|
}
|
|
|
|
client_Email = strings.TrimSpace(message.Text)
|
|
if t.isSingleWord(client_Email) {
|
|
userStateMgr.set(message.Chat.ID, "awaiting_email")
|
|
|
|
cancel_btn_markup := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
|
|
),
|
|
)
|
|
|
|
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup)
|
|
} else {
|
|
t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_email"), 3, tu.ReplyKeyboardRemove())
|
|
userStateMgr.clear(message.Chat.ID)
|
|
t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
|
|
}
|
|
case "awaiting_comment":
|
|
if client_Comment == strings.TrimSpace(message.Text) {
|
|
t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
|
|
userStateMgr.clear(message.Chat.ID)
|
|
return nil
|
|
}
|
|
|
|
client_Comment = strings.TrimSpace(message.Text)
|
|
t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_comment"), 3, tu.ReplyKeyboardRemove())
|
|
userStateMgr.clear(message.Chat.ID)
|
|
t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
|
|
case "awaiting_tg_id":
|
|
input := strings.TrimSpace(message.Text)
|
|
if input == "" || input == "-" || strings.EqualFold(input, "none") {
|
|
client_TgID = ""
|
|
t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
|
|
userStateMgr.clear(message.Chat.ID)
|
|
t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
|
|
return nil
|
|
}
|
|
if _, err := strconv.ParseInt(input, 10, 64); err != nil {
|
|
cancel_btn_markup := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
|
|
),
|
|
)
|
|
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup)
|
|
return nil
|
|
}
|
|
client_TgID = input
|
|
t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.userSaved"), 3, tu.ReplyKeyboardRemove())
|
|
userStateMgr.clear(message.Chat.ID)
|
|
t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
|
|
}
|
|
|
|
} else {
|
|
if message.UsersShared != nil {
|
|
if checkAdmin(message.From.ID) {
|
|
for _, sharedUser := range message.UsersShared.Users {
|
|
userID := sharedUser.UserID
|
|
needRestart, err := t.clientService.SetClientTelegramUserID(&t.inboundService, message.UsersShared.RequestID, userID)
|
|
if needRestart {
|
|
t.xrayService.SetToNeedRestart()
|
|
}
|
|
output := ""
|
|
if err != nil {
|
|
output += t.I18nBot("tgbot.messages.selectUserFailed")
|
|
} else {
|
|
output += t.I18nBot("tgbot.messages.userSaved")
|
|
}
|
|
t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove())
|
|
}
|
|
} else {
|
|
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove())
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}, th.AnyMessage())
|
|
|
|
h.Start()
|
|
}()
|
|
}
|
|
|
|
// answerCommand processes incoming command messages from Telegram users.
|
|
func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin bool) {
|
|
msg, onlyMessage := "", false
|
|
|
|
command, _, commandArgs := tu.ParseCommand(message.Text)
|
|
|
|
// Helper function to handle unknown commands.
|
|
handleUnknownCommand := func() {
|
|
msg += t.I18nBot("tgbot.commands.unknown")
|
|
}
|
|
|
|
// Handle the command.
|
|
switch command {
|
|
case "help":
|
|
msg += t.I18nBot("tgbot.commands.help")
|
|
msg += t.I18nBot("tgbot.commands.pleaseChoose")
|
|
case "start":
|
|
msg += t.I18nBot("tgbot.commands.start", "Firstname=="+html.EscapeString(message.From.FirstName))
|
|
if isAdmin {
|
|
msg += t.I18nBot("tgbot.commands.welcome", "Hostname=="+hostname)
|
|
}
|
|
msg += "\n\n" + t.I18nBot("tgbot.commands.pleaseChoose")
|
|
case "status":
|
|
onlyMessage = true
|
|
msg += t.I18nBot("tgbot.commands.status")
|
|
case "id":
|
|
onlyMessage = true
|
|
msg += t.I18nBot("tgbot.commands.getID", "ID=="+strconv.FormatInt(message.From.ID, 10))
|
|
case "usage":
|
|
onlyMessage = true
|
|
if len(commandArgs) > 0 {
|
|
if isAdmin {
|
|
t.searchClient(chatId, commandArgs[0])
|
|
} else {
|
|
t.getClientUsage(chatId, int64(message.From.ID), commandArgs[0])
|
|
}
|
|
} else {
|
|
msg += t.I18nBot("tgbot.commands.usage")
|
|
}
|
|
case "inbound":
|
|
onlyMessage = true
|
|
if isAdmin && len(commandArgs) > 0 {
|
|
t.searchInbound(chatId, commandArgs[0])
|
|
} else {
|
|
handleUnknownCommand()
|
|
}
|
|
case "restart":
|
|
onlyMessage = true
|
|
if isAdmin {
|
|
if len(commandArgs) == 0 {
|
|
if t.xrayService.IsXrayRunning() {
|
|
err := t.xrayService.RestartXray(true)
|
|
if err != nil {
|
|
msg += t.I18nBot("tgbot.commands.restartFailed", "Error=="+err.Error())
|
|
} else {
|
|
msg += t.I18nBot("tgbot.commands.restartSuccess")
|
|
}
|
|
} else {
|
|
msg += t.I18nBot("tgbot.commands.xrayNotRunning")
|
|
}
|
|
} else {
|
|
handleUnknownCommand()
|
|
msg += t.I18nBot("tgbot.commands.restartUsage")
|
|
}
|
|
} else {
|
|
handleUnknownCommand()
|
|
}
|
|
default:
|
|
handleUnknownCommand()
|
|
}
|
|
|
|
if msg != "" {
|
|
t.sendResponse(chatId, msg, onlyMessage, isAdmin)
|
|
}
|
|
}
|
|
|
|
func (t *Tgbot) isCommandForCurrentBot(message *telego.Message) bool {
|
|
return isCommandForBot(message.Text, botUsername())
|
|
}
|
|
|
|
func botUsername() string {
|
|
if bot == nil {
|
|
return ""
|
|
}
|
|
return bot.Username()
|
|
}
|
|
|
|
func isCommandForBot(text string, username string) bool {
|
|
_, commandUsername, _ := tu.ParseCommand(text)
|
|
return commandUsername == "" || username == "" || strings.EqualFold(commandUsername, username)
|
|
}
|
|
|
|
// answerCallback processes callback queries from inline keyboards.
|
|
func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool) {
|
|
chatId := callbackQuery.Message.GetChat().ID
|
|
|
|
if isAdmin {
|
|
// get query from hash storage
|
|
decodedQuery, err := t.decodeQuery(callbackQuery.Data)
|
|
if err != nil {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.noQuery"))
|
|
return
|
|
}
|
|
dataArray := strings.Split(decodedQuery, " ")
|
|
|
|
if len(dataArray) >= 2 && len(dataArray[1]) > 0 {
|
|
email := dataArray[1]
|
|
switch dataArray[0] {
|
|
case "get_clients_for_sub":
|
|
inboundId := dataArray[1]
|
|
inboundIdInt, err := strconv.Atoi(inboundId)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
clientsKB, err := t.getInboundClientsFor(inboundIdInt, "client_sub_links")
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
inbound, _ := t.inboundService.GetInbound(inboundIdInt)
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clientsKB)
|
|
case "get_clients_for_individual":
|
|
inboundId := dataArray[1]
|
|
inboundIdInt, err := strconv.Atoi(inboundId)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
clientsKB, err := t.getInboundClientsFor(inboundIdInt, "client_individual_links")
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
inbound, _ := t.inboundService.GetInbound(inboundIdInt)
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clientsKB)
|
|
case "get_clients_for_qr":
|
|
inboundId := dataArray[1]
|
|
inboundIdInt, err := strconv.Atoi(inboundId)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
clientsKB, err := t.getInboundClientsFor(inboundIdInt, "client_qr_links")
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
inbound, _ := t.inboundService.GetInbound(inboundIdInt)
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clientsKB)
|
|
case "client_sub_links":
|
|
t.sendClientSubLinks(chatId, email)
|
|
return
|
|
case "client_individual_links":
|
|
t.sendClientIndividualLinks(chatId, email)
|
|
return
|
|
case "client_qr_links":
|
|
t.sendClientQRLinks(chatId, email)
|
|
return
|
|
case "client_get_usage":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.messages.email", "Email=="+email))
|
|
t.searchClient(chatId, email)
|
|
case "client_refresh":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.clientRefreshSuccess", "Email=="+email))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "client_cancel":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "ips_refresh":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.IpRefreshSuccess", "Email=="+email))
|
|
t.searchClientIps(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "ips_cancel":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email))
|
|
t.searchClientIps(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "tgid_refresh":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.TGIdRefreshSuccess", "Email=="+email))
|
|
t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "tgid_cancel":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email))
|
|
t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "reset_traffic":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.encodeQuery("reset_traffic_c "+email)),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "reset_traffic_c":
|
|
err := t.inboundService.ResetClientTrafficByEmail(email)
|
|
if err == nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.resetTrafficSuccess", "Email=="+email))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
} else {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
}
|
|
case "limit_traffic":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 0")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" 0")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 1")),
|
|
tu.InlineKeyboardButton("5 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 5")),
|
|
tu.InlineKeyboardButton("10 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 10")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("20 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 20")),
|
|
tu.InlineKeyboardButton("30 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 30")),
|
|
tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 40")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 50")),
|
|
tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 60")),
|
|
tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 80")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("100 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 100")),
|
|
tu.InlineKeyboardButton("150 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 150")),
|
|
tu.InlineKeyboardButton("200 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 200")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "limit_traffic_c":
|
|
if len(dataArray) == 3 {
|
|
limitTraffic, err := strconv.Atoi(dataArray[2])
|
|
if err == nil {
|
|
needRestart, err := t.clientService.ResetClientTrafficLimitByEmail(&t.inboundService, email, limitTraffic)
|
|
if needRestart {
|
|
t.xrayService.SetToNeedRestart()
|
|
}
|
|
if err == nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.setTrafficLimitSuccess", "Email=="+email))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
return
|
|
}
|
|
}
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "limit_traffic_in":
|
|
if len(dataArray) >= 3 {
|
|
oldInputNumber, err := strconv.Atoi(dataArray[2])
|
|
inputNumber := oldInputNumber
|
|
if err == nil {
|
|
if len(dataArray) == 4 {
|
|
num, err := strconv.Atoi(dataArray[3])
|
|
if err == nil {
|
|
switch num {
|
|
case -2:
|
|
inputNumber = 0
|
|
case -1:
|
|
if inputNumber > 0 {
|
|
inputNumber = (inputNumber / 10)
|
|
}
|
|
default:
|
|
inputNumber = (inputNumber * 10) + num
|
|
}
|
|
}
|
|
if inputNumber == oldInputNumber {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
return
|
|
}
|
|
if inputNumber >= 999999 {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
return
|
|
}
|
|
}
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" "+strconv.Itoa(inputNumber))),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 2")),
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 3")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 4")),
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 6")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 7")),
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 9")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" -2")),
|
|
tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 0")),
|
|
tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" -1")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
return
|
|
}
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "add_client_limit_traffic_c":
|
|
limitTraffic, _ := strconv.ParseInt(dataArray[1], 10, 64)
|
|
client_TotalGB = limitTraffic * 1024 * 1024 * 1024
|
|
messageId := callbackQuery.Message.GetMessageID()
|
|
message_text := t.BuildClientDraftMessage()
|
|
|
|
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
case "add_client_limit_traffic_in":
|
|
if len(dataArray) >= 2 {
|
|
oldInputNumber, err := strconv.Atoi(dataArray[1])
|
|
inputNumber := oldInputNumber
|
|
if err == nil {
|
|
if len(dataArray) == 3 {
|
|
num, err := strconv.Atoi(dataArray[2])
|
|
if err == nil {
|
|
switch num {
|
|
case -2:
|
|
inputNumber = 0
|
|
case -1:
|
|
if inputNumber > 0 {
|
|
inputNumber = (inputNumber / 10)
|
|
}
|
|
default:
|
|
inputNumber = (inputNumber * 10) + num
|
|
}
|
|
}
|
|
if inputNumber == oldInputNumber {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
return
|
|
}
|
|
if inputNumber >= 999999 {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
return
|
|
}
|
|
}
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c "+strconv.Itoa(inputNumber))),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 2")),
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 3")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 4")),
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 6")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 7")),
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 9")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -2")),
|
|
tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 0")),
|
|
tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -1")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
return
|
|
}
|
|
}
|
|
case "reset_exp":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 0")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("reset_exp_in "+email+" 0")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 7 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 7")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 10")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 14 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 14")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 20")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 30")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 90")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 180")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 365")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "reset_exp_c":
|
|
if len(dataArray) == 3 {
|
|
days, err := strconv.ParseInt(dataArray[2], 10, 64)
|
|
if err == nil {
|
|
var date int64
|
|
if days > 0 {
|
|
traffic, err := t.inboundService.GetClientTrafficByEmail(email)
|
|
if err != nil {
|
|
logger.Warning(err)
|
|
msg := t.I18nBot("tgbot.wentWrong")
|
|
t.SendMsgToTgbot(chatId, msg)
|
|
return
|
|
}
|
|
if traffic == nil {
|
|
msg := t.I18nBot("tgbot.noResult")
|
|
t.SendMsgToTgbot(chatId, msg)
|
|
return
|
|
}
|
|
|
|
if traffic.ExpiryTime > 0 {
|
|
if traffic.ExpiryTime-time.Now().Unix()*1000 < 0 {
|
|
date = -int64(days * 24 * 60 * 60000)
|
|
} else {
|
|
date = traffic.ExpiryTime + int64(days*24*60*60000)
|
|
}
|
|
} else {
|
|
date = traffic.ExpiryTime - int64(days*24*60*60000)
|
|
}
|
|
|
|
}
|
|
needRestart, err := t.clientService.ResetClientExpiryTimeByEmail(&t.inboundService, email, date)
|
|
if needRestart {
|
|
t.xrayService.SetToNeedRestart()
|
|
}
|
|
if err == nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.expireResetSuccess", "Email=="+email))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
return
|
|
}
|
|
}
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "reset_exp_in":
|
|
if len(dataArray) >= 3 {
|
|
oldInputNumber, err := strconv.Atoi(dataArray[2])
|
|
inputNumber := oldInputNumber
|
|
if err == nil {
|
|
if len(dataArray) == 4 {
|
|
num, err := strconv.Atoi(dataArray[3])
|
|
if err == nil {
|
|
switch num {
|
|
case -2:
|
|
inputNumber = 0
|
|
case -1:
|
|
if inputNumber > 0 {
|
|
inputNumber = (inputNumber / 10)
|
|
}
|
|
default:
|
|
inputNumber = (inputNumber * 10) + num
|
|
}
|
|
}
|
|
if inputNumber == oldInputNumber {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
return
|
|
}
|
|
if inputNumber >= 999999 {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
return
|
|
}
|
|
}
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" "+strconv.Itoa(inputNumber))),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 2")),
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 3")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 4")),
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 6")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 7")),
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 9")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" -2")),
|
|
tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 0")),
|
|
tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" -1")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
return
|
|
}
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "add_client_reset_exp_c":
|
|
client_ExpiryTime = 0
|
|
days, _ := strconv.ParseInt(dataArray[1], 10, 64)
|
|
var date int64
|
|
if client_ExpiryTime > 0 {
|
|
if client_ExpiryTime-time.Now().Unix()*1000 < 0 {
|
|
date = -int64(days * 24 * 60 * 60000)
|
|
} else {
|
|
date = client_ExpiryTime + int64(days*24*60*60000)
|
|
}
|
|
} else {
|
|
date = client_ExpiryTime - int64(days*24*60*60000)
|
|
}
|
|
client_ExpiryTime = date
|
|
|
|
messageId := callbackQuery.Message.GetMessageID()
|
|
message_text := t.BuildClientDraftMessage()
|
|
|
|
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
case "add_client_reset_exp_in":
|
|
if len(dataArray) >= 2 {
|
|
oldInputNumber, err := strconv.Atoi(dataArray[1])
|
|
inputNumber := oldInputNumber
|
|
if err == nil {
|
|
if len(dataArray) == 3 {
|
|
num, err := strconv.Atoi(dataArray[2])
|
|
if err == nil {
|
|
switch num {
|
|
case -2:
|
|
inputNumber = 0
|
|
case -1:
|
|
if inputNumber > 0 {
|
|
inputNumber = (inputNumber / 10)
|
|
}
|
|
default:
|
|
inputNumber = (inputNumber * 10) + num
|
|
}
|
|
}
|
|
if inputNumber == oldInputNumber {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
return
|
|
}
|
|
if inputNumber >= 999999 {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
return
|
|
}
|
|
}
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_reset_exp_c "+strconv.Itoa(inputNumber))),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 2")),
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 3")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 4")),
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 6")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 7")),
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 9")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -2")),
|
|
tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 0")),
|
|
tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -1")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
return
|
|
}
|
|
}
|
|
case "ip_limit":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelIpLimit")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 0")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("ip_limit_in "+email+" 0")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 2")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 3")),
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 4")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 6")),
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 7")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 9")),
|
|
tu.InlineKeyboardButton("10").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 10")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "ip_limit_c":
|
|
if len(dataArray) == 3 {
|
|
count, err := strconv.Atoi(dataArray[2])
|
|
if err == nil {
|
|
needRestart, err := t.clientService.ResetClientIpLimitByEmail(&t.inboundService, email, count)
|
|
if needRestart {
|
|
t.xrayService.SetToNeedRestart()
|
|
}
|
|
if err == nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.resetIpSuccess", "Email=="+email, "Count=="+strconv.Itoa(count)))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
return
|
|
}
|
|
}
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "ip_limit_in":
|
|
if len(dataArray) >= 3 {
|
|
oldInputNumber, err := strconv.Atoi(dataArray[2])
|
|
inputNumber := oldInputNumber
|
|
if err == nil {
|
|
if len(dataArray) == 4 {
|
|
num, err := strconv.Atoi(dataArray[3])
|
|
if err == nil {
|
|
switch num {
|
|
case -2:
|
|
inputNumber = 0
|
|
case -1:
|
|
if inputNumber > 0 {
|
|
inputNumber = (inputNumber / 10)
|
|
}
|
|
default:
|
|
inputNumber = (inputNumber * 10) + num
|
|
}
|
|
}
|
|
if inputNumber == oldInputNumber {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
return
|
|
}
|
|
if inputNumber >= 999999 {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
return
|
|
}
|
|
}
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("ip_limit_c "+email+" "+strconv.Itoa(inputNumber))),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 2")),
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 3")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 4")),
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 6")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 7")),
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 9")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" -2")),
|
|
tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 0")),
|
|
tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" -1")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
return
|
|
}
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
case "add_client_ip_limit_c":
|
|
if len(dataArray) == 2 {
|
|
count, _ := strconv.Atoi(dataArray[1])
|
|
client_LimitIP = count
|
|
}
|
|
|
|
messageId := callbackQuery.Message.GetMessageID()
|
|
message_text := t.BuildClientDraftMessage()
|
|
|
|
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
case "add_client_ip_limit_in":
|
|
if len(dataArray) >= 2 {
|
|
oldInputNumber, err := strconv.Atoi(dataArray[1])
|
|
inputNumber := oldInputNumber
|
|
if err == nil {
|
|
if len(dataArray) == 3 {
|
|
num, err := strconv.Atoi(dataArray[2])
|
|
if err == nil {
|
|
switch num {
|
|
case -2:
|
|
inputNumber = 0
|
|
case -1:
|
|
if inputNumber > 0 {
|
|
inputNumber = (inputNumber / 10)
|
|
}
|
|
default:
|
|
inputNumber = (inputNumber * 10) + num
|
|
}
|
|
}
|
|
if inputNumber == oldInputNumber {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
return
|
|
}
|
|
if inputNumber >= 999999 {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
return
|
|
}
|
|
}
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_ip_limit")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_ip_limit_c "+strconv.Itoa(inputNumber))),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 2")),
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 3")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 4")),
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 6")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 7")),
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 9")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -2")),
|
|
tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 0")),
|
|
tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -1")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
return
|
|
}
|
|
}
|
|
case "clear_ips":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("ips_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmClearIps")).WithCallbackData(t.encodeQuery("clear_ips_c "+email)),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "clear_ips_c":
|
|
err := t.inboundService.ClearClientIps(email)
|
|
if err == nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.clearIpSuccess", "Email=="+email))
|
|
t.searchClientIps(chatId, email, callbackQuery.Message.GetMessageID())
|
|
} else {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
}
|
|
case "ip_log":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getIpLog", "Email=="+email))
|
|
t.searchClientIps(chatId, email)
|
|
case "tg_user":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getUserInfo", "Email=="+email))
|
|
t.clientTelegramUserInfo(chatId, email)
|
|
case "tgid_remove":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("tgid_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmRemoveTGUser")).WithCallbackData(t.encodeQuery("tgid_remove_c "+email)),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "tgid_remove_c":
|
|
traffic, err := t.inboundService.GetClientTrafficByEmail(email)
|
|
if err != nil || traffic == nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
return
|
|
}
|
|
needRestart, err := t.clientService.SetClientTelegramUserID(&t.inboundService, traffic.Id, EmptyTelegramUserID)
|
|
if needRestart {
|
|
t.xrayService.SetToNeedRestart()
|
|
}
|
|
if err == nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.removedTGUserSuccess", "Email=="+email))
|
|
t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.GetMessageID())
|
|
} else {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
}
|
|
case "toggle_enable":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmToggle")).WithCallbackData(t.encodeQuery("toggle_enable_c "+email)),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "toggle_enable_c":
|
|
enabled, needRestart, err := t.clientService.ToggleClientEnableByEmail(&t.inboundService, email)
|
|
if needRestart {
|
|
t.xrayService.SetToNeedRestart()
|
|
}
|
|
if err == nil {
|
|
if enabled {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.enableSuccess", "Email=="+email))
|
|
} else {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.disableSuccess", "Email=="+email))
|
|
}
|
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
|
} else {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
|
}
|
|
case "get_clients":
|
|
inboundId := dataArray[1]
|
|
inboundIdInt, err := strconv.Atoi(inboundId)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
inbound, err := t.inboundService.GetInbound(inboundIdInt)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
clients, err := t.getInboundClients(inboundIdInt)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clients)
|
|
case "add_client_to":
|
|
client_Email = t.randomLowerAndNum(8)
|
|
client_LimitIP = 0
|
|
client_TotalGB = 0
|
|
client_ExpiryTime = 0
|
|
client_Enable = true
|
|
client_TgID = ""
|
|
client_SubID = t.randomLowerAndNum(16)
|
|
client_Comment = ""
|
|
client_Reset = 0
|
|
|
|
inboundId := dataArray[1]
|
|
inboundIdInt, err := strconv.Atoi(inboundId)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
receiver_inbound_ID = inboundIdInt
|
|
receiver_inbound_IDs = []int{inboundIdInt}
|
|
t.addClient(callbackQuery.Message.GetChat().ID, t.BuildClientDraftMessage())
|
|
case "add_client_toggle_attach":
|
|
inboundIdStr := dataArray[1]
|
|
inboundIdInt, err := strconv.Atoi(inboundIdStr)
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
found := -1
|
|
for i, id := range receiver_inbound_IDs {
|
|
if id == inboundIdInt {
|
|
found = i
|
|
break
|
|
}
|
|
}
|
|
if found >= 0 {
|
|
receiver_inbound_IDs = append(receiver_inbound_IDs[:found], receiver_inbound_IDs[found+1:]...)
|
|
} else {
|
|
receiver_inbound_IDs = append(receiver_inbound_IDs, inboundIdInt)
|
|
}
|
|
picker, err := t.getInboundsAttachPicker()
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
t.editMessageCallbackTgBot(callbackQuery.Message.GetChat().ID, callbackQuery.Message.GetMessageID(), picker)
|
|
}
|
|
return
|
|
} else {
|
|
switch callbackQuery.Data {
|
|
case "get_inbounds":
|
|
inbounds, err := t.getInbounds()
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.allClients"))
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
|
|
case "admin_client_sub_links":
|
|
inbounds, err := t.getInboundsFor("get_clients_for_sub")
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
|
|
case "admin_client_individual_links":
|
|
inbounds, err := t.getInboundsFor("get_clients_for_individual")
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
|
|
case "admin_client_qr_links":
|
|
inbounds, err := t.getInboundsFor("get_clients_for_qr")
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
switch callbackQuery.Data {
|
|
case "get_usage":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.serverUsage"))
|
|
t.getServerUsage(chatId)
|
|
case "usage_refresh":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
t.getServerUsage(chatId, callbackQuery.Message.GetMessageID())
|
|
case "inbounds":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getInbounds"))
|
|
t.SendMsgToTgbot(chatId, t.getInboundUsages())
|
|
case "deplete_soon":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.depleteSoon"))
|
|
t.getExhausted(chatId)
|
|
case "get_backup":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.dbBackup"))
|
|
t.sendBackup(chatId)
|
|
case "get_banlogs":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getBanLogs"))
|
|
t.sendBanLogs(chatId, true)
|
|
case "client_traffic":
|
|
tgUserID := callbackQuery.From.ID
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.clientUsage"))
|
|
t.getClientUsage(chatId, tgUserID)
|
|
case "client_commands":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands"))
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpClientCommands"))
|
|
case "client_sub_links":
|
|
// show user's own clients to choose one for sub links
|
|
tgUserID := callbackQuery.From.ID
|
|
traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID)
|
|
if err != nil {
|
|
// fallback to message
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation")+"\r\n"+err.Error())
|
|
return
|
|
}
|
|
if len(traffics) == 0 {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10)))
|
|
return
|
|
}
|
|
var buttons []telego.InlineKeyboardButton
|
|
for _, tr := range traffics {
|
|
buttons = append(buttons, tu.InlineKeyboardButton(tr.Email).WithCallbackData(t.encodeQuery("client_sub_links "+tr.Email)))
|
|
}
|
|
cols := 1
|
|
if len(buttons) >= 6 {
|
|
cols = 2
|
|
}
|
|
keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...))
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), keyboard)
|
|
case "client_individual_links":
|
|
// show user's clients to choose for individual links
|
|
tgUserID := callbackQuery.From.ID
|
|
traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID)
|
|
if err != nil {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation")+"\r\n"+err.Error())
|
|
return
|
|
}
|
|
if len(traffics) == 0 {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10)))
|
|
return
|
|
}
|
|
var buttons2 []telego.InlineKeyboardButton
|
|
for _, tr := range traffics {
|
|
buttons2 = append(buttons2, tu.InlineKeyboardButton(tr.Email).WithCallbackData(t.encodeQuery("client_individual_links "+tr.Email)))
|
|
}
|
|
cols2 := 1
|
|
if len(buttons2) >= 6 {
|
|
cols2 = 2
|
|
}
|
|
keyboard2 := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols2, buttons2...))
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), keyboard2)
|
|
case "client_qr_links":
|
|
// show user's clients to choose for QR codes
|
|
tgUserID := callbackQuery.From.ID
|
|
traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID)
|
|
if err != nil {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOccurred")+"\r\n"+err.Error())
|
|
return
|
|
}
|
|
if len(traffics) == 0 {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10)))
|
|
return
|
|
}
|
|
var buttons3 []telego.InlineKeyboardButton
|
|
for _, tr := range traffics {
|
|
buttons3 = append(buttons3, tu.InlineKeyboardButton(tr.Email).WithCallbackData(t.encodeQuery("client_qr_links "+tr.Email)))
|
|
}
|
|
cols3 := 1
|
|
if len(buttons3) >= 6 {
|
|
cols3 = 2
|
|
}
|
|
keyboard3 := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols3, buttons3...))
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), keyboard3)
|
|
case "onlines":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.onlines"))
|
|
t.onlineClients(chatId)
|
|
case "onlines_refresh":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
|
t.onlineClients(chatId, callbackQuery.Message.GetMessageID())
|
|
case "commands":
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands"))
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpAdminCommands"))
|
|
case "add_client":
|
|
client_Email = t.randomLowerAndNum(8)
|
|
client_LimitIP = 0
|
|
client_TotalGB = 0
|
|
client_ExpiryTime = 0
|
|
client_Enable = true
|
|
client_TgID = ""
|
|
client_SubID = t.randomLowerAndNum(16)
|
|
client_Comment = ""
|
|
client_Reset = 0
|
|
|
|
inbounds, err := t.getInboundsAddClient()
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.addClient"))
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
|
|
case "add_client_ch_default_email":
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
userStateMgr.set(chatId, "awaiting_email")
|
|
cancel_btn_markup := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
|
|
),
|
|
)
|
|
prompt_message := t.I18nBot("tgbot.messages.email_prompt", "ClientEmail=="+client_Email)
|
|
t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
|
|
case "add_client_ch_default_comment":
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
userStateMgr.set(chatId, "awaiting_comment")
|
|
cancel_btn_markup := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
|
|
),
|
|
)
|
|
prompt_message := t.I18nBot("tgbot.messages.comment_prompt", "ClientComment=="+client_Comment)
|
|
t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
|
|
case "add_client_ch_default_tg_id":
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
userStateMgr.set(chatId, "awaiting_tg_id")
|
|
cancel_btn_markup := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
|
|
),
|
|
)
|
|
current := client_TgID
|
|
if current == "" {
|
|
current = "—"
|
|
}
|
|
t.SendMsgToTgbot(chatId, fmt.Sprintf("Send the Telegram user id (numeric) to attach to this client, or send `-` / `none` to clear.\nCurrent: `%s`", current), cancel_btn_markup)
|
|
case "add_client_ch_default_traffic":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 0")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_in 0")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 1")),
|
|
tu.InlineKeyboardButton("5 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 5")),
|
|
tu.InlineKeyboardButton("10 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 10")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("20 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 20")),
|
|
tu.InlineKeyboardButton("30 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 30")),
|
|
tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 40")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 50")),
|
|
tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 60")),
|
|
tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 80")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("100 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 100")),
|
|
tu.InlineKeyboardButton("150 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 150")),
|
|
tu.InlineKeyboardButton("200 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 200")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "add_client_ch_default_exp":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 0")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_reset_exp_in 0")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 7 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 7")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 10")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 14 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 14")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 20")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 30")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 90")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 180")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 365")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "add_client_ch_default_ip_limit":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_ip_limit")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_ip_limit_c 0")),
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_ip_limit_in 0")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 1")),
|
|
tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 2")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 3")),
|
|
tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 4")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 5")),
|
|
tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 6")),
|
|
tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 7")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 8")),
|
|
tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 9")),
|
|
tu.InlineKeyboardButton("10").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 10")),
|
|
),
|
|
)
|
|
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
|
case "add_client_default_info":
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
|
|
userStateMgr.clear(chatId)
|
|
t.addClient(chatId, t.BuildClientDraftMessage())
|
|
case "add_client_cancel":
|
|
userStateMgr.clear(chatId)
|
|
receiver_inbound_ID = 0
|
|
receiver_inbound_IDs = nil
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 3, tu.ReplyKeyboardRemove())
|
|
case "add_client_default_traffic_exp":
|
|
messageId := callbackQuery.Message.GetMessageID()
|
|
message_text := t.BuildClientDraftMessage()
|
|
t.addClient(chatId, message_text, messageId)
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
|
|
case "add_client_default_ip_limit":
|
|
messageId := callbackQuery.Message.GetMessageID()
|
|
message_text := t.BuildClientDraftMessage()
|
|
t.addClient(chatId, message_text, messageId)
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
|
|
case "add_client_attach_more":
|
|
picker, err := t.getInboundsAttachPicker()
|
|
if err != nil {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
|
return
|
|
}
|
|
t.SendMsgToTgbot(chatId, "Pick inbound(s) to attach:", picker)
|
|
case "add_client_attach_done":
|
|
if receiver_inbound_ID == 0 && len(receiver_inbound_IDs) > 0 {
|
|
receiver_inbound_ID = receiver_inbound_IDs[0]
|
|
}
|
|
if receiver_inbound_ID == 0 {
|
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getInboundsFailed"))
|
|
return
|
|
}
|
|
message_text := t.BuildClientDraftMessage()
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
t.addClient(chatId, message_text)
|
|
case "add_client_submit_disable":
|
|
client_Enable = false
|
|
_, err := t.SubmitAddClient()
|
|
if err != nil {
|
|
errorMessage := fmt.Sprintf("%v", err)
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove())
|
|
} else {
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove())
|
|
t.sendClientIndividualLinks(chatId, client_Email)
|
|
t.sendClientQRLinks(chatId, client_Email)
|
|
receiver_inbound_ID = 0
|
|
receiver_inbound_IDs = nil
|
|
}
|
|
case "add_client_submit_enable":
|
|
client_Enable = true
|
|
_, err := t.SubmitAddClient()
|
|
if err != nil {
|
|
errorMessage := fmt.Sprintf("%v", err)
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove())
|
|
} else {
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove())
|
|
t.sendClientIndividualLinks(chatId, client_Email)
|
|
t.sendClientQRLinks(chatId, client_Email)
|
|
receiver_inbound_ID = 0
|
|
receiver_inbound_IDs = nil
|
|
}
|
|
case "reset_all_traffics_cancel":
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 1, tu.ReplyKeyboardRemove())
|
|
case "reset_all_traffics":
|
|
inlineKeyboard := tu.InlineKeyboard(
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("reset_all_traffics_cancel")),
|
|
),
|
|
tu.InlineKeyboardRow(
|
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.encodeQuery("reset_all_traffics_c")),
|
|
),
|
|
)
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.AreYouSure"), inlineKeyboard)
|
|
case "reset_all_traffics_c":
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
emails, err := t.inboundService.GetAllEmails()
|
|
if err != nil {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
|
|
return
|
|
}
|
|
|
|
for _, email := range emails {
|
|
err := t.inboundService.ResetClientTrafficByEmail(email)
|
|
if err == nil {
|
|
msg := t.I18nBot("tgbot.messages.SuccessResetTraffic", "ClientEmail=="+email)
|
|
t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
|
|
} else {
|
|
msg := t.I18nBot("tgbot.messages.FailedResetTraffic", "ClientEmail=="+email, "ErrorMessage=="+err.Error())
|
|
t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
|
|
}
|
|
}
|
|
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.FinishProcess"), tu.ReplyKeyboardRemove())
|
|
case "get_sorted_traffic_usage_report":
|
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
|
emails, err := t.inboundService.GetAllEmails()
|
|
|
|
if err != nil {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
|
|
return
|
|
}
|
|
valid_emails, extra_emails, err := t.inboundService.FilterAndSortClientEmails(emails)
|
|
if err != nil {
|
|
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
|
|
return
|
|
}
|
|
|
|
for _, valid_emails := range valid_emails {
|
|
traffic, err := t.inboundService.GetClientTrafficByEmail(valid_emails)
|
|
if err != nil {
|
|
logger.Warning(err)
|
|
msg := t.I18nBot("tgbot.wentWrong")
|
|
t.SendMsgToTgbot(chatId, msg)
|
|
continue
|
|
}
|
|
if traffic == nil {
|
|
msg := t.I18nBot("tgbot.noResult")
|
|
t.SendMsgToTgbot(chatId, msg)
|
|
continue
|
|
}
|
|
|
|
output := t.clientInfoMsg(traffic, false, false, false, false, true, false)
|
|
t.SendMsgToTgbot(chatId, output, tu.ReplyKeyboardRemove())
|
|
}
|
|
for _, extra_emails := range extra_emails {
|
|
msg := fmt.Sprintf("📧 %s\n%s", extra_emails, t.I18nBot("tgbot.noResult"))
|
|
t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
|
|
|
|
}
|
|
default:
|
|
if after, ok := strings.CutPrefix(callbackQuery.Data, "client_sub_links "); ok {
|
|
email := after
|
|
t.sendClientSubLinks(chatId, email)
|
|
return
|
|
}
|
|
if after, ok := strings.CutPrefix(callbackQuery.Data, "client_individual_links "); ok {
|
|
email := after
|
|
t.sendClientIndividualLinks(chatId, email)
|
|
return
|
|
}
|
|
if after, ok := strings.CutPrefix(callbackQuery.Data, "client_qr_links "); ok {
|
|
email := after
|
|
t.sendClientQRLinks(chatId, email)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// checkAdmin checks if the given Telegram ID is an admin.
|
|
func checkAdmin(tgId int64) bool {
|
|
return slices.Contains(adminIds, tgId)
|
|
}
|