tgbot_router.go 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502
  1. package tgbot
  2. import (
  3. "context"
  4. "fmt"
  5. "html"
  6. "slices"
  7. "strconv"
  8. "strings"
  9. "time"
  10. "github.com/mhsanaei/3x-ui/v3/internal/logger"
  11. "github.com/mymmrac/telego"
  12. th "github.com/mymmrac/telego/telegohandler"
  13. tu "github.com/mymmrac/telego/telegoutil"
  14. )
  15. // recoverBotPanic must be deferred by every bot handler entry point: telego's
  16. // dispatch has no recovery of its own, so one bad update would kill the panel.
  17. func recoverBotPanic() {
  18. if r := recover(); r != nil {
  19. logger.Error("Recovered panic in Telegram bot handler:", r)
  20. }
  21. }
  22. // runBotHandler runs a bot handler on a worker slot and recovers panics: a bad
  23. // callback must not take down the whole panel, the way a cron panic would not.
  24. func runBotHandler(fn func()) {
  25. messageWorkerPool <- struct{}{}
  26. defer func() { <-messageWorkerPool }()
  27. defer recoverBotPanic()
  28. fn()
  29. }
  30. // chooseInboundClient fetches the inbound once and reuses the row: the inline
  31. // keyboard outlives the inbound, so a stale tap must answer an error, not panic.
  32. func (t *Tgbot) chooseInboundClient(callbackQuery *telego.CallbackQuery, chatId int64, inboundID int, action string) {
  33. inbound, err := t.inboundService.GetInbound(inboundID)
  34. if err != nil {
  35. logger.Warning("chooseInboundClient GetInbound failed:", err)
  36. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getInboundsFailed"))
  37. return
  38. }
  39. clientsKB, err := t.getInboundClientsFor(inbound, action)
  40. if err != nil {
  41. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  42. return
  43. }
  44. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clientsKB)
  45. }
  46. // OnReceive starts the message receiving loop for the Telegram bot.
  47. func (t *Tgbot) OnReceive() {
  48. params := telego.GetUpdatesParams{
  49. Timeout: 20, // Reduced timeout to detect connection issues faster
  50. }
  51. // Strict singleton: never start a second long-polling loop.
  52. tgBotMutex.Lock()
  53. if botCancel != nil || isRunning {
  54. tgBotMutex.Unlock()
  55. logger.Warning("TgBot OnReceive called while already running; ignoring.")
  56. return
  57. }
  58. ctx, cancel := context.WithCancel(context.Background())
  59. botCancel = cancel
  60. isRunning = true
  61. // Add to WaitGroup before releasing the lock so StopBot() can't return
  62. // before this receiver goroutine is accounted for.
  63. botWG.Add(1)
  64. tgBotMutex.Unlock()
  65. // Get updates channel using the context with shorter timeout for better error recovery
  66. updates, _ := bot.UpdatesViaLongPolling(ctx, &params)
  67. go func() {
  68. defer botWG.Done()
  69. h, _ := th.NewBotHandler(bot, updates)
  70. tgBotMutex.Lock()
  71. botHandler = h
  72. tgBotMutex.Unlock()
  73. h.HandleMessage(func(ctx *th.Context, message telego.Message) error {
  74. defer recoverBotPanic()
  75. userStateMgr.clear(message.Chat.ID)
  76. t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove())
  77. return nil
  78. }, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard")))
  79. h.HandleMessage(func(ctx *th.Context, message telego.Message) error {
  80. defer recoverBotPanic()
  81. if !t.isCommandForCurrentBot(&message) {
  82. return nil
  83. }
  84. // Use goroutine with worker pool for concurrent command processing
  85. go runBotHandler(func() {
  86. userStateMgr.clear(message.Chat.ID)
  87. t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID))
  88. })
  89. return nil
  90. }, th.AnyCommand())
  91. h.HandleCallbackQuery(func(ctx *th.Context, query telego.CallbackQuery) error {
  92. // Use goroutine with worker pool for concurrent callback processing
  93. go runBotHandler(func() {
  94. userStateMgr.clear(query.Message.GetChat().ID)
  95. t.answerCallback(&query, checkAdmin(query.From.ID))
  96. })
  97. return nil
  98. }, th.AnyCallbackQueryWithMessage())
  99. h.HandleMessage(func(ctx *th.Context, message telego.Message) error {
  100. defer recoverBotPanic()
  101. userStateMgr.maybePrune(time.Hour)
  102. if userState, exists := userStateMgr.get(message.Chat.ID); exists {
  103. switch userState {
  104. case "awaiting_email":
  105. if client_Email == strings.TrimSpace(message.Text) {
  106. t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
  107. userStateMgr.clear(message.Chat.ID)
  108. return nil
  109. }
  110. client_Email = strings.TrimSpace(message.Text)
  111. if t.isSingleWord(client_Email) {
  112. userStateMgr.set(message.Chat.ID, "awaiting_email")
  113. cancel_btn_markup := tu.InlineKeyboard(
  114. tu.InlineKeyboardRow(
  115. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
  116. ),
  117. )
  118. t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup)
  119. } else {
  120. t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_email"), 3, tu.ReplyKeyboardRemove())
  121. userStateMgr.clear(message.Chat.ID)
  122. t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
  123. }
  124. case "awaiting_comment":
  125. if client_Comment == strings.TrimSpace(message.Text) {
  126. t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
  127. userStateMgr.clear(message.Chat.ID)
  128. return nil
  129. }
  130. client_Comment = strings.TrimSpace(message.Text)
  131. t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_comment"), 3, tu.ReplyKeyboardRemove())
  132. userStateMgr.clear(message.Chat.ID)
  133. t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
  134. case "awaiting_tg_id":
  135. input := strings.TrimSpace(message.Text)
  136. if input == "" || input == "-" || strings.EqualFold(input, "none") {
  137. client_TgID = ""
  138. t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
  139. userStateMgr.clear(message.Chat.ID)
  140. t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
  141. return nil
  142. }
  143. if _, err := strconv.ParseInt(input, 10, 64); err != nil {
  144. cancel_btn_markup := tu.InlineKeyboard(
  145. tu.InlineKeyboardRow(
  146. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
  147. ),
  148. )
  149. t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup)
  150. return nil
  151. }
  152. client_TgID = input
  153. t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.userSaved"), 3, tu.ReplyKeyboardRemove())
  154. userStateMgr.clear(message.Chat.ID)
  155. t.addClient(message.Chat.ID, t.BuildClientDraftMessage())
  156. }
  157. } else {
  158. if message.UsersShared != nil {
  159. if checkAdmin(message.From.ID) {
  160. for _, sharedUser := range message.UsersShared.Users {
  161. userID := sharedUser.UserID
  162. needRestart, err := t.clientService.SetClientTelegramUserID(&t.inboundService, message.UsersShared.RequestID, userID)
  163. if needRestart {
  164. t.xrayService.SetToNeedRestart()
  165. }
  166. output := ""
  167. if err != nil {
  168. output += t.I18nBot("tgbot.messages.selectUserFailed")
  169. } else {
  170. output += t.I18nBot("tgbot.messages.userSaved")
  171. }
  172. t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove())
  173. }
  174. } else {
  175. t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove())
  176. }
  177. }
  178. }
  179. return nil
  180. }, th.AnyMessage())
  181. _ = h.Start()
  182. }()
  183. }
  184. // answerCommand processes incoming command messages from Telegram users.
  185. func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin bool) {
  186. msg, onlyMessage := "", false
  187. command, _, commandArgs := tu.ParseCommand(message.Text)
  188. // Helper function to handle unknown commands.
  189. handleUnknownCommand := func() {
  190. msg += t.I18nBot("tgbot.commands.unknown")
  191. }
  192. // Handle the command.
  193. switch command {
  194. case "help":
  195. msg += t.I18nBot("tgbot.commands.help")
  196. msg += t.I18nBot("tgbot.commands.pleaseChoose")
  197. case "start":
  198. msg += t.I18nBot("tgbot.commands.start", "Firstname=="+html.EscapeString(message.From.FirstName))
  199. if isAdmin {
  200. msg += t.I18nBot("tgbot.commands.welcome", "Hostname=="+hostname)
  201. }
  202. msg += "\n\n" + t.I18nBot("tgbot.commands.pleaseChoose")
  203. case "status":
  204. onlyMessage = true
  205. msg += t.I18nBot("tgbot.commands.status")
  206. case "id":
  207. onlyMessage = true
  208. msg += t.I18nBot("tgbot.commands.getID", "ID=="+strconv.FormatInt(message.From.ID, 10))
  209. case "usage":
  210. onlyMessage = true
  211. if len(commandArgs) > 0 {
  212. if isAdmin {
  213. t.searchClient(chatId, commandArgs[0])
  214. } else {
  215. t.getClientUsage(chatId, message.From.ID, commandArgs[0])
  216. }
  217. } else {
  218. msg += t.I18nBot("tgbot.commands.usage")
  219. }
  220. case "inbound":
  221. onlyMessage = true
  222. if isAdmin && len(commandArgs) > 0 {
  223. t.searchInbound(chatId, commandArgs[0])
  224. } else {
  225. handleUnknownCommand()
  226. }
  227. case "restart":
  228. onlyMessage = true
  229. if isAdmin {
  230. if len(commandArgs) == 0 {
  231. if t.xrayService.IsXrayRunning() {
  232. err := t.xrayService.RestartXray(true)
  233. if err != nil {
  234. msg += t.I18nBot("tgbot.commands.restartFailed", "Error=="+err.Error())
  235. } else {
  236. msg += t.I18nBot("tgbot.commands.restartSuccess")
  237. }
  238. } else {
  239. msg += t.I18nBot("tgbot.commands.xrayNotRunning")
  240. }
  241. } else {
  242. handleUnknownCommand()
  243. msg += t.I18nBot("tgbot.commands.restartUsage")
  244. }
  245. } else {
  246. handleUnknownCommand()
  247. }
  248. case "clearall":
  249. onlyMessage = true
  250. if isAdmin {
  251. inlineKeyboard := tu.InlineKeyboard(
  252. tu.InlineKeyboardRow(
  253. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("reset_all_traffics_cancel")),
  254. ),
  255. tu.InlineKeyboardRow(
  256. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.encodeQuery("reset_all_traffics_c")),
  257. ),
  258. )
  259. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.AreYouSure"), inlineKeyboard)
  260. } else {
  261. handleUnknownCommand()
  262. }
  263. default:
  264. handleUnknownCommand()
  265. }
  266. if msg != "" {
  267. t.sendResponse(chatId, msg, onlyMessage, isAdmin)
  268. }
  269. }
  270. func (t *Tgbot) isCommandForCurrentBot(message *telego.Message) bool {
  271. return isCommandForBot(message.Text, botUsername())
  272. }
  273. func botUsername() string {
  274. if bot == nil {
  275. return ""
  276. }
  277. return bot.Username()
  278. }
  279. func isCommandForBot(text string, username string) bool {
  280. _, commandUsername, _ := tu.ParseCommand(text)
  281. return commandUsername == "" || username == "" || strings.EqualFold(commandUsername, username)
  282. }
  283. // answerCallback processes callback queries from inline keyboards.
  284. func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool) {
  285. chatId := callbackQuery.Message.GetChat().ID
  286. if isAdmin {
  287. // get query from hash storage
  288. decodedQuery, err := t.decodeQuery(callbackQuery.Data)
  289. if err != nil {
  290. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.noQuery"))
  291. return
  292. }
  293. dataArray := strings.Split(decodedQuery, " ")
  294. if len(dataArray) >= 2 && len(dataArray[1]) > 0 {
  295. email := dataArray[1]
  296. switch dataArray[0] {
  297. case "get_clients_for_sub":
  298. inboundIdInt, err := strconv.Atoi(dataArray[1])
  299. if err != nil {
  300. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  301. return
  302. }
  303. t.chooseInboundClient(callbackQuery, chatId, inboundIdInt, "client_sub_links")
  304. case "get_clients_for_individual":
  305. inboundIdInt, err := strconv.Atoi(dataArray[1])
  306. if err != nil {
  307. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  308. return
  309. }
  310. t.chooseInboundClient(callbackQuery, chatId, inboundIdInt, "client_individual_links")
  311. case "get_clients_for_qr":
  312. inboundIdInt, err := strconv.Atoi(dataArray[1])
  313. if err != nil {
  314. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  315. return
  316. }
  317. t.chooseInboundClient(callbackQuery, chatId, inboundIdInt, "client_qr_links")
  318. case "client_sub_links":
  319. t.sendClientSubLinks(chatId, email)
  320. return
  321. case "client_individual_links":
  322. t.sendClientIndividualLinks(chatId, email)
  323. return
  324. case "client_qr_links":
  325. t.sendClientQRLinks(chatId, email)
  326. return
  327. case "client_get_usage":
  328. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.messages.email", "Email=="+email))
  329. t.searchClient(chatId, email)
  330. case "client_refresh":
  331. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.clientRefreshSuccess", "Email=="+email))
  332. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  333. case "client_cancel":
  334. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email))
  335. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  336. case "ips_refresh":
  337. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.IpRefreshSuccess", "Email=="+email))
  338. t.searchClientIps(chatId, email, callbackQuery.Message.GetMessageID())
  339. case "ips_cancel":
  340. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email))
  341. t.searchClientIps(chatId, email, callbackQuery.Message.GetMessageID())
  342. case "tgid_refresh":
  343. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.TGIdRefreshSuccess", "Email=="+email))
  344. t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.GetMessageID())
  345. case "tgid_cancel":
  346. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+email))
  347. t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.GetMessageID())
  348. case "reset_traffic":
  349. inlineKeyboard := tu.InlineKeyboard(
  350. tu.InlineKeyboardRow(
  351. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  352. ),
  353. tu.InlineKeyboardRow(
  354. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.encodeQuery("reset_traffic_c "+email)),
  355. ),
  356. )
  357. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  358. case "reset_traffic_c":
  359. err := t.inboundService.ResetClientTrafficByEmail(email)
  360. if err == nil {
  361. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.resetTrafficSuccess", "Email=="+email))
  362. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  363. } else {
  364. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  365. }
  366. case "limit_traffic":
  367. inlineKeyboard := tu.InlineKeyboard(
  368. tu.InlineKeyboardRow(
  369. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  370. ),
  371. tu.InlineKeyboardRow(
  372. tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 0")),
  373. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" 0")),
  374. ),
  375. tu.InlineKeyboardRow(
  376. tu.InlineKeyboardButton("1 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 1")),
  377. tu.InlineKeyboardButton("5 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 5")),
  378. tu.InlineKeyboardButton("10 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 10")),
  379. ),
  380. tu.InlineKeyboardRow(
  381. tu.InlineKeyboardButton("20 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 20")),
  382. tu.InlineKeyboardButton("30 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 30")),
  383. tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 40")),
  384. ),
  385. tu.InlineKeyboardRow(
  386. tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 50")),
  387. tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 60")),
  388. tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 80")),
  389. ),
  390. tu.InlineKeyboardRow(
  391. tu.InlineKeyboardButton("100 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 100")),
  392. tu.InlineKeyboardButton("150 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 150")),
  393. tu.InlineKeyboardButton("200 GB").WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" 200")),
  394. ),
  395. )
  396. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  397. case "limit_traffic_c":
  398. if len(dataArray) == 3 {
  399. limitTraffic, err := strconv.Atoi(dataArray[2])
  400. if err == nil {
  401. needRestart, err := t.clientService.ResetClientTrafficLimitByEmail(&t.inboundService, email, limitTraffic)
  402. if needRestart {
  403. t.xrayService.SetToNeedRestart()
  404. }
  405. if err == nil {
  406. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.setTrafficLimitSuccess", "Email=="+email))
  407. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  408. return
  409. }
  410. }
  411. }
  412. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  413. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  414. case "limit_traffic_in":
  415. if len(dataArray) >= 3 {
  416. oldInputNumber, err := strconv.Atoi(dataArray[2])
  417. inputNumber := oldInputNumber
  418. if err == nil {
  419. if len(dataArray) == 4 {
  420. num, err := strconv.Atoi(dataArray[3])
  421. if err == nil {
  422. inputNumber = updateNumericInput(inputNumber, num)
  423. }
  424. if inputNumber == oldInputNumber {
  425. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  426. return
  427. }
  428. if inputNumber >= 999999 {
  429. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  430. return
  431. }
  432. }
  433. inlineKeyboard := tu.InlineKeyboard(
  434. tu.InlineKeyboardRow(
  435. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  436. ),
  437. tu.InlineKeyboardRow(
  438. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("limit_traffic_c "+email+" "+strconv.Itoa(inputNumber))),
  439. ),
  440. tu.InlineKeyboardRow(
  441. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 1")),
  442. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 2")),
  443. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 3")),
  444. ),
  445. tu.InlineKeyboardRow(
  446. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 4")),
  447. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 5")),
  448. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 6")),
  449. ),
  450. tu.InlineKeyboardRow(
  451. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 7")),
  452. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 8")),
  453. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 9")),
  454. ),
  455. tu.InlineKeyboardRow(
  456. tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" -2")),
  457. tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" 0")),
  458. tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("limit_traffic_in "+email+" "+strconv.Itoa(inputNumber)+" -1")),
  459. ),
  460. )
  461. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  462. return
  463. }
  464. }
  465. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  466. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  467. case "add_client_limit_traffic_c":
  468. limitTraffic, _ := strconv.ParseInt(dataArray[1], 10, 64)
  469. client_TotalGB = limitTraffic * 1024 * 1024 * 1024
  470. messageId := callbackQuery.Message.GetMessageID()
  471. message_text := t.BuildClientDraftMessage()
  472. t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
  473. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  474. case "add_client_limit_traffic_in":
  475. if len(dataArray) >= 2 {
  476. oldInputNumber, err := strconv.Atoi(dataArray[1])
  477. inputNumber := oldInputNumber
  478. if err == nil {
  479. if len(dataArray) == 3 {
  480. num, err := strconv.Atoi(dataArray[2])
  481. if err == nil {
  482. inputNumber = updateNumericInput(inputNumber, num)
  483. }
  484. if inputNumber == oldInputNumber {
  485. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  486. return
  487. }
  488. if inputNumber >= 999999 {
  489. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  490. return
  491. }
  492. }
  493. inlineKeyboard := tu.InlineKeyboard(
  494. tu.InlineKeyboardRow(
  495. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
  496. ),
  497. tu.InlineKeyboardRow(
  498. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c "+strconv.Itoa(inputNumber))),
  499. ),
  500. tu.InlineKeyboardRow(
  501. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 1")),
  502. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 2")),
  503. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 3")),
  504. ),
  505. tu.InlineKeyboardRow(
  506. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 4")),
  507. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 5")),
  508. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 6")),
  509. ),
  510. tu.InlineKeyboardRow(
  511. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 7")),
  512. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 8")),
  513. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 9")),
  514. ),
  515. tu.InlineKeyboardRow(
  516. tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -2")),
  517. tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 0")),
  518. tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -1")),
  519. ),
  520. )
  521. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  522. return
  523. }
  524. }
  525. case "reset_exp":
  526. inlineKeyboard := tu.InlineKeyboard(
  527. tu.InlineKeyboardRow(
  528. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  529. ),
  530. tu.InlineKeyboardRow(
  531. tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 0")),
  532. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("reset_exp_in "+email+" 0")),
  533. ),
  534. tu.InlineKeyboardRow(
  535. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 7 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 7")),
  536. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 10")),
  537. ),
  538. tu.InlineKeyboardRow(
  539. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 14 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 14")),
  540. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 20")),
  541. ),
  542. tu.InlineKeyboardRow(
  543. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 30")),
  544. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 90")),
  545. ),
  546. tu.InlineKeyboardRow(
  547. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 180")),
  548. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" 365")),
  549. ),
  550. )
  551. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  552. case "reset_exp_c":
  553. if len(dataArray) == 3 {
  554. days, err := strconv.ParseInt(dataArray[2], 10, 64)
  555. if err == nil {
  556. var date int64
  557. if days > 0 {
  558. traffic, err := t.inboundService.GetClientTrafficByEmail(email)
  559. if err != nil {
  560. logger.Warning(err)
  561. msg := t.I18nBot("tgbot.wentWrong")
  562. t.SendMsgToTgbot(chatId, msg)
  563. return
  564. }
  565. if traffic == nil {
  566. msg := t.I18nBot("tgbot.noResult")
  567. t.SendMsgToTgbot(chatId, msg)
  568. return
  569. }
  570. if traffic.ExpiryTime > 0 {
  571. if traffic.ExpiryTime-time.Now().Unix()*1000 < 0 {
  572. date = -(days * 24 * 60 * 60000)
  573. } else {
  574. date = traffic.ExpiryTime + days*24*60*60000
  575. }
  576. } else {
  577. date = traffic.ExpiryTime - days*24*60*60000
  578. }
  579. }
  580. needRestart, err := t.clientService.ResetClientExpiryTimeByEmail(&t.inboundService, email, date)
  581. if needRestart {
  582. t.xrayService.SetToNeedRestart()
  583. }
  584. if err == nil {
  585. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.expireResetSuccess", "Email=="+email))
  586. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  587. return
  588. }
  589. }
  590. }
  591. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  592. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  593. case "reset_exp_in":
  594. if len(dataArray) >= 3 {
  595. oldInputNumber, err := strconv.Atoi(dataArray[2])
  596. inputNumber := oldInputNumber
  597. if err == nil {
  598. if len(dataArray) == 4 {
  599. num, err := strconv.Atoi(dataArray[3])
  600. if err == nil {
  601. inputNumber = updateNumericInput(inputNumber, num)
  602. }
  603. if inputNumber == oldInputNumber {
  604. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  605. return
  606. }
  607. if inputNumber >= 999999 {
  608. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  609. return
  610. }
  611. }
  612. inlineKeyboard := tu.InlineKeyboard(
  613. tu.InlineKeyboardRow(
  614. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  615. ),
  616. tu.InlineKeyboardRow(
  617. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("reset_exp_c "+email+" "+strconv.Itoa(inputNumber))),
  618. ),
  619. tu.InlineKeyboardRow(
  620. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 1")),
  621. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 2")),
  622. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 3")),
  623. ),
  624. tu.InlineKeyboardRow(
  625. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 4")),
  626. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 5")),
  627. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 6")),
  628. ),
  629. tu.InlineKeyboardRow(
  630. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 7")),
  631. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 8")),
  632. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 9")),
  633. ),
  634. tu.InlineKeyboardRow(
  635. tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" -2")),
  636. tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" 0")),
  637. tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("reset_exp_in "+email+" "+strconv.Itoa(inputNumber)+" -1")),
  638. ),
  639. )
  640. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  641. return
  642. }
  643. }
  644. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  645. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  646. case "add_client_reset_exp_c":
  647. client_ExpiryTime = 0
  648. days, _ := strconv.ParseInt(dataArray[1], 10, 64)
  649. var date int64
  650. if client_ExpiryTime > 0 {
  651. if client_ExpiryTime-time.Now().Unix()*1000 < 0 {
  652. date = -(days * 24 * 60 * 60000)
  653. } else {
  654. date = client_ExpiryTime + days*24*60*60000
  655. }
  656. } else {
  657. date = client_ExpiryTime - days*24*60*60000
  658. }
  659. client_ExpiryTime = date
  660. messageId := callbackQuery.Message.GetMessageID()
  661. message_text := t.BuildClientDraftMessage()
  662. t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
  663. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  664. case "add_client_reset_exp_in":
  665. if len(dataArray) >= 2 {
  666. oldInputNumber, err := strconv.Atoi(dataArray[1])
  667. inputNumber := oldInputNumber
  668. if err == nil {
  669. if len(dataArray) == 3 {
  670. num, err := strconv.Atoi(dataArray[2])
  671. if err == nil {
  672. inputNumber = updateNumericInput(inputNumber, num)
  673. }
  674. if inputNumber == oldInputNumber {
  675. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  676. return
  677. }
  678. if inputNumber >= 999999 {
  679. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  680. return
  681. }
  682. }
  683. inlineKeyboard := tu.InlineKeyboard(
  684. tu.InlineKeyboardRow(
  685. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
  686. ),
  687. tu.InlineKeyboardRow(
  688. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_reset_exp_c "+strconv.Itoa(inputNumber))),
  689. ),
  690. tu.InlineKeyboardRow(
  691. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 1")),
  692. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 2")),
  693. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 3")),
  694. ),
  695. tu.InlineKeyboardRow(
  696. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 4")),
  697. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 5")),
  698. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 6")),
  699. ),
  700. tu.InlineKeyboardRow(
  701. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 7")),
  702. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 8")),
  703. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 9")),
  704. ),
  705. tu.InlineKeyboardRow(
  706. tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -2")),
  707. tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 0")),
  708. tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -1")),
  709. ),
  710. )
  711. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  712. return
  713. }
  714. }
  715. case "ip_limit":
  716. inlineKeyboard := tu.InlineKeyboard(
  717. tu.InlineKeyboardRow(
  718. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelIpLimit")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  719. ),
  720. tu.InlineKeyboardRow(
  721. tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 0")),
  722. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("ip_limit_in "+email+" 0")),
  723. ),
  724. tu.InlineKeyboardRow(
  725. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 1")),
  726. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 2")),
  727. ),
  728. tu.InlineKeyboardRow(
  729. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 3")),
  730. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 4")),
  731. ),
  732. tu.InlineKeyboardRow(
  733. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 5")),
  734. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 6")),
  735. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 7")),
  736. ),
  737. tu.InlineKeyboardRow(
  738. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 8")),
  739. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 9")),
  740. tu.InlineKeyboardButton("10").WithCallbackData(t.encodeQuery("ip_limit_c "+email+" 10")),
  741. ),
  742. )
  743. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  744. case "ip_limit_c":
  745. if len(dataArray) == 3 {
  746. count, err := strconv.Atoi(dataArray[2])
  747. if err == nil {
  748. needRestart, err := t.clientService.ResetClientIpLimitByEmail(&t.inboundService, email, count)
  749. if needRestart {
  750. t.xrayService.SetToNeedRestart()
  751. }
  752. if err == nil {
  753. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.resetIpSuccess", "Email=="+email, "Count=="+strconv.Itoa(count)))
  754. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  755. return
  756. }
  757. }
  758. }
  759. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  760. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  761. case "ip_limit_in":
  762. if len(dataArray) >= 3 {
  763. oldInputNumber, err := strconv.Atoi(dataArray[2])
  764. inputNumber := oldInputNumber
  765. if err == nil {
  766. if len(dataArray) == 4 {
  767. num, err := strconv.Atoi(dataArray[3])
  768. if err == nil {
  769. inputNumber = updateNumericInput(inputNumber, num)
  770. }
  771. if inputNumber == oldInputNumber {
  772. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  773. return
  774. }
  775. if inputNumber >= 999999 {
  776. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  777. return
  778. }
  779. }
  780. inlineKeyboard := tu.InlineKeyboard(
  781. tu.InlineKeyboardRow(
  782. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  783. ),
  784. tu.InlineKeyboardRow(
  785. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("ip_limit_c "+email+" "+strconv.Itoa(inputNumber))),
  786. ),
  787. tu.InlineKeyboardRow(
  788. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 1")),
  789. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 2")),
  790. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 3")),
  791. ),
  792. tu.InlineKeyboardRow(
  793. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 4")),
  794. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 5")),
  795. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 6")),
  796. ),
  797. tu.InlineKeyboardRow(
  798. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 7")),
  799. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 8")),
  800. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 9")),
  801. ),
  802. tu.InlineKeyboardRow(
  803. tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" -2")),
  804. tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" 0")),
  805. tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("ip_limit_in "+email+" "+strconv.Itoa(inputNumber)+" -1")),
  806. ),
  807. )
  808. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  809. return
  810. }
  811. }
  812. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  813. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  814. case "add_client_ip_limit_c":
  815. if len(dataArray) == 2 {
  816. count, _ := strconv.Atoi(dataArray[1])
  817. client_LimitIP = count
  818. }
  819. messageId := callbackQuery.Message.GetMessageID()
  820. message_text := t.BuildClientDraftMessage()
  821. t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
  822. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  823. case "add_client_ip_limit_in":
  824. if len(dataArray) >= 2 {
  825. oldInputNumber, err := strconv.Atoi(dataArray[1])
  826. inputNumber := oldInputNumber
  827. if err == nil {
  828. if len(dataArray) == 3 {
  829. num, err := strconv.Atoi(dataArray[2])
  830. if err == nil {
  831. inputNumber = updateNumericInput(inputNumber, num)
  832. }
  833. if inputNumber == oldInputNumber {
  834. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  835. return
  836. }
  837. if inputNumber >= 999999 {
  838. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  839. return
  840. }
  841. }
  842. inlineKeyboard := tu.InlineKeyboard(
  843. tu.InlineKeyboardRow(
  844. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_ip_limit")),
  845. ),
  846. tu.InlineKeyboardRow(
  847. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_ip_limit_c "+strconv.Itoa(inputNumber))),
  848. ),
  849. tu.InlineKeyboardRow(
  850. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 1")),
  851. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 2")),
  852. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 3")),
  853. ),
  854. tu.InlineKeyboardRow(
  855. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 4")),
  856. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 5")),
  857. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 6")),
  858. ),
  859. tu.InlineKeyboardRow(
  860. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 7")),
  861. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 8")),
  862. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 9")),
  863. ),
  864. tu.InlineKeyboardRow(
  865. tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -2")),
  866. tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 0")),
  867. tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -1")),
  868. ),
  869. )
  870. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  871. return
  872. }
  873. }
  874. case "clear_ips":
  875. inlineKeyboard := tu.InlineKeyboard(
  876. tu.InlineKeyboardRow(
  877. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("ips_cancel "+email)),
  878. ),
  879. tu.InlineKeyboardRow(
  880. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmClearIps")).WithCallbackData(t.encodeQuery("clear_ips_c "+email)),
  881. ),
  882. )
  883. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  884. case "clear_ips_c":
  885. err := t.inboundService.ClearClientIps(email)
  886. if err == nil {
  887. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.clearIpSuccess", "Email=="+email))
  888. t.searchClientIps(chatId, email, callbackQuery.Message.GetMessageID())
  889. } else {
  890. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  891. }
  892. case "ip_log":
  893. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getIpLog", "Email=="+email))
  894. t.searchClientIps(chatId, email)
  895. case "tg_user":
  896. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getUserInfo", "Email=="+email))
  897. t.clientTelegramUserInfo(chatId, email)
  898. case "tgid_remove":
  899. inlineKeyboard := tu.InlineKeyboard(
  900. tu.InlineKeyboardRow(
  901. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("tgid_cancel "+email)),
  902. ),
  903. tu.InlineKeyboardRow(
  904. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmRemoveTGUser")).WithCallbackData(t.encodeQuery("tgid_remove_c "+email)),
  905. ),
  906. )
  907. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  908. case "tgid_remove_c":
  909. traffic, err := t.inboundService.GetClientTrafficByEmail(email)
  910. if err != nil || traffic == nil {
  911. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  912. return
  913. }
  914. needRestart, err := t.clientService.SetClientTelegramUserID(&t.inboundService, traffic.Id, EmptyTelegramUserID)
  915. if needRestart {
  916. t.xrayService.SetToNeedRestart()
  917. }
  918. if err == nil {
  919. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.removedTGUserSuccess", "Email=="+email))
  920. t.clientTelegramUserInfo(chatId, email, callbackQuery.Message.GetMessageID())
  921. } else {
  922. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  923. }
  924. case "toggle_enable":
  925. inlineKeyboard := tu.InlineKeyboard(
  926. tu.InlineKeyboardRow(
  927. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("client_cancel "+email)),
  928. ),
  929. tu.InlineKeyboardRow(
  930. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmToggle")).WithCallbackData(t.encodeQuery("toggle_enable_c "+email)),
  931. ),
  932. )
  933. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  934. case "toggle_enable_c":
  935. enabled, needRestart, err := t.clientService.ToggleClientEnableByEmail(&t.inboundService, email)
  936. if needRestart {
  937. t.xrayService.SetToNeedRestart()
  938. }
  939. if err == nil {
  940. if enabled {
  941. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.enableSuccess", "Email=="+email))
  942. } else {
  943. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.disableSuccess", "Email=="+email))
  944. }
  945. t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
  946. } else {
  947. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
  948. }
  949. case "get_clients":
  950. inboundId := dataArray[1]
  951. inboundIdInt, err := strconv.Atoi(inboundId)
  952. if err != nil {
  953. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  954. return
  955. }
  956. inbound, err := t.inboundService.GetInbound(inboundIdInt)
  957. if err != nil {
  958. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  959. return
  960. }
  961. clients, err := t.getInboundClients(inboundIdInt)
  962. if err != nil {
  963. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  964. return
  965. }
  966. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clients)
  967. case "add_client_to":
  968. client_Email = t.randomLowerAndNum(8)
  969. client_LimitIP = 0
  970. client_TotalGB = 0
  971. client_ExpiryTime = 0
  972. client_Enable = true
  973. client_TgID = ""
  974. client_SubID = t.randomLowerAndNum(16)
  975. client_Comment = ""
  976. client_Reset = 0
  977. inboundId := dataArray[1]
  978. inboundIdInt, err := strconv.Atoi(inboundId)
  979. if err != nil {
  980. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  981. return
  982. }
  983. receiver_inbound_ID = inboundIdInt
  984. receiver_inbound_IDs = []int{inboundIdInt}
  985. t.addClient(callbackQuery.Message.GetChat().ID, t.BuildClientDraftMessage())
  986. case "add_client_toggle_attach":
  987. inboundIdStr := dataArray[1]
  988. inboundIdInt, err := strconv.Atoi(inboundIdStr)
  989. if err != nil {
  990. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  991. return
  992. }
  993. found := -1
  994. for i, id := range receiver_inbound_IDs {
  995. if id == inboundIdInt {
  996. found = i
  997. break
  998. }
  999. }
  1000. if found >= 0 {
  1001. receiver_inbound_IDs = append(receiver_inbound_IDs[:found], receiver_inbound_IDs[found+1:]...)
  1002. } else {
  1003. receiver_inbound_IDs = append(receiver_inbound_IDs, inboundIdInt)
  1004. }
  1005. picker, err := t.getInboundsAttachPicker()
  1006. if err != nil {
  1007. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  1008. return
  1009. }
  1010. t.editMessageCallbackTgBot(callbackQuery.Message.GetChat().ID, callbackQuery.Message.GetMessageID(), picker)
  1011. }
  1012. return
  1013. } else {
  1014. switch callbackQuery.Data {
  1015. case "get_inbounds":
  1016. inbounds, err := t.getInbounds()
  1017. if err != nil {
  1018. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  1019. return
  1020. }
  1021. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.allClients"))
  1022. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
  1023. case "admin_client_sub_links":
  1024. inbounds, err := t.getInboundsFor("get_clients_for_sub")
  1025. if err != nil {
  1026. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  1027. return
  1028. }
  1029. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
  1030. case "admin_client_individual_links":
  1031. inbounds, err := t.getInboundsFor("get_clients_for_individual")
  1032. if err != nil {
  1033. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  1034. return
  1035. }
  1036. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
  1037. case "admin_client_qr_links":
  1038. inbounds, err := t.getInboundsFor("get_clients_for_qr")
  1039. if err != nil {
  1040. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  1041. return
  1042. }
  1043. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
  1044. }
  1045. }
  1046. }
  1047. if !isAdmin && !isClientSelfCallback(callbackQuery.Data) {
  1048. return
  1049. }
  1050. switch callbackQuery.Data {
  1051. case "get_usage":
  1052. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.serverUsage"))
  1053. t.getServerUsage(chatId)
  1054. case "usage_refresh":
  1055. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  1056. t.getServerUsage(chatId, callbackQuery.Message.GetMessageID())
  1057. case "inbounds":
  1058. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getInbounds"))
  1059. t.SendMsgToTgbot(chatId, t.getInboundUsages())
  1060. case "deplete_soon":
  1061. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.depleteSoon"))
  1062. t.getExhausted(chatId)
  1063. case "get_backup":
  1064. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.dbBackup"))
  1065. t.sendBackup(chatId)
  1066. case "get_banlogs":
  1067. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.getBanLogs"))
  1068. t.sendBanLogs(chatId, true)
  1069. case "client_traffic":
  1070. tgUserID := callbackQuery.From.ID
  1071. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.clientUsage"))
  1072. t.getClientUsage(chatId, tgUserID)
  1073. case "client_commands":
  1074. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands"))
  1075. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpClientCommands"))
  1076. case "client_sub_links":
  1077. // show user's own clients to choose one for sub links
  1078. tgUserID := callbackQuery.From.ID
  1079. traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID)
  1080. if err != nil {
  1081. // fallback to message
  1082. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation")+"\r\n"+err.Error())
  1083. return
  1084. }
  1085. if len(traffics) == 0 {
  1086. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10)))
  1087. return
  1088. }
  1089. var buttons []telego.InlineKeyboardButton
  1090. for _, tr := range traffics {
  1091. buttons = append(buttons, tu.InlineKeyboardButton(tr.Email).WithCallbackData(t.encodeQuery("client_sub_links "+tr.Email)))
  1092. }
  1093. cols := 1
  1094. if len(buttons) >= 6 {
  1095. cols = 2
  1096. }
  1097. keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...))
  1098. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), keyboard)
  1099. case "client_individual_links":
  1100. // show user's clients to choose for individual links
  1101. tgUserID := callbackQuery.From.ID
  1102. traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID)
  1103. if err != nil {
  1104. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation")+"\r\n"+err.Error())
  1105. return
  1106. }
  1107. if len(traffics) == 0 {
  1108. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10)))
  1109. return
  1110. }
  1111. var buttons2 []telego.InlineKeyboardButton
  1112. for _, tr := range traffics {
  1113. buttons2 = append(buttons2, tu.InlineKeyboardButton(tr.Email).WithCallbackData(t.encodeQuery("client_individual_links "+tr.Email)))
  1114. }
  1115. cols2 := 1
  1116. if len(buttons2) >= 6 {
  1117. cols2 = 2
  1118. }
  1119. keyboard2 := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols2, buttons2...))
  1120. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), keyboard2)
  1121. case "client_qr_links":
  1122. // show user's clients to choose for QR codes
  1123. tgUserID := callbackQuery.From.ID
  1124. traffics, err := t.inboundService.GetClientTrafficTgBot(tgUserID)
  1125. if err != nil {
  1126. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOccurred")+"\r\n"+err.Error())
  1127. return
  1128. }
  1129. if len(traffics) == 0 {
  1130. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.askToAddUserId", "TgUserID=="+strconv.FormatInt(tgUserID, 10)))
  1131. return
  1132. }
  1133. var buttons3 []telego.InlineKeyboardButton
  1134. for _, tr := range traffics {
  1135. buttons3 = append(buttons3, tu.InlineKeyboardButton(tr.Email).WithCallbackData(t.encodeQuery("client_qr_links "+tr.Email)))
  1136. }
  1137. cols3 := 1
  1138. if len(buttons3) >= 6 {
  1139. cols3 = 2
  1140. }
  1141. keyboard3 := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols3, buttons3...))
  1142. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.pleaseChoose"), keyboard3)
  1143. case "onlines":
  1144. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.onlines"))
  1145. t.onlineClients(chatId)
  1146. case "onlines_refresh":
  1147. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
  1148. t.onlineClients(chatId, callbackQuery.Message.GetMessageID())
  1149. case "commands":
  1150. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands"))
  1151. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpAdminCommands"))
  1152. case "add_client":
  1153. client_Email = t.randomLowerAndNum(8)
  1154. client_LimitIP = 0
  1155. client_TotalGB = 0
  1156. client_ExpiryTime = 0
  1157. client_Enable = true
  1158. client_TgID = ""
  1159. client_SubID = t.randomLowerAndNum(16)
  1160. client_Comment = ""
  1161. client_Reset = 0
  1162. inbounds, err := t.getInboundsAddClient()
  1163. if err != nil {
  1164. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  1165. return
  1166. }
  1167. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.addClient"))
  1168. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
  1169. case "add_client_ch_default_email":
  1170. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1171. userStateMgr.set(chatId, "awaiting_email")
  1172. cancel_btn_markup := tu.InlineKeyboard(
  1173. tu.InlineKeyboardRow(
  1174. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
  1175. ),
  1176. )
  1177. prompt_message := t.I18nBot("tgbot.messages.email_prompt", "ClientEmail=="+client_Email)
  1178. t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
  1179. case "add_client_ch_default_comment":
  1180. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1181. userStateMgr.set(chatId, "awaiting_comment")
  1182. cancel_btn_markup := tu.InlineKeyboard(
  1183. tu.InlineKeyboardRow(
  1184. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
  1185. ),
  1186. )
  1187. prompt_message := t.I18nBot("tgbot.messages.comment_prompt", "ClientComment=="+client_Comment)
  1188. t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
  1189. case "add_client_ch_default_tg_id":
  1190. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1191. userStateMgr.set(chatId, "awaiting_tg_id")
  1192. cancel_btn_markup := tu.InlineKeyboard(
  1193. tu.InlineKeyboardRow(
  1194. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
  1195. ),
  1196. )
  1197. current := client_TgID
  1198. if current == "" {
  1199. current = "—"
  1200. }
  1201. t.SendMsgToTgbot(chatId, fmt.Sprintf("Send the Telegram user id (numeric) to attach to this client, or send `-` / `none` to clear.\nCurrent: `%s`", current), cancel_btn_markup)
  1202. case "add_client_ch_default_traffic":
  1203. inlineKeyboard := tu.InlineKeyboard(
  1204. tu.InlineKeyboardRow(
  1205. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
  1206. ),
  1207. tu.InlineKeyboardRow(
  1208. tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 0")),
  1209. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_in 0")),
  1210. ),
  1211. tu.InlineKeyboardRow(
  1212. tu.InlineKeyboardButton("1 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 1")),
  1213. tu.InlineKeyboardButton("5 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 5")),
  1214. tu.InlineKeyboardButton("10 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 10")),
  1215. ),
  1216. tu.InlineKeyboardRow(
  1217. tu.InlineKeyboardButton("20 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 20")),
  1218. tu.InlineKeyboardButton("30 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 30")),
  1219. tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 40")),
  1220. ),
  1221. tu.InlineKeyboardRow(
  1222. tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 50")),
  1223. tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 60")),
  1224. tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 80")),
  1225. ),
  1226. tu.InlineKeyboardRow(
  1227. tu.InlineKeyboardButton("100 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 100")),
  1228. tu.InlineKeyboardButton("150 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 150")),
  1229. tu.InlineKeyboardButton("200 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 200")),
  1230. ),
  1231. )
  1232. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  1233. case "add_client_ch_default_exp":
  1234. inlineKeyboard := tu.InlineKeyboard(
  1235. tu.InlineKeyboardRow(
  1236. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
  1237. ),
  1238. tu.InlineKeyboardRow(
  1239. tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 0")),
  1240. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_reset_exp_in 0")),
  1241. ),
  1242. tu.InlineKeyboardRow(
  1243. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 7 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 7")),
  1244. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 10")),
  1245. ),
  1246. tu.InlineKeyboardRow(
  1247. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 14 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 14")),
  1248. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 20")),
  1249. ),
  1250. tu.InlineKeyboardRow(
  1251. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 30")),
  1252. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 90")),
  1253. ),
  1254. tu.InlineKeyboardRow(
  1255. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 180")),
  1256. tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 365")),
  1257. ),
  1258. )
  1259. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  1260. case "add_client_ch_default_ip_limit":
  1261. inlineKeyboard := tu.InlineKeyboard(
  1262. tu.InlineKeyboardRow(
  1263. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_ip_limit")),
  1264. ),
  1265. tu.InlineKeyboardRow(
  1266. tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_ip_limit_c 0")),
  1267. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_ip_limit_in 0")),
  1268. ),
  1269. tu.InlineKeyboardRow(
  1270. tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 1")),
  1271. tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 2")),
  1272. ),
  1273. tu.InlineKeyboardRow(
  1274. tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 3")),
  1275. tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 4")),
  1276. ),
  1277. tu.InlineKeyboardRow(
  1278. tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 5")),
  1279. tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 6")),
  1280. tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 7")),
  1281. ),
  1282. tu.InlineKeyboardRow(
  1283. tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 8")),
  1284. tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 9")),
  1285. tu.InlineKeyboardButton("10").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 10")),
  1286. ),
  1287. )
  1288. t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
  1289. case "add_client_default_info":
  1290. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1291. t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
  1292. userStateMgr.clear(chatId)
  1293. t.addClient(chatId, t.BuildClientDraftMessage())
  1294. case "add_client_cancel":
  1295. userStateMgr.clear(chatId)
  1296. receiver_inbound_ID = 0
  1297. receiver_inbound_IDs = nil
  1298. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1299. t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 3, tu.ReplyKeyboardRemove())
  1300. case "add_client_default_traffic_exp":
  1301. messageId := callbackQuery.Message.GetMessageID()
  1302. message_text := t.BuildClientDraftMessage()
  1303. t.addClient(chatId, message_text, messageId)
  1304. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
  1305. case "add_client_default_ip_limit":
  1306. messageId := callbackQuery.Message.GetMessageID()
  1307. message_text := t.BuildClientDraftMessage()
  1308. t.addClient(chatId, message_text, messageId)
  1309. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
  1310. case "add_client_attach_more":
  1311. picker, err := t.getInboundsAttachPicker()
  1312. if err != nil {
  1313. t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
  1314. return
  1315. }
  1316. t.SendMsgToTgbot(chatId, "Pick inbound(s) to attach:", picker)
  1317. case "add_client_attach_done":
  1318. if receiver_inbound_ID == 0 && len(receiver_inbound_IDs) > 0 {
  1319. receiver_inbound_ID = receiver_inbound_IDs[0]
  1320. }
  1321. if receiver_inbound_ID == 0 {
  1322. t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.getInboundsFailed"))
  1323. return
  1324. }
  1325. message_text := t.BuildClientDraftMessage()
  1326. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1327. t.addClient(chatId, message_text)
  1328. case "add_client_submit_disable":
  1329. client_Enable = false
  1330. _, err := t.SubmitAddClient()
  1331. if err != nil {
  1332. errorMessage := fmt.Sprintf("%v", err)
  1333. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove())
  1334. } else {
  1335. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1336. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove())
  1337. t.sendClientIndividualLinks(chatId, client_Email)
  1338. t.sendClientQRLinks(chatId, client_Email)
  1339. receiver_inbound_ID = 0
  1340. receiver_inbound_IDs = nil
  1341. }
  1342. case "add_client_submit_enable":
  1343. client_Enable = true
  1344. _, err := t.SubmitAddClient()
  1345. if err != nil {
  1346. errorMessage := fmt.Sprintf("%v", err)
  1347. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove())
  1348. } else {
  1349. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1350. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove())
  1351. t.sendClientIndividualLinks(chatId, client_Email)
  1352. t.sendClientQRLinks(chatId, client_Email)
  1353. receiver_inbound_ID = 0
  1354. receiver_inbound_IDs = nil
  1355. }
  1356. case "reset_all_traffics_cancel":
  1357. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1358. t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 1, tu.ReplyKeyboardRemove())
  1359. case "reset_all_traffics":
  1360. inlineKeyboard := tu.InlineKeyboard(
  1361. tu.InlineKeyboardRow(
  1362. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("reset_all_traffics_cancel")),
  1363. ),
  1364. tu.InlineKeyboardRow(
  1365. tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.encodeQuery("reset_all_traffics_c")),
  1366. ),
  1367. )
  1368. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.AreYouSure"), inlineKeyboard)
  1369. case "reset_all_traffics_c":
  1370. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1371. emails, err := t.inboundService.GetAllEmails()
  1372. if err != nil {
  1373. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
  1374. return
  1375. }
  1376. for _, email := range emails {
  1377. err := t.inboundService.ResetClientTrafficByEmail(email)
  1378. if err == nil {
  1379. msg := t.I18nBot("tgbot.messages.SuccessResetTraffic", "ClientEmail=="+email)
  1380. t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
  1381. } else {
  1382. msg := t.I18nBot("tgbot.messages.FailedResetTraffic", "ClientEmail=="+email, "ErrorMessage=="+err.Error())
  1383. t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
  1384. }
  1385. }
  1386. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.FinishProcess"), tu.ReplyKeyboardRemove())
  1387. case "get_sorted_traffic_usage_report":
  1388. t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
  1389. emails, err := t.inboundService.GetAllEmails()
  1390. if err != nil {
  1391. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
  1392. return
  1393. }
  1394. valid_emails, extra_emails, err := t.inboundService.FilterAndSortClientEmails(emails)
  1395. if err != nil {
  1396. t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
  1397. return
  1398. }
  1399. for _, valid_emails := range valid_emails {
  1400. traffic, err := t.inboundService.GetClientTrafficByEmail(valid_emails)
  1401. if err != nil {
  1402. logger.Warning(err)
  1403. msg := t.I18nBot("tgbot.wentWrong")
  1404. t.SendMsgToTgbot(chatId, msg)
  1405. continue
  1406. }
  1407. if traffic == nil {
  1408. msg := t.I18nBot("tgbot.noResult")
  1409. t.SendMsgToTgbot(chatId, msg)
  1410. continue
  1411. }
  1412. output := t.clientInfoMsg(traffic, false, false, false, false, true, false)
  1413. t.SendMsgToTgbot(chatId, output, tu.ReplyKeyboardRemove())
  1414. }
  1415. for _, extra_emails := range extra_emails {
  1416. msg := fmt.Sprintf("📧 %s\n%s", extra_emails, t.I18nBot("tgbot.noResult"))
  1417. t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
  1418. }
  1419. default:
  1420. if after, ok := strings.CutPrefix(callbackQuery.Data, "client_sub_links "); ok {
  1421. email := after
  1422. t.sendClientSubLinks(chatId, email)
  1423. return
  1424. }
  1425. if after, ok := strings.CutPrefix(callbackQuery.Data, "client_individual_links "); ok {
  1426. email := after
  1427. t.sendClientIndividualLinks(chatId, email)
  1428. return
  1429. }
  1430. if after, ok := strings.CutPrefix(callbackQuery.Data, "client_qr_links "); ok {
  1431. email := after
  1432. t.sendClientQRLinks(chatId, email)
  1433. return
  1434. }
  1435. }
  1436. }
  1437. // checkAdmin checks if the given Telegram ID is an admin.
  1438. func checkAdmin(tgId int64) bool {
  1439. return slices.Contains(adminIds, tgId)
  1440. }
  1441. // isClientSelfCallback reports whether a callback is one of the per-user client
  1442. // actions that resolve their own data from the caller's Telegram id, and so are
  1443. // safe to run for a non-admin. Every other callback is admin-only (default-deny).
  1444. func isClientSelfCallback(data string) bool {
  1445. switch data {
  1446. case "client_traffic", "client_commands", "client_sub_links",
  1447. "client_individual_links", "client_qr_links":
  1448. return true
  1449. }
  1450. return strings.HasPrefix(data, "client_sub_links ") ||
  1451. strings.HasPrefix(data, "client_individual_links ") ||
  1452. strings.HasPrefix(data, "client_qr_links ")
  1453. }