This commit is contained in:
nistootsin 2025-03-26 13:05:33 +01:00 committed by GitHub
commit a69e6f8f01
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 1168 additions and 49 deletions

1
go.mod
View file

@ -7,6 +7,7 @@ require (
github.com/gin-contrib/sessions v1.0.2 github.com/gin-contrib/sessions v1.0.2
github.com/gin-gonic/gin v1.10.0 github.com/gin-gonic/gin v1.10.0
github.com/goccy/go-json v0.10.5 github.com/goccy/go-json v0.10.5
github.com/google/uuid v1.6.0
github.com/mymmrac/telego v0.32.0 github.com/mymmrac/telego v0.32.0
github.com/nicksnyder/go-i18n/v2 v2.5.1 github.com/nicksnyder/go-i18n/v2 v2.5.1
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/op/go-logging v0.0.0-20160315200505-970db520ece7

View file

@ -1,12 +1,16 @@
package service package service
import ( import (
"crypto/rand"
"embed" "embed"
"encoding/base64"
"errors" "errors"
"fmt" "fmt"
"math/big"
"net" "net"
"net/url" "net/url"
"os" "os"
"regexp"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -20,8 +24,7 @@ import (
"x-ui/web/locale" "x-ui/web/locale"
"x-ui/xray" "x-ui/xray"
"slices" "github.com/google/uuid"
"github.com/mymmrac/telego" "github.com/mymmrac/telego"
th "github.com/mymmrac/telego/telegohandler" th "github.com/mymmrac/telego/telegohandler"
tu "github.com/mymmrac/telego/telegoutil" tu "github.com/mymmrac/telego/telegoutil"
@ -36,8 +39,32 @@ var (
isRunning bool isRunning bool
hostname string hostname string
hashStorage *global.HashStorage 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 type LoginStatus byte
const ( const (
@ -46,6 +73,8 @@ const (
EmptyTelegramUserID = int64(0) EmptyTelegramUserID = int64(0)
) )
type Tgbot struct { type Tgbot struct {
inboundService InboundService inboundService InboundService
settingService SettingService settingService SettingService
@ -54,6 +83,7 @@ type Tgbot struct {
lastStatus *Status lastStatus *Status
} }
func (t *Tgbot) NewTgbot() *Tgbot { func (t *Tgbot) NewTgbot() *Tgbot {
return new(Tgbot) return new(Tgbot)
} }
@ -223,18 +253,94 @@ func (t *Tgbot) OnReceive() {
botHandler, _ = th.NewBotHandler(bot, updates) botHandler, _ = th.NewBotHandler(bot, updates)
botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) {
delete(userStates, message.Chat.ID)
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove()) t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove())
}, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard"))) }, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard")))
botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) {
delete(userStates, message.Chat.ID)
t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID)) t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID))
}, th.AnyCommand()) }, th.AnyCommand())
botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) { botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) {
delete(userStates,query.Message.GetChat().ID)
t.answerCallback(&query, checkAdmin(query.From.ID)) t.answerCallback(&query, checkAdmin(query.From.ID))
}, th.AnyCallbackQueryWithMessage()) }, th.AnyCallbackQueryWithMessage())
botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) { botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) {
if userState, exists := userStates[message.Chat.ID]; exists {
switch userState {
case "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"),
),
)
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)
}
case "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"),
),
)
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)
}
case "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"),
),
)
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)
}
case "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"),
),
)
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)
}
case "awaiting_comment":
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)
}
} else {
if message.UsersShared != nil { if message.UsersShared != nil {
if checkAdmin(message.From.ID) { if checkAdmin(message.From.ID) {
for _, sharedUser := range message.UsersShared.Users { for _, sharedUser := range message.UsersShared.Users {
@ -255,6 +361,7 @@ func (t *Tgbot) OnReceive() {
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove()) t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove())
} }
} }
}
}, th.AnyMessage()) }, th.AnyMessage())
botHandler.Start() botHandler.Start()
@ -344,6 +451,28 @@ func (t *Tgbot) sendResponse(chatId int64, msg string, onlyMessage, isAdmin bool
} }
} }
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) { func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool) {
chatId := callbackQuery.Message.GetChat().ID chatId := callbackQuery.Message.GetChat().ID
@ -507,6 +636,78 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
} }
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID()) 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": case "reset_exp":
inlineKeyboard := tu.InlineKeyboard( inlineKeyboard := tu.InlineKeyboard(
tu.InlineKeyboardRow( tu.InlineKeyboardRow(
@ -638,6 +839,90 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
} }
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation")) t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID()) 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": case "ip_limit":
inlineKeyboard := tu.InlineKeyboard( inlineKeyboard := tu.InlineKeyboard(
tu.InlineKeyboardRow( tu.InlineKeyboardRow(
@ -838,7 +1123,40 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
return return
} }
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clients) 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 return
} else { } else {
@ -892,11 +1210,325 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
case "commands": case "commands":
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands")) t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands"))
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpAdminCommands")) 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_refresh":
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.clientRefreshSuccess", "Email=="+client_Email))
case "add_client_ch_default_email":
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":
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":
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":
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":
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.cancelReset")).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.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
delete(userStates, chatId)
case "add_client_cancel":
delete(userStates, chatId)
t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 5, 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.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
}
} }
} }
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)
default:
return "", errors.New("unknown protocol")
}
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 { func checkAdmin(tgId int64) bool {
return slices.Contains(adminIds, tgId) for _, adminId := range adminIds {
if adminId == tgId {
return true
}
}
return false
} }
func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) { func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) {
@ -915,7 +1547,10 @@ func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) {
tu.InlineKeyboardRow( tu.InlineKeyboardRow(
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.encodeQuery("commands")), tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.encodeQuery("commands")),
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.onlines")).WithCallbackData(t.encodeQuery("onlines")), 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.allClients")).WithCallbackData(t.encodeQuery("get_inbounds")),
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.addClient")).WithCallbackData(t.encodeQuery("add_client")),
), ),
// TODOOOOOOOOOOOOOO: Add restart button here. // TODOOOOOOOOOOOOOO: Add restart button here.
) )
@ -1161,35 +1796,75 @@ func (t *Tgbot) getInboundUsages() string {
} }
return info return info
} }
func (t *Tgbot) getInbounds() (*telego.InlineKeyboardMarkup, error) { func (t *Tgbot) getInbounds() (*telego.InlineKeyboardMarkup, error) {
inbounds, err := t.inboundService.GetAllInbounds() inbounds, err := t.inboundService.GetAllInbounds()
var buttons []telego.InlineKeyboardButton
if err != nil { if err != nil {
logger.Warning("GetAllInbounds run failed:", err) logger.Warning("GetAllInbounds run failed:", err)
return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed"))
} else { }
if len(inbounds) > 0 {
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 { for _, inbound := range inbounds {
status := "❌" status := "❌"
if inbound.Enable { if inbound.Enable {
status = "✅" status = "✅"
} }
buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(t.encodeQuery("get_clients "+strconv.Itoa(inbound.Id)))) 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))
} }
} else {
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) logger.Warning("GetAllInbounds run failed:", err)
return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed")) 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"))
} }
cols := 0
if len(buttons) < 6 { excludedProtocols := map[model.Protocol]bool{
cols = 3 model.DOKODEMO: true,
} else { 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 cols = 2
} }
keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...)) keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...))
return keyboard, nil return keyboard, nil
} }
@ -1484,6 +2159,100 @@ func (t *Tgbot) searchClient(chatId int64, email string, messageID ...int) {
} }
} }
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.refresh")).WithCallbackData("add_client_refresh"),
),
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.refresh")).WithCallbackData("add_client_refresh"),
),
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.refresh")).WithCallbackData("add_client_refresh"),
),
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) { func (t *Tgbot) searchInbound(chatId int64, remark string) {
inbounds, err := t.inboundService.SearchInbounds(remark) inbounds, err := t.inboundService.SearchInbounds(remark)
if err != nil { if err != nil {
@ -1689,7 +2458,12 @@ func (t *Tgbot) notifyExhausted() {
} }
func int64Contains(slice []int64, item int64) bool { func int64Contains(slice []int64, item int64) bool {
return slices.Contains(slice, item) for _, s := range slice {
if s == item {
return true
}
}
return false
} }
func (t *Tgbot) onlineClients(chatId int64, messageID ...int) { func (t *Tgbot) onlineClients(chatId int64, messageID ...int) {
@ -1849,3 +2623,49 @@ func (t *Tgbot) editMessageTgBot(chatId int64, messageID int, text string, inlin
logger.Warning(err) 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(&params); 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)
}

View file

@ -582,6 +582,21 @@
"yes" = "✅ Yes" "yes" = "✅ Yes"
"no" = "❌ No" "no" = "❌ No"
"received_id" = "🔑📥 ID updated. Press refresh to see changes."
"received_password" = "🔑📥 Password updated. Press refresh to see changes."
"received_email" = "📧📥 Email updated. Press refresh to see changes."
"received_comment" = "💬📥 Comment updated. Press refresh to see changes."
"id_prompt" = "🔑 Default ID: {{ .ClientId }}\n\nEnter your id."
"pass_prompt" = "🔑 Default Password: {{ .ClientPassword }}\n\nEnter your password."
"email_prompt" = "📧 Default Email: {{ .ClientEmail }}\n\nEnter your email."
"comment_prompt" = "💬 Default Comment: {{ .ClientComment }}\n\nEnter your Comment."
"inbound_client_data_id" = "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!"
"inbound_client_data_pass" = "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 Password: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!"
"cancel" = "❌ Process Canceled! \n\nYou can /start again anytime. 🔄"
"error_add_client" = "⚠️ Error:\n\n {{ .error }}"
"using_default_value" = "Okay, I'll stick with the default value. 😊"
"incorrect_input" ="Your input is not valid.\nThe phrases should be continuous without spaces.\nCorrect example: aaaaaa\nIncorrect example: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Close Keyboard" "closeKeyboard" = "❌ Close Keyboard"
"cancel" = "❌ Cancel" "cancel" = "❌ Cancel"
@ -616,6 +631,14 @@
"getBanLogs" = "Get Ban Logs" "getBanLogs" = "Get Ban Logs"
"allClients" = "All Clients" "allClients" = "All Clients"
"addClient" = "Add Client"
"submitDisable" = "Submit As Disable ✅"
"use_default" = "🏷️ Use default"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Password"
"change_email" = "⚙️📧 Email"
"change_comment" = "⚙️💬 Comment"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ Operation successful!" "successfulOperation" = "✅ Operation successful!"
"errorOperation" = "❗ Error in operation." "errorOperation" = "❗ Error in operation."

View file

@ -584,6 +584,22 @@
"yes" = "✅ Sí" "yes" = "✅ Sí"
"no" = "❌ No" "no" = "❌ No"
"received_id" = "🔑📥 ID actualizado. Presiona actualizar para ver los cambios."
"received_password" = "🔑📥 Contraseña actualizada. Presiona actualizar para ver los cambios."
"received_email" = "📧📥 Correo electrónico actualizado. Presiona actualizar para ver los cambios."
"received_comment" = "💬📥 Comentario actualizado. Presiona actualizar para ver los cambios."
"id_prompt" = "🔑 ID predeterminado: {{ .ClientId }}\n\nIntroduce tu ID."
"pass_prompt" = "🔑 Contraseña predeterminada: {{ .ClientPassword }}\n\nIntroduce tu contraseña."
"email_prompt" = "📧 Correo electrónico predeterminado: {{ .ClientEmail }}\n\nIntroduce tu correo electrónico."
"comment_prompt" = "💬 Comentario predeterminado: {{ .ClientComment }}\n\nIntroduce tu comentario."
"inbound_client_data_id" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfico: {{ .ClientTraffic }}\n📅 Fecha de vencimiento: {{ .ClientExp }}\n💬 Comentario: {{ .ClientComment }}\n\n¡Ahora puedes agregar al cliente a la entrada!"
"inbound_client_data_pass" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 Contraseña: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfico: {{ .ClientTraffic }}\n📅 Fecha de vencimiento: {{ .ClientExp }}\n💬 Comentario: {{ .ClientComment }}\n\n¡Ahora puedes agregar al cliente a la entrada!"
"cancel" = "❌ ¡Proceso cancelado! \n\nPuedes /start de nuevo en cualquier momento. 🔄"
"error_add_client" = "⚠️ Error:\n\n {{ .error }}"
"using_default_value" = "Está bien, me quedaré con el valor predeterminado. 😊"
"incorrect_input" ="Tu entrada no es válida.\nLas frases deben ser continuas sin espacios.\nEjemplo correcto: aaaaaa\nEjemplo incorrecto: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Cerrar Teclado" "closeKeyboard" = "❌ Cerrar Teclado"
"cancel" = "❌ Cancelar" "cancel" = "❌ Cancelar"
@ -618,6 +634,15 @@
"getBanLogs" = "Registros de prohibición" "getBanLogs" = "Registros de prohibición"
"allClients" = "Todos los Clientes" "allClients" = "Todos los Clientes"
"addClient" = "Añadir Cliente"
"submitDisable" = "Enviar como Deshabilitado ✅"
"use_default" = "🏷️ Usar predeterminado"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Contraseña"
"change_email" = "⚙️📧 Correo electrónico"
"change_comment" = "⚙️💬 Comentario"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ ¡Exitosa!" "successfulOperation" = "✅ ¡Exitosa!"
"errorOperation" = "❗ Error en la Operación." "errorOperation" = "❗ Error en la Operación."

View file

@ -584,6 +584,22 @@
"yes" = "✅ بله" "yes" = "✅ بله"
"no" = "❌ خیر" "no" = "❌ خیر"
"received_id" = "🔑📥 شناسه به‌روزرسانی شد. برای مشاهده تغییرات، دکمه تازه‌سازی را فشار دهید."
"received_password" = "🔑📥 رمز عبور به‌روزرسانی شد. برای مشاهده تغییرات، دکمه تازه‌سازی را فشار دهید."
"received_email" = "📧📥 ایمیل به‌روزرسانی شد. برای مشاهده تغییرات، دکمه تازه‌سازی را فشار دهید."
"received_comment" = "💬📥 نظر به‌روزرسانی شد. برای مشاهده تغییرات، دکمه تازه‌سازی را فشار دهید."
"id_prompt" = "🔑 شناسه پیش‌فرض: {{ .ClientId }}\n\nشناسه خود را وارد کنید."
"pass_prompt" = "🔑 رمز عبور پیش‌فرض: {{ .ClientPassword }}\n\nرمز عبور خود را وارد کنید."
"email_prompt" = "📧 ایمیل پیش‌فرض: {{ .ClientEmail }}\n\nایمیل خود را وارد کنید."
"comment_prompt" = "💬 نظر پیش‌فرض: {{ .ClientComment }}\n\nنظر خود را وارد کنید."
"inbound_client_data_id" = "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 شناسه: {{ .ClientId }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n💬 نظر: {{ .ClientComment }}\n\nحالا می‌توانید مشتری را به ورودی اضافه کنید!"
"inbound_client_data_pass" = "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 رمز عبور: {{ .ClientPass }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n💬 نظر: {{ .ClientComment }}\n\nحالا می‌توانید مشتری را به ورودی اضافه کنید!"
"cancel" = "❌ فرآیند لغو شد! \n\nمیتوانید هر زمان که خواستید /start را دوباره اجرا کنید. 🔄"
"error_add_client" = "⚠️ خطا:\n\n {{ .error }}"
"using_default_value" = "باشه، از مقدار پیش‌فرض استفاده می‌کنم. 😊"
"incorrect_input" ="ورودی شما معتبر نیست.\nعبارتها باید بدون فاصله باشند.\nمثال صحیح: aaaaaa\nمثال نادرست: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ بستن کیبورد" "closeKeyboard" = "❌ بستن کیبورد"
"cancel" = "❌ لغو" "cancel" = "❌ لغو"
@ -618,6 +634,15 @@
"getBanLogs" = "گزارش های بلوک را دریافت کنید" "getBanLogs" = "گزارش های بلوک را دریافت کنید"
"allClients" = "همه مشتریان" "allClients" = "همه مشتریان"
"addClient" = "اضافه کردن مشتری"
"submitDisable" = "ارسال به عنوان غیرفعال ✅"
"use_default" = "🏷️ استفاده از پیش‌فرض"
"change_id" = "⚙️🔑 شناسه"
"change_password" = "⚙️🔑 رمز عبور"
"change_email" = "⚙️📧 ایمیل"
"change_comment" = "⚙️💬 نظر"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ انجام شد!" "successfulOperation" = "✅ انجام شد!"
"errorOperation" = "❗ خطا در عملیات." "errorOperation" = "❗ خطا در عملیات."

View file

@ -583,6 +583,22 @@
"yes" = "✅ Ya" "yes" = "✅ Ya"
"no" = "❌ Tidak" "no" = "❌ Tidak"
"received_id" = "🔑📥 ID diperbarui. Tekan segarkan untuk melihat perubahan."
"received_password" = "🔑📥 Kata sandi diperbarui. Tekan segarkan untuk melihat perubahan."
"received_email" = "📧📥 Email diperbarui. Tekan segarkan untuk melihat perubahan."
"received_comment" = "💬📥 Komentar diperbarui. Tekan segarkan untuk melihat perubahan."
"id_prompt" = "🔑 ID Default: {{ .ClientId }}\n\nMasukkan ID Anda."
"pass_prompt" = "🔑 Kata Sandi Default: {{ .ClientPassword }}\n\nMasukkan kata sandi Anda."
"email_prompt" = "📧 Email Default: {{ .ClientEmail }}\n\nMasukkan email Anda."
"comment_prompt" = "💬 Komentar Default: {{ .ClientComment }}\n\nMasukkan komentar Anda."
"inbound_client_data_id" = "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu Lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang Anda bisa menambahkan klien ke masuk!"
"inbound_client_data_pass" = "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 Kata Sandi: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu Lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang Anda bisa menambahkan klien ke masuk!"
"cancel" = "❌ Proses Dibatalkan! \n\nAnda dapat /start lagi kapan saja. 🔄"
"error_add_client" = "⚠️ Kesalahan:\n\n {{ .error }}"
"using_default_value" = "Oke, saya akan tetap menggunakan nilai default. 😊"
"incorrect_input" ="Masukan Anda tidak valid.\nFrasa harus berlanjut tanpa spasi.\nContoh benar: aaaaaa\nContoh salah: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Tutup Papan Ketik" "closeKeyboard" = "❌ Tutup Papan Ketik"
"cancel" = "❌ Batal" "cancel" = "❌ Batal"
@ -617,6 +633,15 @@
"getBanLogs" = "Dapatkan Log Pemblokiran" "getBanLogs" = "Dapatkan Log Pemblokiran"
"allClients" = "Semua Klien" "allClients" = "Semua Klien"
"addClient" = "Tambah Klien"
"submitDisable" = "Kirim Sebagai Nonaktif ✅"
"use_default" = "🏷️ Gunakan default"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Kata Sandi"
"change_email" = "⚙️📧 Email"
"change_comment" = "⚙️💬 Komentar"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ Operasi berhasil!" "successfulOperation" = "✅ Operasi berhasil!"
"errorOperation" = "❗ Kesalahan dalam operasi." "errorOperation" = "❗ Kesalahan dalam operasi."

View file

@ -584,6 +584,22 @@
"yes" = "✅ はい" "yes" = "✅ はい"
"no" = "❌ いいえ" "no" = "❌ いいえ"
"received_id" = "🔑📥 IDが更新されました。更新ボタンを押して変更を確認してください。"
"received_password" = "🔑📥 パスワードが更新されました。更新ボタンを押して変更を確認してください。"
"received_email" = "📧📥 メールが更新されました。更新ボタンを押して変更を確認してください。"
"received_comment" = "💬📥 コメントが更新されました。更新ボタンを押して変更を確認してください。"
"id_prompt" = "🔑 デフォルトID: {{ .ClientId }}\n\nIDを入力してください。"
"pass_prompt" = "🔑 デフォルトパスワード: {{ .ClientPassword }}\n\nパスワードを入力してください。"
"email_prompt" = "📧 デフォルトメール: {{ .ClientEmail }}\n\nメールを入力してください。"
"comment_prompt" = "💬 デフォルトコメント: {{ .ClientComment }}\n\nコメントを入力してください。"
"inbound_client_data_id" = "🔄 入力: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 メール: {{ .ClientEmail }}\n📊 トラフィック: {{ .ClientTraffic }}\n📅 期限日: {{ .ClientExp }}\n💬 コメント: {{ .ClientComment }}\n\n今すぐクライアントをインバウンドに追加できます"
"inbound_client_data_pass" = "🔄 入力: {{ .InboundRemark }}\n\n🔑 パスワード: {{ .ClientPass }}\n📧 メール: {{ .ClientEmail }}\n📊 トラフィック: {{ .ClientTraffic }}\n📅 期限日: {{ .ClientExp }}\n💬 コメント: {{ .ClientComment }}\n\n今すぐクライアントをインバウンドに追加できます"
"cancel" = "❌ プロセスがキャンセルされました!\n\nいつでも /start で再開できます。 🔄"
"error_add_client" = "⚠️ エラー:\n\n {{ .error }}"
"using_default_value" = "わかりました、デフォルト値を使用します。 😊"
"incorrect_input" ="入力が無効です。\nフレーズはスペースなしで続けて入力してください。\n正しい例: aaaaaa\n間違った例: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ キーボードを閉じる" "closeKeyboard" = "❌ キーボードを閉じる"
"cancel" = "❌ キャンセル" "cancel" = "❌ キャンセル"
@ -618,6 +634,15 @@
"getBanLogs" = "禁止ログ" "getBanLogs" = "禁止ログ"
"allClients" = "すべてのクライアント" "allClients" = "すべてのクライアント"
"addClient" = "クライアントを追加"
"submitDisable" = "無効として送信 ✅"
"use_default" = "🏷️ デフォルトを使用"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 パスワード"
"change_email" = "⚙️📧 メール"
"change_comment" = "⚙️💬 コメント"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ 成功!" "successfulOperation" = "✅ 成功!"
"errorOperation" = "❗ 操作エラー。" "errorOperation" = "❗ 操作エラー。"

View file

@ -584,6 +584,22 @@
"yes" = "✅ Sim" "yes" = "✅ Sim"
"no" = "❌ Não" "no" = "❌ Não"
"received_id" = "🔑📥 ID atualizado. Pressione atualizar para ver as mudanças."
"received_password" = "🔑📥 Senha atualizada. Pressione atualizar para ver as mudanças."
"received_email" = "📧📥 E-mail atualizado. Pressione atualizar para ver as mudanças."
"received_comment" = "💬📥 Comentário atualizado. Pressione atualizar para ver as mudanças."
"id_prompt" = "🔑 ID Padrão: {{ .ClientId }}\n\nDigite seu ID."
"pass_prompt" = "🔑 Senha Padrão: {{ .ClientPassword }}\n\nDigite sua senha."
"email_prompt" = "📧 E-mail Padrão: {{ .ClientEmail }}\n\nDigite seu e-mail."
"comment_prompt" = "💬 Comentário Padrão: {{ .ClientComment }}\n\nDigite seu comentário."
"inbound_client_data_id" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!"
"inbound_client_data_pass" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 Senha: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!"
"cancel" = "❌ Processo Cancelado! \n\nVocê pode iniciar novamente a qualquer momento com /start. 🔄"
"error_add_client" = "⚠️ Erro:\n\n {{ .error }}"
"using_default_value" = "Tudo bem, vou manter o valor padrão. 😊"
"incorrect_input" ="Sua entrada não é válida.\nAs frases devem ser contínuas, sem espaços.\nExemplo correto: aaaaaa\nExemplo incorreto: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Fechar teclado" "closeKeyboard" = "❌ Fechar teclado"
"cancel" = "❌ Cancelar" "cancel" = "❌ Cancelar"
@ -618,6 +634,15 @@
"getBanLogs" = "Obter logs de banimento" "getBanLogs" = "Obter logs de banimento"
"allClients" = "Todos os clientes" "allClients" = "Todos os clientes"
"addClient" = "Adicionar Cliente"
"submitDisable" = "Enviar como Desativado ✅"
"use_default" = "🏷️ Usar padrão"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Senha"
"change_email" = "⚙️📧 E-mail"
"change_comment" = "⚙️💬 Comentário"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ Operação bem-sucedida!" "successfulOperation" = "✅ Operação bem-sucedida!"
"errorOperation" = "❗ Erro na operação." "errorOperation" = "❗ Erro na operação."

View file

@ -584,6 +584,22 @@
"yes" = "✅ Да" "yes" = "✅ Да"
"no" = "❌ Нет" "no" = "❌ Нет"
"received_id" = "🔑📥 ID обновлён. Нажмите обновить, чтобы увидеть изменения."
"received_password" = "🔑📥 Пароль обновлён. Нажмите обновить, чтобы увидеть изменения."
"received_email" = "📧📥 Электронная почта обновлена. Нажмите обновить, чтобы увидеть изменения."
"received_comment" = "💬📥 Комментарий обновлён. Нажмите обновить, чтобы увидеть изменения."
"id_prompt" = "🔑 Стандартный ID: {{ .ClientId }}\n\nВведите ваш ID."
"pass_prompt" = "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль."
"email_prompt" = "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email."
"comment_prompt" = "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий."
"inbound_client_data_id" = "🔄 Входящие: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата истечения: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента во входящие!"
"inbound_client_data_pass" = "🔄 Входящие: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата истечения: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента во входящие!"
"cancel" = "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄"
"error_add_client" = "⚠️ Ошибка:\n\n {{ .error }}"
"using_default_value" = "Хорошо, оставлю значение по умолчанию. 😊"
"incorrect_input" ="Ваш ввод недействителен.\nФразы должны быть непрерывными без пробелов.\nПравильный пример: aaaaaa\nНеправильный пример: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Закрыть клавиатуру" "closeKeyboard" = "❌ Закрыть клавиатуру"
"cancel" = "❌ Отмена" "cancel" = "❌ Отмена"
@ -618,6 +634,15 @@
"getBanLogs" = "Журнал блокировок" "getBanLogs" = "Журнал блокировок"
"allClients" = "Все клиенты" "allClients" = "Все клиенты"
"addClient" = "Добавить клиента"
"submitDisable" = "Отправить как отключенный ✅"
"use_default" = "🏷️ Использовать по умолчанию"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Пароль"
"change_email" = "⚙️📧 Электронная почта"
"change_comment" = "⚙️💬 Комментарий"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ Успешно!" "successfulOperation" = "✅ Успешно!"
"errorOperation" = "❗ Ошибка в операции." "errorOperation" = "❗ Ошибка в операции."

View file

@ -584,6 +584,22 @@
"yes" = "✅ Evet" "yes" = "✅ Evet"
"no" = "❌ Hayır" "no" = "❌ Hayır"
"received_id" = "🔑📥 Kimlik güncellendi. Değişiklikleri görmek için yenileye basın."
"received_password" = "🔑📥 Şifre güncellendi. Değişiklikleri görmek için yenileye basın."
"received_email" = "📧📥 E-posta güncellendi. Değişiklikleri görmek için yenileye basın."
"received_comment" = "💬📥 Yorum güncellendi. Değişiklikleri görmek için yenileye basın."
"id_prompt" = "🔑 Varsayılan Kimlik: {{ .ClientId }}\n\nKimliğinizi girin."
"pass_prompt" = "🔑 Varsayılan Şifre: {{ .ClientPassword }}\n\nŞifrenizi girin."
"email_prompt" = "📧 Varsayılan E-posta: {{ .ClientEmail }}\n\nE-postanızı girin."
"comment_prompt" = "💬 Varsayılan Yorum: {{ .ClientComment }}\n\nYorumunuzu girin."
"inbound_client_data_id" = "🔄 Giriş: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 E-posta: {{ .ClientEmail }}\n📊 Trafik: {{ .ClientTraffic }}\n📅 Son Kullanım Tarihi: {{ .ClientExp }}\n💬 Yorum: {{ .ClientComment }}\n\nŞimdi müşteriyi girişe ekleyebilirsiniz!"
"inbound_client_data_pass" = "🔄 Giriş: {{ .InboundRemark }}\n\n🔑 Şifre: {{ .ClientPass }}\n📧 E-posta: {{ .ClientEmail }}\n📊 Trafik: {{ .ClientTraffic }}\n📅 Son Kullanım Tarihi: {{ .ClientExp }}\n💬 Yorum: {{ .ClientComment }}\n\nŞimdi müşteriyi girişe ekleyebilirsiniz!"
"cancel" = "❌ İşlem iptal edildi! \n\nİstediğiniz zaman /start ile yeniden başlayabilirsiniz. 🔄"
"error_add_client" = "⚠️ Hata:\n\n {{ .error }}"
"using_default_value" = "Tamam, varsayılan değeri kullanacağım. 😊"
"incorrect_input" ="Girdiğiniz değer geçerli değil.\nKelime öbekleri boşluk olmadan devam etmelidir.\nDoğru örnek: aaaaaa\nYanlış örnek: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Klavyeyi Kapat" "closeKeyboard" = "❌ Klavyeyi Kapat"
"cancel" = "❌ İptal" "cancel" = "❌ İptal"
@ -618,6 +634,15 @@
"getBanLogs" = "Yasak Günlüklerini Al" "getBanLogs" = "Yasak Günlüklerini Al"
"allClients" = "Tüm Müşteriler" "allClients" = "Tüm Müşteriler"
"addClient" = "Müşteri Ekle"
"submitDisable" = "Devre Dışı Olarak Gönder ✅"
"use_default" = "🏷️ Varsayılanı Kullan"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Şifre"
"change_email" = "⚙️📧 E-posta"
"change_comment" = "⚙️💬 Yorum"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ İşlem başarılı!" "successfulOperation" = "✅ İşlem başarılı!"
"errorOperation" = "❗ İşlemde hata." "errorOperation" = "❗ İşlemde hata."

View file

@ -584,6 +584,22 @@
"yes" = "✅ Так" "yes" = "✅ Так"
"no" = "❌ Ні" "no" = "❌ Ні"
"received_id" = "🔑📥 ID оновлено. Натисніть оновити, щоб побачити зміни."
"received_password" = "🔑📥 Пароль оновлено. Натисніть оновити, щоб побачити зміни."
"received_email" = "📧📥 Електронна пошта оновлена. Натисніть оновити, щоб побачити зміни."
"received_comment" = "💬📥 Коментар оновлено. Натисніть оновити, щоб побачити зміни."
"id_prompt" = "🔑 Стандартний ID: {{ .ClientId }}\n\nВведіть ваш ID."
"pass_prompt" = "🔑 Стандартний пароль: {{ .ClientPassword }}\n\nВведіть ваш пароль."
"email_prompt" = "📧 Стандартний email: {{ .ClientEmail }}\n\nВведіть ваш email."
"comment_prompt" = "💬 Стандартний коментар: {{ .ClientComment }}\n\nВведіть ваш коментар."
"inbound_client_data_id" = "🔄 Вхідні: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафік: {{ .ClientTraffic }}\n📅 Термін придатності: {{ .ClientExp }}\n💬 Коментар: {{ .ClientComment }}\n\nТепер ви можете додати клієнта до вхідних!"
"inbound_client_data_pass" = "🔄 Вхідні: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафік: {{ .ClientTraffic }}\n📅 Термін придатності: {{ .ClientExp }}\n💬 Коментар: {{ .ClientComment }}\n\nТепер ви можете додати клієнта до вхідних!"
"cancel" = "❌ Процес скасовано! \n\nВи можете знову розпочати, використовуючи /start у будь-який час. 🔄"
"error_add_client" = "⚠️ Помилка:\n\n {{ .error }}"
"using_default_value" = "Гаразд, залишу значення за замовчуванням. 😊"
"incorrect_input" ="Ваш ввід невірний.\nФрази повинні бути без пробілів.\nПравильний приклад: aaaaaa\nНеправильний приклад: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Закрити клавіатуру" "closeKeyboard" = "❌ Закрити клавіатуру"
"cancel" = "❌ Скасувати" "cancel" = "❌ Скасувати"
@ -618,6 +634,15 @@
"getBanLogs" = "Отримати журнали заборон" "getBanLogs" = "Отримати журнали заборон"
"allClients" = "Всі Клієнти" "allClients" = "Всі Клієнти"
"addClient" = "Додати клієнта"
"submitDisable" = "Надіслати як вимкнене ✅"
"use_default" = "🏷️ Використовувати за замовчуванням"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Пароль"
"change_email" = "⚙️📧 Електронна пошта"
"change_comment" = "⚙️💬 Коментар"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ Операція успішна!" "successfulOperation" = "✅ Операція успішна!"
"errorOperation" = "❗ Помилка в роботі." "errorOperation" = "❗ Помилка в роботі."

View file

@ -584,6 +584,22 @@
"yes" = "✅ Có" "yes" = "✅ Có"
"no" = "❌ Không" "no" = "❌ Không"
"received_id" = "🔑📥 ID đã được cập nhật. Nhấn làm mới để xem thay đổi."
"received_password" = "🔑📥 Mật khẩu đã được cập nhật. Nhấn làm mới để xem thay đổi."
"received_email" = "📧📥 Email đã được cập nhật. Nhấn làm mới để xem thay đổi."
"received_comment" = "💬📥 Bình luận đã được cập nhật. Nhấn làm mới để xem thay đổi."
"id_prompt" = "🔑 ID mặc định: {{ .ClientId }}\n\nVui lòng nhập ID của bạn."
"pass_prompt" = "🔑 Mật khẩu mặc định: {{ .ClientPassword }}\n\nVui lòng nhập mật khẩu của bạn."
"email_prompt" = "📧 Email mặc định: {{ .ClientEmail }}\n\nVui lòng nhập email của bạn."
"comment_prompt" = "💬 Bình luận mặc định: {{ .ClientComment }}\n\nVui lòng nhập bình luận của bạn."
"inbound_client_data_id" = "🔄 Vào: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lưu lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n💬 Bình luận: {{ .ClientComment }}\n\nBạn có thể thêm khách hàng vào vào ngay bây giờ!"
"inbound_client_data_pass" = "🔄 Vào: {{ .InboundRemark }}\n\n🔑 Mật khẩu: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lưu lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n💬 Bình luận: {{ .ClientComment }}\n\nBạn có thể thêm khách hàng vào vào ngay bây giờ!"
"cancel" = "❌ Quá trình đã bị hủy! \n\nBạn có thể bắt đầu lại bất cứ lúc nào bằng cách nhập /start. 🔄"
"error_add_client" = "⚠️ Lỗi:\n\n {{ .error }}"
"using_default_value" = "Được rồi, tôi sẽ sử dụng giá trị mặc định. 😊"
"incorrect_input" ="Dữ liệu bạn nhập không hợp lệ.\nCác chuỗi phải liền mạch và không có dấu cách.\nVí dụ đúng: aaaaaa\nVí dụ sai: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ Đóng Bàn Phím" "closeKeyboard" = "❌ Đóng Bàn Phím"
"cancel" = "❌ Hủy" "cancel" = "❌ Hủy"
@ -618,6 +634,15 @@
"getBanLogs" = "Cấm nhật ký" "getBanLogs" = "Cấm nhật ký"
"allClients" = "Tất cả Khách hàng" "allClients" = "Tất cả Khách hàng"
"addClient" = "Thêm Khách Hàng"
"submitDisable" = "Gửi Dưới Dạng Tắt ✅"
"use_default" = "🏷️ Sử dụng mặc định"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 Mật khẩu"
"change_email" = "⚙️📧 Email"
"change_comment" = "⚙️💬 Bình luận"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ Thành công!" "successfulOperation" = "✅ Thành công!"
"errorOperation" = "❗ Lỗi Trong Quá Trình Thực Hiện." "errorOperation" = "❗ Lỗi Trong Quá Trình Thực Hiện."

View file

@ -584,6 +584,22 @@
"yes" = "✅ 是的" "yes" = "✅ 是的"
"no" = "❌ 没有" "no" = "❌ 没有"
"received_id" = "🔑📥 ID 已更新。请按刷新查看更改。"
"received_password" = "🔑📥 密码已更新。请按刷新查看更改。"
"received_email" = "📧📥 邮箱已更新。请按刷新查看更改。"
"received_comment" = "💬📥 评论已更新。请按刷新查看更改。"
"id_prompt" = "🔑 默认 ID: {{ .ClientId }}\n\n请输入您的 ID。"
"pass_prompt" = "🔑 默认密码: {{ .ClientPassword }}\n\n请输入您的密码。"
"email_prompt" = "📧 默认邮箱: {{ .ClientEmail }}\n\n请输入您的邮箱。"
"comment_prompt" = "💬 默认评论: {{ .ClientComment }}\n\n请输入您的评论。"
"inbound_client_data_id" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 过期日期: {{ .ClientExp }}\n💬 评论: {{ .ClientComment }}\n\n您现在可以将客户添加到入站"
"inbound_client_data_pass" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 密码: {{ .ClientPass }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 过期日期: {{ .ClientExp }}\n💬 评论: {{ .ClientComment }}\n\n您现在可以将客户添加到入站"
"cancel" = "❌ 进程已取消!\n\n您可以随时使用 /start 重新开始。 🔄"
"error_add_client" = "⚠️ 错误:\n\n {{ .error }}"
"using_default_value" = "好的,我会使用默认值。 😊"
"incorrect_input" ="您的输入无效。\n短语应连续输入不能有空格。\n正确示例: aaaaaa\n错误示例: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ 关闭键盘" "closeKeyboard" = "❌ 关闭键盘"
"cancel" = "❌ 取消" "cancel" = "❌ 取消"
@ -618,6 +634,15 @@
"getBanLogs" = "禁止日志" "getBanLogs" = "禁止日志"
"allClients" = "所有客户" "allClients" = "所有客户"
"addClient" = "添加客户"
"submitDisable" = "提交为禁用 ✅"
"use_default" = "🏷️ 使用默认"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 密码"
"change_email" = "⚙️📧 邮箱"
"change_comment" = "⚙️💬 评论"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ 成功!" "successfulOperation" = "✅ 成功!"
"errorOperation" = "❗ 操作错误。" "errorOperation" = "❗ 操作错误。"

View file

@ -584,6 +584,22 @@
"yes" = "✅ 是的" "yes" = "✅ 是的"
"no" = "❌ 沒有" "no" = "❌ 沒有"
"received_id" = "🔑📥 ID 已更新。請按刷新查看變更。"
"received_password" = "🔑📥 密碼已更新。請按刷新查看變更。"
"received_email" = "📧📥 電子郵件已更新。請按刷新查看變更。"
"received_comment" = "💬📥 評論已更新。請按刷新查看變更。"
"id_prompt" = "🔑 預設 ID: {{ .ClientId }}\n\n請輸入您的 ID。"
"pass_prompt" = "🔑 預設密碼: {{ .ClientPassword }}\n\n請輸入您的密碼。"
"email_prompt" = "📧 預設電子郵件: {{ .ClientEmail }}\n\n請輸入您的電子郵件。"
"comment_prompt" = "💬 預設評論: {{ .ClientComment }}\n\n請輸入您的評論。"
"inbound_client_data_id" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n💬 評論: {{ .ClientComment }}\n\n您現在可以將客戶新增至入站"
"inbound_client_data_pass" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 密碼: {{ .ClientPass }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n💬 評論: {{ .ClientComment }}\n\n您現在可以將客戶新增至入站"
"cancel" = "❌ 程序已取消!\n\n您可以隨時使用 /start 重新開始。 🔄"
"error_add_client" = "⚠️ 錯誤:\n\n {{ .error }}"
"using_default_value" = "好的,我會使用預設值。 😊"
"incorrect_input" ="您的輸入無效。\n短語應連續輸入不能有空格。\n正確示例: aaaaaa\n錯誤示例: aaa aaa 🚫"
[tgbot.buttons] [tgbot.buttons]
"closeKeyboard" = "❌ 關閉鍵盤" "closeKeyboard" = "❌ 關閉鍵盤"
"cancel" = "❌ 取消" "cancel" = "❌ 取消"
@ -618,6 +634,15 @@
"getBanLogs" = "禁止日誌" "getBanLogs" = "禁止日誌"
"allClients" = "所有客戶" "allClients" = "所有客戶"
"addClient" = "新增客戶"
"submitDisable" = "提交為停用 ✅"
"use_default" = "🏷️ 使用預設"
"change_id" = "⚙️🔑 ID"
"change_password" = "⚙️🔑 密碼"
"change_email" = "⚙️📧 電子郵件"
"change_comment" = "⚙️💬 評論"
[tgbot.answers] [tgbot.answers]
"successfulOperation" = "✅ 成功!" "successfulOperation" = "✅ 成功!"
"errorOperation" = "❗ 操作錯誤。" "errorOperation" = "❗ 操作錯誤。"