diff --git a/web/service/tgbot.go b/web/service/tgbot.go index 3764d71a..a3dd805f 100644 --- a/web/service/tgbot.go +++ b/web/service/tgbot.go @@ -1,2709 +1,471 @@ package service import ( - "crypto/rand" - "embed" - "encoding/base64" - "errors" - "fmt" - "math/big" - "net" - "net/url" - "os" - "regexp" - "strconv" - "strings" - "time" + "context" + "crypto/rand" + "embed" + "encoding/base64" + "errors" + "fmt" + "math/big" + "net" + "net/url" + "os" + "regexp" + "strconv" + "strings" + "time" - "x-ui/config" - "x-ui/database" - "x-ui/database/model" - "x-ui/logger" - "x-ui/util/common" - "x-ui/web/global" - "x-ui/web/locale" - "x-ui/xray" + "x-ui/config" + "x-ui/database" + "x-ui/database/model" + "x-ui/logger" + "x-ui/util/common" + "x-ui/web/global" + "x-ui/web/locale" + "x-ui/xray" - "github.com/google/uuid" - "github.com/mymmrac/telego" - th "github.com/mymmrac/telego/telegohandler" - tu "github.com/mymmrac/telego/telegoutil" - "github.com/valyala/fasthttp" - "github.com/valyala/fasthttp/fasthttpproxy" + "github.com/google/uuid" + "github.com/mymmrac/telego" + th "github.com/mymmrac/telego/telegohandler" + tu "github.com/mymmrac/telego/telegoutil" + "github.com/valyala/fasthttp" + "github.com/valyala/fasthttp/fasthttpproxy" ) var ( - bot *telego.Bot - botHandler *th.BotHandler - adminIds []int64 - isRunning bool - hostname string - hashStorage *global.HashStorage - handler *th.Handler - - // clients data to adding new client - receiver_inbound_ID int - client_Id string - client_Flow string - client_Email string - client_LimitIP int - client_TotalGB int64 - client_ExpiryTime int64 - client_Enable bool - client_TgID string - client_SubID string - client_Comment string - client_Reset int - client_Security string - client_ShPassword string - client_TrPassword string - client_Method string + bot *telego.Bot + botHandler *th.BotHandler + adminIds []int64 + isRunning bool + hostname string + hashStorage *global.HashStorage + handler *th.Handler + // clients data to adding new client + receiver_inbound_ID int + client_Id string + client_Flow string + client_Email string + client_LimitIP int + client_TotalGB int64 + client_ExpiryTime int64 + client_Enable bool + client_TgID string + client_SubID string + client_Comment string + client_Reset int + client_Security string + client_ShPassword string + client_TrPassword string + client_Method string ) - var userStates = make(map[int64]string) - type LoginStatus byte const ( - LoginSuccess LoginStatus = 1 - LoginFail LoginStatus = 0 - EmptyTelegramUserID = int64(0) + LoginSuccess LoginStatus = 1 + LoginFail LoginStatus = 0 + EmptyTelegramUserID = int64(0) ) - - type Tgbot struct { - inboundService InboundService - settingService SettingService - serverService ServerService - xrayService XrayService - lastStatus *Status + inboundService InboundService + settingService SettingService + serverService ServerService + xrayService XrayService + lastStatus *Status } - func (t *Tgbot) NewTgbot() *Tgbot { - return new(Tgbot) + return new(Tgbot) } func (t *Tgbot) I18nBot(name string, params ...string) string { - return locale.I18n(locale.Bot, name, params...) + return locale.I18n(locale.Bot, name, params...) } func (t *Tgbot) GetHashStorage() *global.HashStorage { - return hashStorage + return hashStorage } func (t *Tgbot) Start(i18nFS embed.FS) error { - // Initialize localizer - err := locale.InitLocalizer(i18nFS, &t.settingService) - if err != nil { - return err - } + err := locale.InitLocalizer(i18nFS, &t.settingService) + if err != nil { + return err + } - // Initialize hash storage to store callback queries - hashStorage = global.NewHashStorage(20 * time.Minute) + hashStorage = global.NewHashStorage(20 * time.Minute) - t.SetHostname() + t.SetHostname() - // Get Telegram bot token - tgBotToken, err := t.settingService.GetTgBotToken() - if err != nil || tgBotToken == "" { - logger.Warning("Failed to get Telegram bot token:", err) - return err - } + tgBotToken, err := t.settingService.GetTgBotToken() + if err != nil || tgBotToken == "" { + logger.Warning("Failed to get Telegram bot token:", err) + return err + } - // Get Telegram bot chat ID(s) - tgBotID, err := t.settingService.GetTgBotChatId() - if err != nil { - logger.Warning("Failed to get Telegram bot chat ID:", err) - return err - } + tgBotID, err := t.settingService.GetTgBotChatId() + if err != nil { + logger.Warning("Failed to get Telegram bot chat ID:", err) + return err + } - // Parse admin IDs from comma-separated string - if tgBotID != "" { - for _, adminID := range strings.Split(tgBotID, ",") { - id, err := strconv.Atoi(adminID) - if err != nil { - logger.Warning("Failed to parse admin ID from Telegram bot chat ID:", err) - return err - } - adminIds = append(adminIds, int64(id)) - } - } + if tgBotID != "" { + for _, adminID := range strings.Split(tgBotID, ",") { + id, err := strconv.Atoi(adminID) + if err != nil { + logger.Warning("Failed to parse admin ID from Telegram bot chat ID:", err) + return err + } + adminIds = append(adminIds, int64(id)) + } + } - // Get Telegram bot proxy URL - tgBotProxy, err := t.settingService.GetTgBotProxy() - if err != nil { - logger.Warning("Failed to get Telegram bot proxy URL:", err) - } + tgBotProxy, err := t.settingService.GetTgBotProxy() + if err != nil { + logger.Warning("Failed to get Telegram bot proxy URL:", err) + } - // Get Telegram bot API server URL - tgBotAPIServer, err := t.settingService.GetTgBotAPIServer() - if err != nil { - logger.Warning("Failed to get Telegram bot API server URL:", err) - } + tgBotAPIServer, err := t.settingService.GetTgBotAPIServer() + if err != nil { + logger.Warning("Failed to get Telegram bot API server URL:", err) + } - // Create new Telegram bot instance - bot, err = t.NewBot(tgBotToken, tgBotProxy, tgBotAPIServer) - if err != nil { - logger.Error("Failed to initialize Telegram bot API:", err) - return err - } + bot, err = t.NewBot(tgBotToken, tgBotProxy, tgBotAPIServer) + if err != nil { + logger.Error("Failed to initialize Telegram bot API:", err) + return err + } - // Start receiving Telegram bot messages - if !isRunning { - logger.Info("Telegram bot receiver started") - go t.OnReceive() - isRunning = true - } + if !isRunning { + logger.Info("Telegram bot receiver started") + go t.OnReceive() + isRunning = true + } - return nil + return nil } func (t *Tgbot) NewBot(token string, proxyUrl string, apiServerUrl string) (*telego.Bot, error) { - if proxyUrl == "" && apiServerUrl == "" { - return telego.NewBot(token) - } + if proxyUrl == "" && apiServerUrl == "" { + return telego.NewBot(token) + } - if proxyUrl != "" { - if !strings.HasPrefix(proxyUrl, "socks5://") { - logger.Warning("Invalid socks5 URL, using default") - return telego.NewBot(token) - } + if proxyUrl != "" { + if !strings.HasPrefix(proxyUrl, "socks5://") { + logger.Warning("Invalid socks5 URL, using default") + return telego.NewBot(token) + } - _, err := url.Parse(proxyUrl) - if err != nil { - logger.Warningf("Can't parse proxy URL, using default instance for tgbot: %v", err) - return telego.NewBot(token) - } + _, err := url.Parse(proxyUrl) + if err != nil { + logger.Warningf("Can't parse proxy URL, using default instance for tgbot: %v", err) + return telego.NewBot(token) + } - return telego.NewBot(token, telego.WithFastHTTPClient(&fasthttp.Client{ - Dial: fasthttpproxy.FasthttpSocksDialer(proxyUrl), - })) - } + return telego.NewBot(token, telego.WithFastHTTPClient(&fasthttp.Client{ + Dial: fasthttpproxy.FasthttpSocksDialer(proxyUrl), + })) + } - if !strings.HasPrefix(apiServerUrl, "http") { - logger.Warning("Invalid http(s) URL, using default") - return telego.NewBot(token) - } + if !strings.HasPrefix(apiServerUrl, "http") { + logger.Warning("Invalid http(s) URL, using default") + return telego.NewBot(token) + } - _, err := url.Parse(apiServerUrl) - if err != nil { - logger.Warningf("Can't parse API server URL, using default instance for tgbot: %v", err) - return telego.NewBot(token) - } + _, err := url.Parse(apiServerUrl) + if err != nil { + logger.Warningf("Can't parse API server URL, using default instance for tgbot: %v", err) + return telego.NewBot(token) + } - return telego.NewBot(token, telego.WithAPIServer(apiServerUrl)) + return telego.NewBot(token, telego.WithAPIServer(apiServerUrl)) } func (t *Tgbot) IsRunning() bool { - return isRunning + return isRunning } func (t *Tgbot) SetHostname() { - host, err := os.Hostname() - if err != nil { - logger.Error("get hostname error:", err) - hostname = "" - return - } - hostname = host + host, err := os.Hostname() + if err != nil { + logger.Error("get hostname error:", err) + hostname = "" + return + } + hostname = host } func (t *Tgbot) Stop() { - botHandler.Stop() - bot.StopLongPolling() - logger.Info("Stop Telegram receiver ...") - isRunning = false - adminIds = nil + botHandler.Stop() + logger.Info("Stop Telegram receiver ...") + isRunning = false + adminIds = nil } func (t *Tgbot) encodeQuery(query string) string { - // NOTE: we only need to hash for more than 64 chars - if len(query) <= 64 { - return query - } + if len(query) <= 64 { + return query + } - return hashStorage.SaveHash(query) + return hashStorage.SaveHash(query) } func (t *Tgbot) decodeQuery(query string) (string, error) { - if !hashStorage.IsMD5(query) { - return query, nil - } + if !hashStorage.IsMD5(query) { + return query, nil + } - decoded, exists := hashStorage.GetValue(query) - if !exists { - return "", common.NewError("hash not found in storage!") - } + decoded, exists := hashStorage.GetValue(query) + if !exists { + return "", common.NewError("hash not found in storage!") + } - return decoded, nil + return decoded, nil } func (t *Tgbot) OnReceive() { - params := telego.GetUpdatesParams{ - Timeout: 10, - } + params := telego.GetUpdatesParams{ + Timeout: 10, + } - updates, _ := bot.UpdatesViaLongPolling(¶ms) + updates, _ := bot.UpdatesViaLongPolling(context.Background(), ¶ms) - botHandler, _ = th.NewBotHandler(bot, updates) + botHandler, _ = th.NewBotHandler(bot, updates) - botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { - delete(userStates, message.Chat.ID) - t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove()) - }, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard"))) + botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { + delete(userStates, message.Chat.ID) + t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove()) + }, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard"))) - botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { - delete(userStates, message.Chat.ID) - t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) - }, th.AnyCommand()) + botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { + delete(userStates, message.Chat.ID) + t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) + }, th.AnyCommand()) - botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) { - delete(userStates,query.Message.GetChat().ID) - t.answerCallback(&query, checkAdmin(query.From.ID)) - }, th.AnyCallbackQueryWithMessage()) + botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) { + delete(userStates, query.Message.GetChat().ID) + t.answerCallback(&query, checkAdmin(query.From.ID)) + }, th.AnyCallbackQueryWithMessage()) - botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { - if userState, exists := userStates[message.Chat.ID]; exists { - switch userState { - case "awaiting_id": - if client_Id == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - return - } + botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { + if userState, exists := userStates[message.Chat.ID]; exists { + switch userState { + case "awaiting_id": + if client_Id == strings.TrimSpace(message.Text) { + t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) + delete(userStates, message.Chat.ID) + inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) + message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) + t.addClient(message.Chat.ID, message_text) + return + } - client_Id = strings.TrimSpace(message.Text) - if t.isSingleWord(client_Id) { - userStates[message.Chat.ID] = "awaiting_id" + client_Id = strings.TrimSpace(message.Text) + if t.isSingleWord(client_Id) { + userStates[message.Chat.ID] = "awaiting_id" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) + 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_id"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - case "awaiting_password_tr": - if client_TrPassword == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - return - } + 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_id"), 3, tu.ReplyKeyboardRemove()) + delete(userStates, message.Chat.ID) + inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) + message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) + t.addClient(message.Chat.ID, message_text) + } + case "awaiting_password_tr": + if client_TrPassword == strings.TrimSpace(message.Text) { + t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) + delete(userStates, message.Chat.ID) + return + } - client_TrPassword = strings.TrimSpace(message.Text) - if t.isSingleWord(client_TrPassword) { - userStates[message.Chat.ID] = "awaiting_password_tr" + client_TrPassword = strings.TrimSpace(message.Text) + if t.isSingleWord(client_TrPassword) { + userStates[message.Chat.ID] = "awaiting_password_tr" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) + 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_password"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - case "awaiting_password_sh": - if client_ShPassword == strings.TrimSpace(message.Text) { - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - return - } + 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_password"), 3, tu.ReplyKeyboardRemove()) + delete(userStates, message.Chat.ID) + inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) + message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) + t.addClient(message.Chat.ID, message_text) + } + case "awaiting_password_sh": + if client_ShPassword == strings.TrimSpace(message.Text) { + t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) + delete(userStates, message.Chat.ID) + return + } - client_ShPassword = strings.TrimSpace(message.Text) - if t.isSingleWord(client_ShPassword) { - userStates[message.Chat.ID] = "awaiting_password_sh" + client_ShPassword = strings.TrimSpace(message.Text) + if t.isSingleWord(client_ShPassword) { + userStates[message.Chat.ID] = "awaiting_password_sh" - cancel_btn_markup := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"), - ), - ) + 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_password"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - 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()) - delete(userStates, message.Chat.ID) - return - } + 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_password"), 3, tu.ReplyKeyboardRemove()) + delete(userStates, message.Chat.ID) + inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) + message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) + t.addClient(message.Chat.ID, message_text) + } + 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()) + delete(userStates, message.Chat.ID) + return + } - client_Email = strings.TrimSpace(message.Text) - if t.isSingleWord(client_Email) { - userStates[message.Chat.ID] = "awaiting_email" + client_Email = strings.TrimSpace(message.Text) + if t.isSingleWord(client_Email) { + userStates[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"), - ), - ) + 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()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } - 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()) - delete(userStates, message.Chat.ID) - return - } + 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()) + delete(userStates, message.Chat.ID) + inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) + message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) + t.addClient(message.Chat.ID, message_text) + } + 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()) + delete(userStates, message.Chat.ID) + return + } - client_Comment = strings.TrimSpace(message.Text) - t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_comment"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, message.Chat.ID) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(message.Chat.ID, message_text) - } + client_Comment = strings.TrimSpace(message.Text) + t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_comment"), 3, tu.ReplyKeyboardRemove()) + delete(userStates, message.Chat.ID) + inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) + message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) + t.addClient(message.Chat.ID, message_text) + } - } else { - if message.UsersShared != nil { - if checkAdmin(message.From.ID) { - for _, sharedUser := range message.UsersShared.Users { - userID := sharedUser.UserID - needRestart, err := t.inboundService.SetClientTelegramUserID(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()) - } - } - } - }, th.AnyMessage()) + } else { + if message.UsersShared != nil { + if checkAdmin(message.From.ID) { + for _, sharedUser := range message.UsersShared.Users { + userID := sharedUser.UserID + needRestart, err := t.inboundService.SetClientTelegramUserID(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()) + } + } + } + }, th.AnyMessage()) - botHandler.Start() + botHandler.Start() } func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin bool) { - msg, onlyMessage := "", false + msg, onlyMessage := "", false - command, _, commandArgs := tu.ParseCommand(message.Text) + 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=="+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) - } -} - -// Helper function to send the message based on onlyMessage flag. -func (t *Tgbot) sendResponse(chatId int64, msg string, onlyMessage, isAdmin bool) { - if onlyMessage { - t.SendMsgToTgbot(chatId, msg) - } else { - t.SendAnswer(chatId, msg, isAdmin) - } -} - - -func (t *Tgbot) randomLowerAndNum(length int) string { - charset := "abcdefghijklmnopqrstuvwxyz0123456789" - bytes := make([]byte, length) - for i := range bytes { - randomIndex, _ := rand.Int(rand.Reader, big.NewInt(int64(len(charset)))) - bytes[i] = charset[randomIndex.Int64()] - } - return string(bytes) -} - - -func (t *Tgbot) randomShadowSocksPassword() string { - array := make([]byte, 32) - _, err := rand.Read(array) - if err != nil { - return t.randomLowerAndNum(32) - } - return base64.StdEncoding.EncodeToString(array) -} - - -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 "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.inboundService.ResetClientTrafficLimitByEmail(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 { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - 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.Atoi(dataArray[1]) - client_TotalGB = int64(limitTraffic) * 1024 * 1024 * 1024 - messageId := callbackQuery.Message.GetMessageID() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - - t.addClient(chatId,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 { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - 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.Atoi(dataArray[2]) - if err == nil { - var date int64 = 0 - 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.inboundService.ResetClientExpiryTimeByEmail(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 { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - 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.Atoi(dataArray[1]) - var date int64 = 0 - 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() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - - t.addClient(chatId,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 { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - 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.confirmNumber", "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.inboundService.ResetClientIpLimitByEmail(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 { - if num == -2 { - inputNumber = 0 - } else if num == -1 { - if inputNumber > 0 { - inputNumber = (inputNumber / 10) - } - } else { - 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 "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.inboundService.SetClientTelegramUserID(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.inboundService.ToggleClientEnableByEmail(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": - // assign default values to clients variables - client_Id = uuid.New().String() - client_Flow = "" - 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 - client_Security="auto" - client_ShPassword=t.randomShadowSocksPassword() - client_TrPassword=t.randomLowerAndNum(10) - client_Method="" - - inboundId := dataArray[1] - inboundIdInt, err := strconv.Atoi(inboundId) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - receiver_inbound_ID = inboundIdInt - inbound, err := t.inboundService.GetInbound(inboundIdInt) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - - t.addClient(chatId, message_text) - } - 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) - } - - } - } - - 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 "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": - // assign default values to clients variables - client_Id = uuid.New().String() - client_Flow = "" - 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 - client_Security="auto" - client_ShPassword=t.randomShadowSocksPassword() - client_TrPassword=t.randomLowerAndNum(10) - client_Method="" - - 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()) - userStates[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_id": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_id" - 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.id_prompt", "ClientId=="+client_Id) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_pass_tr": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_password_tr" - 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.pass_prompt", "ClientPassword=="+client_TrPassword) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_pass_sh": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[chatId] = "awaiting_password_sh" - 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.pass_prompt", "ClientPassword=="+client_ShPassword) - t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup) - case "add_client_ch_default_comment": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - userStates[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_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_default_info": - t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID()) - t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove()) - delete(userStates, chatId) - inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID) - message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(chatId, message_text) - case "add_client_cancel": - delete(userStates, chatId) - 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() - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error()) - return - } - message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol) - t.addClient(chatId,message_text,messageId) - t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email)) - 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()) - } - } -} - - -func (t *Tgbot) BuildInboundClientDataMessage(inbound_remark string ,protocol model.Protocol) (string, error) { - var message string - - currentTime := time.Now() - timestampMillis := currentTime.UnixNano() / int64(time.Millisecond) - - expiryTime := "" - diff := client_ExpiryTime/1000 - timestampMillis - if client_ExpiryTime == 0 { - expiryTime = t.I18nBot("tgbot.unlimited") - } else if diff > 172800 { - expiryTime = time.Unix((client_ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") - } else if client_ExpiryTime < 0 { - expiryTime = fmt.Sprintf("%d %s", client_ExpiryTime/-86400000, t.I18nBot("tgbot.days")) - } else { - expiryTime = fmt.Sprintf("%d %s", diff/3600, t.I18nBot("tgbot.hours")) - } - - traffic_value := "" - if client_TotalGB == 0 { - traffic_value = "♾️ Unlimited(Reset)" - }else { - traffic_value = common.FormatTraffic(client_TotalGB) - } - - switch protocol { - case model.VMESS, model.VLESS: - message = t.I18nBot("tgbot.messages.inbound_client_data_id", "InboundRemark=="+inbound_remark,"ClientId=="+client_Id,"ClientEmail=="+client_Email,"ClientTraffic=="+traffic_value,"ClientExp=="+expiryTime,"ClientComment=="+client_Comment) - - case model.Trojan: - message = t.I18nBot("tgbot.messages.inbound_client_data_pass", "InboundRemark=="+inbound_remark,"ClientPass=="+client_TrPassword,"ClientEmail=="+client_Email,"ClientTraffic=="+traffic_value,"ClientExp=="+expiryTime,"ClientComment=="+client_Comment) - - case model.Shadowsocks: - message = t.I18nBot("tgbot.messages.inbound_client_data_pass", "InboundRemark=="+inbound_remark,"ClientPass=="+client_ShPassword,"ClientEmail=="+client_Email,"ClientTraffic=="+traffic_value,"ClientExp=="+expiryTime,"ClientComment=="+client_Comment) + handleUnknownCommand := func() { + msg += t.I18nBot("tgbot.commands.unknown") + } + 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=="+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: - return "", errors.New("unknown protocol") + handleUnknownCommand() } - return message, nil -} - - -func (t *Tgbot) BuildJSONForProtocol(protocol model.Protocol) (string, error) { - var jsonString string - - switch protocol { - case model.VMESS: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "id": "%s", - "security": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_Id, client_Security, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - case model.VLESS: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "id": "%s", - "flow": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_Id, client_Flow, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - case model.Trojan: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "password": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_TrPassword, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - case model.Shadowsocks: - jsonString = fmt.Sprintf(`{ - "clients": [{ - "method": "%s", - "password": "%s", - "email": "%s", - "limitIp": %d, - "totalGB": %d, - "expiryTime": %d, - "enable": %t, - "tgId": "%s", - "subId": "%s", - "comment": "%s", - "reset": %d - }] - }`, client_Method, client_ShPassword, client_Email, client_LimitIP, client_TotalGB, client_ExpiryTime, client_Enable, client_TgID, client_SubID, client_Comment, client_Reset) - - default: - return "", errors.New("unknown protocol") - } - - return jsonString, nil -} - - -func (t *Tgbot) SubmitAddClient() (bool, error) { - - - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - logger.Warning("getIboundClients run failed:", err) - return false, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - - - jsonString, err := t.BuildJSONForProtocol(inbound.Protocol) - - newInbound := &model.Inbound{ - Id: receiver_inbound_ID, - Settings: jsonString, - } - - - return t.inboundService.AddInboundClient(newInbound) -} - -func checkAdmin(tgId int64) bool { - for _, adminId := range adminIds { - if adminId == tgId { - return true - } - } - return false -} - -func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { - numericKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.serverUsage")).WithCallbackData(t.encodeQuery("get_usage")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getBanLogs")).WithCallbackData(t.encodeQuery("get_banlogs")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getInbounds")).WithCallbackData(t.encodeQuery("inbounds")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.depleteSoon")).WithCallbackData(t.encodeQuery("deplete_soon")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.encodeQuery("commands")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.onlines")).WithCallbackData(t.encodeQuery("onlines")), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.allClients")).WithCallbackData(t.encodeQuery("get_inbounds")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.addClient")).WithCallbackData(t.encodeQuery("add_client")), - ), - // TODOOOOOOOOOOOOOO: Add restart button here. - ) - numericKeyboardClient := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.clientUsage")).WithCallbackData(t.encodeQuery("client_traffic")), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.encodeQuery("client_commands")), - ), - ) - - var ReplyMarkup telego.ReplyMarkup - if isAdmin { - ReplyMarkup = numericKeyboard - } else { - ReplyMarkup = numericKeyboardClient - } - t.SendMsgToTgbot(chatId, msg, ReplyMarkup) -} - -func (t *Tgbot) SendMsgToTgbot(chatId int64, msg string, replyMarkup ...telego.ReplyMarkup) { - if !isRunning { - return - } - - if msg == "" { - logger.Info("[tgbot] message is empty!") - return - } - - var allMessages []string - limit := 2000 - - // paging message if it is big - if len(msg) > limit { - messages := strings.Split(msg, "\r\n\r\n") - lastIndex := -1 - - for _, message := range messages { - if (len(allMessages) == 0) || (len(allMessages[lastIndex])+len(message) > limit) { - allMessages = append(allMessages, message) - lastIndex++ - } else { - allMessages[lastIndex] += "\r\n\r\n" + message - } - } - if strings.TrimSpace(allMessages[len(allMessages)-1]) == "" { - allMessages = allMessages[:len(allMessages)-1] - } - } else { - allMessages = append(allMessages, msg) - } - for n, message := range allMessages { - params := telego.SendMessageParams{ - ChatID: tu.ID(chatId), - Text: message, - ParseMode: "HTML", - } - // only add replyMarkup to last message - if len(replyMarkup) > 0 && n == (len(allMessages)-1) { - params.ReplyMarkup = replyMarkup[0] - } - _, err := bot.SendMessage(¶ms) - if err != nil { - logger.Warning("Error sending telegram message :", err) - } - time.Sleep(500 * time.Millisecond) - } -} - -func (t *Tgbot) SendMsgToTgbotAdmins(msg string, replyMarkup ...telego.ReplyMarkup) { - if len(replyMarkup) > 0 { - for _, adminId := range adminIds { - t.SendMsgToTgbot(adminId, msg, replyMarkup[0]) - } - } else { - for _, adminId := range adminIds { - t.SendMsgToTgbot(adminId, msg) - } - } -} - -func (t *Tgbot) SendReport() { - runTime, err := t.settingService.GetTgbotRuntime() - if err == nil && len(runTime) > 0 { - msg := "" - msg += t.I18nBot("tgbot.messages.report", "RunTime=="+runTime) - msg += t.I18nBot("tgbot.messages.datetime", "DateTime=="+time.Now().Format("2006-01-02 15:04:05")) - t.SendMsgToTgbotAdmins(msg) - } - - info := t.sendServerUsage() - t.SendMsgToTgbotAdmins(info) - - t.sendExhaustedToAdmins() - t.notifyExhausted() - - backupEnable, err := t.settingService.GetTgBotBackup() - if err == nil && backupEnable { - t.SendBackupToAdmins() - } -} - -func (t *Tgbot) SendBackupToAdmins() { - if !t.IsRunning() { - return - } - for _, adminId := range adminIds { - t.sendBackup(int64(adminId)) - } -} - -func (t *Tgbot) sendExhaustedToAdmins() { - if !t.IsRunning() { - return - } - for _, adminId := range adminIds { - t.getExhausted(int64(adminId)) - } -} - -func (t *Tgbot) getServerUsage(chatId int64, messageID ...int) string { - info := t.prepareServerUsageInfo() - - keyboard := tu.InlineKeyboard(tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.encodeQuery("usage_refresh")))) - - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], info, keyboard) - } else { - t.SendMsgToTgbot(chatId, info, keyboard) - } - - return info -} - -// Send server usage without an inline keyboard -func (t *Tgbot) sendServerUsage() string { - info := t.prepareServerUsageInfo() - return info -} - -func (t *Tgbot) prepareServerUsageInfo() string { - info, ipv4, ipv6 := "", "", "" - - // get latest status of server - t.lastStatus = t.serverService.GetStatus(t.lastStatus) - onlines := p.GetOnlineClients() - - info += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname) - info += t.I18nBot("tgbot.messages.version", "Version=="+config.GetVersion()) - info += t.I18nBot("tgbot.messages.xrayVersion", "XrayVersion=="+fmt.Sprint(t.lastStatus.Xray.Version)) - - // get ip address - netInterfaces, err := net.Interfaces() - if err != nil { - logger.Error("net.Interfaces failed, err: ", err.Error()) - info += t.I18nBot("tgbot.messages.ip", "IP=="+t.I18nBot("tgbot.unknown")) - info += "\r\n" - } else { - for i := 0; i < len(netInterfaces); i++ { - if (netInterfaces[i].Flags & net.FlagUp) != 0 { - addrs, _ := netInterfaces[i].Addrs() - - for _, address := range addrs { - if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { - if ipnet.IP.To4() != nil { - ipv4 += ipnet.IP.String() + " " - } else if ipnet.IP.To16() != nil && !ipnet.IP.IsLinkLocalUnicast() { - ipv6 += ipnet.IP.String() + " " - } - } - } - } - } - - info += t.I18nBot("tgbot.messages.ipv4", "IPv4=="+ipv4) - info += t.I18nBot("tgbot.messages.ipv6", "IPv6=="+ipv6) - } - - info += t.I18nBot("tgbot.messages.serverUpTime", "UpTime=="+strconv.FormatUint(t.lastStatus.Uptime/86400, 10), "Unit=="+t.I18nBot("tgbot.days")) - info += t.I18nBot("tgbot.messages.serverLoad", "Load1=="+strconv.FormatFloat(t.lastStatus.Loads[0], 'f', 2, 64), "Load2=="+strconv.FormatFloat(t.lastStatus.Loads[1], 'f', 2, 64), "Load3=="+strconv.FormatFloat(t.lastStatus.Loads[2], 'f', 2, 64)) - info += t.I18nBot("tgbot.messages.serverMemory", "Current=="+common.FormatTraffic(int64(t.lastStatus.Mem.Current)), "Total=="+common.FormatTraffic(int64(t.lastStatus.Mem.Total))) - info += t.I18nBot("tgbot.messages.onlinesCount", "Count=="+fmt.Sprint(len(onlines))) - info += t.I18nBot("tgbot.messages.tcpCount", "Count=="+strconv.Itoa(t.lastStatus.TcpCount)) - info += t.I18nBot("tgbot.messages.udpCount", "Count=="+strconv.Itoa(t.lastStatus.UdpCount)) - info += t.I18nBot("tgbot.messages.traffic", "Total=="+common.FormatTraffic(int64(t.lastStatus.NetTraffic.Sent+t.lastStatus.NetTraffic.Recv)), "Upload=="+common.FormatTraffic(int64(t.lastStatus.NetTraffic.Sent)), "Download=="+common.FormatTraffic(int64(t.lastStatus.NetTraffic.Recv))) - info += t.I18nBot("tgbot.messages.xrayStatus", "State=="+fmt.Sprint(t.lastStatus.Xray.State)) - return info -} - -func (t *Tgbot) UserLoginNotify(username string, password string, ip string, time string, status LoginStatus) { - if !t.IsRunning() { - return - } - - if username == "" || ip == "" || time == "" { - logger.Warning("UserLoginNotify failed, invalid info!") - return - } - - loginNotifyEnabled, err := t.settingService.GetTgBotLoginNotify() - if err != nil || !loginNotifyEnabled { - return - } - - msg := "" - if status == LoginSuccess { - msg += t.I18nBot("tgbot.messages.loginSuccess") - msg += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname) - } else if status == LoginFail { - msg += t.I18nBot("tgbot.messages.loginFailed") - msg += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname) - msg += t.I18nBot("tgbot.messages.password", "Password=="+password) - } - msg += t.I18nBot("tgbot.messages.username", "Username=="+username) - msg += t.I18nBot("tgbot.messages.ip", "IP=="+ip) - msg += t.I18nBot("tgbot.messages.time", "Time=="+time) - t.SendMsgToTgbotAdmins(msg) -} - -func (t *Tgbot) getInboundUsages() string { - info := "" - // get traffic - inbounds, err := t.inboundService.GetAllInbounds() - if err != nil { - logger.Warning("GetAllInbounds run failed:", err) - info += t.I18nBot("tgbot.answers.getInboundsFailed") - } else { - // NOTE:If there no any sessions here,need to notify here - // TODO:Sub-node push, automatic conversion format - for _, inbound := range inbounds { - info += t.I18nBot("tgbot.messages.inbound", "Remark=="+inbound.Remark) - info += t.I18nBot("tgbot.messages.port", "Port=="+strconv.Itoa(inbound.Port)) - info += t.I18nBot("tgbot.messages.traffic", "Total=="+common.FormatTraffic((inbound.Up+inbound.Down)), "Upload=="+common.FormatTraffic(inbound.Up), "Download=="+common.FormatTraffic(inbound.Down)) - - if inbound.ExpiryTime == 0 { - info += t.I18nBot("tgbot.messages.expire", "Time=="+t.I18nBot("tgbot.unlimited")) - } else { - info += t.I18nBot("tgbot.messages.expire", "Time=="+time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) - } - info += "\r\n" - } - } - return info -} -func (t *Tgbot) getInbounds() (*telego.InlineKeyboardMarkup, error) { - inbounds, err := t.inboundService.GetAllInbounds() - if err != nil { - logger.Warning("GetAllInbounds run failed:", err) - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - if len(inbounds) == 0 { - logger.Warning("No inbounds found") - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - var buttons []telego.InlineKeyboardButton - for _, inbound := range inbounds { - status := "❌" - if inbound.Enable { - status = "βœ…" - } - callbackData := t.encodeQuery(fmt.Sprintf("%s %d","get_clients", inbound.Id)) - buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(callbackData)) - } - - cols := 1 - if len(buttons) >= 6 { - cols = 2 - } - - keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) - return keyboard, nil -} - -func (t *Tgbot) getInboundsAddClient() (*telego.InlineKeyboardMarkup, error) { - inbounds, err := t.inboundService.GetAllInbounds() - if err != nil { - logger.Warning("GetAllInbounds run failed:", err) - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - if len(inbounds) == 0 { - logger.Warning("No inbounds found") - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - - excludedProtocols := map[model.Protocol]bool{ - model.DOKODEMO: true, - model.Socks: true, - model.WireGuard: true, - model.HTTP: true, - } - - var buttons []telego.InlineKeyboardButton - for _, inbound := range inbounds { - if excludedProtocols[inbound.Protocol] { - continue - } - - status := "❌" - if inbound.Enable { - status = "βœ…" - } - callbackData := t.encodeQuery(fmt.Sprintf("%s %d","add_client_to", inbound.Id)) - buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(callbackData)) - } - - cols := 1 - if len(buttons) >= 6 { - cols = 2 - } - - keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) - return keyboard, nil -} - -func (t *Tgbot) getInboundClients(id int) (*telego.InlineKeyboardMarkup, error) { - inbound, err := t.inboundService.GetInbound(id) - if err != nil { - logger.Warning("getIboundClients run failed:", err) - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } - clients, err := t.inboundService.GetClients(inbound) - var buttons []telego.InlineKeyboardButton - - if err != nil { - logger.Warning("GetInboundClients run failed:", err) - return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) - } else { - if len(clients) > 0 { - for _, client := range clients { - buttons = append(buttons, tu.InlineKeyboardButton(client.Email).WithCallbackData(t.encodeQuery("client_get_usage "+client.Email))) - } - - } else { - return nil, errors.New(t.I18nBot("tgbot.answers.getClientsFailed")) - } - - } - cols := 0 - if len(buttons) < 6 { - cols = 3 - } else { - cols = 2 - } - keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) - - return keyboard, nil -} - -func (t *Tgbot) clientInfoMsg( - traffic *xray.ClientTraffic, - printEnabled bool, - printOnline bool, - printActive bool, - printDate bool, - printTraffic bool, - printRefreshed bool, -) string { - now := time.Now().Unix() - expiryTime := "" - flag := false - diff := traffic.ExpiryTime/1000 - now - if traffic.ExpiryTime == 0 { - expiryTime = t.I18nBot("tgbot.unlimited") - } else if diff > 172800 || !traffic.Enable { - expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05") - } else if traffic.ExpiryTime < 0 { - expiryTime = fmt.Sprintf("%d %s", traffic.ExpiryTime/-86400000, t.I18nBot("tgbot.days")) - flag = true - } else { - expiryTime = fmt.Sprintf("%d %s", diff/3600, t.I18nBot("tgbot.hours")) - flag = true - } - - total := "" - if traffic.Total == 0 { - total = t.I18nBot("tgbot.unlimited") - } else { - total = common.FormatTraffic((traffic.Total)) - } - - enabled := "" - isEnabled, err := t.inboundService.checkIsEnabledByEmail(traffic.Email) - if err != nil { - logger.Warning(err) - enabled = t.I18nBot("tgbot.wentWrong") - } else if isEnabled { - enabled = t.I18nBot("tgbot.messages.yes") - } else { - enabled = t.I18nBot("tgbot.messages.no") - } - - active := "" - if traffic.Enable { - active = t.I18nBot("tgbot.messages.yes") - } else { - active = t.I18nBot("tgbot.messages.no") - } - - status := t.I18nBot("tgbot.offline") - if p.IsRunning() { - for _, online := range p.GetOnlineClients() { - if online == traffic.Email { - status = t.I18nBot("tgbot.online") - break - } - } - } - - output := "" - output += t.I18nBot("tgbot.messages.email", "Email=="+traffic.Email) - if printEnabled { - output += t.I18nBot("tgbot.messages.enabled", "Enable=="+enabled) - } - if printOnline { - output += t.I18nBot("tgbot.messages.online", "Status=="+status) - } - if printActive { - output += t.I18nBot("tgbot.messages.active", "Enable=="+active) - } - if printDate { - if flag { - output += t.I18nBot("tgbot.messages.expireIn", "Time=="+expiryTime) - } else { - output += t.I18nBot("tgbot.messages.expire", "Time=="+expiryTime) - } - } - if printTraffic { - output += t.I18nBot("tgbot.messages.upload", "Upload=="+common.FormatTraffic(traffic.Up)) - output += t.I18nBot("tgbot.messages.download", "Download=="+common.FormatTraffic(traffic.Down)) - output += t.I18nBot("tgbot.messages.total", "UpDown=="+common.FormatTraffic((traffic.Up+traffic.Down)), "Total=="+total) - } - if printRefreshed { - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - } - - return output -} - -func (t *Tgbot) getClientUsage(chatId int64, tgUserID int64, email ...string) { - traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID) - if err != nil { - logger.Warning(err) - msg := t.I18nBot("tgbot.wentWrong") - t.SendMsgToTgbot(chatId, msg) - return - } - - if len(traffics) == 0 { - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10))) - return - } - - output := "" - - if len(traffics) > 0 { - if len(email) > 0 { - for _, traffic := range traffics { - if traffic.Email == email[0] { - output := t.clientInfoMsg(traffic, true, true, true, true, true, true) - t.SendMsgToTgbot(chatId, output) - return - } - } - msg := t.I18nBot("tgbot.noResult") - t.SendMsgToTgbot(chatId, msg) - return - } else { - for _, traffic := range traffics { - output += t.clientInfoMsg(traffic, true, true, true, true, true, false) - output += "\r\n" - } - } - } - - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - t.SendMsgToTgbot(chatId, output) - output = t.I18nBot("tgbot.commands.pleaseChoose") - t.SendAnswer(chatId, output, false) -} - -func (t *Tgbot) searchClientIps(chatId int64, email string, messageID ...int) { - ips, err := t.inboundService.GetInboundClientIps(email) - if err != nil || len(ips) == 0 { - ips = t.I18nBot("tgbot.noIpRecord") - } - - output := "" - output += t.I18nBot("tgbot.messages.email", "Email=="+email) - output += t.I18nBot("tgbot.messages.ips", "IPs=="+ips) - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.encodeQuery("ips_refresh "+email)), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.clearIPs")).WithCallbackData(t.encodeQuery("clear_ips "+email)), - ), - ) - - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], output, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, output, inlineKeyboard) - } -} - -func (t *Tgbot) clientTelegramUserInfo(chatId int64, email string, messageID ...int) { - traffic, client, err := t.inboundService.GetClientByEmail(email) - if err != nil { - logger.Warning(err) - msg := t.I18nBot("tgbot.wentWrong") - t.SendMsgToTgbot(chatId, msg) - return - } - if client == nil { - msg := t.I18nBot("tgbot.noResult") - t.SendMsgToTgbot(chatId, msg) - return - } - tgId := "None" - if client.TgID != 0 { - tgId = strconv.FormatInt(client.TgID, 10) - } - - output := "" - output += t.I18nBot("tgbot.messages.email", "Email=="+email) - output += t.I18nBot("tgbot.messages.TGUser", "TelegramID=="+tgId) - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.encodeQuery("tgid_refresh "+email)), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.removeTGUser")).WithCallbackData(t.encodeQuery("tgid_remove "+email)), - ), - ) - - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], output, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, output, inlineKeyboard) - requestUser := telego.KeyboardButtonRequestUsers{ - RequestID: int32(traffic.Id), - UserIsBot: new(bool), - } - keyboard := tu.Keyboard( - tu.KeyboardRow( - tu.KeyboardButton(t.I18nBot("tgbot.buttons.selectTGUser")).WithRequestUsers(&requestUser), - ), - tu.KeyboardRow( - tu.KeyboardButton(t.I18nBot("tgbot.buttons.closeKeyboard")), - ), - ).WithIsPersistent().WithResizeKeyboard() - t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.buttons.selectOneTGUser"), keyboard) - } -} - -func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) { - 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 - } - - output := t.clientInfoMsg(traffic, true, true, true, true, true, true) - - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.encodeQuery("client_refresh "+email)), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetTraffic")).WithCallbackData(t.encodeQuery("reset_traffic "+email)), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData(t.encodeQuery("limit_traffic "+email)), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData(t.encodeQuery("reset_exp "+email)), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.ipLog")).WithCallbackData(t.encodeQuery("ip_log "+email)), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.ipLimit")).WithCallbackData(t.encodeQuery("ip_limit "+email)), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.setTGUser")).WithCallbackData(t.encodeQuery("tg_user "+email)), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.toggle")).WithCallbackData(t.encodeQuery("toggle_enable "+email)), - ), - ) - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], output, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, output, inlineKeyboard) - } -} - -func (t *Tgbot) addClient(chatId int64, msg string, messageID ...int) { - inbound, err := t.inboundService.GetInbound(receiver_inbound_ID) - if err != nil { - t.SendMsgToTgbot(chatId, err.Error()) - return - } - - protocol := inbound.Protocol - - switch protocol { - case model.VMESS, model.VLESS: - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_id")).WithCallbackData("add_client_ch_default_id"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"), - ), - ) - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, msg, inlineKeyboard) - } - case model.Trojan: - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_password")).WithCallbackData("add_client_ch_default_pass_tr"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"), - ), - ) - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, msg, inlineKeyboard) - } - case model.Shadowsocks: - inlineKeyboard := tu.InlineKeyboard( - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_password")).WithCallbackData("add_client_ch_default_pass_sh"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"), - ), - tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"), - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"), - ), - ) - - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard) - } else { - t.SendMsgToTgbot(chatId, msg, inlineKeyboard) - } - } - -} - -func (t *Tgbot) searchInbound(chatId int64, remark string) { - inbounds, err := t.inboundService.SearchInbounds(remark) - if err != nil { - logger.Warning(err) - msg := t.I18nBot("tgbot.wentWrong") - t.SendMsgToTgbot(chatId, msg) - return - } - if len(inbounds) == 0 { - msg := t.I18nBot("tgbot.noInbounds") - t.SendMsgToTgbot(chatId, msg) - return - } - - for _, inbound := range inbounds { - info := "" - info += t.I18nBot("tgbot.messages.inbound", "Remark=="+inbound.Remark) - info += t.I18nBot("tgbot.messages.port", "Port=="+strconv.Itoa(inbound.Port)) - info += t.I18nBot("tgbot.messages.traffic", "Total=="+common.FormatTraffic((inbound.Up+inbound.Down)), "Upload=="+common.FormatTraffic(inbound.Up), "Download=="+common.FormatTraffic(inbound.Down)) - - if inbound.ExpiryTime == 0 { - info += t.I18nBot("tgbot.messages.expire", "Time=="+t.I18nBot("tgbot.unlimited")) - } else { - info += t.I18nBot("tgbot.messages.expire", "Time=="+time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) - } - t.SendMsgToTgbot(chatId, info) - - if len(inbound.ClientStats) > 0 { - output := "" - for _, traffic := range inbound.ClientStats { - output += t.clientInfoMsg(&traffic, true, true, true, true, true, true) - } - t.SendMsgToTgbot(chatId, output) - } - } -} - -func (t *Tgbot) getExhausted(chatId int64) { - trDiff := int64(0) - exDiff := int64(0) - now := time.Now().Unix() * 1000 - var exhaustedInbounds []model.Inbound - var exhaustedClients []xray.ClientTraffic - var disabledInbounds []model.Inbound - var disabledClients []xray.ClientTraffic - - TrafficThreshold, err := t.settingService.GetTrafficDiff() - if err == nil && TrafficThreshold > 0 { - trDiff = int64(TrafficThreshold) * 1073741824 - } - ExpireThreshold, err := t.settingService.GetExpireDiff() - if err == nil && ExpireThreshold > 0 { - exDiff = int64(ExpireThreshold) * 86400000 - } - inbounds, err := t.inboundService.GetAllInbounds() - if err != nil { - logger.Warning("Unable to load Inbounds", err) - } - - for _, inbound := range inbounds { - if inbound.Enable { - if (inbound.ExpiryTime > 0 && (inbound.ExpiryTime-now < exDiff)) || - (inbound.Total > 0 && (inbound.Total-(inbound.Up+inbound.Down) < trDiff)) { - exhaustedInbounds = append(exhaustedInbounds, *inbound) - } - if len(inbound.ClientStats) > 0 { - for _, client := range inbound.ClientStats { - if client.Enable { - if (client.ExpiryTime > 0 && (client.ExpiryTime-now < exDiff)) || - (client.Total > 0 && (client.Total-(client.Up+client.Down) < trDiff)) { - exhaustedClients = append(exhaustedClients, client) - } - } else { - disabledClients = append(disabledClients, client) - } - } - } - } else { - disabledInbounds = append(disabledInbounds, *inbound) - } - } - - // Inbounds - output := "" - output += t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.inbounds")) - output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledInbounds))) - output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(len(exhaustedInbounds))) - - if len(exhaustedInbounds) > 0 { - output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+t.I18nBot("tgbot.inbounds")) - - for _, inbound := range exhaustedInbounds { - output += t.I18nBot("tgbot.messages.inbound", "Remark=="+inbound.Remark) - output += t.I18nBot("tgbot.messages.port", "Port=="+strconv.Itoa(inbound.Port)) - output += t.I18nBot("tgbot.messages.traffic", "Total=="+common.FormatTraffic((inbound.Up+inbound.Down)), "Upload=="+common.FormatTraffic(inbound.Up), "Download=="+common.FormatTraffic(inbound.Down)) - if inbound.ExpiryTime == 0 { - output += t.I18nBot("tgbot.messages.expire", "Time=="+t.I18nBot("tgbot.unlimited")) - } else { - output += t.I18nBot("tgbot.messages.expire", "Time=="+time.Unix((inbound.ExpiryTime/1000), 0).Format("2006-01-02 15:04:05")) - } - output += "\r\n" - } - } - - // Clients - exhaustedCC := len(exhaustedClients) - output += t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.clients")) - output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledClients))) - output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(exhaustedCC)) - - if exhaustedCC > 0 { - output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+t.I18nBot("tgbot.clients")) - var buttons []telego.InlineKeyboardButton - for _, traffic := range exhaustedClients { - output += t.clientInfoMsg(&traffic, true, false, false, true, true, false) - output += "\r\n" - buttons = append(buttons, tu.InlineKeyboardButton(traffic.Email).WithCallbackData(t.encodeQuery("client_get_usage "+traffic.Email))) - } - cols := 0 - if exhaustedCC < 11 { - cols = 1 - } else { - cols = 2 - } - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) - t.SendMsgToTgbot(chatId, output, keyboard) - } else { - output += t.I18nBot("tgbot.messages.refreshedOn", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - t.SendMsgToTgbot(chatId, output) - } -} - -func (t *Tgbot) notifyExhausted() { - trDiff := int64(0) - exDiff := int64(0) - now := time.Now().Unix() * 1000 - - TrafficThreshold, err := t.settingService.GetTrafficDiff() - if err == nil && TrafficThreshold > 0 { - trDiff = int64(TrafficThreshold) * 1073741824 - } - ExpireThreshold, err := t.settingService.GetExpireDiff() - if err == nil && ExpireThreshold > 0 { - exDiff = int64(ExpireThreshold) * 86400000 - } - inbounds, err := t.inboundService.GetAllInbounds() - if err != nil { - logger.Warning("Unable to load Inbounds", err) - } - - var chatIDsDone []int64 - for _, inbound := range inbounds { - if inbound.Enable { - if len(inbound.ClientStats) > 0 { - clients, err := t.inboundService.GetClients(inbound) - if err == nil { - for _, client := range clients { - if client.TgID != 0 { - chatID := client.TgID - if !int64Contains(chatIDsDone, chatID) && !checkAdmin(chatID) { - var disabledClients []xray.ClientTraffic - var exhaustedClients []xray.ClientTraffic - traffics, err := t.inboundService.GetClientTrafficTgBot(client.TgID) - if err == nil && len(traffics) > 0 { - output := t.I18nBot("tgbot.messages.exhaustedCount", "Type=="+t.I18nBot("tgbot.clients")) - for _, traffic := range traffics { - if traffic.Enable { - if (traffic.ExpiryTime > 0 && (traffic.ExpiryTime-now < exDiff)) || - (traffic.Total > 0 && (traffic.Total-(traffic.Up+traffic.Down) < trDiff)) { - exhaustedClients = append(exhaustedClients, *traffic) - } - } else { - disabledClients = append(disabledClients, *traffic) - } - } - if len(exhaustedClients) > 0 { - output += t.I18nBot("tgbot.messages.disabled", "Disabled=="+strconv.Itoa(len(disabledClients))) - if len(disabledClients) > 0 { - output += t.I18nBot("tgbot.clients") + ":\r\n" - for _, traffic := range disabledClients { - output += " " + traffic.Email - } - output += "\r\n" - } - output += "\r\n" - output += t.I18nBot("tgbot.messages.depleteSoon", "Deplete=="+strconv.Itoa(len(exhaustedClients))) - for _, traffic := range exhaustedClients { - output += t.clientInfoMsg(&traffic, true, false, false, true, true, false) - output += "\r\n" - } - t.SendMsgToTgbot(chatID, output) - } - chatIDsDone = append(chatIDsDone, chatID) - } - } - } - } - } - } - } - } -} - -func int64Contains(slice []int64, item int64) bool { - for _, s := range slice { - if s == item { - return true - } - } - return false -} - -func (t *Tgbot) onlineClients(chatId int64, messageID ...int) { - if !p.IsRunning() { - return - } - - onlines := p.GetOnlineClients() - onlinesCount := len(onlines) - output := t.I18nBot("tgbot.messages.onlinesCount", "Count=="+fmt.Sprint(onlinesCount)) - keyboard := tu.InlineKeyboard(tu.InlineKeyboardRow( - tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.refresh")).WithCallbackData(t.encodeQuery("onlines_refresh")))) - - if onlinesCount > 0 { - var buttons []telego.InlineKeyboardButton - for _, online := range onlines { - buttons = append(buttons, tu.InlineKeyboardButton(online).WithCallbackData(t.encodeQuery("client_get_usage "+online))) - } - cols := 0 - if onlinesCount < 21 { - cols = 2 - } else if onlinesCount < 61 { - cols = 3 - } else { - cols = 4 - } - keyboard.InlineKeyboard = append(keyboard.InlineKeyboard, tu.InlineKeyboardCols(cols, buttons...)...) - } - - if len(messageID) > 0 { - t.editMessageTgBot(chatId, messageID[0], output, keyboard) - } else { - t.SendMsgToTgbot(chatId, output, keyboard) - } -} - -func (t *Tgbot) sendBackup(chatId int64) { - output := t.I18nBot("tgbot.messages.backupTime", "Time=="+time.Now().Format("2006-01-02 15:04:05")) - t.SendMsgToTgbot(chatId, output) - - // Update by manually trigger a checkpoint operation - err := database.Checkpoint() - if err != nil { - logger.Error("Error in trigger a checkpoint operation: ", err) - } - - file, err := os.Open(config.GetDBPath()) - if err == nil { - document := tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Error("Error in uploading backup: ", err) - } - } else { - logger.Error("Error in opening db file for backup: ", err) - } - - file, err = os.Open(xray.GetConfigPath()) - if err == nil { - document := tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Error("Error in uploading config.json: ", err) - } - } else { - logger.Error("Error in opening config.json file for backup: ", err) - } -} - -func (t *Tgbot) sendBanLogs(chatId int64, dt bool) { - if dt { - output := t.I18nBot("tgbot.messages.datetime", "DateTime=="+time.Now().Format("2006-01-02 15:04:05")) - t.SendMsgToTgbot(chatId, output) - } - - file, err := os.Open(xray.GetIPLimitBannedPrevLogPath()) - if err == nil { - // Check if the file is non-empty before attempting to upload - fileInfo, _ := file.Stat() - if fileInfo.Size() > 0 { - document := tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Error("Error in uploading IPLimitBannedPrevLog: ", err) - } - } else { - logger.Warning("IPLimitBannedPrevLog file is empty, not uploading.") - } - file.Close() - } else { - logger.Error("Error in opening IPLimitBannedPrevLog file for backup: ", err) - } - - file, err = os.Open(xray.GetIPLimitBannedLogPath()) - if err == nil { - // Check if the file is non-empty before attempting to upload - fileInfo, _ := file.Stat() - if fileInfo.Size() > 0 { - document := tu.Document( - tu.ID(chatId), - tu.File(file), - ) - _, err = bot.SendDocument(document) - if err != nil { - logger.Error("Error in uploading IPLimitBannedLog: ", err) - } - } else { - logger.Warning("IPLimitBannedLog file is empty, not uploading.") - } - file.Close() - } else { - logger.Error("Error in opening IPLimitBannedLog file for backup: ", err) - } -} - -func (t *Tgbot) sendCallbackAnswerTgBot(id string, message string) { - params := telego.AnswerCallbackQueryParams{ - CallbackQueryID: id, - Text: message, - } - if err := bot.AnswerCallbackQuery(¶ms); err != nil { - logger.Warning(err) - } -} - -func (t *Tgbot) editMessageCallbackTgBot(chatId int64, messageID int, inlineKeyboard *telego.InlineKeyboardMarkup) { - params := telego.EditMessageReplyMarkupParams{ - ChatID: tu.ID(chatId), - MessageID: messageID, - ReplyMarkup: inlineKeyboard, - } - if _, err := bot.EditMessageReplyMarkup(¶ms); err != nil { - logger.Warning(err) - } -} - -func (t *Tgbot) editMessageTgBot(chatId int64, messageID int, text string, inlineKeyboard ...*telego.InlineKeyboardMarkup) { - params := telego.EditMessageTextParams{ - ChatID: tu.ID(chatId), - MessageID: messageID, - Text: text, - ParseMode: "HTML", - } - if len(inlineKeyboard) > 0 { - params.ReplyMarkup = inlineKeyboard[0] - } - if _, err := bot.EditMessageText(¶ms); err != nil { - logger.Warning(err) - } -} - - -func (t *Tgbot) SendMsgToTgbotDeleteAfter(chatId int64, msg string, delayInSeconds int, replyMarkup ...telego.ReplyMarkup) { - // Determine if replyMarkup was passed; otherwise, set it to nil - var replyMarkupParam telego.ReplyMarkup - if len(replyMarkup) > 0 { - replyMarkupParam = replyMarkup[0] // Use the first element - } - - // Send the message - sentMsg, err := bot.SendMessage(&telego.SendMessageParams{ - ChatID: tu.ID(chatId), - Text: msg, - ReplyMarkup: replyMarkupParam, // Use the correct replyMarkup value - }) - if err != nil { - logger.Warning("Failed to send message:", err) - return - } - - // Delete the sent message after the specified number of seconds - go func() { - time.Sleep(time.Duration(delayInSeconds) * time.Second) // Wait for the specified delay - t.deleteMessageTgBot(chatId, sentMsg.MessageID) // Delete the message - delete(userStates, chatId) - }() -} - -func (t *Tgbot) deleteMessageTgBot(chatId int64, messageID int) { - params := telego.DeleteMessageParams{ - ChatID: tu.ID(chatId), - MessageID: messageID, - } - if err := bot.DeleteMessage(¶ms); err != nil { - logger.Warning("Failed to delete message:", err) - } else { - logger.Info("Message deleted successfully") - } -} - -func (t *Tgbot) isSingleWord(text string) bool { - text = strings.TrimSpace(text) - re := regexp.MustCompile(`\s+`) - return re.MatchString(text) -} - + if msg != "" { + t.sendResponse(chatId