+
+
+
+
二、判断VPS服务器的IP是否【送中】?
+
***点击打开:https://music.youtube.com/,能正常打开访问,就代表【没送中】,反之就是送中了。
+
***如果送中了如何解决去【拉回来】?
+
1:关闭/取消登录了谷歌账户的APP定位权限/授权;2:将常用的一个谷歌账号的位置记录功能打开;3:在电脑上打开Chrome/谷歌浏览器,登录开了位置记录功能的谷歌账号,安装Location Guard拓展插件https://chrome.google.com/webstore/detail/location-guard/cfohepagpmnodfdmjliccbbigdkfcgia(也可在其他支持此插件的浏览器使用);4:打开Location Guard插件,选择Fixed Location,并在给出的地图上单击,即可标记上你想要IP所处的国家/地区
+Google IP定位错误,使用Location Guard修改;5:转换到Options选项,Default level默认设置为Use fixed location;6:打开谷歌地图google.com/maps,点击右下角定位授权图标,使google maps获取当前“我的GPS位置”
+Google IP定位错误,使用Location Guard修改GPS位置地址;7:谷歌搜索my ip,即可看到谷歌IP定位到了刚才地图上标记的位置;8:在此网页向谷歌报告IP问题:https://support.google.com/websearch/workflow/9308722
+
+
三、在自己的VPS服务器部署【订阅转换】功能
+
如何把vless/vmess等协议转换成Clash/Surge等软件支持的格式?
+ 1、进入脚本输入x-ui命令调取面板,选择第【24】选项安装订阅转换模块,
+ 2、等待安装【订阅转换】成功之后,访问地址:你的IP:18080(端口号)进行转换,
+ 3、因为在转换过程中需要调取后端API,所以请确保端口25500是打开放行的,
+4、在得到【转换链接】之后,只要你的VPS服务器25500端口是能ping通的,就能导入Clash/Surge等软件成功下载配置,
+5、此功能集成到3x-ui面板中,是为了保证安全,通过调取24选项把【订阅转换】功能部署在自己的VPS中,不会造成链接泄露。
+
+
四、如何保护自己的IP不被墙被封?
+
1、使用的代理协议要安全,加密是必备,推荐使用vless+reality+vision协议组合,
+2、因为有时节点会共享,在不同的地区,多个省份之间不要共同连接同一个IP,
+3、连接同一个IP就算了,不要同一个端口,不要同IP+同端口到处漫游,要分开,
+4、同一台VPS,不要在一天内一直大流量去下载东西使用,不要流量过高要切换,
+5、创建【入站协议】的时候,尽量用【高位端口】,比如40000--65000之间的端口号。
+提醒:为什么在特殊时期,比如:两会,春节等被封得最严重最惨?
+尼玛同一个IP+同一个端口号,多个省份去漫游,跟开飞机场一样!不封你,封谁的IP和端口?
+总结:不要多终端/多省份/多个朋友/共同使用同一个IP和端口号!使用3x-ui多创建几个【入站】,
+多做几条备用,各用各的!各行其道才比较安全!GFW的思维模式是干掉机场,机场的特征个人用户不要去沾染,自然IP就保护好了。
+
+
五、检测IP纯净度的方法:
+
网址:https://scamalytics.com/,输入IP进行检测,看【欺诈分数】,分数越高IP越脏。
+
+
六、常见的软件工具:
+
+ 1、Windows系统v2rayN:https://github.com/2dust/v2rayN
+ 2、安卓手机版【v2rayNG】:https://github.com/2dust/v2rayNG
+ 3、苹果手机IOS【小火箭】:https://apple02.com/
+ 4、苹果MacOS电脑【Clash Verge】:https://github.com/clash-verge-rev/clash-verge-rev/releases
+
+
+
七、查看节点【指定端口】的网络连接数/命令:
+
netstat -ntu | grep :节点端口 | grep ESTABLISHED | awk '{print $5}'
+
+
八、用3x-ui如何实现【自己偷自己】?
+
其实很简单,只要你为面板设置了证书,
+ 开启了HTTPS登录,就可以将3x-ui自身作为web server,
+ 无需Nginx等,这里给一个示例:
+ 其中目标网站(Dest)请填写面板监听端口,
+ 可选域名(SNI)填写面板登录域名,
+ 如果您使用其他web server(如nginx)等,
+ 将目标网站改为对应监听端口也可。
+ 需要说明的是,如果您处于白名单地区,自己“偷”自己并不适合你;其次,可选域名一项实际上可以填写任意SNI,只要客户端保持一致即可,不过并不推荐这样做。
+
+
九、【接码】网站:
+
网址:https://sms-activate.org/cn,直接注册账号购买。
+
+
十、一些MJJ经常逛的网站和群组:
+
+ 1、NodeSeek论坛:https://www.nodeseek.com/
+ 2、V2EX论坛:https://www.v2ex.com/
+ 3、搬瓦工TG群:https://t.me/BWHOfficial
+ 4、Xray的官方群:https://t.me/projectXray
+ 5、Dmit交流群:https://t.me/DmitChat
+ 6、白丝云用户群:https://t.me/+VHZLKELTQyzPNgOV
+ 7、NameSilo域名注册:https://www.namesilo.com/
+
+
+
十一、若此项目对你有帮助,你正想购买VPS的话,可以走一下我的AFF:
+
+ 1、搬瓦工GIA线路:https://bandwagonhost.com/aff.php?aff=75015
+ 2、Dmit高端GIA:https://www.dmit.io/aff.php?aff=9326
+ 3、白丝云【4837】:https://cloudsilk.io/aff.php?aff=706
+
+
+
十二、若需要进行GV保号,请主动发信息到:+1 215 346 6666
+
+
十三、项目〔声明和注意〕
+
+ 1、声明: 此项目仅供个人学习、交流使用,请遵守当地法律法规,勿用于非法用途;请勿用于生产环境;
+ 2、注意: 在使用此项目和〔教程〕过程中,若因违反以上声明使用规则而产生的一切后果由使用者自负。
+
+
+
+
diff --git a/web/service/inbound.go b/web/service/inbound.go
index f2646dbb..a76c5e2c 100644
--- a/web/service/inbound.go
+++ b/web/service/inbound.go
@@ -3,7 +3,6 @@ package service
import (
"encoding/json"
"fmt"
- "sort"
"strconv"
"strings"
"time"
@@ -414,13 +413,13 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
return false, err
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(data.Settings), &settings)
if err != nil {
return false, err
}
- interfaceClients := settings["clients"].([]any)
+ interfaceClients := settings["clients"].([]interface{})
existEmail, err := s.checkEmailsExistForClients(clients)
if err != nil {
return false, err
@@ -451,13 +450,13 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
}
}
- var oldSettings map[string]any
+ var oldSettings map[string]interface{}
err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings)
if err != nil {
return false, err
}
- oldClients := oldSettings["clients"].([]any)
+ oldClients := oldSettings["clients"].([]interface{})
oldClients = append(oldClients, interfaceClients...)
oldSettings["clients"] = oldClients
@@ -490,7 +489,7 @@ func (s *InboundService) AddInboundClient(data *model.Inbound) (bool, error) {
if oldInbound.Protocol == "shadowsocks" {
cipher = oldSettings["method"].(string)
}
- err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]any{
+ err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
"email": client.Email,
"id": client.ID,
"security": client.Security,
@@ -520,7 +519,7 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool,
logger.Error("Load Old Data Error")
return false, err
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(oldInbound.Settings), &settings)
if err != nil {
return false, err
@@ -535,11 +534,11 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool,
client_key = "email"
}
- interfaceClients := settings["clients"].([]any)
- var newClients []any
+ interfaceClients := settings["clients"].([]interface{})
+ var newClients []interface{}
needApiDel := false
for _, client := range interfaceClients {
- c := client.(map[string]any)
+ c := client.(map[string]interface{})
c_id := c[client_key].(string)
if c_id == clientId {
email, _ = c["email"].(string)
@@ -589,12 +588,8 @@ func (s *InboundService) DelInboundClient(inboundId int, clientId string) (bool,
logger.Debug("Client deleted by api:", email)
needRestart = false
} else {
- if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", email)) {
- logger.Debug("User is already deleted. Nothing to do more...")
- } else {
- logger.Debug("Error in deleting client by api:", err1)
- needRestart = true
- }
+ logger.Debug("Unable to del client by api:", err1)
+ needRestart = true
}
s.xrayApi.Close()
}
@@ -608,13 +603,13 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
return false, err
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(data.Settings), &settings)
if err != nil {
return false, err
}
- interfaceClients := settings["clients"].([]any)
+ interfaceClients := settings["clients"].([]interface{})
oldInbound, err := s.GetInbound(data.Id)
if err != nil {
@@ -628,7 +623,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
oldEmail := ""
newClientId := ""
- clientIndex := -1
+ clientIndex := 0
for index, oldClient := range oldClients {
oldClientId := ""
if oldInbound.Protocol == "trojan" {
@@ -649,7 +644,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
}
// Validate new client ID
- if newClientId == "" || clientIndex == -1 {
+ if newClientId == "" {
return false, common.NewError("empty client ID")
}
@@ -663,12 +658,12 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
}
}
- var oldSettings map[string]any
+ var oldSettings map[string]interface{}
err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings)
if err != nil {
return false, err
}
- settingsClients := oldSettings["clients"].([]any)
+ settingsClients := oldSettings["clients"].([]interface{})
settingsClients[clientIndex] = interfaceClients[0]
oldSettings["clients"] = settingsClients
@@ -718,14 +713,10 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
if oldClients[clientIndex].Enable {
err1 := s.xrayApi.RemoveUser(oldInbound.Tag, oldEmail)
if err1 == nil {
- logger.Debug("Old client deleted by api:", oldEmail)
+ logger.Debug("Old client deleted by api:", clients[0].Email)
} else {
- if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", oldEmail)) {
- logger.Debug("User is already deleted. Nothing to do more...")
- } else {
- logger.Debug("Error in deleting client by api:", err1)
- needRestart = true
- }
+ logger.Debug("Error in deleting client by api:", err1)
+ needRestart = true
}
}
if clients[0].Enable {
@@ -733,7 +724,7 @@ func (s *InboundService) UpdateInboundClient(data *model.Inbound, clientId strin
if oldInbound.Protocol == "shadowsocks" {
cipher = oldSettings["method"].(string)
}
- err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]any{
+ err1 := s.xrayApi.AddUser(string(oldInbound.Protocol), oldInbound.Tag, map[string]interface{}{
"email": clients[0].Email,
"id": clients[0].ID,
"security": clients[0].Security,
@@ -810,7 +801,7 @@ func (s *InboundService) addInboundTraffic(tx *gorm.DB, traffics []*xray.Traffic
for _, traffic := range traffics {
if traffic.IsInbound {
err = tx.Model(&model.Inbound{}).Where("tag = ?", traffic.Tag).
- Updates(map[string]any{
+ Updates(map[string]interface{}{
"up": gorm.Expr("up + ?", traffic.Up),
"down": gorm.Expr("down + ?", traffic.Down),
}).Error
@@ -894,13 +885,13 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl
return nil, err
}
for inbound_index := range inbounds {
- settings := map[string]any{}
+ settings := map[string]interface{}{}
json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings)
- clients, ok := settings["clients"].([]any)
+ clients, ok := settings["clients"].([]interface{})
if ok {
- var newClients []any
+ var newClients []interface{}
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
for traffic_index := range dbClientTraffics {
if dbClientTraffics[traffic_index].ExpiryTime < 0 && c["email"] == dbClientTraffics[traffic_index].Email {
oldExpiryTime := c["expiryTime"].(float64)
@@ -910,7 +901,7 @@ func (s *InboundService) adjustTraffics(tx *gorm.DB, dbClientTraffics []*xray.Cl
break
}
}
- newClients = append(newClients, any(c))
+ newClients = append(newClients, interface{}(c))
}
settings["clients"] = newClients
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
@@ -952,7 +943,7 @@ func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) {
var clientsToAdd []struct {
protocol string
tag string
- client map[string]any
+ client map[string]interface{}
}
for _, traffic := range traffics {
@@ -963,11 +954,11 @@ func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) {
return false, 0, err
}
for inbound_index := range inbounds {
- settings := map[string]any{}
+ settings := map[string]interface{}{}
json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings)
- clients := settings["clients"].([]any)
+ clients := settings["clients"].([]interface{})
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
for traffic_index, traffic := range traffics {
if traffic.Email == c["email"].(string) {
newExpiryTime := traffic.ExpiryTime
@@ -984,14 +975,14 @@ func (s *InboundService) autoRenewClients(tx *gorm.DB) (bool, int64, error) {
struct {
protocol string
tag string
- client map[string]any
+ client map[string]interface{}
}{
protocol: string(inbounds[inbound_index].Protocol),
tag: inbounds[inbound_index].Tag,
client: c,
})
}
- clients[client_index] = any(c)
+ clients[client_index] = interface{}(c)
break
}
}
@@ -1046,8 +1037,12 @@ func (s *InboundService) disableInvalidInbounds(tx *gorm.DB) (bool, int64, error
if err1 == nil {
logger.Debug("Inbound disabled by api:", tag)
} else {
- logger.Debug("Error in disabling inbound by api:", err1)
- needRestart = true
+ if strings.Contains(err1.Error(), fmt.Sprintf("User %s not found.", tag)) {
+ logger.Debug("User is already disabled. Nothing to do more...")
+ } else {
+ logger.Debug("Error in disabling client by api:", err1)
+ needRestart = true
+ }
}
}
s.xrayApi.Close()
@@ -1148,7 +1143,7 @@ func (s *InboundService) AddClientStat(tx *gorm.DB, inboundId int, client *model
func (s *InboundService) UpdateClientStat(tx *gorm.DB, email string, client *model.Client) error {
result := tx.Model(xray.ClientTraffic{}).
Where("email = ?", email).
- Updates(map[string]any{
+ Updates(map[string]interface{}{
"enable": true,
"email": client.Email,
"total": client.TotalGB,
@@ -1259,18 +1254,18 @@ func (s *InboundService) SetClientTelegramUserID(trafficId int, tgId int64) (boo
return false, common.NewError("Client Not Found For Email:", clientEmail)
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(inbound.Settings), &settings)
if err != nil {
return false, err
}
- clients := settings["clients"].([]any)
- var newClients []any
+ clients := settings["clients"].([]interface{})
+ var newClients []interface{}
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
if c["email"] == clientEmail {
c["tgId"] = tgId
- newClients = append(newClients, any(c))
+ newClients = append(newClients, interface{}(c))
}
}
settings["clients"] = newClients
@@ -1344,18 +1339,18 @@ func (s *InboundService) ToggleClientEnableByEmail(clientEmail string) (bool, bo
return false, false, common.NewError("Client Not Found For Email:", clientEmail)
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(inbound.Settings), &settings)
if err != nil {
return false, false, err
}
- clients := settings["clients"].([]any)
- var newClients []any
+ clients := settings["clients"].([]interface{})
+ var newClients []interface{}
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
if c["email"] == clientEmail {
c["enable"] = !clientOldEnabled
- newClients = append(newClients, any(c))
+ newClients = append(newClients, interface{}(c))
}
}
settings["clients"] = newClients
@@ -1406,18 +1401,18 @@ func (s *InboundService) ResetClientIpLimitByEmail(clientEmail string, count int
return false, common.NewError("Client Not Found For Email:", clientEmail)
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(inbound.Settings), &settings)
if err != nil {
return false, err
}
- clients := settings["clients"].([]any)
- var newClients []any
+ clients := settings["clients"].([]interface{})
+ var newClients []interface{}
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
if c["email"] == clientEmail {
c["limitIp"] = count
- newClients = append(newClients, any(c))
+ newClients = append(newClients, interface{}(c))
}
}
settings["clients"] = newClients
@@ -1463,18 +1458,18 @@ func (s *InboundService) ResetClientExpiryTimeByEmail(clientEmail string, expiry
return false, common.NewError("Client Not Found For Email:", clientEmail)
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(inbound.Settings), &settings)
if err != nil {
return false, err
}
- clients := settings["clients"].([]any)
- var newClients []any
+ clients := settings["clients"].([]interface{})
+ var newClients []interface{}
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
if c["email"] == clientEmail {
c["expiryTime"] = expiry_time
- newClients = append(newClients, any(c))
+ newClients = append(newClients, interface{}(c))
}
}
settings["clients"] = newClients
@@ -1523,18 +1518,18 @@ func (s *InboundService) ResetClientTrafficLimitByEmail(clientEmail string, tota
return false, common.NewError("Client Not Found For Email:", clientEmail)
}
- var settings map[string]any
+ var settings map[string]interface{}
err = json.Unmarshal([]byte(inbound.Settings), &settings)
if err != nil {
return false, err
}
- clients := settings["clients"].([]any)
- var newClients []any
+ clients := settings["clients"].([]interface{})
+ var newClients []interface{}
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
if c["email"] == clientEmail {
c["totalGB"] = totalGB * 1024 * 1024 * 1024
- newClients = append(newClients, any(c))
+ newClients = append(newClients, interface{}(c))
}
}
settings["clients"] = newClients
@@ -1552,7 +1547,7 @@ func (s *InboundService) ResetClientTrafficByEmail(clientEmail string) error {
result := db.Model(xray.ClientTraffic{}).
Where("email = ?", clientEmail).
- Updates(map[string]any{"enable": true, "up": 0, "down": 0})
+ Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0})
err := result.Error
if err != nil {
@@ -1583,14 +1578,14 @@ func (s *InboundService) ResetClientTraffic(id int, clientEmail string) (bool, e
s.xrayApi.Init(p.GetAPIPort())
cipher := ""
if string(inbound.Protocol) == "shadowsocks" {
- var oldSettings map[string]any
+ var oldSettings map[string]interface{}
err = json.Unmarshal([]byte(inbound.Settings), &oldSettings)
if err != nil {
return false, err
}
cipher = oldSettings["method"].(string)
}
- err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]any{
+ err1 := s.xrayApi.AddUser(string(inbound.Protocol), inbound.Tag, map[string]interface{}{
"email": client.Email,
"id": client.ID,
"security": client.Security,
@@ -1635,7 +1630,7 @@ func (s *InboundService) ResetAllClientTraffics(id int) error {
result := db.Model(xray.ClientTraffic{}).
Where(whereText, id).
- Updates(map[string]any{"enable": true, "up": 0, "down": 0})
+ Updates(map[string]interface{}{"enable": true, "up": 0, "down": 0})
err := result.Error
return err
@@ -1646,7 +1641,7 @@ func (s *InboundService) ResetAllTraffics() error {
result := db.Model(model.Inbound{}).
Where("user_id > ?", 0).
- Updates(map[string]any{"up": 0, "down": 0})
+ Updates(map[string]interface{}{"up": 0, "down": 0})
err := result.Error
return err
@@ -1682,17 +1677,17 @@ func (s *InboundService) DelDepletedClients(id int) (err error) {
if err != nil {
return err
}
- var oldSettings map[string]any
+ var oldSettings map[string]interface{}
err = json.Unmarshal([]byte(oldInbound.Settings), &oldSettings)
if err != nil {
return err
}
- oldClients := oldSettings["clients"].([]any)
- var newClients []any
+ oldClients := oldSettings["clients"].([]interface{})
+ var newClients []interface{}
for _, client := range oldClients {
deplete := false
- c := client.(map[string]any)
+ c := client.(map[string]interface{})
for _, email := range emails {
if email == c["email"].(string) {
deplete = true
@@ -1908,14 +1903,14 @@ func (s *InboundService) MigrationRequirements() {
return
}
for inbound_index := range inbounds {
- settings := map[string]any{}
+ settings := map[string]interface{}{}
json.Unmarshal([]byte(inbounds[inbound_index].Settings), &settings)
- clients, ok := settings["clients"].([]any)
+ clients, ok := settings["clients"].([]interface{})
if ok {
// Fix Client configuration problems
- var newClients []any
+ var newClients []interface{}
for client_index := range clients {
- c := clients[client_index].(map[string]any)
+ c := clients[client_index].(map[string]interface{})
// Add email='' if it is not exists
if _, ok := c["email"]; !ok {
@@ -1924,7 +1919,7 @@ func (s *InboundService) MigrationRequirements() {
// Convert string tgId to int64
if _, ok := c["tgId"]; ok {
- var tgId any = c["tgId"]
+ var tgId interface{} = c["tgId"]
if tgIdStr, ok2 := tgId.(string); ok2 {
tgIdInt64, err := strconv.ParseInt(strings.ReplaceAll(tgIdStr, " ", ""), 10, 64)
if err == nil {
@@ -1939,7 +1934,7 @@ func (s *InboundService) MigrationRequirements() {
c["flow"] = ""
}
}
- newClients = append(newClients, any(c))
+ newClients = append(newClients, interface{}(c))
}
settings["clients"] = newClients
modifiedSettings, err := json.MarshalIndent(settings, "", " ")
@@ -1986,14 +1981,14 @@ func (s *InboundService) MigrationRequirements() {
}
for _, ep := range externalProxy {
- var reverses any
- var stream map[string]any
+ var reverses interface{}
+ var stream map[string]interface{}
json.Unmarshal(ep.StreamSettings, &stream)
- if tlsSettings, ok := stream["tlsSettings"].(map[string]any); ok {
- if settings, ok := tlsSettings["settings"].(map[string]any); ok {
- if domains, ok := settings["domains"].([]any); ok {
+ if tlsSettings, ok := stream["tlsSettings"].(map[string]interface{}); ok {
+ if settings, ok := tlsSettings["settings"].(map[string]interface{}); ok {
+ if domains, ok := settings["domains"].([]interface{}); ok {
for _, domain := range domains {
- if domainMap, ok := domain.(map[string]any); ok {
+ if domainMap, ok := domain.(map[string]interface{}); ok {
domainMap["forceTls"] = "same"
domainMap["port"] = ep.Port
domainMap["dest"] = domainMap["domain"].(string)
@@ -2026,37 +2021,3 @@ func (s *InboundService) MigrateDB() {
func (s *InboundService) GetOnlineClients() []string {
return p.GetOnlineClients()
}
-
-func (s *InboundService) FilterAndSortClientEmails(emails []string) ([]string, []string, error) {
- db := database.GetDB()
-
- // Step 1: Get ClientTraffic records for emails in the input list
- var clients []xray.ClientTraffic
- err := db.Where("email IN ?", emails).Find(&clients).Error
- if err != nil && err != gorm.ErrRecordNotFound {
- return nil, nil, err
- }
-
- // Step 2: Sort clients by (Up + Down) descending
- sort.Slice(clients, func(i, j int) bool {
- return (clients[i].Up + clients[i].Down) > (clients[j].Up + clients[j].Down)
- })
-
- // Step 3: Extract sorted valid emails and track found ones
- validEmails := make([]string, 0, len(clients))
- found := make(map[string]bool)
- for _, client := range clients {
- validEmails = append(validEmails, client.Email)
- found[client.Email] = true
- }
-
- // Step 4: Identify emails that were not found in the database
- extraEmails := make([]string, 0)
- for _, email := range emails {
- if !found[email] {
- extraEmails = append(extraEmails, email)
- }
- }
-
- return validEmails, extraEmails, nil
-}
diff --git a/web/service/setting.go b/web/service/setting.go
index 868d55bc..f6b9087b 100644
--- a/web/service/setting.go
+++ b/web/service/setting.go
@@ -24,60 +24,56 @@ import (
var xrayTemplateConfig string
var defaultValueMap = map[string]string{
- "xrayTemplateConfig": xrayTemplateConfig,
- "webListen": "",
- "webDomain": "",
- "webPort": "2053",
- "webCertFile": "",
- "webKeyFile": "",
- "secret": random.Seq(32),
- "webBasePath": "/",
- "sessionMaxAge": "60",
- "pageSize": "50",
- "expireDiff": "0",
- "trafficDiff": "0",
- "remarkModel": "-ieo",
- "timeLocation": "Local",
- "tgBotEnable": "false",
- "tgBotToken": "",
- "tgBotProxy": "",
- "tgBotAPIServer": "",
- "tgBotChatId": "",
- "tgRunTime": "@daily",
- "tgBotBackup": "false",
- "tgBotLoginNotify": "true",
- "tgCpu": "80",
- "tgLang": "en-US",
- "twoFactorEnable": "false",
- "twoFactorToken": "",
- "subEnable": "false",
- "subTitle": "",
- "subListen": "",
- "subPort": "2096",
- "subPath": "/sub/",
- "subDomain": "",
- "subCertFile": "",
- "subKeyFile": "",
- "subUpdates": "12",
- "subEncrypt": "true",
- "subShowInfo": "true",
- "subURI": "",
- "subJsonPath": "/json/",
- "subJsonURI": "",
- "subJsonFragment": "",
- "subJsonNoises": "",
- "subJsonMux": "",
- "subJsonRules": "",
- "datepicker": "gregorian",
- "warp": "",
- "externalTrafficInformEnable": "false",
- "externalTrafficInformURI": "",
+ "xrayTemplateConfig": xrayTemplateConfig,
+ "webListen": "",
+ "webDomain": "",
+ "webPort": "2053",
+ "webCertFile": "",
+ "webKeyFile": "",
+ "secret": random.Seq(32),
+ "webBasePath": "/",
+ "sessionMaxAge": "60",
+ "pageSize": "50",
+ "expireDiff": "0",
+ "trafficDiff": "0",
+ "remarkModel": "-ieo",
+ "timeLocation": "Asia/Shanghai",
+ "tgBotEnable": "false",
+ "tgBotToken": "",
+ "tgBotProxy": "",
+ "tgBotAPIServer": "",
+ "tgBotChatId": "",
+ "tgRunTime": "@daily",
+ "tgBotBackup": "false",
+ "tgBotLoginNotify": "true",
+ "tgCpu": "30",
+ "tgLang": "zh-Hans",
+ "secretEnable": "false",
+ "subEnable": "false",
+ "subListen": "",
+ "subPort": "2096",
+ "subPath": "/sub/",
+ "subDomain": "",
+ "subCertFile": "",
+ "subKeyFile": "",
+ "subUpdates": "12",
+ "subEncrypt": "true",
+ "subShowInfo": "true",
+ "subURI": "",
+ "subJsonPath": "/json/",
+ "subJsonURI": "",
+ "subJsonFragment": "",
+ "subJsonNoises": "",
+ "subJsonMux": "",
+ "subJsonRules": "",
+ "datepicker": "gregorian",
+ "warp": "",
}
type SettingService struct{}
-func (s *SettingService) GetDefaultJsonConfig() (any, error) {
- var jsonData any
+func (s *SettingService) GetDefaultJsonConfig() (interface{}, error) {
+ var jsonData interface{}
err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData)
if err != nil {
return nil, err
@@ -167,7 +163,8 @@ func (s *SettingService) ResetSettings() error {
return err
}
return db.Model(model.User{}).
- Where("1 = 1").Error
+ Where("1 = 1").
+ Update("login_secret", "").Error
}
func (s *SettingService) getSetting(key string) (*model.Setting, error) {
@@ -318,22 +315,6 @@ func (s *SettingService) GetTgLang() (string, error) {
return s.getString("tgLang")
}
-func (s *SettingService) GetTwoFactorEnable() (bool, error) {
- return s.getBool("twoFactorEnable")
-}
-
-func (s *SettingService) SetTwoFactorEnable(value bool) error {
- return s.setBool("twoFactorEnable", value)
-}
-
-func (s *SettingService) GetTwoFactorToken() (string, error) {
- return s.getString("twoFactorToken")
-}
-
-func (s *SettingService) SetTwoFactorToken(value string) error {
- return s.setString("twoFactorToken", value)
-}
-
func (s *SettingService) GetPort() (int, error) {
return s.getInt("webPort")
}
@@ -374,6 +355,14 @@ func (s *SettingService) GetRemarkModel() (string, error) {
return s.getString("remarkModel")
}
+func (s *SettingService) GetSecretStatus() (bool, error) {
+ return s.getBool("secretEnable")
+}
+
+func (s *SettingService) SetSecretStatus(value bool) error {
+ return s.setBool("secretEnable", value)
+}
+
func (s *SettingService) GetSecret() ([]byte, error) {
secret, err := s.getString("secret")
if secret == defaultValueMap["secret"] {
@@ -427,10 +416,6 @@ func (s *SettingService) GetSubEnable() (bool, error) {
return s.getBool("subEnable")
}
-func (s *SettingService) GetSubTitle() (string, error) {
- return s.getString("subTitle")
-}
-
func (s *SettingService) GetSubListen() (string, error) {
return s.getString("subListen")
}
@@ -511,22 +496,6 @@ func (s *SettingService) SetWarp(data string) error {
return s.setString("warp", data)
}
-func (s *SettingService) GetExternalTrafficInformEnable() (bool, error) {
- return s.getBool("externalTrafficInformEnable")
-}
-
-func (s *SettingService) SetExternalTrafficInformEnable(value bool) error {
- return s.setBool("externalTrafficInformEnable", value)
-}
-
-func (s *SettingService) GetExternalTrafficInformURI() (string, error) {
- return s.getString("externalTrafficInformURI")
-}
-
-func (s *SettingService) SetExternalTrafficInformURI(InformURI string) error {
- return s.setString("externalTrafficInformURI", InformURI)
-}
-
func (s *SettingService) GetIpLimitEnable() (bool, error) {
accessLogPath, err := xray.GetAccessLogPath()
if err != nil {
@@ -556,8 +525,8 @@ func (s *SettingService) UpdateAllSetting(allSetting *entity.AllSetting) error {
return common.Combine(errs...)
}
-func (s *SettingService) GetDefaultXrayConfig() (any, error) {
- var jsonData any
+func (s *SettingService) GetDefaultXrayConfig() (interface{}, error) {
+ var jsonData interface{}
err := json.Unmarshal([]byte(xrayTemplateConfig), &jsonData)
if err != nil {
return nil, err
@@ -565,25 +534,24 @@ func (s *SettingService) GetDefaultXrayConfig() (any, error) {
return jsonData, nil
}
-func (s *SettingService) GetDefaultSettings(host string) (any, error) {
- type settingFunc func() (any, error)
+func (s *SettingService) GetDefaultSettings(host string) (interface{}, error) {
+ type settingFunc func() (interface{}, error)
settings := map[string]settingFunc{
- "expireDiff": func() (any, error) { return s.GetExpireDiff() },
- "trafficDiff": func() (any, error) { return s.GetTrafficDiff() },
- "pageSize": func() (any, error) { return s.GetPageSize() },
- "defaultCert": func() (any, error) { return s.GetCertFile() },
- "defaultKey": func() (any, error) { return s.GetKeyFile() },
- "tgBotEnable": func() (any, error) { return s.GetTgbotEnabled() },
- "subEnable": func() (any, error) { return s.GetSubEnable() },
- "subTitle": func() (any, error) { return s.GetSubTitle() },
- "subURI": func() (any, error) { return s.GetSubURI() },
- "subJsonURI": func() (any, error) { return s.GetSubJsonURI() },
- "remarkModel": func() (any, error) { return s.GetRemarkModel() },
- "datepicker": func() (any, error) { return s.GetDatepicker() },
- "ipLimitEnable": func() (any, error) { return s.GetIpLimitEnable() },
+ "expireDiff": func() (interface{}, error) { return s.GetExpireDiff() },
+ "trafficDiff": func() (interface{}, error) { return s.GetTrafficDiff() },
+ "pageSize": func() (interface{}, error) { return s.GetPageSize() },
+ "defaultCert": func() (interface{}, error) { return s.GetCertFile() },
+ "defaultKey": func() (interface{}, error) { return s.GetKeyFile() },
+ "tgBotEnable": func() (interface{}, error) { return s.GetTgbotEnabled() },
+ "subEnable": func() (interface{}, error) { return s.GetSubEnable() },
+ "subURI": func() (interface{}, error) { return s.GetSubURI() },
+ "subJsonURI": func() (interface{}, error) { return s.GetSubJsonURI() },
+ "remarkModel": func() (interface{}, error) { return s.GetRemarkModel() },
+ "datepicker": func() (interface{}, error) { return s.GetDatepicker() },
+ "ipLimitEnable": func() (interface{}, error) { return s.GetIpLimitEnable() },
}
- result := make(map[string]any)
+ result := make(map[string]interface{})
for key, fn := range settings {
value, err := fn()
@@ -595,7 +563,6 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
if result["subEnable"].(bool) && (result["subURI"].(string) == "" || result["subJsonURI"].(string) == "") {
subURI := ""
- subTitle, _ := s.GetSubTitle()
subPort, _ := s.GetSubPort()
subPath, _ := s.GetSubPath()
subJsonPath, _ := s.GetSubJsonPath()
@@ -622,9 +589,6 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
if result["subURI"].(string) == "" {
result["subURI"] = subURI + subPath
}
- if result["subTitle"].(string) == "" {
- result["subTitle"] = subTitle
- }
if result["subJsonURI"].(string) == "" {
result["subJsonURI"] = subURI + subJsonPath
}
diff --git a/web/service/tgbot.go b/web/service/tgbot.go
index ffdb63f9..af51e253 100644
--- a/web/service/tgbot.go
+++ b/web/service/tgbot.go
@@ -1,16 +1,12 @@
package service
import (
- "crypto/rand"
"embed"
- "encoding/base64"
"errors"
"fmt"
- "math/big"
"net"
"net/url"
"os"
- "regexp"
"strconv"
"strings"
"time"
@@ -24,7 +20,6 @@ import (
"x-ui/web/locale"
"x-ui/xray"
- "github.com/google/uuid"
"github.com/mymmrac/telego"
th "github.com/mymmrac/telego/telegohandler"
tu "github.com/mymmrac/telego/telegoutil"
@@ -39,29 +34,8 @@ var (
isRunning bool
hostname string
hashStorage *global.HashStorage
- handler *th.Handler
-
- // clients data to adding new client
- receiver_inbound_ID int
- client_Id string
- client_Flow string
- client_Email string
- client_LimitIP int
- client_TotalGB int64
- client_ExpiryTime int64
- client_Enable bool
- client_TgID string
- client_SubID string
- client_Comment string
- client_Reset int
- client_Security string
- client_ShPassword string
- client_TrPassword string
- client_Method string
)
-var userStates = make(map[int64]string)
-
type LoginStatus byte
const (
@@ -147,19 +121,6 @@ func (t *Tgbot) Start(i18nFS embed.FS) error {
return err
}
- // After bot initialization, set up bot commands with localized descriptions
- err = bot.SetMyCommands(&telego.SetMyCommandsParams{
- Commands: []telego.BotCommand{
- {Command: "start", Description: t.I18nBot("tgbot.commands.startDesc")},
- {Command: "help", Description: t.I18nBot("tgbot.commands.helpDesc")},
- {Command: "status", Description: t.I18nBot("tgbot.commands.statusDesc")},
- {Command: "id", Description: t.I18nBot("tgbot.commands.idDesc")},
- },
- })
- if err != nil {
- logger.Warning("Failed to set bot commands:", err)
- }
-
// Start receiving Telegram bot messages
if !isRunning {
logger.Info("Telegram bot receiver started")
@@ -260,161 +221,36 @@ func (t *Tgbot) OnReceive() {
botHandler, _ = th.NewBotHandler(bot, updates)
botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) {
- delete(userStates, message.Chat.ID)
t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.keyboardClosed"), tu.ReplyKeyboardRemove())
}, th.TextEqual(t.I18nBot("tgbot.buttons.closeKeyboard")))
botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) {
- delete(userStates, message.Chat.ID)
t.answerCommand(&message, message.Chat.ID, checkAdmin(message.From.ID))
}, th.AnyCommand())
botHandler.HandleCallbackQuery(func(_ *telego.Bot, query telego.CallbackQuery) {
- delete(userStates, query.Message.GetChat().ID)
t.answerCallback(&query, checkAdmin(query.From.ID))
}, th.AnyCallbackQueryWithMessage())
botHandler.HandleMessage(func(_ *telego.Bot, message telego.Message) {
- if userState, exists := userStates[message.Chat.ID]; exists {
- switch userState {
- case "awaiting_id":
- if client_Id == strings.TrimSpace(message.Text) {
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID)
- message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(message.Chat.ID, message_text)
- return
- }
-
- client_Id = strings.TrimSpace(message.Text)
- if t.isSingleWord(client_Id) {
- userStates[message.Chat.ID] = "awaiting_id"
-
- cancel_btn_markup := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
- ),
- )
-
- t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup)
- } else {
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_id"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID)
- message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(message.Chat.ID, message_text)
- }
- case "awaiting_password_tr":
- if client_TrPassword == strings.TrimSpace(message.Text) {
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- return
- }
-
- 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)
- inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID)
- message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(message.Chat.ID, message_text)
- }
- case "awaiting_password_sh":
- if client_ShPassword == strings.TrimSpace(message.Text) {
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- return
- }
-
- client_ShPassword = strings.TrimSpace(message.Text)
- if t.isSingleWord(client_ShPassword) {
- userStates[message.Chat.ID] = "awaiting_password_sh"
-
- cancel_btn_markup := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
- ),
- )
-
- t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.messages.incorrect_input"), cancel_btn_markup)
- } else {
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_password"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID)
- message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(message.Chat.ID, message_text)
- }
- case "awaiting_email":
- if client_Email == strings.TrimSpace(message.Text) {
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- return
- }
-
- 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)
- inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID)
- message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(message.Chat.ID, message_text)
- }
- case "awaiting_comment":
- if client_Comment == strings.TrimSpace(message.Text) {
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- return
- }
-
- client_Comment = strings.TrimSpace(message.Text)
- t.SendMsgToTgbotDeleteAfter(message.Chat.ID, t.I18nBot("tgbot.messages.received_comment"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, message.Chat.ID)
- inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID)
- message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(message.Chat.ID, message_text)
- }
-
- } else {
- if message.UsersShared != nil {
- if checkAdmin(message.From.ID) {
- for _, sharedUser := range message.UsersShared.Users {
- userID := sharedUser.UserID
- needRestart, err := t.inboundService.SetClientTelegramUserID(message.UsersShared.RequestID, userID)
- if needRestart {
- t.xrayService.SetToNeedRestart()
- }
- output := ""
- if err != nil {
- output += t.I18nBot("tgbot.messages.selectUserFailed")
- } else {
- output += t.I18nBot("tgbot.messages.userSaved")
- }
- t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove())
+ if message.UsersShared != nil {
+ if checkAdmin(message.From.ID) {
+ for _, sharedUser := range message.UsersShared.Users {
+ userID := sharedUser.UserID
+ needRestart, err := t.inboundService.SetClientTelegramUserID(message.UsersShared.RequestID, userID)
+ if needRestart {
+ t.xrayService.SetToNeedRestart()
}
- } else {
- t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove())
+ output := ""
+ if err != nil {
+ output += t.I18nBot("tgbot.messages.selectUserFailed")
+ } else {
+ output += t.I18nBot("tgbot.messages.userSaved")
+ }
+ t.SendMsgToTgbot(message.Chat.ID, output, tu.ReplyKeyboardRemove())
}
+ } else {
+ t.SendMsgToTgbot(message.Chat.ID, t.I18nBot("tgbot.noResult"), tu.ReplyKeyboardRemove())
}
}
}, th.AnyMessage())
@@ -471,6 +307,8 @@ func (t *Tgbot) answerCommand(message *telego.Message, chatId int64, isAdmin boo
onlyMessage = true
if isAdmin {
if len(commandArgs) == 0 {
+ msg += t.I18nBot("tgbot.commands.restartUsage")
+ } else if strings.ToLower(commandArgs[0]) == "force" {
if t.xrayService.IsXrayRunning() {
err := t.xrayService.RestartXray(true)
if err != nil {
@@ -506,25 +344,6 @@ 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) {
chatId := callbackQuery.Message.GetChat().ID
@@ -688,78 +507,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
}
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
- case "add_client_limit_traffic_c":
- limitTraffic, _ := strconv.Atoi(dataArray[1])
- client_TotalGB = int64(limitTraffic) * 1024 * 1024 * 1024
- messageId := callbackQuery.Message.GetMessageID()
- inbound, err := t.inboundService.GetInbound(receiver_inbound_ID)
- if err != nil {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
- return
- }
- message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
-
- t.addClient(chatId, message_text, messageId)
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
- case "add_client_limit_traffic_in":
- if len(dataArray) >= 2 {
- oldInputNumber, err := strconv.Atoi(dataArray[1])
- inputNumber := oldInputNumber
- if err == nil {
- if len(dataArray) == 3 {
- num, err := strconv.Atoi(dataArray[2])
- if err == nil {
- if num == -2 {
- inputNumber = 0
- } else if num == -1 {
- if inputNumber > 0 {
- inputNumber = (inputNumber / 10)
- }
- } else {
- inputNumber = (inputNumber * 10) + num
- }
- }
- if inputNumber == oldInputNumber {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
- return
- }
- if inputNumber >= 999999 {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
- return
- }
- }
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c "+strconv.Itoa(inputNumber))),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 1")),
- tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 2")),
- tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 3")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 4")),
- tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 5")),
- tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 6")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 7")),
- tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 8")),
- tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 9")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -2")),
- tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" 0")),
- tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_limit_traffic_in "+strconv.Itoa(inputNumber)+" -1")),
- ),
- )
- t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
- return
- }
- }
case "reset_exp":
inlineKeyboard := tu.InlineKeyboard(
tu.InlineKeyboardRow(
@@ -891,90 +638,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
}
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
- case "add_client_reset_exp_c":
- client_ExpiryTime = 0
- days, _ := strconv.Atoi(dataArray[1])
- var date int64 = 0
- if client_ExpiryTime > 0 {
- if client_ExpiryTime-time.Now().Unix()*1000 < 0 {
- date = -int64(days * 24 * 60 * 60000)
- } else {
- date = client_ExpiryTime + int64(days*24*60*60000)
- }
- } else {
- date = client_ExpiryTime - int64(days*24*60*60000)
- }
- client_ExpiryTime = date
-
- messageId := callbackQuery.Message.GetMessageID()
- inbound, err := t.inboundService.GetInbound(receiver_inbound_ID)
- if err != nil {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
- return
- }
- message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
-
- t.addClient(chatId, message_text, messageId)
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
- case "add_client_reset_exp_in":
- if len(dataArray) >= 2 {
- oldInputNumber, err := strconv.Atoi(dataArray[1])
- inputNumber := oldInputNumber
- if err == nil {
- if len(dataArray) == 3 {
- num, err := strconv.Atoi(dataArray[2])
- if err == nil {
- if num == -2 {
- inputNumber = 0
- } else if num == -1 {
- if inputNumber > 0 {
- inputNumber = (inputNumber / 10)
- }
- } else {
- inputNumber = (inputNumber * 10) + num
- }
- }
- if inputNumber == oldInputNumber {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.successfulOperation"))
- return
- }
- if inputNumber >= 999999 {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
- return
- }
- }
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumberAdd", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_reset_exp_c "+strconv.Itoa(inputNumber))),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 1")),
- tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 2")),
- tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 3")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 4")),
- tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 5")),
- tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 6")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 7")),
- tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 8")),
- tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 9")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -2")),
- tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" 0")),
- tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_reset_exp_in "+strconv.Itoa(inputNumber)+" -1")),
- ),
- )
- t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
- return
- }
- }
case "ip_limit":
inlineKeyboard := tu.InlineKeyboard(
tu.InlineKeyboardRow(
@@ -1082,83 +745,6 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
}
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
- case "add_client_ip_limit_c":
- if len(dataArray) == 2 {
- count, _ := strconv.Atoi(dataArray[1])
- client_LimitIP = count
- }
-
- messageId := callbackQuery.Message.GetMessageID()
- 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_ip_limit_in":
- if len(dataArray) >= 2 {
- oldInputNumber, err := strconv.Atoi(dataArray[1])
- inputNumber := oldInputNumber
- if err == nil {
- if len(dataArray) == 3 {
- num, err := strconv.Atoi(dataArray[2])
- if err == nil {
- 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_ip_limit")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmNumber", "Num=="+strconv.Itoa(inputNumber))).WithCallbackData(t.encodeQuery("add_client_ip_limit_c "+strconv.Itoa(inputNumber))),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 1")),
- tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 2")),
- tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 3")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 4")),
- tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 5")),
- tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 6")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 7")),
- tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 8")),
- tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 9")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("🔄").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -2")),
- tu.InlineKeyboardButton("0").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" 0")),
- tu.InlineKeyboardButton("⬅️").WithCallbackData(t.encodeQuery("add_client_ip_limit_in "+strconv.Itoa(inputNumber)+" -1")),
- ),
- )
- t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
- return
- }
- }
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
- t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
case "clear_ips":
inlineKeyboard := tu.InlineKeyboard(
tu.InlineKeyboardRow(
@@ -1252,40 +838,7 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
return
}
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseClient", "Inbound=="+inbound.Remark), clients)
- case "add_client_to":
- // assign default values to clients variables
- client_Id = uuid.New().String()
- client_Flow = ""
- client_Email = t.randomLowerAndNum(8)
- client_LimitIP = 0
- client_TotalGB = 0
- client_ExpiryTime = 0
- client_Enable = true
- client_TgID = ""
- client_SubID = t.randomLowerAndNum(16)
- client_Comment = ""
- client_Reset = 0
- client_Security = "auto"
- client_ShPassword = t.randomShadowSocksPassword()
- client_TrPassword = t.randomLowerAndNum(10)
- client_Method = ""
- inboundId := dataArray[1]
- inboundIdInt, err := strconv.Atoi(inboundId)
- if err != nil {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
- return
- }
- receiver_inbound_ID = inboundIdInt
- inbound, err := t.inboundService.GetInbound(inboundIdInt)
- if err != nil {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
- return
- }
-
- message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
-
- t.addClient(chatId, message_text)
}
return
} else {
@@ -1339,432 +892,9 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
case "commands":
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.commands"))
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.commands.helpAdminCommands"))
- case "add_client":
- // assign default values to clients variables
- client_Id = uuid.New().String()
- client_Flow = ""
- client_Email = t.randomLowerAndNum(8)
- client_LimitIP = 0
- client_TotalGB = 0
- client_ExpiryTime = 0
- client_Enable = true
- client_TgID = ""
- client_SubID = t.randomLowerAndNum(16)
- client_Comment = ""
- client_Reset = 0
- client_Security = "auto"
- client_ShPassword = t.randomShadowSocksPassword()
- client_TrPassword = t.randomLowerAndNum(10)
- client_Method = ""
-
- inbounds, err := t.getInboundsAddClient()
- if err != nil {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
- return
- }
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.buttons.addClient"))
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.chooseInbound"), inbounds)
- case "add_client_ch_default_email":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- userStates[chatId] = "awaiting_email"
- cancel_btn_markup := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
- ),
- )
- prompt_message := t.I18nBot("tgbot.messages.email_prompt", "ClientEmail=="+client_Email)
- t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
- case "add_client_ch_default_id":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- userStates[chatId] = "awaiting_id"
- cancel_btn_markup := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
- ),
- )
- prompt_message := t.I18nBot("tgbot.messages.id_prompt", "ClientId=="+client_Id)
- t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
- case "add_client_ch_default_pass_tr":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- userStates[chatId] = "awaiting_password_tr"
- cancel_btn_markup := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
- ),
- )
- prompt_message := t.I18nBot("tgbot.messages.pass_prompt", "ClientPassword=="+client_TrPassword)
- t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
- case "add_client_ch_default_pass_sh":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- userStates[chatId] = "awaiting_password_sh"
- cancel_btn_markup := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
- ),
- )
- prompt_message := t.I18nBot("tgbot.messages.pass_prompt", "ClientPassword=="+client_ShPassword)
- t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
- case "add_client_ch_default_comment":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- userStates[chatId] = "awaiting_comment"
- cancel_btn_markup := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.use_default")).WithCallbackData("add_client_default_info"),
- ),
- )
- prompt_message := t.I18nBot("tgbot.messages.comment_prompt", "ClientComment=="+client_Comment)
- t.SendMsgToTgbot(chatId, prompt_message, cancel_btn_markup)
- case "add_client_ch_default_traffic":
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 0")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_limit_traffic_in 0")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("1 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 1")),
- tu.InlineKeyboardButton("5 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 5")),
- tu.InlineKeyboardButton("10 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 10")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("20 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 20")),
- tu.InlineKeyboardButton("30 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 30")),
- tu.InlineKeyboardButton("40 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 40")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("50 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 50")),
- tu.InlineKeyboardButton("60 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 60")),
- tu.InlineKeyboardButton("80 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 80")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("100 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 100")),
- tu.InlineKeyboardButton("150 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 150")),
- tu.InlineKeyboardButton("200 GB").WithCallbackData(t.encodeQuery("add_client_limit_traffic_c 200")),
- ),
- )
- t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
- case "add_client_ch_default_exp":
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_traffic_exp")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 0")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_reset_exp_in 0")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 7 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 7")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 10 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 10")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 14 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 14")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 20 "+t.I18nBot("tgbot.days")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 20")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 1 "+t.I18nBot("tgbot.month")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 30")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 3 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 90")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 6 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 180")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.add")+" 12 "+t.I18nBot("tgbot.months")).WithCallbackData(t.encodeQuery("add_client_reset_exp_c 365")),
- ),
- )
- t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
- case "add_client_ch_default_ip_limit":
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData(t.encodeQuery("add_client_default_ip_limit")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.unlimited")).WithCallbackData(t.encodeQuery("add_client_ip_limit_c 0")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.custom")).WithCallbackData(t.encodeQuery("add_client_ip_limit_in 0")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("1").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 1")),
- tu.InlineKeyboardButton("2").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 2")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("3").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 3")),
- tu.InlineKeyboardButton("4").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 4")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("5").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 5")),
- tu.InlineKeyboardButton("6").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 6")),
- tu.InlineKeyboardButton("7").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 7")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton("8").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 8")),
- tu.InlineKeyboardButton("9").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 9")),
- tu.InlineKeyboardButton("10").WithCallbackData(t.encodeQuery("add_client_ip_limit_c 10")),
- ),
- )
- t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
- case "add_client_default_info":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
- delete(userStates, chatId)
- inbound, _ := t.inboundService.GetInbound(receiver_inbound_ID)
- message_text, _ := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(chatId, message_text)
- case "add_client_cancel":
- delete(userStates, chatId)
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 3, tu.ReplyKeyboardRemove())
- case "add_client_default_traffic_exp":
- messageId := callbackQuery.Message.GetMessageID()
- inbound, err := t.inboundService.GetInbound(receiver_inbound_ID)
- if err != nil {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
- return
- }
- message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(chatId, message_text, messageId)
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
- case "add_client_default_ip_limit":
- messageId := callbackQuery.Message.GetMessageID()
- inbound, err := t.inboundService.GetInbound(receiver_inbound_ID)
- if err != nil {
- t.sendCallbackAnswerTgBot(callbackQuery.ID, err.Error())
- return
- }
- message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
- t.addClient(chatId, message_text, messageId)
- t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
- case "add_client_submit_disable":
- client_Enable = false
- _, err := t.SubmitAddClient()
- if err != nil {
- errorMessage := fmt.Sprintf("%v", err)
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove())
- } else {
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove())
- }
- case "add_client_submit_enable":
- client_Enable = true
- _, err := t.SubmitAddClient()
- if err != nil {
- errorMessage := fmt.Sprintf("%v", err)
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.error_add_client", "error=="+errorMessage), tu.ReplyKeyboardRemove())
- } else {
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove())
- }
- case "reset_all_traffics_cancel":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.cancel"), 1, tu.ReplyKeyboardRemove())
- case "reset_all_traffics":
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancelReset")).WithCallbackData(t.encodeQuery("reset_all_traffics_cancel")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.confirmResetTraffic")).WithCallbackData(t.encodeQuery("reset_all_traffics_c")),
- ),
- )
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.AreYouSure"), inlineKeyboard)
- case "reset_all_traffics_c":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- emails, err := t.inboundService.getAllEmails()
- if err != nil {
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
- return
- }
-
- for _, email := range emails {
- err := t.inboundService.ResetClientTrafficByEmail(email)
- if err == nil {
- msg := t.I18nBot("tgbot.messages.SuccessResetTraffic", "ClientEmail=="+email)
- t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
- } else {
- msg := t.I18nBot("tgbot.messages.FailedResetTraffic", "ClientEmail=="+email, "ErrorMessage=="+err.Error())
- t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
- }
- }
-
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.messages.FinishProcess"), tu.ReplyKeyboardRemove())
- case "get_sorted_traffic_usage_report":
- t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
- emails, err := t.inboundService.getAllEmails()
-
- if err != nil {
- t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.errorOperation"), tu.ReplyKeyboardRemove())
- return
- }
- valid_emails, extra_emails, err := t.inboundService.FilterAndSortClientEmails(emails)
-
- for _, valid_emails := range valid_emails {
- traffic, err := t.inboundService.GetClientTrafficByEmail(valid_emails)
- if err != nil {
- logger.Warning(err)
- msg := t.I18nBot("tgbot.wentWrong")
- t.SendMsgToTgbot(chatId, msg)
- continue
- }
- if traffic == nil {
- msg := t.I18nBot("tgbot.noResult")
- t.SendMsgToTgbot(chatId, msg)
- continue
- }
-
- output := t.clientInfoMsg(traffic, false, false, false, false, true, false)
- t.SendMsgToTgbot(chatId, output, tu.ReplyKeyboardRemove())
- }
- for _, extra_emails := range extra_emails {
- msg := fmt.Sprintf("📧 %s\n%s", extra_emails, t.I18nBot("tgbot.noResult"))
- t.SendMsgToTgbot(chatId, msg, tu.ReplyKeyboardRemove())
-
- }
}
}
-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)
- }
-
- ip_limit := ""
- if client_LimitIP == 0 {
- ip_limit = "♾️ Unlimited(Reset)"
- } else {
- ip_limit = fmt.Sprint(client_LimitIP)
- }
-
- 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, "IpLimit=="+ip_limit, "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, "IpLimit=="+ip_limit, "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, "IpLimit=="+ip_limit, "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 {
for _, adminId := range adminIds {
if adminId == tgId {
@@ -1777,27 +907,20 @@ func checkAdmin(tgId int64) bool {
func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) {
numericKeyboard := tu.InlineKeyboard(
tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.SortedTrafficUsageReport")).WithCallbackData(t.encodeQuery("get_sorted_traffic_usage_report")),
- ),
- tu.InlineKeyboardRow(
+ tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.allClients")).WithCallbackData(t.encodeQuery("get_inbounds")),
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.serverUsage")).WithCallbackData(t.encodeQuery("get_usage")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.ResetAllTraffics")).WithCallbackData(t.encodeQuery("reset_all_traffics")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getBanLogs")).WithCallbackData(t.encodeQuery("get_banlogs")),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getInbounds")).WithCallbackData(t.encodeQuery("inbounds")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.depleteSoon")).WithCallbackData(t.encodeQuery("deplete_soon")),
),
tu.InlineKeyboardRow(
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.commands")).WithCallbackData(t.encodeQuery("commands")),
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.onlines")).WithCallbackData(t.encodeQuery("onlines")),
),
tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.allClients")).WithCallbackData(t.encodeQuery("get_inbounds")),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.addClient")).WithCallbackData(t.encodeQuery("add_client")),
+ tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.depleteSoon")).WithCallbackData(t.encodeQuery("deplete_soon")),
+ tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getInbounds")).WithCallbackData(t.encodeQuery("inbounds")),
+ ),
+ tu.InlineKeyboardRow(
+ tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.getBanLogs")).WithCallbackData(t.encodeQuery("get_banlogs")),
+ tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")),
),
// TODOOOOOOOOOOOOOO: Add restart button here.
)
@@ -2043,75 +1166,35 @@ func (t *Tgbot) getInboundUsages() string {
}
return info
}
+
func (t *Tgbot) getInbounds() (*telego.InlineKeyboardMarkup, error) {
inbounds, err := t.inboundService.GetAllInbounds()
+ var buttons []telego.InlineKeyboardButton
+
if err != nil {
logger.Warning("GetAllInbounds run failed:", err)
return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed"))
- }
-
- if len(inbounds) == 0 {
- logger.Warning("No inbounds found")
- return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed"))
- }
-
- var buttons []telego.InlineKeyboardButton
- for _, inbound := range inbounds {
- status := "❌"
- if inbound.Enable {
- status = "✅"
+ } else {
+ if len(inbounds) > 0 {
+ for _, inbound := range inbounds {
+ status := "❌"
+ if inbound.Enable {
+ status = "✅"
+ }
+ buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(t.encodeQuery("get_clients "+strconv.Itoa(inbound.Id))))
+ }
+ } else {
+ logger.Warning("GetAllInbounds run failed:", err)
+ return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed"))
}
- callbackData := t.encodeQuery(fmt.Sprintf("%s %d", "get_clients", inbound.Id))
- buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(callbackData))
- }
- cols := 1
- if len(buttons) >= 6 {
+ }
+ cols := 0
+ if len(buttons) < 6 {
+ cols = 3
+ } else {
cols = 2
}
-
- keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...))
- return keyboard, nil
-}
-
-func (t *Tgbot) getInboundsAddClient() (*telego.InlineKeyboardMarkup, error) {
- inbounds, err := t.inboundService.GetAllInbounds()
- if err != nil {
- logger.Warning("GetAllInbounds run failed:", err)
- return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed"))
- }
-
- if len(inbounds) == 0 {
- logger.Warning("No inbounds found")
- return nil, errors.New(t.I18nBot("tgbot.answers.getInboundsFailed"))
- }
-
- excludedProtocols := map[model.Protocol]bool{
- model.DOKODEMO: true,
- model.Socks: true,
- model.WireGuard: true,
- model.HTTP: true,
- }
-
- var buttons []telego.InlineKeyboardButton
- for _, inbound := range inbounds {
- if excludedProtocols[inbound.Protocol] {
- continue
- }
-
- status := "❌"
- if inbound.Enable {
- status = "✅"
- }
- callbackData := t.encodeQuery(fmt.Sprintf("%s %d", "add_client_to", inbound.Id))
- buttons = append(buttons, tu.InlineKeyboardButton(fmt.Sprintf("%v - %v", inbound.Remark, status)).WithCallbackData(callbackData))
- }
-
- cols := 1
- if len(buttons) >= 6 {
- cols = 2
- }
-
keyboard := tu.InlineKeyboardGrid(tu.InlineKeyboardCols(cols, buttons...))
return keyboard, nil
}
@@ -2406,102 +1489,6 @@ 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.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.InlineKeyboardButton(t.I18nBot("tgbot.buttons.ipLimit")).WithCallbackData("add_client_ch_default_ip_limit"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitEnable")).WithCallbackData("add_client_submit_enable"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"),
- ),
- )
- if len(messageID) > 0 {
- t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard)
- } else {
- t.SendMsgToTgbot(chatId, msg, inlineKeyboard)
- }
- case model.Trojan:
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_password")).WithCallbackData("add_client_ch_default_pass_tr"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"),
- tu.InlineKeyboardButton("ip limit").WithCallbackData("add_client_ch_default_ip_limit"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitEnable")).WithCallbackData("add_client_submit_enable"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"),
- ),
- )
- if len(messageID) > 0 {
- t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard)
- } else {
- t.SendMsgToTgbot(chatId, msg, inlineKeyboard)
- }
- case model.Shadowsocks:
- inlineKeyboard := tu.InlineKeyboard(
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_email")).WithCallbackData("add_client_ch_default_email"),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_password")).WithCallbackData("add_client_ch_default_pass_sh"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.limitTraffic")).WithCallbackData("add_client_ch_default_traffic"),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.resetExpire")).WithCallbackData("add_client_ch_default_exp"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"),
- tu.InlineKeyboardButton("ip limit").WithCallbackData("add_client_ch_default_ip_limit"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitEnable")).WithCallbackData("add_client_submit_enable"),
- ),
- tu.InlineKeyboardRow(
- tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.cancel")).WithCallbackData("add_client_cancel"),
- ),
- )
-
- if len(messageID) > 0 {
- t.editMessageTgBot(chatId, messageID[0], msg, inlineKeyboard)
- } else {
- t.SendMsgToTgbot(chatId, msg, inlineKeyboard)
- }
- }
-
-}
-
func (t *Tgbot) searchInbound(chatId int64, remark string) {
inbounds, err := t.inboundService.SearchInbounds(remark)
if err != nil {
@@ -2872,47 +1859,3 @@ func (t *Tgbot) editMessageTgBot(chatId int64, messageID int, text string, inlin
logger.Warning(err)
}
}
-
-func (t *Tgbot) SendMsgToTgbotDeleteAfter(chatId int64, msg string, delayInSeconds int, replyMarkup ...telego.ReplyMarkup) {
- // Determine if replyMarkup was passed; otherwise, set it to nil
- var replyMarkupParam telego.ReplyMarkup
- if len(replyMarkup) > 0 {
- replyMarkupParam = replyMarkup[0] // Use the first element
- }
-
- // Send the message
- sentMsg, err := bot.SendMessage(&telego.SendMessageParams{
- ChatID: tu.ID(chatId),
- Text: msg,
- ReplyMarkup: replyMarkupParam, // Use the correct replyMarkup value
- })
- if err != nil {
- logger.Warning("Failed to send message:", err)
- return
- }
-
- // Delete the sent message after the specified number of seconds
- go func() {
- time.Sleep(time.Duration(delayInSeconds) * time.Second) // Wait for the specified delay
- t.deleteMessageTgBot(chatId, sentMsg.MessageID) // Delete the message
- delete(userStates, chatId)
- }()
-}
-
-func (t *Tgbot) deleteMessageTgBot(chatId int64, messageID int) {
- params := telego.DeleteMessageParams{
- ChatID: tu.ID(chatId),
- MessageID: messageID,
- }
- if err := bot.DeleteMessage(¶ms); err != nil {
- logger.Warning("Failed to delete message:", err)
- } else {
- logger.Info("Message deleted successfully")
- }
-}
-
-func (t *Tgbot) isSingleWord(text string) bool {
- text = strings.TrimSpace(text)
- re := regexp.MustCompile(`\s+`)
- return re.MatchString(text)
-}
diff --git a/web/translation/translate.zh_CN.toml b/web/translation/translate.zh_CN.toml
index 26cc3322..f746bae6 100644
--- a/web/translation/translate.zh_CN.toml
+++ b/web/translation/translate.zh_CN.toml
@@ -4,8 +4,6 @@
"confirm" = "确定"
"cancel" = "取消"
"close" = "关闭"
-"create" = "创建"
-"update" = "更新"
"copy" = "复制"
"copied" = "已复制"
"download" = "下载"
@@ -28,11 +26,9 @@
"edit" = "编辑"
"delete" = "删除"
"reset" = "重置"
-"noData" = "无数据。"
"copySuccess" = "复制成功"
"sure" = "确定"
"encryption" = "加密"
-"useIPv4ForHost" = "使用 IPv4 连接主机"
"transmission" = "传输"
"host" = "主机"
"path" = "路径"
@@ -48,13 +44,12 @@
"monitor" = "监听"
"certificate" = "数字证书"
"fail" = "失败"
-"comment" = "评论"
"success" = "成功"
"getVersion" = "获取版本"
"install" = "安装"
"clients" = "客户端"
"usage" = "使用情况"
-"twoFactorCode" = "代码"
+"secretToken" = "安全密钥"
"remained" = "剩余"
"security" = "安全"
"secAlertTitle" = "安全警报"
@@ -65,22 +60,15 @@
"secAlertPanelURI" = "面板默认 URI 路径不安全。请配置复杂的 URI 路径。"
"secAlertSubURI" = "订阅默认 URI 路径不安全。请配置复杂的 URI 路径。"
"secAlertSubJsonURI" = "订阅 JSON 默认 URI 路径不安全。请配置复杂的 URI 路径。"
-"emptyDnsDesc" = "未添加DNS服务器。"
-"emptyFakeDnsDesc" = "未添加Fake DNS服务器。"
-"emptyBalancersDesc" = "未添加负载均衡器。"
-"emptyReverseDesc" = "未添加反向代理。"
-"somethingWentWrong" = "出了点问题"
[menu]
-"theme" = "主题"
-"dark" = "暗色"
-"ultraDark" = "超暗色"
"dashboard" = "系统状态"
"inbounds" = "入站列表"
"settings" = "面板设置"
-"xray" = "Xray 设置"
+"xray" = "Xray设置"
"logout" = "退出登录"
"link" = "管理"
+"navigation" = "实用导航"
[pages.login]
"hello" = "你好"
@@ -91,64 +79,39 @@
"invalidFormData" = "数据格式错误"
"emptyUsername" = "请输入用户名"
"emptyPassword" = "请输入密码"
-"wrongUsernameOrPassword" = "用户名、密码或双重验证码无效。"
-"successLogin" = "您已成功登录您的账户。"
+"wrongUsernameOrPassword" = "用户名或密码错误"
+"successLogin" = "登录"
[pages.index]
"title" = "系统状态"
-"cpu" = "CPU"
-"logicalProcessors" = "逻辑处理器"
-"frequency" = "频率"
-"swap" = "交换分区"
-"storage" = "存储"
"memory" = "内存"
-"threads" = "线程"
+"hard" = "磁盘"
"xrayStatus" = "Xray"
"stopXray" = "停止"
"restartXray" = "重启"
"xraySwitch" = "版本"
"xraySwitchClick" = "选择你要切换到的版本"
"xraySwitchClickDesk" = "请谨慎选择,因为较旧版本可能与当前配置不兼容"
-"xrayStatusUnknown" = "未知"
-"xrayStatusRunning" = "运行中"
-"xrayStatusStop" = "停止"
-"xrayStatusError" = "错误"
-"xrayErrorPopoverTitle" = "运行Xray时发生错误"
"operationHours" = "系统正常运行时间"
"systemLoad" = "系统负载"
"systemLoadDesc" = "过去 1、5 和 15 分钟的系统平均负载"
"connectionTcpCountDesc" = "系统中所有 TCP 连接数"
"connectionUdpCountDesc" = "系统中所有 UDP 连接数"
"connectionCount" = "连接数"
-"ipAddresses" = "IP地址"
-"toggleIpVisibility" = "切换IP可见性"
-"overallSpeed" = "整体速度"
-"upload" = "上传"
-"download" = "下载"
-"totalData" = "总数据"
-"sent" = "已发送"
-"received" = "已接收"
-"documentation" = "文档"
-"xraySwitchVersionDialog" = "您确定要更改Xray版本吗?"
-"xraySwitchVersionDialogDesc" = "这将把Xray版本更改为#version#。"
-"xraySwitchVersionPopover" = "Xray 更新成功"
-"geofileUpdateDialog" = "您确定要更新地理文件吗?"
-"geofileUpdateDialogDesc" = "这将更新 #filename# 文件。"
-"geofileUpdatePopover" = "地理文件更新成功"
+"upSpeed" = "总上传速度"
+"downSpeed" = "总下载速度"
+"totalSent" = "系统启动以来发送的总数据量"
+"totalReceive" = "系统启动以来接收的总数据量"
+"xraySwitchVersionDialog" = "切换 Xray 版本"
+"xraySwitchVersionDialogDesc" = "是否切换 Xray 版本至"
"dontRefresh" = "安装中,请勿刷新此页面"
"logs" = "日志"
"config" = "配置"
-"backup" = "备份"
+"backup" = "备份和恢复"
"backupTitle" = "备份和恢复数据库"
+"backupDescription" = "恢复数据库之前建议进行备份"
"exportDatabase" = "备份"
-"exportDatabaseDesc" = "点击下载包含当前数据库备份的 .db 文件到您的设备。"
"importDatabase" = "恢复"
-"importDatabaseDesc" = "点击选择并上传设备中的 .db 文件以从备份恢复数据库。"
-"importDatabaseSuccess" = "数据库导入成功"
-"importDatabaseError" = "导入数据库时出错"
-"readDatabaseError" = "读取数据库时出错"
-"getDatabaseError" = "检索数据库时出错"
-"getConfigError" = "检索配置文件时出错"
[pages.inbounds]
"title" = "入站列表"
@@ -167,16 +130,14 @@
"resetTraffic" = "重置流量"
"addInbound" = "添加入站"
"generalActions" = "通用操作"
-"autoRefresh" = "自动刷新"
-"autoRefreshInterval" = "间隔"
+"create" = "添加"
+"update" = "修改"
"modifyInbound" = "修改入站"
"deleteInbound" = "删除入站"
"deleteInboundContent" = "确定要删除入站吗?"
"deleteClient" = "删除客户端"
"deleteClientContent" = "确定要删除客户端吗?"
"resetTrafficContent" = "确定要重置流量吗?"
-"inboundUpdateSuccess" = "入站连接已成功更新。"
-"inboundCreateSuccess" = "入站连接已成功创建。"
"copyLink" = "复制链接"
"address" = "地址"
"network" = "网络"
@@ -211,14 +172,16 @@
"delDepletedClientsTitle" = "删除流量耗尽的客户端"
"delDepletedClientsContent" = "确定要删除所有流量耗尽的客户端吗?"
"email" = "电子邮件"
-"emailDesc" = "电子邮件必须完全唯一"
+"emailDesc" = "电子邮件必须确保唯一"
"IPLimit" = "IP 限制"
"IPLimitDesc" = "如果数量超过设置值,则禁用入站流量。(0 = 禁用)"
"IPLimitlog" = "IP 日志"
"IPLimitlogDesc" = "IP 历史日志(要启用被禁用的入站流量,请清除日志)"
"IPLimitlogclear" = "清除日志"
"setDefaultCert" = "从面板设置证书"
-"telegramDesc" = "请提供Telegram聊天ID。(在机器人中使用'/id'命令)或(@userinfobot"
+"xtlsDesc" = "Xray 核心需要 1.7.5"
+"realityDesc" = "Xray 核心需要 1.8.0 及以上版本"
+"telegramDesc" = "请提供Telegram聊天ID。(在机器人中使用'/id'命令或跟@userinfobot机器人对话获取)"
"subscriptionDesc" = "要找到你的订阅 URL,请导航到“详细信息”。此外,你可以为多个客户端使用相同的名称。"
"info" = "信息"
"same" = "相同"
@@ -247,21 +210,6 @@
[pages.inbounds.toasts]
"obtain" = "获取"
-"updateSuccess" = "更新成功"
-"logCleanSuccess" = "日志已清除"
-"inboundsUpdateSuccess" = "入站连接已成功更新"
-"inboundUpdateSuccess" = "入站连接已成功更新"
-"inboundCreateSuccess" = "入站连接已成功创建"
-"inboundDeleteSuccess" = "入站连接已成功删除"
-"inboundClientAddSuccess" = "已添加入站客户端"
-"inboundClientDeleteSuccess" = "入站客户端已删除"
-"inboundClientUpdateSuccess" = "入站客户端已更新"
-"delDepletedClientsSuccess" = "所有耗尽客户端已删除"
-"resetAllClientTrafficSuccess" = "客户端所有流量已重置"
-"resetAllTrafficSuccess" = "所有流量已重置"
-"resetInboundClientTrafficSuccess" = "流量已重置"
-"trafficGetError" = "获取流量数据时出错"
-"getNewX25519CertError" = "获取X25519证书时出错。"
[pages.inbounds.stream.general]
"request" = "请求"
@@ -284,12 +232,11 @@
"infoDesc" = "此处的所有更改都需要保存并重启面板才能生效"
"restartPanel" = "重启面板"
"restartPanelDesc" = "确定要重启面板吗?若重启后无法访问面板,请前往服务器查看面板日志信息"
-"restartPanelSuccess" = "面板已成功重启"
"actions" = "操作"
"resetDefaultConfig" = "重置为默认配置"
"panelSettings" = "常规"
"securitySettings" = "安全设定"
-"TGBotSettings" = "Telegram 机器人配置"
+"TGBotSettings" = "Telegram机器人配置"
"panelListeningIP" = "面板监听 IP"
"panelListeningIPDesc" = "默认留空监听所有 IP"
"panelListeningDomain" = "面板监听域名"
@@ -297,10 +244,12 @@
"panelPort" = "面板监听端口"
"panelPortDesc" = "重启面板生效"
"publicKeyPath" = "面板证书公钥文件路径"
-"publicKeyPathDesc" = "填写一个 '/' 开头的绝对路径"
+"DefaultpublicKeyPath" = "/root/.acme.sh/域名_ecc/域名.cer"
+"publicKeyPathDesc" = "填写一个 '/' 开头的绝对路径,〔acme方式〕请自行在填入时修改域名"
"privateKeyPath" = "面板证书密钥文件路径"
-"privateKeyPathDesc" = "填写一个 '/' 开头的绝对路径"
-"panelUrlPath" = "面板 url 根路径"
+"DefaultprivateKeyPath" = "/root/.acme.sh/域名_ecc/域名.key"
+"privateKeyPathDesc" = "填写一个 '/' 开头的绝对路径,〔acme方式〕请自行在填入时修改域名"
+"panelUrlPath" = "面板登录访问路径"
"panelUrlPathDesc" = "必须以 '/' 开头,以 '/' 结尾"
"pageSize" = "分页大小"
"pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用"
@@ -316,7 +265,7 @@
"telegramBotEnable" = "启用 Telegram 机器人"
"telegramBotEnableDesc" = "启用 Telegram 机器人功能"
"telegramToken" = "Telegram 机器人令牌(token)"
-"telegramTokenDesc" = "从 '@BotFather' 获取的 Telegram 机器人令牌"
+"telegramTokenDesc" = "跟 '@BotFather' 对话获取的 Telegram 机器人令牌"
"telegramProxy" = "SOCKS5 Proxy"
"telegramProxyDesc" = "启用 SOCKS5 代理连接到 Telegram(根据指南调整设置)"
"telegramAPIServer" = "Telegram API Server"
@@ -342,8 +291,6 @@
"subSettings" = "订阅设置"
"subEnable" = "启用订阅服务"
"subEnableDesc" = "启用订阅服务功能"
-"subTitle" = "订阅标题"
-"subTitleDesc" = "在VPN客户端中显示的标题"
"subListen" = "监听 IP"
"subListenDesc" = "订阅服务监听的 IP 地址(留空表示监听所有 IP)"
"subPort" = "监听端口"
@@ -364,10 +311,6 @@
"subShowInfoDesc" = "客户端应用中将显示剩余流量和日期信息"
"subURI" = "反向代理 URI"
"subURIDesc" = "用于代理后面的订阅 URL 的 URI 路径"
-"externalTrafficInformEnable" = "外部交通通知"
-"externalTrafficInformEnableDesc" = "每次流量更新时通知外部 API"
-"externalTrafficInformURI" = "外部流量通知 URI"
-"externalTrafficInformURIDesc" = "流量更新将发送到此 URI"
"fragment" = "分片"
"fragmentDesc" = "启用 TLS hello 数据包分片"
"fragmentSett" = "设置"
@@ -378,30 +321,19 @@
"muxSett" = "复用器设置"
"direct" = "直接连接"
"directDesc" = "直接与特定国家的域或IP范围建立连接"
-"notifications" = "通知"
-"certs" = "证书"
-"externalTraffic" = "外部流量"
-"dateAndTime" = "日期和时间"
-"proxyAndServer" = "代理和服务器"
-"intervals" = "间隔"
-"information" = "信息"
-"language" = "语言"
-"telegramBotLanguage" = "Telegram 机器人语言"
+
[pages.xray]
"title" = "Xray 配置"
"save" = "保存"
"restart" = "重新启动 Xray"
-"restartSuccess" = "Xray 已成功重新启动"
-"stopSuccess" = "Xray 已成功停止"
-"restartError" = "重启Xray时发生错误。"
-"stopError" = "停止Xray时发生错误。"
"basicTemplate" = "基础配置"
"advancedTemplate" = "高级配置"
"generalConfigs" = "常规配置"
"generalConfigsDesc" = "这些选项将决定常规配置"
"logConfigs" = "日志"
"logConfigsDesc" = "日志可能会影响服务器的性能,建议仅在需要时启用"
+"blockConfigs" = "防护屏蔽"
"blockConfigsDesc" = "这些选项将阻止用户连接到特定协议和网站"
"basicRouting" = "基本路由"
"blockConnectionsConfigsDesc" = "这些选项将根据特定的请求国家阻止流量。"
@@ -421,6 +353,9 @@
"RoutingStrategy" = "配置路由域策略"
"RoutingStrategyDesc" = "设置 DNS 解析的整体路由策略"
"Torrent" = "屏蔽 BitTorrent 协议"
+"TorrentDesc" = "禁止使用 BitTorrent"
+"Family" = "家庭保护"
+"FamilyDesc" = "屏蔽成人内容和恶意网站"
"Inbounds" = "入站规则"
"InboundsDesc" = "接受来自特定客户端的流量"
"Outbounds" = "出站规则"
@@ -439,15 +374,9 @@
"dnsLogDesc" = "是否启用 DNS 查询日志"
"maskAddress" = "隐藏地址"
"maskAddressDesc" = "IP 地址掩码,启用时会自动替换日志中出现的 IP 地址。"
-"statistics" = "统计"
-"statsInboundUplink" = "入站上传统计"
-"statsInboundUplinkDesc" = "启用所有入站代理的上行流量统计收集。"
-"statsInboundDownlink" = "入站下载统计"
-"statsInboundDownlinkDesc" = "启用所有入站代理的下行流量统计收集。"
-"statsOutboundUplink" = "出站上传统计"
-"statsOutboundUplinkDesc" = "启用所有出站代理的上行流量统计收集。"
-"statsOutboundDownlink" = "出站下载统计"
-"statsOutboundDownlinkDesc" = "启用所有出站代理的下行流量统计收集。"
+
+[pages.navigation]
+"title" = "实用导航"
[pages.xray.rules]
"first" = "置顶"
@@ -455,7 +384,7 @@
"up" = "向上"
"down" = "向下"
"source" = "来源"
-"dest" = "目的地址"
+"dest" = "目标地址"
"inbound" = "入站"
"outbound" = "出站"
"balancer" = "负载均衡"
@@ -463,6 +392,18 @@
"add" = "添加规则"
"edit" = "编辑规则"
"useComma" = "逗号分隔的项目"
+"DomainMatcher" = "域匹配类型"
+"SourceIPs" = "源IP"
+"SourcePort" = "源端口"
+"Network" = "网络类型"
+"Protocol" = "传输协议"
+"Attributes" = "属性"
+"Domain" = "域地址"
+"User" = "用户"
+"Port" = "端口"
+"InboundTag" = "入站 Tag"
+"OutboundTag" = "出站 Tag"
+"BalancerTag" = "负载均衡 Tag"
[pages.xray.outbound]
"addOutbound" = "添加出站"
@@ -477,7 +418,6 @@
"type" = "类型"
"bridge" = "Bridge"
"portal" = "Portal"
-"link" = "链接"
"intercon" = "互连"
"settings" = "设置"
"accountInfo" = "帐户信息"
@@ -506,26 +446,12 @@
"enableDesc" = "启用内置 DNS 服务器"
"tag" = "DNS 入站标签"
"tagDesc" = "此标签将在路由规则中可用作入站标签"
-"clientIp" = "客户端IP"
-"clientIpDesc" = "用于在DNS查询期间通知服务器指定的IP位置"
-"disableCache" = "禁用缓存"
-"disableCacheDesc" = "禁用DNS缓存"
-"disableFallback" = "禁用回退"
-"disableFallbackDesc" = "禁用回退DNS查询"
-"disableFallbackIfMatch" = "匹配时禁用回退"
-"disableFallbackIfMatchDesc" = "当DNS服务器的匹配域名列表命中时,禁用回退DNS查询"
"strategy" = "查询策略"
"strategyDesc" = "解析域名的总体策略"
"add" = "添加服务器"
"edit" = "编辑服务器"
"domains" = "域"
"expectIPs" = "预期 IP"
-"unexpectIPs" = "意外IP"
-"useSystemHosts" = "使用系统Hosts"
-"useSystemHostsDesc" = "使用已安装系统的hosts文件"
-"usePreset" = "使用模板"
-"dnsPresetTitle" = "DNS模板"
-"dnsPresetFamily" = "家庭"
[pages.xray.fakedns]
"add" = "添加假 DNS"
@@ -534,31 +460,19 @@
"poolSize" = "池大小"
[pages.settings.security]
-"admin" = "管理员凭据"
-"twoFactor" = "双重验证"
-"twoFactorEnable" = "启用2FA"
-"twoFactorEnableDesc" = "增加额外的验证层以提高安全性。"
-"twoFactorModalSetTitle" = "启用双重认证"
-"twoFactorModalDeleteTitle" = "停用双重认证"
-"twoFactorModalSteps" = "要设定双重认证,请执行以下步骤:"
-"twoFactorModalFirstStep" = "1. 在认证应用程序中扫描此QR码,或复制QR码附近的令牌并粘贴到应用程序中"
-"twoFactorModalSecondStep" = "2. 输入应用程序中的验证码"
-"twoFactorModalRemoveStep" = "输入应用程序中的验证码以移除双重认证。"
-"twoFactorModalChangeCredentialsTitle" = "更改凭据"
-"twoFactorModalChangeCredentialsStep" = "输入应用程序中的代码以更改管理员凭据。"
-"twoFactorModalSetSuccess" = "双因素认证已成功建立"
-"twoFactorModalDeleteSuccess" = "双因素认证已成功删除"
-"twoFactorModalError" = "验证码错误"
+"admin" = "管理员"
+"secret" = "安全令牌"
+"loginSecurity" = "登录安全"
+"loginSecurityDesc" = "添加额外的身份验证以提高安全性"
+"secretToken" = "安全令牌"
+"secretTokenDesc" = "请将此令牌存储在安全的地方。此令牌用于登录,丢失无法恢复。"
[pages.settings.toasts]
-"modifySettings" = "参数已更改。"
-"getSettings" = "获取参数时发生错误"
-"modifyUserError" = "更改管理员凭据时发生错误。"
-"modifyUser" = "您已成功更改管理员凭据。"
+"modifySettings" = "修改设置"
+"getSettings" = "获取设置"
+"modifyUser" = "修改管理员"
"originalUserPassIncorrect" = "原用户名或原密码错误"
"userPassMustBeNotEmpty" = "新用户名和新密码不能为空"
-"getOutboundTrafficError" = "获取出站流量错误"
-"resetOutboundTrafficError" = "重置出站流量错误"
[tgbot]
"keyboardClosed" = "❌ 自定义键盘已关闭!"
@@ -582,23 +496,20 @@
[tgbot.commands]
"unknown" = "❗ 未知命令"
-"pleaseChoose" = "👇 请选择:\r\n"
+"pleaseChoose" = "👇请〔按照需求〕选择下方按钮:\r\n"
"help" = "🤖 欢迎使用本机器人!它旨在为您提供来自服务器的特定数据,并允许您进行必要的修改。\r\n\r\n"
"start" = "👋 你好,