Merge branch 'MHSanaei:main' into main
This commit is contained in:
commit
7c03d7f940
@ -209,9 +209,10 @@ func (s *SubJsonService) streamData(stream string) map[string]any {
|
||||
var streamSettings map[string]any
|
||||
json.Unmarshal([]byte(stream), &streamSettings)
|
||||
security, _ := streamSettings["security"].(string)
|
||||
if security == "tls" {
|
||||
switch security {
|
||||
case "tls":
|
||||
streamSettings["tlsSettings"] = s.tlsData(streamSettings["tlsSettings"].(map[string]any))
|
||||
} else if security == "reality" {
|
||||
case "reality":
|
||||
streamSettings["realitySettings"] = s.realityData(streamSettings["realitySettings"].(map[string]any))
|
||||
}
|
||||
delete(streamSettings, "sockopt")
|
||||
|
||||
@ -2,10 +2,10 @@ package entity
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"math"
|
||||
"net"
|
||||
"strings"
|
||||
"time"
|
||||
"math"
|
||||
|
||||
"x-ui/util/common"
|
||||
)
|
||||
@ -39,8 +39,8 @@ type AllSetting struct {
|
||||
TgCpu int `json:"tgCpu" form:"tgCpu"`
|
||||
TgLang string `json:"tgLang" form:"tgLang"`
|
||||
TimeLocation string `json:"timeLocation" form:"timeLocation"`
|
||||
TwoFactorEnable bool `json:"twoFactorEnable" form:"twoFactorEnable"`
|
||||
TwoFactorToken string `json:"twoFactorToken" form:"twoFactorToken"`
|
||||
TwoFactorEnable bool `json:"twoFactorEnable" form:"twoFactorEnable"`
|
||||
TwoFactorToken string `json:"twoFactorToken" form:"twoFactorToken"`
|
||||
SubEnable bool `json:"subEnable" form:"subEnable"`
|
||||
SubTitle string `json:"subTitle" form:"subTitle"`
|
||||
SubListen string `json:"subListen" form:"subListen"`
|
||||
|
||||
@ -11,7 +11,6 @@ import (
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"slices"
|
||||
"x-ui/database"
|
||||
"x-ui/database/model"
|
||||
"x-ui/logger"
|
||||
@ -58,21 +57,21 @@ func (j *CheckClientIpJob) Run() {
|
||||
func (j *CheckClientIpJob) clearAccessLog() {
|
||||
logAccessP, err := os.OpenFile(xray.GetAccessPersistentLogPath(), os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0o644)
|
||||
j.checkError(err)
|
||||
defer logAccessP.Close()
|
||||
|
||||
accessLogPath, err := xray.GetAccessLogPath()
|
||||
j.checkError(err)
|
||||
|
||||
file, err := os.Open(accessLogPath)
|
||||
j.checkError(err)
|
||||
defer file.Close()
|
||||
|
||||
_, err = io.Copy(logAccessP, file)
|
||||
j.checkError(err)
|
||||
|
||||
logAccessP.Close()
|
||||
file.Close()
|
||||
|
||||
err = os.Truncate(accessLogPath, 0)
|
||||
j.checkError(err)
|
||||
|
||||
j.lastClear = time.Now().Unix()
|
||||
}
|
||||
|
||||
@ -193,10 +192,6 @@ func (j *CheckClientIpJob) checkError(e error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (j *CheckClientIpJob) contains(s []string, str string) bool {
|
||||
return slices.Contains(s, str)
|
||||
}
|
||||
|
||||
func (j *CheckClientIpJob) getInboundClientIps(clientEmail string) (*model.InboundClientIps, error) {
|
||||
db := database.GetDB()
|
||||
InboundClientIps := &model.InboundClientIps{}
|
||||
|
||||
@ -177,15 +177,16 @@ func (s *InboundService) AddInbound(inbound *model.Inbound) (*model.Inbound, boo
|
||||
|
||||
// Secure client ID
|
||||
for _, client := range clients {
|
||||
if inbound.Protocol == "trojan" {
|
||||
switch inbound.Protocol {
|
||||
case "trojan":
|
||||
if client.Password == "" {
|
||||
return inbound, false, common.NewError("empty client ID")
|
||||
}
|
||||
} else if inbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
if client.Email == "" {
|
||||
return inbound, false, common.NewError("empty client ID")
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
if client.ID == "" {
|
||||
return inbound, false, common.NewError("empty client ID")
|
||||
}
|
||||
@ -436,15 +437,16 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
|
||||
|
||||
// Secure client ID
|
||||
for _, client := range clients {
|
||||
if oldInbound.Protocol == "trojan" {
|
||||
switch oldInbound.Protocol {
|
||||
case "trojan":
|
||||
if client.Password == "" {
|
||||
return false, common.NewError("empty client ID")
|
||||
}
|
||||
} else if oldInbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
if client.Email == "" {
|
||||
return false, common.NewError("empty client ID")
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
if client.ID == "" {
|
||||
return false, common.NewError("empty client ID")
|
||||
}
|
||||
@ -631,13 +633,14 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
|
||||
clientIndex := -1
|
||||
for index, oldClient := range oldClients {
|
||||
oldClientId := ""
|
||||
if oldInbound.Protocol == "trojan" {
|
||||
switch oldInbound.Protocol {
|
||||
case "trojan":
|
||||
oldClientId = oldClient.Password
|
||||
newClientId = clients[0].Password
|
||||
} else if oldInbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
oldClientId = oldClient.Email
|
||||
newClientId = clients[0].Email
|
||||
} else {
|
||||
default:
|
||||
oldClientId = oldClient.ID
|
||||
newClientId = clients[0].ID
|
||||
}
|
||||
@ -1244,11 +1247,12 @@ func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId int64) (boo
|
||||
|
||||
for _, oldClient := range oldClients {
|
||||
if oldClient.Email == clientEmail {
|
||||
if inbound.Protocol == "trojan" {
|
||||
switch inbound.Protocol {
|
||||
case "trojan":
|
||||
clientId = oldClient.Password
|
||||
} else if inbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
clientId = oldClient.Email
|
||||
} else {
|
||||
default:
|
||||
clientId = oldClient.ID
|
||||
}
|
||||
break
|
||||
@ -1328,11 +1332,12 @@ func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, bo
|
||||
|
||||
for _, oldClient := range oldClients {
|
||||
if oldClient.Email == clientEmail {
|
||||
if inbound.Protocol == "trojan" {
|
||||
switch inbound.Protocol {
|
||||
case "trojan":
|
||||
clientId = oldClient.Password
|
||||
} else if inbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
clientId = oldClient.Email
|
||||
} else {
|
||||
default:
|
||||
clientId = oldClient.ID
|
||||
}
|
||||
clientOldEnabled = oldClient.Enable
|
||||
@ -1391,11 +1396,12 @@ func (s *InboundService) ResetClientIpLimitByEmail(clientEmail string, count int
|
||||
|
||||
for _, oldClient := range oldClients {
|
||||
if oldClient.Email == clientEmail {
|
||||
if inbound.Protocol == "trojan" {
|
||||
switch inbound.Protocol {
|
||||
case "trojan":
|
||||
clientId = oldClient.Password
|
||||
} else if inbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
clientId = oldClient.Email
|
||||
} else {
|
||||
default:
|
||||
clientId = oldClient.ID
|
||||
}
|
||||
break
|
||||
@ -1448,11 +1454,12 @@ func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiry
|
||||
|
||||
for _, oldClient := range oldClients {
|
||||
if oldClient.Email == clientEmail {
|
||||
if inbound.Protocol == "trojan" {
|
||||
switch inbound.Protocol {
|
||||
case "trojan":
|
||||
clientId = oldClient.Password
|
||||
} else if inbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
clientId = oldClient.Email
|
||||
} else {
|
||||
default:
|
||||
clientId = oldClient.ID
|
||||
}
|
||||
break
|
||||
@ -1508,11 +1515,12 @@ func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, tota
|
||||
|
||||
for _, oldClient := range oldClients {
|
||||
if oldClient.Email == clientEmail {
|
||||
if inbound.Protocol == "trojan" {
|
||||
switch inbound.Protocol {
|
||||
case "trojan":
|
||||
clientId = oldClient.Password
|
||||
} else if inbound.Protocol == "shadowsocks" {
|
||||
case "shadowsocks":
|
||||
clientId = oldClient.Email
|
||||
} else {
|
||||
default:
|
||||
clientId = oldClient.ID
|
||||
}
|
||||
break
|
||||
|
||||
@ -40,7 +40,6 @@ var (
|
||||
isRunning bool
|
||||
hostname string
|
||||
hashStorage *global.HashStorage
|
||||
handler *th.Handler
|
||||
|
||||
// clients data to adding new client
|
||||
receiver_inbound_ID int
|
||||
@ -641,13 +640,14 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
if len(dataArray) == 4 {
|
||||
num, err := strconv.Atoi(dataArray[3])
|
||||
if err == nil {
|
||||
if num == -2 {
|
||||
switch num {
|
||||
case -2:
|
||||
inputNumber = 0
|
||||
} else if num == -1 {
|
||||
case -1:
|
||||
if inputNumber > 0 {
|
||||
inputNumber = (inputNumber / 10)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
inputNumber = (inputNumber * 10) + num
|
||||
}
|
||||
}
|
||||
@ -704,6 +704,10 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
||||
@ -715,13 +719,14 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
if len(dataArray) == 3 {
|
||||
num, err := strconv.Atoi(dataArray[2])
|
||||
if err == nil {
|
||||
if num == -2 {
|
||||
switch num {
|
||||
case -2:
|
||||
inputNumber = 0
|
||||
} else if num == -1 {
|
||||
case -1:
|
||||
if inputNumber > 0 {
|
||||
inputNumber = (inputNumber / 10)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
inputNumber = (inputNumber * 10) + num
|
||||
}
|
||||
}
|
||||
@ -844,13 +849,14 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
if len(dataArray) == 4 {
|
||||
num, err := strconv.Atoi(dataArray[3])
|
||||
if err == nil {
|
||||
if num == -2 {
|
||||
switch num {
|
||||
case -2:
|
||||
inputNumber = 0
|
||||
} else if num == -1 {
|
||||
case -1:
|
||||
if inputNumber > 0 {
|
||||
inputNumber = (inputNumber / 10)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
inputNumber = (inputNumber * 10) + num
|
||||
}
|
||||
}
|
||||
@ -919,6 +925,10 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
||||
@ -930,13 +940,14 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
if len(dataArray) == 3 {
|
||||
num, err := strconv.Atoi(dataArray[2])
|
||||
if err == nil {
|
||||
if num == -2 {
|
||||
switch num {
|
||||
case -2:
|
||||
inputNumber = 0
|
||||
} else if num == -1 {
|
||||
case -1:
|
||||
if inputNumber > 0 {
|
||||
inputNumber = (inputNumber / 10)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
inputNumber = (inputNumber * 10) + num
|
||||
}
|
||||
}
|
||||
@ -1035,13 +1046,14 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
if len(dataArray) == 4 {
|
||||
num, err := strconv.Atoi(dataArray[3])
|
||||
if err == nil {
|
||||
if num == -2 {
|
||||
switch num {
|
||||
case -2:
|
||||
inputNumber = 0
|
||||
} else if num == -1 {
|
||||
case -1:
|
||||
if inputNumber > 0 {
|
||||
inputNumber = (inputNumber / 10)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
inputNumber = (inputNumber * 10) + num
|
||||
}
|
||||
}
|
||||
@ -1101,6 +1113,10 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
t.addClient(callbackQuery.Message.GetChat().ID, message_text, messageId)
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
|
||||
@ -1112,13 +1128,14 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
if len(dataArray) == 3 {
|
||||
num, err := strconv.Atoi(dataArray[2])
|
||||
if err == nil {
|
||||
if num == -2 {
|
||||
switch num {
|
||||
case -2:
|
||||
inputNumber = 0
|
||||
} else if num == -1 {
|
||||
case -1:
|
||||
if inputNumber > 0 {
|
||||
inputNumber = (inputNumber / 10)
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
inputNumber = (inputNumber * 10) + num
|
||||
}
|
||||
}
|
||||
@ -1288,6 +1305,10 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
}
|
||||
|
||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
t.addClient(callbackQuery.Message.GetChat().ID, message_text)
|
||||
}
|
||||
@ -1524,6 +1545,10 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
t.addClient(chatId, message_text, messageId)
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
|
||||
case "add_client_default_ip_limit":
|
||||
@ -1534,6 +1559,10 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||
if err != nil {
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
|
||||
return
|
||||
}
|
||||
t.addClient(chatId, message_text, messageId)
|
||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
|
||||
case "add_client_submit_disable":
|
||||
@ -1598,6 +1627,10 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||
return
|
||||
}
|
||||
valid_emails, extra_emails, err := t.inboundService.FilterAndSortClientEmails(emails)
|
||||
if err != nil {
|
||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
|
||||
return
|
||||
}
|
||||
|
||||
for _, valid_emails := range valid_emails {
|
||||
traffic, err := t.inboundService.GetClientTrafficByEmail(valid_emails)
|
||||
@ -1760,6 +1793,10 @@ func (t *Tgbot) SubmitAddClient() (bool, error) {
|
||||
}
|
||||
|
||||
jsonString, err := t.BuildJSONForProtocol(inbound.Protocol)
|
||||
if err != nil {
|
||||
logger.Warning("BuildJSONForProtocol run failed:", err)
|
||||
return false, errors.New("failed to build JSON for protocol")
|
||||
}
|
||||
|
||||
newInbound := &model.Inbound{
|
||||
Id: receiver_inbound_ID,
|
||||
@ -2008,10 +2045,11 @@ func (t *Tgbot) UserLoginNotify(username string, password string, ip string, tim
|
||||
}
|
||||
|
||||
msg := ""
|
||||
if status == LoginSuccess {
|
||||
switch status {
|
||||
case LoginSuccess:
|
||||
msg += t.I18nBot("tgbot.messages.loginSuccess")
|
||||
msg += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname)
|
||||
} else if status == LoginFail {
|
||||
case LoginFail:
|
||||
msg += t.I18nBot("tgbot.messages.loginFailed")
|
||||
msg += t.I18nBot("tgbot.messages.hostname", "Hostname=="+hostname)
|
||||
msg += t.I18nBot("tgbot.messages.password", "Password=="+password)
|
||||
@ -2171,6 +2209,22 @@ func (t *Tgbot) clientInfoMsg(
|
||||
expiryTime = t.I18nBot("tgbot.unlimited")
|
||||
} else if diff > 172800 || !traffic.Enable {
|
||||
expiryTime = time.Unix((traffic.ExpiryTime / 1000), 0).Format("2006-01-02 15:04:05")
|
||||
if diff > 0 {
|
||||
days := diff / 86400
|
||||
hours := (diff % 86400) / 3600
|
||||
minutes := (diff % 3600) / 60
|
||||
remainingTime := ""
|
||||
if days > 0 {
|
||||
remainingTime += fmt.Sprintf("%d %s ", days, t.I18nBot("tgbot.days"))
|
||||
}
|
||||
if hours > 0 {
|
||||
remainingTime += fmt.Sprintf("%d %s ", hours, t.I18nBot("tgbot.hours"))
|
||||
}
|
||||
if minutes > 0 {
|
||||
remainingTime += fmt.Sprintf("%d %s", minutes, t.I18nBot("tgbot.minutes"))
|
||||
}
|
||||
expiryTime += fmt.Sprintf(" (%s)", remainingTime)
|
||||
}
|
||||
} else if traffic.ExpiryTime < 0 {
|
||||
expiryTime = fmt.Sprintf("%d %s", traffic.ExpiryTime/-86400000, t.I18nBot("tgbot.days"))
|
||||
flag = true
|
||||
|
||||
@ -561,24 +561,25 @@
|
||||
"resetOutboundTrafficError" = "خطأ في إعادة تعيين حركات المرور الصادرة"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ الكيبورد المخصص اتقفلت!"
|
||||
"noResult" = "❗ مفيش نتيجة!"
|
||||
"noQuery" = "❌ مش لاقي السؤال! استخدم الأمر تاني!"
|
||||
"wentWrong" = "❌ حصل خطأ!"
|
||||
"noIpRecord" = "❗ مفيش سجل IP!"
|
||||
"noInbounds" = "❗ مفيش إدخال متواجد!"
|
||||
"unlimited" = "♾ غير محدود (إعادة ضبط)"
|
||||
"add" = "أضف"
|
||||
"keyboardClosed" = "❌ لوحة المفاتيح مغلقة!"
|
||||
"noResult" = "❗ لا يوجد نتائج!"
|
||||
"noQuery" = "❌ لم يتم العثور على الاستعلام! يرجى استخدام الأمر مرة أخرى!"
|
||||
"wentWrong" = "❌ حدث خطأ ما!"
|
||||
"noIpRecord" = "❗ لا يوجد سجل IP!"
|
||||
"noInbounds" = "❗ لم يتم العثور على أي وارد!"
|
||||
"unlimited" = "♾ غير محدود (إعادة تعيين)"
|
||||
"add" = "إضافة"
|
||||
"month" = "شهر"
|
||||
"months" = "شهور"
|
||||
"months" = "أشهر"
|
||||
"day" = "يوم"
|
||||
"days" = "أيام"
|
||||
"hours" = "ساعات"
|
||||
"unknown" = "مش معروف"
|
||||
"inbounds" = "الإدخالات"
|
||||
"minutes" = "دقائق"
|
||||
"unknown" = "غير معروف"
|
||||
"inbounds" = "الواردات"
|
||||
"clients" = "العملاء"
|
||||
"offline" = "🔴 أوفلاين"
|
||||
"online" = "🟢 أونلاين"
|
||||
"offline" = "🔴 غير متصل"
|
||||
"online" = "🟢 متصل"
|
||||
|
||||
[tgbot.commands]
|
||||
"unknown" = "❗ أمر مش معروف."
|
||||
|
||||
@ -578,6 +578,7 @@
|
||||
"day" = "Day"
|
||||
"days" = "Days"
|
||||
"hours" = "Hours"
|
||||
"minutes" = "Minutes"
|
||||
"unknown" = "Unknown"
|
||||
"inbounds" = "Inbounds"
|
||||
"clients" = "Clients"
|
||||
|
||||
@ -91,7 +91,7 @@
|
||||
"invalidFormData" = "El formato de los datos de entrada es inválido."
|
||||
"emptyUsername" = "Por favor ingresa el nombre de usuario."
|
||||
"emptyPassword" = "Por favor ingresa la contraseña."
|
||||
"wrongUsernameOrPassword" = "Nombre de usuario, contraseña o código de dos factores incorrecto."
|
||||
"wrongUsernameOrPassword" = "Nombre de usuario, contraseña o código de dos factores incorrecto."
|
||||
"successLogin" = "Has iniciado sesión en tu cuenta correctamente."
|
||||
|
||||
[pages.index]
|
||||
@ -535,9 +535,9 @@
|
||||
|
||||
[pages.settings.security]
|
||||
"admin" = "Credenciales de administrador"
|
||||
"twoFactor" = "Autenticación de dos factores"
|
||||
"twoFactorEnable" = "Habilitar 2FA"
|
||||
"twoFactorEnableDesc" = "Añade una capa adicional de autenticación para mayor seguridad."
|
||||
"twoFactor" = "Autenticación de dos factores"
|
||||
"twoFactorEnable" = "Habilitar 2FA"
|
||||
"twoFactorEnableDesc" = "Añade una capa adicional de autenticación para mayor seguridad."
|
||||
"twoFactorModalSetTitle" = "Activar autenticación de dos factores"
|
||||
"twoFactorModalDeleteTitle" = "Desactivar autenticación de dos factores"
|
||||
"twoFactorModalSteps" = "Para configurar la autenticación de dos factores, sigue estos pasos:"
|
||||
@ -561,23 +561,24 @@
|
||||
"resetOutboundTrafficError" = "Error al reiniciar el tráfico saliente"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ ¡Teclado personalizado cerrado!"
|
||||
"noResult" = "❗ ¡Sin resultados!"
|
||||
"noQuery" = "❌ ¡Consulta no encontrada! ¡Por favor utiliza el comando nuevamente!"
|
||||
"keyboardClosed" = "❌ Teclado cerrado!"
|
||||
"noResult" = "❗ ¡No hay resultados!"
|
||||
"noQuery" = "❌ ¡Consulta no encontrada! ¡Por favor, use el comando de nuevo!"
|
||||
"wentWrong" = "❌ ¡Algo salió mal!"
|
||||
"noIpRecord" = "❗ ¡Sin Registro de IP!"
|
||||
"noIpRecord" = "❗ ¡No hay registro de IP!"
|
||||
"noInbounds" = "❗ ¡No se encontraron entradas!"
|
||||
"unlimited" = "♾ Ilimitado"
|
||||
"add" = "Agregar"
|
||||
"unlimited" = "♾ Ilimitado (Restablecer)"
|
||||
"add" = "Añadir"
|
||||
"month" = "Mes"
|
||||
"months" = "Meses"
|
||||
"day" = "Día"
|
||||
"days" = "Días"
|
||||
"hours" = "Horas"
|
||||
"minutes" = "Minutos"
|
||||
"unknown" = "Desconocido"
|
||||
"inbounds" = "Entradas"
|
||||
"clients" = "Clientes"
|
||||
"offline" = "🔴 Sin conexión"
|
||||
"offline" = "🔴 Desconectado"
|
||||
"online" = "🟢 En línea"
|
||||
|
||||
[tgbot.commands]
|
||||
|
||||
@ -561,22 +561,23 @@
|
||||
"resetOutboundTrafficError" = "خطا در بازنشانی ترافیک خروجی"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ کیبورد سفارشی بسته شد!"
|
||||
"noResult" = "❗ نتیجهای یافت نشد!"
|
||||
"noQuery" = "❌ کوئری یافت نشد! لطفاً دستور را مجدداً استفاده کنید!"
|
||||
"wentWrong" = "❌ مشکلی رخ داده است!"
|
||||
"noIpRecord" = "❗ رکورد IP یافت نشد!"
|
||||
"keyboardClosed" = "❌ صفحه کلید بسته شد!"
|
||||
"noResult" = "❗ نتیجه ای یافت نشد!"
|
||||
"noQuery" = "❌ درخواست یافت نشد! لطفا دوباره تلاش کنید!"
|
||||
"wentWrong" = "❌ مشکلی پیش آمد!"
|
||||
"noIpRecord" = "❗ رکورد آی پی وجود ندارد!"
|
||||
"noInbounds" = "❗ هیچ ورودی یافت نشد!"
|
||||
"unlimited" = "♾ - نامحدود(ریست)"
|
||||
"add" = "اضافه کردن"
|
||||
"unlimited" = "♾ نامحدود(ریست)"
|
||||
"add" = "افزودن"
|
||||
"month" = "ماه"
|
||||
"months" = "ماه"
|
||||
"months" = "ماه"
|
||||
"day" = "روز"
|
||||
"days" = "روز"
|
||||
"hours" = "ساعت"
|
||||
"hours" = "ساعت"
|
||||
"minutes" = "دقیقه"
|
||||
"unknown" = "نامشخص"
|
||||
"inbounds" = "ورودیها"
|
||||
"clients" = "کلاینتها"
|
||||
"inbounds" = "ورودی ها"
|
||||
"clients" = "کاربران"
|
||||
"offline" = "🔴 آفلاین"
|
||||
"online" = "🟢 آنلاین"
|
||||
|
||||
|
||||
@ -561,21 +561,22 @@
|
||||
"resetOutboundTrafficError" = "Gagal mereset lalu lintas keluar"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ Papan ketik kustom ditutup!"
|
||||
"keyboardClosed" = "❌ Keyboard ditutup!"
|
||||
"noResult" = "❗ Tidak ada hasil!"
|
||||
"noQuery" = "❌ Permintaan tidak ditemukan! Harap gunakan perintah lagi!"
|
||||
"wentWrong" = "❌ Ada yang salah!"
|
||||
"noQuery" = "❌ Kueri tidak ditemukan! Silakan gunakan perintah lagi!"
|
||||
"wentWrong" = "❌ Terjadi kesalahan!"
|
||||
"noIpRecord" = "❗ Tidak ada Catatan IP!"
|
||||
"noInbounds" = "❗ Tidak ada masuk ditemukan!"
|
||||
"unlimited" = "♾ Tak terbatas"
|
||||
"noInbounds" = "❗ Tidak ada inbound yang ditemukan!"
|
||||
"unlimited" = "♾ Tidak terbatas (Reset)"
|
||||
"add" = "Tambah"
|
||||
"month" = "Bulan"
|
||||
"months" = "Bulan"
|
||||
"day" = "Hari"
|
||||
"days" = "Hari"
|
||||
"hours" = "Jam"
|
||||
"minutes" = "Menit"
|
||||
"unknown" = "Tidak diketahui"
|
||||
"inbounds" = "Masuk"
|
||||
"inbounds" = "Inbound"
|
||||
"clients" = "Klien"
|
||||
"offline" = "🔴 Offline"
|
||||
"online" = "🟢 Online"
|
||||
|
||||
@ -561,21 +561,22 @@
|
||||
"resetOutboundTrafficError" = "送信トラフィックのリセットエラー"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ カスタムキーボードが閉じられました!"
|
||||
"keyboardClosed" = "❌ キーボードを閉じました!"
|
||||
"noResult" = "❗ 結果がありません!"
|
||||
"noQuery" = "❌ クエリが見つかりませんでした!もう一度コマンドを使用してください!"
|
||||
"wentWrong" = "❌ 問題が発生しました!"
|
||||
"noIpRecord" = "❗ IP記録がありません!"
|
||||
"noInbounds" = "❗ インバウンド接続が見つかりません!"
|
||||
"unlimited" = "♾ 無制限"
|
||||
"noQuery" = "❌ クエリが見つかりません!コマンドを再利用してください!"
|
||||
"wentWrong" = "❌ 何かがうまくいかなかった!"
|
||||
"noIpRecord" = "❗ IPレコードがありません!"
|
||||
"noInbounds" = "❗ インバウンドが見つかりません!"
|
||||
"unlimited" = "♾ 無制限(リセット)"
|
||||
"add" = "追加"
|
||||
"month" = "月"
|
||||
"months" = "月"
|
||||
"months" = "ヶ月"
|
||||
"day" = "日"
|
||||
"days" = "日"
|
||||
"days" = "日間"
|
||||
"hours" = "時間"
|
||||
"minutes" = "分"
|
||||
"unknown" = "不明"
|
||||
"inbounds" = "インバウンド接続"
|
||||
"inbounds" = "インバウンド"
|
||||
"clients" = "クライアント"
|
||||
"offline" = "🔴 オフライン"
|
||||
"online" = "🟢 オンライン"
|
||||
|
||||
@ -561,21 +561,22 @@
|
||||
"resetOutboundTrafficError" = "Erro ao redefinir tráfego de saída"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ Teclado personalizado fechado!"
|
||||
"keyboardClosed" = "❌ Teclado fechado!"
|
||||
"noResult" = "❗ Nenhum resultado!"
|
||||
"noQuery" = "❌ Consulta não encontrada! Por favor, use o comando novamente!"
|
||||
"wentWrong" = "❌ Algo deu errado!"
|
||||
"noIpRecord" = "❗ Nenhum registro de IP!"
|
||||
"noInbounds" = "❗ Nenhuma entrada encontrada!"
|
||||
"unlimited" = "♾ Ilimitado (Reiniciar)"
|
||||
"noInbounds" = "❗ Nenhum inbound encontrado!"
|
||||
"unlimited" = "♾ Ilimitado (Reset)"
|
||||
"add" = "Adicionar"
|
||||
"month" = "Mês"
|
||||
"months" = "Meses"
|
||||
"day" = "Dia"
|
||||
"days" = "Dias"
|
||||
"hours" = "Horas"
|
||||
"minutes" = "Minutos"
|
||||
"unknown" = "Desconhecido"
|
||||
"inbounds" = "Entradas"
|
||||
"inbounds" = "Inbounds"
|
||||
"clients" = "Clientes"
|
||||
"offline" = "🔴 Offline"
|
||||
"online" = "🟢 Online"
|
||||
|
||||
@ -574,6 +574,7 @@
|
||||
"day" = "День"
|
||||
"days" = "Дней"
|
||||
"hours" = "Часов"
|
||||
"minutes" = "Минуты"
|
||||
"unknown" = "Неизвестно"
|
||||
"inbounds" = "Инбаунды"
|
||||
"clients" = "Клиенты"
|
||||
|
||||
@ -561,22 +561,23 @@
|
||||
"resetOutboundTrafficError" = "Giden trafik sıfırlanırken hata"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ Özel klavye kapalı!"
|
||||
"keyboardClosed" = "❌ Klavye kapatıldı!"
|
||||
"noResult" = "❗ Sonuç yok!"
|
||||
"noQuery" = "❌ Sorgu bulunamadı! Lütfen komutu tekrar kullanın!"
|
||||
"wentWrong" = "❌ Bir şeyler yanlış gitti!"
|
||||
"noIpRecord" = "❗ IP Kaydı yok!"
|
||||
"noInbounds" = "❗ Gelen bulunamadı!"
|
||||
"unlimited" = "♾ Sınırsız(Sıfırla)"
|
||||
"noIpRecord" = "❗ IP Kaydı Yok!"
|
||||
"noInbounds" = "❗ Gelen bağlantı bulunamadı!"
|
||||
"unlimited" = "♾ Sınırsız (Sıfırla)"
|
||||
"add" = "Ekle"
|
||||
"month" = "Ay"
|
||||
"months" = "Aylar"
|
||||
"day" = "Gün"
|
||||
"days" = "Günler"
|
||||
"hours" = "Saatler"
|
||||
"unknown" = "Bilinmiyor"
|
||||
"minutes" = "Dakika"
|
||||
"unknown" = "Bilinmeyen"
|
||||
"inbounds" = "Gelenler"
|
||||
"clients" = "Müşteriler"
|
||||
"clients" = "İstemciler"
|
||||
"offline" = "🔴 Çevrimdışı"
|
||||
"online" = "🟢 Çevrimiçi"
|
||||
|
||||
|
||||
@ -561,19 +561,20 @@
|
||||
"resetOutboundTrafficError" = "Помилка скидання вихідного трафіку"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ Спеціальна клавіатура закрита!"
|
||||
"keyboardClosed" = "❌ Клавіатуру закрито!"
|
||||
"noResult" = "❗ Немає результату!"
|
||||
"noQuery" = "❌ Запит не знайдено! Скористайтеся командою ще раз!"
|
||||
"noQuery" = "❌ Запит не знайдено! Будь ласка, використовуйте команду ще раз!"
|
||||
"wentWrong" = "❌ Щось пішло не так!"
|
||||
"noIpRecord" = "❗ Немає IP-запису!"
|
||||
"noInbounds" = "❗ Вхідних не знайдено!"
|
||||
"unlimited" = "♾ Необмежений (скинути)"
|
||||
"noIpRecord" = "❗ Немає запису IP!"
|
||||
"noInbounds" = "❗ Вхідні не знайдені!"
|
||||
"unlimited" = "♾ Необмежено (Скинути)"
|
||||
"add" = "Додати"
|
||||
"month" = "Місяць"
|
||||
"months" = "Місяці"
|
||||
"day" = "День"
|
||||
"days" = "Дні"
|
||||
"hours" = "Годинник"
|
||||
"hours" = "Години"
|
||||
"minutes" = "Хвилини"
|
||||
"unknown" = "Невідомо"
|
||||
"inbounds" = "Вхідні"
|
||||
"clients" = "Клієнти"
|
||||
|
||||
@ -91,7 +91,7 @@
|
||||
"invalidFormData" = "Dạng dữ liệu nhập không hợp lệ."
|
||||
"emptyUsername" = "Vui lòng nhập tên người dùng."
|
||||
"emptyPassword" = "Vui lòng nhập mật khẩu."
|
||||
"wrongUsernameOrPassword" = "Tên người dùng, mật khẩu hoặc mã xác thực hai yếu tố không hợp lệ."
|
||||
"wrongUsernameOrPassword" = "Tên người dùng, mật khẩu hoặc mã xác thực hai yếu tố không hợp lệ."
|
||||
"successLogin" = "Bạn đã đăng nhập vào tài khoản thành công."
|
||||
|
||||
[pages.index]
|
||||
@ -535,9 +535,9 @@
|
||||
|
||||
[pages.settings.security]
|
||||
"admin" = "Thông tin đăng nhập quản trị viên"
|
||||
"twoFactor" = "Xác thực hai yếu tố"
|
||||
"twoFactorEnable" = "Bật 2FA"
|
||||
"twoFactorEnableDesc" = "Thêm một lớp bảo mật bổ sung để tăng cường an toàn."
|
||||
"twoFactor" = "Xác thực hai yếu tố"
|
||||
"twoFactorEnable" = "Bật 2FA"
|
||||
"twoFactorEnableDesc" = "Thêm một lớp bảo mật bổ sung để tăng cường an toàn."
|
||||
"twoFactorModalSetTitle" = "Bật xác thực hai yếu tố"
|
||||
"twoFactorModalDeleteTitle" = "Tắt xác thực hai yếu tố"
|
||||
"twoFactorModalSteps" = "Để thiết lập xác thực hai yếu tố, hãy thực hiện các bước sau:"
|
||||
@ -561,22 +561,23 @@
|
||||
"resetOutboundTrafficError" = "Lỗi khi đặt lại lưu lượng truy cập đi"
|
||||
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ Bàn phím tùy chỉnh đã đóng!"
|
||||
"keyboardClosed" = "❌ Bàn phím đã đóng!"
|
||||
"noResult" = "❗ Không có kết quả!"
|
||||
"noQuery" = "❌ Không tìm thấy truy vấn! Vui lòng sử dụng lệnh lại!"
|
||||
"noQuery" = "❌ Không tìm thấy truy vấn! Vui lòng sử dụng lại lệnh!"
|
||||
"wentWrong" = "❌ Đã xảy ra lỗi!"
|
||||
"noIpRecord" = "❗ Không có bản ghi IP!"
|
||||
"noInbounds" = "❗ Không tìm thấy inbound!"
|
||||
"unlimited" = "♾ Không giới hạn"
|
||||
"unlimited" = "♾ Không giới hạn (Đặt lại)"
|
||||
"add" = "Thêm"
|
||||
"month" = "Tháng"
|
||||
"months" = "Tháng"
|
||||
"day" = "Ngày"
|
||||
"days" = "Ngày"
|
||||
"hours" = "Giờ"
|
||||
"unknown" = "Không rõ"
|
||||
"inbounds" = "Vào"
|
||||
"clients" = "Các người dùng"
|
||||
"minutes" = "Phút"
|
||||
"unknown" = "Không xác định"
|
||||
"inbounds" = "Inbound"
|
||||
"clients" = "Client"
|
||||
"offline" = "🔴 Ngoại tuyến"
|
||||
"online" = "🟢 Trực tuyến"
|
||||
|
||||
|
||||
@ -585,19 +585,20 @@
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ 自定义键盘已关闭!"
|
||||
"noResult" = "❗ 没有结果!"
|
||||
"noQuery" = "❌ 未找到查询!请重新使用命令!"
|
||||
"noQuery" = "❌ 未找到查询!请再次使用该命令!"
|
||||
"wentWrong" = "❌ 出了点问题!"
|
||||
"noIpRecord" = "❗ 没有 IP 记录!"
|
||||
"noInbounds" = "❗ 没有找到入站连接!"
|
||||
"unlimited" = "♾ 无限制"
|
||||
"noIpRecord" = "❗ 没有IP记录!"
|
||||
"noInbounds" = "❗ 未找到入站!"
|
||||
"unlimited" = "♾ 无限(重置)"
|
||||
"add" = "添加"
|
||||
"month" = "月"
|
||||
"months" = "月"
|
||||
"day" = "天"
|
||||
"days" = "天"
|
||||
"hours" = "小时"
|
||||
"minutes" = "分钟"
|
||||
"unknown" = "未知"
|
||||
"inbounds" = "入站连接"
|
||||
"inbounds" = "入站"
|
||||
"clients" = "客户端"
|
||||
"offline" = "🔴 离线"
|
||||
"online" = "🟢 在线"
|
||||
|
||||
@ -563,22 +563,23 @@
|
||||
[tgbot]
|
||||
"keyboardClosed" = "❌ 自定義鍵盤已關閉!"
|
||||
"noResult" = "❗ 沒有結果!"
|
||||
"noQuery" = "❌ 未找到查詢!請重新使用命令!"
|
||||
"noQuery" = "❌ 未找到查詢!請再次使用該命令!"
|
||||
"wentWrong" = "❌ 出了點問題!"
|
||||
"noIpRecord" = "❗ 沒有 IP 記錄!"
|
||||
"noInbounds" = "❗ 沒有找到入站連線!"
|
||||
"unlimited" = "♾ 無限制"
|
||||
"add" = "新增"
|
||||
"noIpRecord" = "❗ 沒有IP記錄!"
|
||||
"noInbounds" = "❗ 未找到入站!"
|
||||
"unlimited" = "♾ 無限(重置)"
|
||||
"add" = "添加"
|
||||
"month" = "月"
|
||||
"months" = "月"
|
||||
"day" = "天"
|
||||
"days" = "天"
|
||||
"hours" = "小時"
|
||||
"minutes" = "分鐘"
|
||||
"unknown" = "未知"
|
||||
"inbounds" = "入站連線"
|
||||
"inbounds" = "入站"
|
||||
"clients" = "客戶端"
|
||||
"offline" = "🔴 離線"
|
||||
"online" = "🟢 線上"
|
||||
"online" = "🟢 在線"
|
||||
|
||||
[tgbot.commands]
|
||||
"unknown" = "❗ 未知命令"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user