mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2025-09-12 05:00:05 +00:00
Merge branch 'main' into feat/2fa
This commit is contained in:
commit
ca0cf0b8ea
27 changed files with 546 additions and 86 deletions
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
لتثبيت المشروع أو تحديثه، نفذ الأمر ده:
|
لتثبيت المشروع أو تحديثه، نفذ الأمر ده:
|
||||||
```bash
|
```bash
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.5.8/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## تثبيت النسخة القديمة (مش موصى بيها)
|
## تثبيت النسخة القديمة (مش موصى بيها)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
## Instalar y Actualizar
|
## Instalar y Actualizar
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.5.8/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Instalar versión antigua (no recomendamos)
|
## Instalar versión antigua (no recomendamos)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
## نصب و ارتقا
|
## نصب و ارتقا
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.5.8/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## نصب نسخههای قدیمی (توصیه نمیشود)
|
## نصب نسخههای قدیمی (توصیه نمیشود)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
## Install & Upgrade
|
## Install & Upgrade
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.5.8/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Install legacy Version (we don't recommend)
|
## Install legacy Version (we don't recommend)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
## Установка и обновление
|
## Установка и обновление
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.5.8/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## Установить старую версию (мы не рекомендуем)
|
## Установить старую версию (мы не рекомендуем)
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
## 安装 & 升级
|
## 安装 & 升级
|
||||||
|
|
||||||
```
|
```
|
||||||
bash <(curl -Ls https://raw.githubusercontent.com/mhsanaei/3x-ui/master/install.sh)
|
bash <(curl -Ls https://raw.githubusercontent.com/MHSanaei/3x-ui/refs/tags/v2.5.8/install.sh)
|
||||||
```
|
```
|
||||||
|
|
||||||
## 安装旧版本 (我们不建议)
|
## 安装旧版本 (我们不建议)
|
||||||
|
|
|
@ -82,14 +82,13 @@ gen_random_string() {
|
||||||
}
|
}
|
||||||
|
|
||||||
config_after_install() {
|
config_after_install() {
|
||||||
local existing_username=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'username: .+' | awk '{print $2}')
|
local existing_hasDefaultCredential=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'hasDefaultCredential: .+' | awk '{print $2}')
|
||||||
local existing_password=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'password: .+' | awk '{print $2}')
|
|
||||||
local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
|
local existing_webBasePath=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'webBasePath: .+' | awk '{print $2}')
|
||||||
local existing_port=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}')
|
local existing_port=$(/usr/local/x-ui/x-ui setting -show true | grep -Eo 'port: .+' | awk '{print $2}')
|
||||||
local server_ip=$(curl -s https://api.ipify.org)
|
local server_ip=$(curl -s https://api.ipify.org)
|
||||||
|
|
||||||
if [[ ${#existing_webBasePath} -lt 4 ]]; then
|
if [[ ${#existing_webBasePath} -lt 4 ]]; then
|
||||||
if [[ "$existing_username" == "admin" && "$existing_password" == "admin" ]]; then
|
if [[ "$existing_hasDefaultCredential" == "true" ]]; then
|
||||||
local config_webBasePath=$(gen_random_string 15)
|
local config_webBasePath=$(gen_random_string 15)
|
||||||
local config_username=$(gen_random_string 10)
|
local config_username=$(gen_random_string 10)
|
||||||
local config_password=$(gen_random_string 10)
|
local config_password=$(gen_random_string 10)
|
||||||
|
@ -112,7 +111,6 @@ config_after_install() {
|
||||||
echo -e "${green}WebBasePath: ${config_webBasePath}${plain}"
|
echo -e "${green}WebBasePath: ${config_webBasePath}${plain}"
|
||||||
echo -e "${green}Access URL: http://${server_ip}:${config_port}/${config_webBasePath}${plain}"
|
echo -e "${green}Access URL: http://${server_ip}:${config_port}/${config_webBasePath}${plain}"
|
||||||
echo -e "###############################################"
|
echo -e "###############################################"
|
||||||
echo -e "${yellow}If you forgot your login info, you can type 'x-ui settings' to check${plain}"
|
|
||||||
else
|
else
|
||||||
local config_webBasePath=$(gen_random_string 15)
|
local config_webBasePath=$(gen_random_string 15)
|
||||||
echo -e "${yellow}WebBasePath is missing or too short. Generating a new one...${plain}"
|
echo -e "${yellow}WebBasePath is missing or too short. Generating a new one...${plain}"
|
||||||
|
@ -121,7 +119,7 @@ config_after_install() {
|
||||||
echo -e "${green}Access URL: http://${server_ip}:${existing_port}/${config_webBasePath}${plain}"
|
echo -e "${green}Access URL: http://${server_ip}:${existing_port}/${config_webBasePath}${plain}"
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [[ "$existing_username" == "admin" && "$existing_password" == "admin" ]]; then
|
if [[ "$existing_hasDefaultCredential" == "true" ]]; then
|
||||||
local config_username=$(gen_random_string 10)
|
local config_username=$(gen_random_string 10)
|
||||||
local config_password=$(gen_random_string 10)
|
local config_password=$(gen_random_string 10)
|
||||||
|
|
||||||
|
@ -132,7 +130,6 @@ config_after_install() {
|
||||||
echo -e "${green}Username: ${config_username}${plain}"
|
echo -e "${green}Username: ${config_username}${plain}"
|
||||||
echo -e "${green}Password: ${config_password}${plain}"
|
echo -e "${green}Password: ${config_password}${plain}"
|
||||||
echo -e "###############################################"
|
echo -e "###############################################"
|
||||||
echo -e "${yellow}If you forgot your login info, you can type 'x-ui settings' to check${plain}"
|
|
||||||
else
|
else
|
||||||
echo -e "${green}Username, Password, and WebBasePath are properly set. Exiting...${plain}"
|
echo -e "${green}Username, Password, and WebBasePath are properly set. Exiting...${plain}"
|
||||||
fi
|
fi
|
||||||
|
|
13
main.go
13
main.go
|
@ -16,6 +16,7 @@ import (
|
||||||
"x-ui/web"
|
"x-ui/web"
|
||||||
"x-ui/web/global"
|
"x-ui/web/global"
|
||||||
"x-ui/web/service"
|
"x-ui/web/service"
|
||||||
|
"x-ui/util/crypto"
|
||||||
|
|
||||||
"github.com/op/go-logging"
|
"github.com/op/go-logging"
|
||||||
)
|
)
|
||||||
|
@ -151,9 +152,7 @@ func showSetting(show bool) {
|
||||||
fmt.Println("get current user info failed, error info:", err)
|
fmt.Println("get current user info failed, error info:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
username := userModel.Username
|
if userModel.Username == "" || userModel.Password == "" {
|
||||||
userpasswd := userModel.Password
|
|
||||||
if username == "" || userpasswd == "" {
|
|
||||||
fmt.Println("current username or password is empty")
|
fmt.Println("current username or password is empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,8 +162,12 @@ func showSetting(show bool) {
|
||||||
} else {
|
} else {
|
||||||
fmt.Println("Panel is secure with SSL")
|
fmt.Println("Panel is secure with SSL")
|
||||||
}
|
}
|
||||||
fmt.Println("username:", username)
|
|
||||||
fmt.Println("password:", userpasswd)
|
hasDefaultCredential := func() bool {
|
||||||
|
return userModel.Username == "admin" && crypto.CheckPasswordHash(userModel.Password, "admin")
|
||||||
|
}()
|
||||||
|
|
||||||
|
fmt.Println("hasDefaultCredential:", hasDefaultCredential)
|
||||||
fmt.Println("port:", port)
|
fmt.Println("port:", port)
|
||||||
fmt.Println("webBasePath:", webBasePath)
|
fmt.Println("webBasePath:", webBasePath)
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ func (a *ServerController) initRouter(g *gin.RouterGroup) {
|
||||||
g.POST("/stopXrayService", a.stopXrayService)
|
g.POST("/stopXrayService", a.stopXrayService)
|
||||||
g.POST("/restartXrayService", a.restartXrayService)
|
g.POST("/restartXrayService", a.restartXrayService)
|
||||||
g.POST("/installXray/:version", a.installXray)
|
g.POST("/installXray/:version", a.installXray)
|
||||||
|
g.POST("/updateGeofile/:fileName", a.updateGeofile)
|
||||||
g.POST("/logs/:count", a.getLogs)
|
g.POST("/logs/:count", a.getLogs)
|
||||||
g.POST("/getConfigJson", a.getConfigJson)
|
g.POST("/getConfigJson", a.getConfigJson)
|
||||||
g.GET("/getDb", a.getDb)
|
g.GET("/getDb", a.getDb)
|
||||||
|
@ -95,7 +96,13 @@ func (a *ServerController) getXrayVersion(c *gin.Context) {
|
||||||
func (a *ServerController) installXray(c *gin.Context) {
|
func (a *ServerController) installXray(c *gin.Context) {
|
||||||
version := c.Param("version")
|
version := c.Param("version")
|
||||||
err := a.serverService.UpdateXray(version)
|
err := a.serverService.UpdateXray(version)
|
||||||
jsonMsg(c, I18nWeb(c, "install")+" xray", err)
|
jsonMsg(c, I18nWeb(c, "pages.index.xraySwitchVersionPopover"), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *ServerController) updateGeofile(c *gin.Context) {
|
||||||
|
fileName := c.Param("fileName")
|
||||||
|
err := a.serverService.UpdateGeofile(fileName)
|
||||||
|
jsonMsg(c, I18nWeb(c, "pages.index.geofileUpdatePopover"), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *ServerController) stopXrayService(c *gin.Context) {
|
func (a *ServerController) stopXrayService(c *gin.Context) {
|
||||||
|
|
|
@ -22,11 +22,14 @@
|
||||||
.ant-backup-list-item {
|
.ant-backup-list-item {
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
.ant-xray-version-list-item {
|
.ant-version-list-item {
|
||||||
--padding: 12px;
|
--padding: 12px;
|
||||||
padding: var(--padding) !important;
|
padding: var(--padding) !important;
|
||||||
gap: var(--padding);
|
gap: var(--padding);
|
||||||
}
|
}
|
||||||
|
.dark .ant-version-list-item svg{
|
||||||
|
color: var(--dark-color-text-primary);
|
||||||
|
}
|
||||||
.dark .ant-backup-list-item svg,
|
.dark .ant-backup-list-item svg,
|
||||||
.dark .ant-badge-status-text,
|
.dark .ant-badge-status-text,
|
||||||
.dark .ant-card-extra {
|
.dark .ant-card-extra {
|
||||||
|
@ -43,7 +46,7 @@
|
||||||
border-color: var(--color-primary-100);
|
border-color: var(--color-primary-100);
|
||||||
}
|
}
|
||||||
.dark .ant-backup-list,
|
.dark .ant-backup-list,
|
||||||
.dark .ant-xray-version-list,
|
.dark .ant-version-list,
|
||||||
.dark .ant-card-actions,
|
.dark .ant-card-actions,
|
||||||
.dark .ant-card-actions>li:not(:last-child) {
|
.dark .ant-card-actions>li:not(:last-child) {
|
||||||
border-color: var(--dark-color-stroke);
|
border-color: var(--dark-color-stroke);
|
||||||
|
@ -353,14 +356,25 @@
|
||||||
</a-layout>
|
</a-layout>
|
||||||
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"
|
<a-modal id="version-modal" v-model="versionModal.visible" title='{{ i18n "pages.index.xraySwitch" }}' :closable="true"
|
||||||
@ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
|
@ok="() => versionModal.visible = false" :class="themeSwitcher.currentTheme" footer="">
|
||||||
<a-alert type="warning" :style="{ marginBottom: '12px', width: '100%' }"
|
<a-collapse default-active-key="1">
|
||||||
message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
|
<a-collapse-panel key="1" header='Xray'>
|
||||||
<a-list class="ant-xray-version-list" bordered :style="{ width: '100%' }">
|
<a-alert type="warning" :style="{ marginBottom: '12px', width: '100%' }" message='{{ i18n "pages.index.xraySwitchClickDesk" }}' show-icon></a-alert>
|
||||||
<a-list-item class="ant-xray-version-list-item" v-for="version, index in versionModal.versions">
|
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-version-list-item" v-for="version, index in versionModal.versions">
|
||||||
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ version ]]</a-tag>
|
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ version ]]</a-tag>
|
||||||
<a-radio :class="themeSwitcher.currentTheme" :checked="version === `v${status.xray.version}`" @click="switchV2rayVersion(version)"></a-radio>
|
<a-radio :class="themeSwitcher.currentTheme" :checked="version === `v${status.xray.version}`" @click="switchV2rayVersion(version)"></a-radio>
|
||||||
</a-list-item>
|
</a-list-item>
|
||||||
</a-list>
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
<a-collapse-panel key="2" header='Geofiles'>
|
||||||
|
<a-list class="ant-version-list" bordered :style="{ width: '100%' }">
|
||||||
|
<a-list-item class="ant-version-list-item" v-for="file, index in ['geosite.dat', 'geoip.dat', 'geosite_IR.dat', 'geoip_IR.dat', 'geosite_RU.dat', 'geoip_RU.dat']">
|
||||||
|
<a-tag :color="index % 2 == 0 ? 'purple' : 'green'">[[ file ]]</a-tag>
|
||||||
|
<a-icon type="reload" @click="updateGeofile(file)" :style="{ marginRight: '8px' }"/>
|
||||||
|
</a-list-item>
|
||||||
|
</a-list>
|
||||||
|
</a-collapse-panel>
|
||||||
|
</a-collapse>
|
||||||
</a-modal>
|
</a-modal>
|
||||||
<a-modal id="log-modal" v-model="logModal.visible"
|
<a-modal id="log-modal" v-model="logModal.visible"
|
||||||
:closable="true" @cancel="() => logModal.visible = false"
|
:closable="true" @cancel="() => logModal.visible = false"
|
||||||
|
@ -645,7 +659,7 @@
|
||||||
switchV2rayVersion(version) {
|
switchV2rayVersion(version) {
|
||||||
this.$confirm({
|
this.$confirm({
|
||||||
title: '{{ i18n "pages.index.xraySwitchVersionDialog"}}',
|
title: '{{ i18n "pages.index.xraySwitchVersionDialog"}}',
|
||||||
content: '{{ i18n "pages.index.xraySwitchVersionDialogDesc"}}' + ` ${version}?`,
|
content: '{{ i18n "pages.index.xraySwitchVersionDialogDesc"}}'.replace('#version#', version),
|
||||||
okText: '{{ i18n "confirm"}}',
|
okText: '{{ i18n "confirm"}}',
|
||||||
class: themeSwitcher.currentTheme,
|
class: themeSwitcher.currentTheme,
|
||||||
cancelText: '{{ i18n "cancel"}}',
|
cancelText: '{{ i18n "cancel"}}',
|
||||||
|
@ -657,6 +671,21 @@
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
updateGeofile(fileName) {
|
||||||
|
this.$confirm({
|
||||||
|
title: '{{ i18n "pages.index.geofileUpdateDialog" }}',
|
||||||
|
content: '{{ i18n "pages.index.geofileUpdateDialogDesc" }}'.replace("#filename#", fileName),
|
||||||
|
okText: '{{ i18n "confirm"}}',
|
||||||
|
class: themeSwitcher.currentTheme,
|
||||||
|
cancelText: '{{ i18n "cancel"}}',
|
||||||
|
onOk: async () => {
|
||||||
|
versionModal.hide();
|
||||||
|
this.loading(true, '{{ i18n "pages.index.dontRefresh"}}');
|
||||||
|
await HttpUtil.post(`/server/updateGeofile/${fileName}`);
|
||||||
|
this.loading(false);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
async stopXrayService() {
|
async stopXrayService() {
|
||||||
this.loading(true);
|
this.loading(true);
|
||||||
const msg = await HttpUtil.post('server/stopXrayService');
|
const msg = await HttpUtil.post('server/stopXrayService');
|
||||||
|
|
|
@ -287,6 +287,7 @@
|
||||||
{ label: 'Malware 🇮🇷', value: 'ext:geosite_IR.dat:malware' },
|
{ label: 'Malware 🇮🇷', value: 'ext:geosite_IR.dat:malware' },
|
||||||
{ label: 'Phishing 🇮🇷', value: 'ext:geosite_IR.dat:phishing' },
|
{ label: 'Phishing 🇮🇷', value: 'ext:geosite_IR.dat:phishing' },
|
||||||
{ label: 'Cryptominers 🇮🇷', value: 'ext:geosite_IR.dat:cryptominers' },
|
{ label: 'Cryptominers 🇮🇷', value: 'ext:geosite_IR.dat:cryptominers' },
|
||||||
|
{ label: 'Adult +18', value: 'geosite:category-porn' },
|
||||||
{ label: '🇮🇷 Iran', value: 'ext:geosite_IR.dat:ir' },
|
{ label: '🇮🇷 Iran', value: 'ext:geosite_IR.dat:ir' },
|
||||||
{ label: '🇮🇷 .ir', value: 'regexp:.*\\.ir$' },
|
{ label: '🇮🇷 .ir', value: 'regexp:.*\\.ir$' },
|
||||||
{ label: '🇮🇷 .ایران', value: 'regexp:.*\\.xn--mgba3a4f16a$' },
|
{ label: '🇮🇷 .ایران', value: 'regexp:.*\\.xn--mgba3a4f16a$' },
|
||||||
|
|
|
@ -3,6 +3,7 @@ package service
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -2025,3 +2026,37 @@ func (s *InboundService) MigrateDB() {
|
||||||
func (s *InboundService) GetOnlineClients() []string {
|
func (s *InboundService) GetOnlineClients() []string {
|
||||||
return p.GetOnlineClients()
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -591,6 +591,66 @@ func (s *ServerService) ImportDB(file multipart.File) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *ServerService) UpdateGeofile(fileName string) error {
|
||||||
|
files := []struct {
|
||||||
|
URL string
|
||||||
|
FileName string
|
||||||
|
}{
|
||||||
|
{"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip.dat"},
|
||||||
|
{"https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite.dat"},
|
||||||
|
{"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geoip.dat", "geoip_IR.dat"},
|
||||||
|
{"https://github.com/chocolate4u/Iran-v2ray-rules/releases/latest/download/geosite.dat", "geosite_IR.dat"},
|
||||||
|
{"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geoip.dat", "geoip_RU.dat"},
|
||||||
|
{"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/geosite.dat", "geosite_RU.dat"},
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadFile := func(url, destPath string) error {
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return common.NewErrorf("Failed to download Geofile from %s: %v", url, err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
file, err := os.Create(destPath)
|
||||||
|
if err != nil {
|
||||||
|
return common.NewErrorf("Failed to create Geofile %s: %v", destPath, err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(file, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return common.NewErrorf("Failed to save Geofile %s: %v", destPath, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var fileURL string
|
||||||
|
for _, file := range files {
|
||||||
|
if file.FileName == fileName {
|
||||||
|
fileURL = file.URL
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fileURL == "" {
|
||||||
|
return common.NewErrorf("File '%s' not found in the list of Geofiles", fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
destPath := fmt.Sprintf("%s/%s", config.GetBinFolderPath(), fileName)
|
||||||
|
|
||||||
|
if err := downloadFile(fileURL, destPath); err != nil {
|
||||||
|
return common.NewErrorf("Error downloading Geofile '%s': %v", fileName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := s.RestartXrayService()
|
||||||
|
if err != nil {
|
||||||
|
return common.NewErrorf("Updated Geofile '%s' but Failed to start Xray: %v", fileName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *ServerService) GetNewX25519Cert() (any, error) {
|
func (s *ServerService) GetNewX25519Cert() (any, error) {
|
||||||
// Run the command
|
// Run the command
|
||||||
cmd := exec.Command(xray.GetBinaryPath(), "x25519")
|
cmd := exec.Command(xray.GetBinaryPath(), "x25519")
|
||||||
|
|
|
@ -1069,6 +1069,83 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||||
}
|
}
|
||||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.errorOperation"))
|
||||||
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
t.searchClient(chatId, email, callbackQuery.Message.GetMessageID())
|
||||||
|
case "add_client_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":
|
case "clear_ips":
|
||||||
inlineKeyboard := tu.InlineKeyboard(
|
inlineKeyboard := tu.InlineKeyboard(
|
||||||
tu.InlineKeyboardRow(
|
tu.InlineKeyboardRow(
|
||||||
|
@ -1382,6 +1459,35 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
t.editMessageCallbackTgBot(chatId, callbackQuery.Message.GetMessageID(), inlineKeyboard)
|
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":
|
case "add_client_default_info":
|
||||||
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
||||||
t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
|
t.SendMsgToTgbotDeleteAfter(chatId, t.I18nBot("tgbot.messages.using_default_value"), 3, tu.ReplyKeyboardRemove())
|
||||||
|
@ -1403,6 +1509,16 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||||
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
message_text, err := t.BuildInboundClientDataMessage(inbound.Remark, inbound.Protocol)
|
||||||
t.addClient(chatId, message_text, messageId)
|
t.addClient(chatId, message_text, messageId)
|
||||||
t.sendCallbackAnswerTgBot(callbackQuery.ID, t.I18nBot("tgbot.answers.canceled", "Email=="+client_Email))
|
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":
|
case "add_client_submit_disable":
|
||||||
client_Enable = false
|
client_Enable = false
|
||||||
_, err := t.SubmitAddClient()
|
_, err := t.SubmitAddClient()
|
||||||
|
@ -1423,6 +1539,71 @@ func (t *Tgbot) answerCallback(callbackQuery *telego.CallbackQuery, isAdmin bool
|
||||||
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
t.deleteMessageTgBot(chatId, callbackQuery.Message.GetMessageID())
|
||||||
t.SendMsgToTgbot(chatId, t.I18nBot("tgbot.answers.successfulOperation"), tu.ReplyKeyboardRemove())
|
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())
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1451,15 +1632,22 @@ func (t *Tgbot) BuildInboundClientDataMessage(inbound_remark string, protocol mo
|
||||||
traffic_value = common.FormatTraffic(client_TotalGB)
|
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 {
|
switch protocol {
|
||||||
case model.VMESS, model.VLESS:
|
case model.VMESS, model.VLESS:
|
||||||
message = t.I18nBot("tgbot.messages.inbound_client_data_id", "InboundRemark=="+inbound_remark, "ClientId=="+client_Id, "ClientEmail=="+client_Email, "ClientTraffic=="+traffic_value, "ClientExp=="+expiryTime, "ClientComment=="+client_Comment)
|
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:
|
case model.Trojan:
|
||||||
message = t.I18nBot("tgbot.messages.inbound_client_data_pass", "InboundRemark=="+inbound_remark, "ClientPass=="+client_TrPassword, "ClientEmail=="+client_Email, "ClientTraffic=="+traffic_value, "ClientExp=="+expiryTime, "ClientComment=="+client_Comment)
|
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:
|
case model.Shadowsocks:
|
||||||
message = t.I18nBot("tgbot.messages.inbound_client_data_pass", "InboundRemark=="+inbound_remark, "ClientPass=="+client_ShPassword, "ClientEmail=="+client_Email, "ClientTraffic=="+traffic_value, "ClientExp=="+expiryTime, "ClientComment=="+client_Comment)
|
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:
|
default:
|
||||||
return "", errors.New("unknown protocol")
|
return "", errors.New("unknown protocol")
|
||||||
|
@ -1575,8 +1763,12 @@ func checkAdmin(tgId int64) bool {
|
||||||
|
|
||||||
func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) {
|
func (t *Tgbot) SendAnswer(chatId int64, msg string, isAdmin bool) {
|
||||||
numericKeyboard := tu.InlineKeyboard(
|
numericKeyboard := tu.InlineKeyboard(
|
||||||
|
tu.InlineKeyboardRow(
|
||||||
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.SortedTrafficUsageReport")).WithCallbackData(t.encodeQuery("get_sorted_traffic_usage_report")),
|
||||||
|
),
|
||||||
tu.InlineKeyboardRow(
|
tu.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.serverUsage")).WithCallbackData(t.encodeQuery("get_usage")),
|
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.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")),
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.dbBackup")).WithCallbackData(t.encodeQuery("get_backup")),
|
||||||
|
@ -2223,6 +2415,7 @@ func (t *Tgbot) addClient(chatId int64, msg string, messageID ...int) {
|
||||||
),
|
),
|
||||||
tu.InlineKeyboardRow(
|
tu.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"),
|
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.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
|
||||||
|
@ -2249,6 +2442,7 @@ func (t *Tgbot) addClient(chatId int64, msg string, messageID ...int) {
|
||||||
),
|
),
|
||||||
tu.InlineKeyboardRow(
|
tu.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"),
|
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.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
|
||||||
|
@ -2275,6 +2469,7 @@ func (t *Tgbot) addClient(chatId int64, msg string, messageID ...int) {
|
||||||
),
|
),
|
||||||
tu.InlineKeyboardRow(
|
tu.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.change_comment")).WithCallbackData("add_client_ch_default_comment"),
|
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.InlineKeyboardRow(
|
||||||
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
|
tu.InlineKeyboardButton(t.I18nBot("tgbot.buttons.submitDisable")).WithCallbackData("add_client_submit_disable"),
|
||||||
|
|
|
@ -122,8 +122,12 @@
|
||||||
"totalData" = "إجمالي البيانات"
|
"totalData" = "إجمالي البيانات"
|
||||||
"sent" = "مرسل"
|
"sent" = "مرسل"
|
||||||
"received" = "مستقبل"
|
"received" = "مستقبل"
|
||||||
"xraySwitchVersionDialog" = "تغيير نسخة Xray"
|
"xraySwitchVersionDialog" = "هل تريد حقًا تغيير إصدار Xray؟"
|
||||||
"xraySwitchVersionDialogDesc" = "متأكد إنك عايز تغير نسخة Xray لـ"
|
"xraySwitchVersionDialogDesc" = "سيؤدي هذا إلى تغيير إصدار Xray إلى #version#."
|
||||||
|
"xraySwitchVersionPopover" = "تم تحديث Xray بنجاح"
|
||||||
|
"geofileUpdateDialog" = "هل تريد حقًا تحديث ملف الجغرافيا؟"
|
||||||
|
"geofileUpdateDialogDesc" = "سيؤدي هذا إلى تحديث ملف #filename#."
|
||||||
|
"geofileUpdatePopover" = "تم تحديث ملف الجغرافيا بنجاح"
|
||||||
"dontRefresh" = "التثبيت شغال، متعملش Refresh للصفحة"
|
"dontRefresh" = "التثبيت شغال، متعملش Refresh للصفحة"
|
||||||
"logs" = "السجلات"
|
"logs" = "السجلات"
|
||||||
"config" = "الإعدادات"
|
"config" = "الإعدادات"
|
||||||
|
@ -601,12 +605,17 @@
|
||||||
"pass_prompt" = "🔑 الباسورد الافتراضي: {{ .ClientPassword }}\n\nادخل الباسورد بتاعك."
|
"pass_prompt" = "🔑 الباسورد الافتراضي: {{ .ClientPassword }}\n\nادخل الباسورد بتاعك."
|
||||||
"email_prompt" = "📧 الإيميل الافتراضي: {{ .ClientEmail }}\n\nادخل الإيميل بتاعك."
|
"email_prompt" = "📧 الإيميل الافتراضي: {{ .ClientEmail }}\n\nادخل الإيميل بتاعك."
|
||||||
"comment_prompt" = "💬 التعليق الافتراضي: {{ .ClientComment }}\n\nادخل تعليقك."
|
"comment_prompt" = "💬 التعليق الافتراضي: {{ .ClientComment }}\n\nادخل تعليقك."
|
||||||
"inbound_client_data_id" = "🔄 للإدخال: {{ .InboundRemark }}\n\n🔑 الـ ID: {{ .ClientId }}\n📧 الإيميل: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n💬 التعليق: {{ .ClientComment }}\n\nممكن تضيف العميل للإدخال دلوقتي!"
|
"inbound_client_data_id" = "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 المعرف: {{ .ClientId }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!"
|
||||||
"inbound_client_data_pass" = "🔄 للإدخال: {{ .InboundRemark }}\n\n🔑 الباسورد: {{ .ClientPass }}\n📧 الإيميل: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n💬 التعليق: {{ .ClientComment }}\n\nممكن تضيف العميل للإدخال دلوقتي!"
|
"inbound_client_data_pass" = "🔄 الدخول: {{ .InboundRemark }}\n\n🔑 كلمة المرور: {{ .ClientPass }}\n📧 البريد الإلكتروني: {{ .ClientEmail }}\n📊 الترافيك: {{ .ClientTraffic }}\n📅 تاريخ الانتهاء: {{ .ClientExp }}\n🌐 حدّ IP: {{ .IpLimit }}\n💬 تعليق: {{ .ClientComment }}\n\nدلوقتي تقدر تضيف العميل على الدخول!"
|
||||||
"cancel" = "❌ العملية اتلغت! \n\nممكن تبدأ من /start في أي وقت. 🔄"
|
"cancel" = "❌ العملية اتلغت! \n\nممكن تبدأ من /start في أي وقت. 🔄"
|
||||||
"error_add_client" = "⚠️ حصل خطأ:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ حصل خطأ:\n\n {{ .error }}"
|
||||||
"using_default_value" = "تمام، هشيل على القيمة الافتراضية. 😊"
|
"using_default_value" = "تمام، هشيل على القيمة الافتراضية. 😊"
|
||||||
"incorrect_input" = "المدخلات مش صحيحة.\nالكلمات لازم تكون متصلة من غير فراغات.\nمثال صحيح: aaaaaa\nمثال غلط: aaa aaa 🚫"
|
"incorrect_input" = "المدخلات مش صحيحة.\nالكلمات لازم تكون متصلة من غير فراغات.\nمثال صحيح: aaaaaa\nمثال غلط: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "إنت متأكد؟ 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 البريد الإلكتروني: {{ .ClientEmail }}\n🏁 النتيجة: ✅ تم بنجاح"
|
||||||
|
"FailedResetTraffic" = "📧 البريد الإلكتروني: {{ .ClientEmail }}\n🏁 النتيجة: ❌ فشل \n\n🛠️ الخطأ: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 عملية إعادة ضبط الترافيك خلصت لكل العملاء."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
"closeKeyboard" = "❌ اقفل الكيبورد"
|
"closeKeyboard" = "❌ اقفل الكيبورد"
|
||||||
|
@ -650,6 +659,9 @@
|
||||||
"change_password" = "⚙️🔑 كلمة السر"
|
"change_password" = "⚙️🔑 كلمة السر"
|
||||||
"change_email" = "⚙️📧 البريد الإلكتروني"
|
"change_email" = "⚙️📧 البريد الإلكتروني"
|
||||||
"change_comment" = "⚙️💬 تعليق"
|
"change_comment" = "⚙️💬 تعليق"
|
||||||
|
"ResetAllTraffics" = "إعادة ضبط جميع الترافيك"
|
||||||
|
"SortedTrafficUsageReport" = "تقرير استخدام الترافيك المرتب"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
"successfulOperation" = "✅ العملية نجحت!"
|
"successfulOperation" = "✅ العملية نجحت!"
|
||||||
|
|
|
@ -122,8 +122,12 @@
|
||||||
"totalData" = "Total Data"
|
"totalData" = "Total Data"
|
||||||
"sent" = "Sent"
|
"sent" = "Sent"
|
||||||
"received" = "Received"
|
"received" = "Received"
|
||||||
"xraySwitchVersionDialog" = "Change Xray Version"
|
"xraySwitchVersionDialog" = "Do you really want to change the Xray version?"
|
||||||
"xraySwitchVersionDialogDesc" = "Are you sure you want to change the Xray version to"
|
"xraySwitchVersionDialogDesc" = "This will change the Xray version to #version#."
|
||||||
|
"xraySwitchVersionPopover" = "Xray updated successfully"
|
||||||
|
"geofileUpdateDialog" = "Do you really want to update the geofile?"
|
||||||
|
"geofileUpdateDialogDesc" = "This will update the #filename# file."
|
||||||
|
"geofileUpdatePopover" = "Geofile updated successfully"
|
||||||
"dontRefresh" = "Installation is in progress, please do not refresh this page"
|
"dontRefresh" = "Installation is in progress, please do not refresh this page"
|
||||||
"logs" = "Logs"
|
"logs" = "Logs"
|
||||||
"config" = "Config"
|
"config" = "Config"
|
||||||
|
@ -601,12 +605,17 @@
|
||||||
"pass_prompt" = "🔑 Default Password: {{ .ClientPassword }}\n\nEnter your password."
|
"pass_prompt" = "🔑 Default Password: {{ .ClientPassword }}\n\nEnter your password."
|
||||||
"email_prompt" = "📧 Default Email: {{ .ClientEmail }}\n\nEnter your email."
|
"email_prompt" = "📧 Default Email: {{ .ClientEmail }}\n\nEnter your email."
|
||||||
"comment_prompt" = "💬 Default Comment: {{ .ClientComment }}\n\nEnter your Comment."
|
"comment_prompt" = "💬 Default Comment: {{ .ClientComment }}\n\nEnter your Comment."
|
||||||
"inbound_client_data_id" = "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!"
|
"inbound_client_data_id" = "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n🌐 IP Limit: {{ .IpLimit }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!"
|
||||||
"inbound_client_data_pass" = "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 Password: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!"
|
"inbound_client_data_pass" = "🔄 Inbound: {{ .InboundRemark }}\n\n🔑 Password: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Traffic: {{ .ClientTraffic }}\n📅 Expire Date: {{ .ClientExp }}\n🌐 IP Limit: {{ .IpLimit }}\n💬 Comment: {{ .ClientComment }}\n\nYou can add the client to inbound now!"
|
||||||
"cancel" = "❌ Process Canceled! \n\nYou can /start again anytime. 🔄"
|
"cancel" = "❌ Process Canceled! \n\nYou can /start again anytime. 🔄"
|
||||||
"error_add_client" = "⚠️ Error:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Error:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Okay, I'll stick with the default value. 😊"
|
"using_default_value" = "Okay, I'll stick with the default value. 😊"
|
||||||
"incorrect_input" ="Your input is not valid.\nThe phrases should be continuous without spaces.\nCorrect example: aaaaaa\nIncorrect example: aaa aaa 🚫"
|
"incorrect_input" ="Your input is not valid.\nThe phrases should be continuous without spaces.\nCorrect example: aaaaaa\nIncorrect example: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "Are you sure? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Result: ✅ Success"
|
||||||
|
"FailedResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Result: ❌ Failed \n\n🛠️ Error: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Traffic reset process finished for all clients."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
"closeKeyboard" = "❌ Close Keyboard"
|
"closeKeyboard" = "❌ Close Keyboard"
|
||||||
|
@ -650,6 +659,8 @@
|
||||||
"change_password" = "⚙️🔑 Password"
|
"change_password" = "⚙️🔑 Password"
|
||||||
"change_email" = "⚙️📧 Email"
|
"change_email" = "⚙️📧 Email"
|
||||||
"change_comment" = "⚙️💬 Comment"
|
"change_comment" = "⚙️💬 Comment"
|
||||||
|
"ResetAllTraffics" = "Reset All Traffics"
|
||||||
|
"SortedTrafficUsageReport" = "Sorted Traffic Usage Report"
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
"successfulOperation" = "✅ Operation successful!"
|
"successfulOperation" = "✅ Operation successful!"
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "Datos totales"
|
"totalData" = "Datos totales"
|
||||||
"sent" = "Enviado"
|
"sent" = "Enviado"
|
||||||
"received" = "Recibido"
|
"received" = "Recibido"
|
||||||
"xraySwitchVersionDialog" = "Cambiar Versión de Xray"
|
"xraySwitchVersionDialog" = "¿Realmente deseas cambiar la versión de Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "¿Estás seguro de que deseas cambiar la versión de Xray a"
|
"xraySwitchVersionDialogDesc" = "Esto cambiará la versión de Xray a #version#."
|
||||||
|
"xraySwitchVersionPopover" = "Xray se actualizó correctamente"
|
||||||
|
"geofileUpdateDialog" = "¿Realmente deseas actualizar el geofichero?"
|
||||||
|
"geofileUpdateDialogDesc" = "Esto actualizará el archivo #filename#."
|
||||||
|
"geofileUpdatePopover" = "Geofichero actualizado correctamente"
|
||||||
"dontRefresh" = "La instalación está en progreso, por favor no actualices esta página."
|
"dontRefresh" = "La instalación está en progreso, por favor no actualices esta página."
|
||||||
"logs" = "Registros"
|
"logs" = "Registros"
|
||||||
"config" = "Configuración"
|
"config" = "Configuración"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 Contraseña predeterminada: {{ .ClientPassword }}\n\nIntroduce tu contraseña."
|
"pass_prompt" = "🔑 Contraseña predeterminada: {{ .ClientPassword }}\n\nIntroduce tu contraseña."
|
||||||
"email_prompt" = "📧 Correo electrónico predeterminado: {{ .ClientEmail }}\n\nIntroduce tu correo electrónico."
|
"email_prompt" = "📧 Correo electrónico predeterminado: {{ .ClientEmail }}\n\nIntroduce tu correo electrónico."
|
||||||
"comment_prompt" = "💬 Comentario predeterminado: {{ .ClientComment }}\n\nIntroduce tu comentario."
|
"comment_prompt" = "💬 Comentario predeterminado: {{ .ClientComment }}\n\nIntroduce tu comentario."
|
||||||
"inbound_client_data_id" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfico: {{ .ClientTraffic }}\n📅 Fecha de vencimiento: {{ .ClientExp }}\n💬 Comentario: {{ .ClientComment }}\n\n¡Ahora puedes agregar al cliente a la entrada!"
|
"inbound_client_data_id" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Correo: {{ .ClientEmail }}\n📊 Tráfico: {{ .ClientTraffic }}\n📅 Fecha de expiración: {{ .ClientExp }}\n🌐 Límite de IP: {{ .IpLimit }}\n💬 Comentario: {{ .ClientComment }}\n\n¡Ahora puedes agregar al cliente a la entrada!"
|
||||||
"inbound_client_data_pass" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 Contraseña: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfico: {{ .ClientTraffic }}\n📅 Fecha de vencimiento: {{ .ClientExp }}\n💬 Comentario: {{ .ClientComment }}\n\n¡Ahora puedes agregar al cliente a la entrada!"
|
"inbound_client_data_pass" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 Contraseña: {{ .ClientPass }}\n📧 Correo: {{ .ClientEmail }}\n📊 Tráfico: {{ .ClientTraffic }}\n📅 Fecha de expiración: {{ .ClientExp }}\n🌐 Límite de IP: {{ .IpLimit }}\n💬 Comentario: {{ .ClientComment }}\n\n¡Ahora puedes agregar al cliente a la entrada!"
|
||||||
"cancel" = "❌ ¡Proceso cancelado! \n\nPuedes /start de nuevo en cualquier momento. 🔄"
|
"cancel" = "❌ ¡Proceso cancelado! \n\nPuedes /start de nuevo en cualquier momento. 🔄"
|
||||||
"error_add_client" = "⚠️ Error:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Error:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Está bien, me quedaré con el valor predeterminado. 😊"
|
"using_default_value" = "Está bien, me quedaré con el valor predeterminado. 😊"
|
||||||
"incorrect_input" ="Tu entrada no es válida.\nLas frases deben ser continuas sin espacios.\nEjemplo correcto: aaaaaa\nEjemplo incorrecto: aaa aaa 🚫"
|
"incorrect_input" ="Tu entrada no es válida.\nLas frases deben ser continuas sin espacios.\nEjemplo correcto: aaaaaa\nEjemplo incorrecto: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "¿Estás seguro? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 Correo: {{ .ClientEmail }}\n🏁 Resultado: ✅ Éxito"
|
||||||
|
"FailedResetTraffic" = "📧 Correo: {{ .ClientEmail }}\n🏁 Resultado: ❌ Fallido \n\n🛠️ Error: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Proceso de reinicio de tráfico finalizado para todos los clientes."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,7 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 Contraseña"
|
"change_password" = "⚙️🔑 Contraseña"
|
||||||
"change_email" = "⚙️📧 Correo electrónico"
|
"change_email" = "⚙️📧 Correo electrónico"
|
||||||
"change_comment" = "⚙️💬 Comentario"
|
"change_comment" = "⚙️💬 Comentario"
|
||||||
|
"ResetAllTraffics" = "Reiniciar todo el tráfico"
|
||||||
|
"SortedTrafficUsageReport" = "Informe de uso de tráfico ordenado"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "دادههای کل"
|
"totalData" = "دادههای کل"
|
||||||
"sent" = "ارسال شده"
|
"sent" = "ارسال شده"
|
||||||
"received" = "دریافت شده"
|
"received" = "دریافت شده"
|
||||||
"xraySwitchVersionDialog" = "تغییر نسخه ایکسری"
|
"xraySwitchVersionDialog" = "آیا واقعاً میخواهید نسخه Xray را تغییر دهید؟"
|
||||||
"xraySwitchVersionDialogDesc" = "آیا از تغییر نسخه مطمئن هستید؟"
|
"xraySwitchVersionDialogDesc" = "این کار نسخه Xray را به #version# تغییر میدهد."
|
||||||
|
"xraySwitchVersionPopover" = "Xray با موفقیت بهروز شد"
|
||||||
|
"geofileUpdateDialog" = "آیا واقعاً میخواهید فایل جغرافیایی را بهروز کنید؟"
|
||||||
|
"geofileUpdateDialogDesc" = "این عمل فایل #filename# را بهروز میکند."
|
||||||
|
"geofileUpdatePopover" = "فایل جغرافیایی با موفقیت بهروز شد"
|
||||||
"dontRefresh" = "در حال نصب، لطفا صفحه را رفرش نکنید"
|
"dontRefresh" = "در حال نصب، لطفا صفحه را رفرش نکنید"
|
||||||
"logs" = "گزارشها"
|
"logs" = "گزارشها"
|
||||||
"config" = "پیکربندی"
|
"config" = "پیکربندی"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 رمز عبور پیشفرض: {{ .ClientPassword }}\n\nرمز عبور خود را وارد کنید."
|
"pass_prompt" = "🔑 رمز عبور پیشفرض: {{ .ClientPassword }}\n\nرمز عبور خود را وارد کنید."
|
||||||
"email_prompt" = "📧 ایمیل پیشفرض: {{ .ClientEmail }}\n\nایمیل خود را وارد کنید."
|
"email_prompt" = "📧 ایمیل پیشفرض: {{ .ClientEmail }}\n\nایمیل خود را وارد کنید."
|
||||||
"comment_prompt" = "💬 نظر پیشفرض: {{ .ClientComment }}\n\nنظر خود را وارد کنید."
|
"comment_prompt" = "💬 نظر پیشفرض: {{ .ClientComment }}\n\nنظر خود را وارد کنید."
|
||||||
"inbound_client_data_id" = "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 شناسه: {{ .ClientId }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n💬 نظر: {{ .ClientComment }}\n\nحالا میتوانید مشتری را به ورودی اضافه کنید!"
|
"inbound_client_data_id" = "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 شناسه: {{ .ClientId }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n🌐 محدودیت IP: {{ .IpLimit }}\n💬 توضیح: {{ .ClientComment }}\n\nاکنون میتونی مشتری را به ورودی اضافه کنی!"
|
||||||
"inbound_client_data_pass" = "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 رمز عبور: {{ .ClientPass }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n💬 نظر: {{ .ClientComment }}\n\nحالا میتوانید مشتری را به ورودی اضافه کنید!"
|
"inbound_client_data_pass" = "🔄 ورودی: {{ .InboundRemark }}\n\n🔑 رمز عبور: {{ .ClientPass }}\n📧 ایمیل: {{ .ClientEmail }}\n📊 ترافیک: {{ .ClientTraffic }}\n📅 تاریخ انقضا: {{ .ClientExp }}\n🌐 محدودیت IP: {{ .IpLimit }}\n💬 توضیح: {{ .ClientComment }}\n\nاکنون میتونی مشتری را به ورودی اضافه کنی!"
|
||||||
"cancel" = "❌ فرآیند لغو شد! \n\nمیتوانید هر زمان که خواستید /start را دوباره اجرا کنید. 🔄"
|
"cancel" = "❌ فرآیند لغو شد! \n\nمیتوانید هر زمان که خواستید /start را دوباره اجرا کنید. 🔄"
|
||||||
"error_add_client" = "⚠️ خطا:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ خطا:\n\n {{ .error }}"
|
||||||
"using_default_value" = "باشه، از مقدار پیشفرض استفاده میکنم. 😊"
|
"using_default_value" = "باشه، از مقدار پیشفرض استفاده میکنم. 😊"
|
||||||
"incorrect_input" ="ورودی شما معتبر نیست.\nعبارتها باید بدون فاصله باشند.\nمثال صحیح: aaaaaa\nمثال نادرست: aaa aaa 🚫"
|
"incorrect_input" ="ورودی شما معتبر نیست.\nعبارتها باید بدون فاصله باشند.\nمثال صحیح: aaaaaa\nمثال نادرست: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "مطمئنی؟ 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 ایمیل: {{ .ClientEmail }}\n🏁 نتیجه: ✅ موفقیتآمیز"
|
||||||
|
"FailedResetTraffic" = "📧 ایمیل: {{ .ClientEmail }}\n🏁 نتیجه: ❌ ناموفق \n\n🛠️ خطا: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 فرآیند بازنشانی ترافیک برای همه مشتریان به پایان رسید."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,9 @@
|
||||||
"change_password" = "⚙️🔑 گذرواژه"
|
"change_password" = "⚙️🔑 گذرواژه"
|
||||||
"change_email" = "⚙️📧 ایمیل"
|
"change_email" = "⚙️📧 ایمیل"
|
||||||
"change_comment" = "⚙️💬 نظر"
|
"change_comment" = "⚙️💬 نظر"
|
||||||
|
"ResetAllTraffics" = "بازنشانی همه ترافیکها"
|
||||||
|
"SortedTrafficUsageReport" = "گزارش استفاده از ترافیک مرتبشده"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
"successfulOperation" = "✅ انجام شد!"
|
"successfulOperation" = "✅ انجام شد!"
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "Total data"
|
"totalData" = "Total data"
|
||||||
"sent" = "Dikirim"
|
"sent" = "Dikirim"
|
||||||
"received" = "Diterima"
|
"received" = "Diterima"
|
||||||
"xraySwitchVersionDialog" = "Ganti Versi Xray"
|
"xraySwitchVersionDialog" = "Apakah Anda yakin ingin mengubah versi Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Apakah Anda yakin ingin mengubah versi Xray menjadi"
|
"xraySwitchVersionDialogDesc" = "Ini akan mengubah versi Xray ke #version#."
|
||||||
|
"xraySwitchVersionPopover" = "Xray berhasil diperbarui"
|
||||||
|
"geofileUpdateDialog" = "Apakah Anda yakin ingin memperbarui geofile?"
|
||||||
|
"geofileUpdateDialogDesc" = "Ini akan memperbarui file #filename#."
|
||||||
|
"geofileUpdatePopover" = "Geofile berhasil diperbarui"
|
||||||
"dontRefresh" = "Instalasi sedang berlangsung, harap jangan menyegarkan halaman ini"
|
"dontRefresh" = "Instalasi sedang berlangsung, harap jangan menyegarkan halaman ini"
|
||||||
"logs" = "Log"
|
"logs" = "Log"
|
||||||
"config" = "Konfigurasi"
|
"config" = "Konfigurasi"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 Kata Sandi Default: {{ .ClientPassword }}\n\nMasukkan kata sandi Anda."
|
"pass_prompt" = "🔑 Kata Sandi Default: {{ .ClientPassword }}\n\nMasukkan kata sandi Anda."
|
||||||
"email_prompt" = "📧 Email Default: {{ .ClientEmail }}\n\nMasukkan email Anda."
|
"email_prompt" = "📧 Email Default: {{ .ClientEmail }}\n\nMasukkan email Anda."
|
||||||
"comment_prompt" = "💬 Komentar Default: {{ .ClientComment }}\n\nMasukkan komentar Anda."
|
"comment_prompt" = "💬 Komentar Default: {{ .ClientComment }}\n\nMasukkan komentar Anda."
|
||||||
"inbound_client_data_id" = "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu Lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang Anda bisa menambahkan klien ke masuk!"
|
"inbound_client_data_id" = "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!"
|
||||||
"inbound_client_data_pass" = "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 Kata Sandi: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu Lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang Anda bisa menambahkan klien ke masuk!"
|
"inbound_client_data_pass" = "🔄 Masuk: {{ .InboundRemark }}\n\n🔑 Kata sandi: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lalu lintas: {{ .ClientTraffic }}\n📅 Tanggal Kedaluwarsa: {{ .ClientExp }}\n🌐 Batas IP: {{ .IpLimit }}\n💬 Komentar: {{ .ClientComment }}\n\nSekarang kamu bisa menambahkan klien ke inbound!"
|
||||||
"cancel" = "❌ Proses Dibatalkan! \n\nAnda dapat /start lagi kapan saja. 🔄"
|
"cancel" = "❌ Proses Dibatalkan! \n\nAnda dapat /start lagi kapan saja. 🔄"
|
||||||
"error_add_client" = "⚠️ Kesalahan:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Kesalahan:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Oke, saya akan tetap menggunakan nilai default. 😊"
|
"using_default_value" = "Oke, saya akan tetap menggunakan nilai default. 😊"
|
||||||
"incorrect_input" ="Masukan Anda tidak valid.\nFrasa harus berlanjut tanpa spasi.\nContoh benar: aaaaaa\nContoh salah: aaa aaa 🚫"
|
"incorrect_input" ="Masukan Anda tidak valid.\nFrasa harus berlanjut tanpa spasi.\nContoh benar: aaaaaa\nContoh salah: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "Apakah kamu yakin? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Hasil: ✅ Berhasil"
|
||||||
|
"FailedResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Hasil: ❌ Gagal \n\n🛠️ Kesalahan: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Proses reset traffic selesai untuk semua klien."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,7 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 Kata Sandi"
|
"change_password" = "⚙️🔑 Kata Sandi"
|
||||||
"change_email" = "⚙️📧 Email"
|
"change_email" = "⚙️📧 Email"
|
||||||
"change_comment" = "⚙️💬 Komentar"
|
"change_comment" = "⚙️💬 Komentar"
|
||||||
|
"ResetAllTraffics" = "Reset Semua Lalu Lintas"
|
||||||
|
"SortedTrafficUsageReport" = "Laporan Penggunaan Lalu Lintas yang Terurut"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "総データ量"
|
"totalData" = "総データ量"
|
||||||
"sent" = "送信"
|
"sent" = "送信"
|
||||||
"received" = "受信"
|
"received" = "受信"
|
||||||
"xraySwitchVersionDialog" = "Xrayバージョン切り替え"
|
"xraySwitchVersionDialog" = "Xrayのバージョンを本当に変更しますか?"
|
||||||
"xraySwitchVersionDialogDesc" = "Xrayのバージョンを切り替えますか?"
|
"xraySwitchVersionDialogDesc" = "Xrayのバージョンが#version#に変更されます。"
|
||||||
|
"xraySwitchVersionPopover" = "Xrayの更新が成功しました"
|
||||||
|
"geofileUpdateDialog" = "ジオファイルを本当に更新しますか?"
|
||||||
|
"geofileUpdateDialogDesc" = "これにより#filename#ファイルが更新されます。"
|
||||||
|
"geofileUpdatePopover" = "ジオファイルの更新が成功しました"
|
||||||
"dontRefresh" = "インストール中、このページをリロードしないでください"
|
"dontRefresh" = "インストール中、このページをリロードしないでください"
|
||||||
"logs" = "ログ"
|
"logs" = "ログ"
|
||||||
"config" = "設定"
|
"config" = "設定"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 デフォルトパスワード: {{ .ClientPassword }}\n\nパスワードを入力してください。"
|
"pass_prompt" = "🔑 デフォルトパスワード: {{ .ClientPassword }}\n\nパスワードを入力してください。"
|
||||||
"email_prompt" = "📧 デフォルトメール: {{ .ClientEmail }}\n\nメールを入力してください。"
|
"email_prompt" = "📧 デフォルトメール: {{ .ClientEmail }}\n\nメールを入力してください。"
|
||||||
"comment_prompt" = "💬 デフォルトコメント: {{ .ClientComment }}\n\nコメントを入力してください。"
|
"comment_prompt" = "💬 デフォルトコメント: {{ .ClientComment }}\n\nコメントを入力してください。"
|
||||||
"inbound_client_data_id" = "🔄 入力: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 メール: {{ .ClientEmail }}\n📊 トラフィック: {{ .ClientTraffic }}\n📅 期限日: {{ .ClientExp }}\n💬 コメント: {{ .ClientComment }}\n\n今すぐクライアントをインバウンドに追加できます!"
|
"inbound_client_data_id" = "🔄 インバウンド: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 メール: {{ .ClientEmail }}\n📊 トラフィック: {{ .ClientTraffic }}\n📅 有効期限: {{ .ClientExp }}\n🌐 IP制限: {{ .IpLimit }}\n💬 コメント: {{ .ClientComment }}\n\n今すぐこのクライアントをインバウンドに追加できます!"
|
||||||
"inbound_client_data_pass" = "🔄 入力: {{ .InboundRemark }}\n\n🔑 パスワード: {{ .ClientPass }}\n📧 メール: {{ .ClientEmail }}\n📊 トラフィック: {{ .ClientTraffic }}\n📅 期限日: {{ .ClientExp }}\n💬 コメント: {{ .ClientComment }}\n\n今すぐクライアントをインバウンドに追加できます!"
|
"inbound_client_data_pass" = "🔄 インバウンド: {{ .InboundRemark }}\n\n🔑 パスワード: {{ .ClientPass }}\n📧 メール: {{ .ClientEmail }}\n📊 トラフィック: {{ .ClientTraffic }}\n📅 有効期限: {{ .ClientExp }}\n🌐 IP制限: {{ .IpLimit }}\n💬 コメント: {{ .ClientComment }}\n\n今すぐこのクライアントをインバウンドに追加できます!"
|
||||||
"cancel" = "❌ プロセスがキャンセルされました!\n\nいつでも /start で再開できます。 🔄"
|
"cancel" = "❌ プロセスがキャンセルされました!\n\nいつでも /start で再開できます。 🔄"
|
||||||
"error_add_client" = "⚠️ エラー:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ エラー:\n\n {{ .error }}"
|
||||||
"using_default_value" = "わかりました、デフォルト値を使用します。 😊"
|
"using_default_value" = "わかりました、デフォルト値を使用します。 😊"
|
||||||
"incorrect_input" ="入力が無効です。\nフレーズはスペースなしで続けて入力してください。\n正しい例: aaaaaa\n間違った例: aaa aaa 🚫"
|
"incorrect_input" ="入力が無効です。\nフレーズはスペースなしで続けて入力してください。\n正しい例: aaaaaa\n間違った例: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "本当にいいですか?🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 メール: {{ .ClientEmail }}\n🏁 結果: ✅ 成功"
|
||||||
|
"FailedResetTraffic" = "📧 メール: {{ .ClientEmail }}\n🏁 結果: ❌ 失敗 \n\n🛠️ エラー: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 すべてのクライアントのトラフィックリセットが完了しました。"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,9 @@
|
||||||
"change_password" = "⚙️🔑 パスワード"
|
"change_password" = "⚙️🔑 パスワード"
|
||||||
"change_email" = "⚙️📧 メールアドレス"
|
"change_email" = "⚙️📧 メールアドレス"
|
||||||
"change_comment" = "⚙️💬 コメント"
|
"change_comment" = "⚙️💬 コメント"
|
||||||
|
"ResetAllTraffics" = "すべてのトラフィックをリセット"
|
||||||
|
"SortedTrafficUsageReport" = "ソートされたトラフィック使用レポート"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
"successfulOperation" = "✅ 成功!"
|
"successfulOperation" = "✅ 成功!"
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "Dados totais"
|
"totalData" = "Dados totais"
|
||||||
"sent" = "Enviado"
|
"sent" = "Enviado"
|
||||||
"received" = "Recebido"
|
"received" = "Recebido"
|
||||||
"xraySwitchVersionDialog" = "Alterar Versão do Xray"
|
"xraySwitchVersionDialog" = "Você realmente deseja alterar a versão do Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Tem certeza de que deseja alterar a versão do Xray para"
|
"xraySwitchVersionDialogDesc" = "Isso mudará a versão do Xray para #version#."
|
||||||
|
"xraySwitchVersionPopover" = "Xray atualizado com sucesso"
|
||||||
|
"geofileUpdateDialog" = "Você realmente deseja atualizar o geofile?"
|
||||||
|
"geofileUpdateDialogDesc" = "Isso atualizará o arquivo #filename#."
|
||||||
|
"geofileUpdatePopover" = "Geofile atualizado com sucesso"
|
||||||
"dontRefresh" = "Instalação em andamento, por favor não atualize a página"
|
"dontRefresh" = "Instalação em andamento, por favor não atualize a página"
|
||||||
"logs" = "Logs"
|
"logs" = "Logs"
|
||||||
"config" = "Configuração"
|
"config" = "Configuração"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 Senha Padrão: {{ .ClientPassword }}\n\nDigite sua senha."
|
"pass_prompt" = "🔑 Senha Padrão: {{ .ClientPassword }}\n\nDigite sua senha."
|
||||||
"email_prompt" = "📧 E-mail Padrão: {{ .ClientEmail }}\n\nDigite seu e-mail."
|
"email_prompt" = "📧 E-mail Padrão: {{ .ClientEmail }}\n\nDigite seu e-mail."
|
||||||
"comment_prompt" = "💬 Comentário Padrão: {{ .ClientComment }}\n\nDigite seu comentário."
|
"comment_prompt" = "💬 Comentário Padrão: {{ .ClientComment }}\n\nDigite seu comentário."
|
||||||
"inbound_client_data_id" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!"
|
"inbound_client_data_id" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n🌐 Limite de IP: {{ .IpLimit }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!"
|
||||||
"inbound_client_data_pass" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 Senha: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!"
|
"inbound_client_data_pass" = "🔄 Entrada: {{ .InboundRemark }}\n\n🔑 Senha: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Tráfego: {{ .ClientTraffic }}\n📅 Data de expiração: {{ .ClientExp }}\n🌐 Limite de IP: {{ .IpLimit }}\n💬 Comentário: {{ .ClientComment }}\n\nAgora você pode adicionar o cliente à entrada!"
|
||||||
"cancel" = "❌ Processo Cancelado! \n\nVocê pode iniciar novamente a qualquer momento com /start. 🔄"
|
"cancel" = "❌ Processo Cancelado! \n\nVocê pode iniciar novamente a qualquer momento com /start. 🔄"
|
||||||
"error_add_client" = "⚠️ Erro:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Erro:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Tudo bem, vou manter o valor padrão. 😊"
|
"using_default_value" = "Tudo bem, vou manter o valor padrão. 😊"
|
||||||
"incorrect_input" ="Sua entrada não é válida.\nAs frases devem ser contínuas, sem espaços.\nExemplo correto: aaaaaa\nExemplo incorreto: aaa aaa 🚫"
|
"incorrect_input" ="Sua entrada não é válida.\nAs frases devem ser contínuas, sem espaços.\nExemplo correto: aaaaaa\nExemplo incorreto: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "Você tem certeza? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Resultado: ✅ Sucesso"
|
||||||
|
"FailedResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Resultado: ❌ Falhou \n\n🛠️ Erro: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Processo de redefinição de tráfego concluído para todos os clientes."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 Senha"
|
"change_password" = "⚙️🔑 Senha"
|
||||||
"change_email" = "⚙️📧 E-mail"
|
"change_email" = "⚙️📧 E-mail"
|
||||||
"change_comment" = "⚙️💬 Comentário"
|
"change_comment" = "⚙️💬 Comentário"
|
||||||
|
"ResetAllTraffics" = "Redefinir Todo o Tráfego"
|
||||||
|
"SortedTrafficUsageReport" = "Relatório de Uso de Tráfego Ordenado"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "Общий объем данных"
|
"totalData" = "Общий объем данных"
|
||||||
"sent" = "Отправлено"
|
"sent" = "Отправлено"
|
||||||
"received" = "Получено"
|
"received" = "Получено"
|
||||||
"xraySwitchVersionDialog" = "Переключить версию Xray"
|
"xraySwitchVersionDialog" = "Вы действительно хотите изменить версию Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Вы точно хотите сменить версию Xray?"
|
"xraySwitchVersionDialogDesc" = "Это изменит версию Xray на #version#."
|
||||||
|
"xraySwitchVersionPopover" = "Xray успешно обновлён"
|
||||||
|
"geofileUpdateDialog" = "Вы действительно хотите обновить геофайл?"
|
||||||
|
"geofileUpdateDialogDesc" = "Это обновит файл #filename#."
|
||||||
|
"geofileUpdatePopover" = "Геофайл успешно обновлён"
|
||||||
"dontRefresh" = "Установка в процессе. Не обновляйте страницу"
|
"dontRefresh" = "Установка в процессе. Не обновляйте страницу"
|
||||||
"logs" = "Журнал"
|
"logs" = "Журнал"
|
||||||
"config" = "Конфигурация"
|
"config" = "Конфигурация"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль."
|
"pass_prompt" = "🔑 Стандартный пароль: {{ .ClientPassword }}\n\nВведите ваш пароль."
|
||||||
"email_prompt" = "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email."
|
"email_prompt" = "📧 Стандартный email: {{ .ClientEmail }}\n\nВведите ваш email."
|
||||||
"comment_prompt" = "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий."
|
"comment_prompt" = "💬 Стандартный комментарий: {{ .ClientComment }}\n\nВведите ваш комментарий."
|
||||||
"inbound_client_data_id" = "🔄 Входящие: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата истечения: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента во входящие!"
|
"inbound_client_data_id" = "🔄 Вход: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Почта: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата окончания: {{ .ClientExp }}\n🌐 Лимит IP: {{ .IpLimit }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента во входящий поток!"
|
||||||
"inbound_client_data_pass" = "🔄 Входящие: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата истечения: {{ .ClientExp }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента во входящие!"
|
"inbound_client_data_pass" = "🔄 Вход: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Почта: {{ .ClientEmail }}\n📊 Трафик: {{ .ClientTraffic }}\n📅 Дата окончания: {{ .ClientExp }}\n🌐 Лимит IP: {{ .IpLimit }}\n💬 Комментарий: {{ .ClientComment }}\n\nТеперь вы можете добавить клиента во входящий поток!"
|
||||||
"cancel" = "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄"
|
"cancel" = "❌ Процесс отменён! \n\nВы можете снова начать с /start в любое время. 🔄"
|
||||||
"error_add_client" = "⚠️ Ошибка:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Ошибка:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Хорошо, оставлю значение по умолчанию. 😊"
|
"using_default_value" = "Хорошо, оставлю значение по умолчанию. 😊"
|
||||||
"incorrect_input" ="Ваш ввод недействителен.\nФразы должны быть непрерывными без пробелов.\nПравильный пример: aaaaaa\nНеправильный пример: aaa aaa 🚫"
|
"incorrect_input" ="Ваш ввод недействителен.\nФразы должны быть непрерывными без пробелов.\nПравильный пример: aaaaaa\nНеправильный пример: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "Вы уверены? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 Почта: {{ .ClientEmail }}\n🏁 Результат: ✅ Успешно"
|
||||||
|
"FailedResetTraffic" = "📧 Почта: {{ .ClientEmail }}\n🏁 Результат: ❌ Неудача \n\n🛠️ Ошибка: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Сброс трафика завершён для всех клиентов."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 Пароль"
|
"change_password" = "⚙️🔑 Пароль"
|
||||||
"change_email" = "⚙️📧 Электронная почта"
|
"change_email" = "⚙️📧 Электронная почта"
|
||||||
"change_comment" = "⚙️💬 Комментарий"
|
"change_comment" = "⚙️💬 Комментарий"
|
||||||
|
"ResetAllTraffics" = "Сбросить весь трафик"
|
||||||
|
"SortedTrafficUsageReport" = "Отсортированный отчет об использовании трафика"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "Toplam veri"
|
"totalData" = "Toplam veri"
|
||||||
"sent" = "Gönderilen"
|
"sent" = "Gönderilen"
|
||||||
"received" = "Alınan"
|
"received" = "Alınan"
|
||||||
"xraySwitchVersionDialog" = "Xray Sürümünü Değiştir"
|
"xraySwitchVersionDialog" = "Xray sürümünü gerçekten değiştirmek istiyor musunuz?"
|
||||||
"xraySwitchVersionDialogDesc" = "Xray sürümünü değiştirmek istediğinizden emin misiniz"
|
"xraySwitchVersionDialogDesc" = "Bu işlem Xray sürümünü #version# olarak değiştirecektir."
|
||||||
|
"xraySwitchVersionPopover" = "Xray başarıyla güncellendi"
|
||||||
|
"geofileUpdateDialog" = "Geofile'ı gerçekten güncellemek istiyor musunuz?"
|
||||||
|
"geofileUpdateDialogDesc" = "Bu işlem #filename# dosyasını güncelleyecektir."
|
||||||
|
"geofileUpdatePopover" = "Geofile başarıyla güncellendi"
|
||||||
"dontRefresh" = "Kurulum devam ediyor, lütfen bu sayfayı yenilemeyin"
|
"dontRefresh" = "Kurulum devam ediyor, lütfen bu sayfayı yenilemeyin"
|
||||||
"logs" = "Günlükler"
|
"logs" = "Günlükler"
|
||||||
"config" = "Yapılandırma"
|
"config" = "Yapılandırma"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 Varsayılan Şifre: {{ .ClientPassword }}\n\nŞifrenizi girin."
|
"pass_prompt" = "🔑 Varsayılan Şifre: {{ .ClientPassword }}\n\nŞifrenizi girin."
|
||||||
"email_prompt" = "📧 Varsayılan E-posta: {{ .ClientEmail }}\n\nE-postanızı girin."
|
"email_prompt" = "📧 Varsayılan E-posta: {{ .ClientEmail }}\n\nE-postanızı girin."
|
||||||
"comment_prompt" = "💬 Varsayılan Yorum: {{ .ClientComment }}\n\nYorumunuzu girin."
|
"comment_prompt" = "💬 Varsayılan Yorum: {{ .ClientComment }}\n\nYorumunuzu girin."
|
||||||
"inbound_client_data_id" = "🔄 Giriş: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 E-posta: {{ .ClientEmail }}\n📊 Trafik: {{ .ClientTraffic }}\n📅 Son Kullanım Tarihi: {{ .ClientExp }}\n💬 Yorum: {{ .ClientComment }}\n\nŞimdi müşteriyi girişe ekleyebilirsiniz!"
|
"inbound_client_data_id" = "🔄 Giriş: {{ .InboundRemark }}\n\n🔑 Kimlik: {{ .ClientId }}\n📧 E-posta: {{ .ClientEmail }}\n📊 Trafik: {{ .ClientTraffic }}\n📅 Bitiş Tarihi: {{ .ClientExp }}\n🌐 IP Sınırı: {{ .IpLimit }}\n💬 Yorum: {{ .ClientComment }}\n\nArtık bu müşteriyi girişe ekleyebilirsin!"
|
||||||
"inbound_client_data_pass" = "🔄 Giriş: {{ .InboundRemark }}\n\n🔑 Şifre: {{ .ClientPass }}\n📧 E-posta: {{ .ClientEmail }}\n📊 Trafik: {{ .ClientTraffic }}\n📅 Son Kullanım Tarihi: {{ .ClientExp }}\n💬 Yorum: {{ .ClientComment }}\n\nŞimdi müşteriyi girişe ekleyebilirsiniz!"
|
"inbound_client_data_pass" = "🔄 Giriş: {{ .InboundRemark }}\n\n🔑 Şifre: {{ .ClientPass }}\n📧 E-posta: {{ .ClientEmail }}\n📊 Trafik: {{ .ClientTraffic }}\n📅 Bitiş Tarihi: {{ .ClientExp }}\n🌐 IP Sınırı: {{ .IpLimit }}\n💬 Yorum: {{ .ClientComment }}\n\nArtık bu müşteriyi girişe ekleyebilirsin!"
|
||||||
"cancel" = "❌ İşlem iptal edildi! \n\nİstediğiniz zaman /start ile yeniden başlayabilirsiniz. 🔄"
|
"cancel" = "❌ İşlem iptal edildi! \n\nİstediğiniz zaman /start ile yeniden başlayabilirsiniz. 🔄"
|
||||||
"error_add_client" = "⚠️ Hata:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Hata:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Tamam, varsayılan değeri kullanacağım. 😊"
|
"using_default_value" = "Tamam, varsayılan değeri kullanacağım. 😊"
|
||||||
"incorrect_input" ="Girdiğiniz değer geçerli değil.\nKelime öbekleri boşluk olmadan devam etmelidir.\nDoğru örnek: aaaaaa\nYanlış örnek: aaa aaa 🚫"
|
"incorrect_input" ="Girdiğiniz değer geçerli değil.\nKelime öbekleri boşluk olmadan devam etmelidir.\nDoğru örnek: aaaaaa\nYanlış örnek: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "Emin misin? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 E-posta: {{ .ClientEmail }}\n🏁 Sonuç: ✅ Başarılı"
|
||||||
|
"FailedResetTraffic" = "📧 E-posta: {{ .ClientEmail }}\n🏁 Sonuç: ❌ Başarısız \n\n🛠️ Hata: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Tüm müşteriler için trafik sıfırlama işlemi tamamlandı."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 Şifre"
|
"change_password" = "⚙️🔑 Şifre"
|
||||||
"change_email" = "⚙️📧 E-posta"
|
"change_email" = "⚙️📧 E-posta"
|
||||||
"change_comment" = "⚙️💬 Yorum"
|
"change_comment" = "⚙️💬 Yorum"
|
||||||
|
"ResetAllTraffics" = "Tüm Trafikleri Sıfırla"
|
||||||
|
"SortedTrafficUsageReport" = "Sıralı Trafik Kullanım Raporu"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "Загальний обсяг даних"
|
"totalData" = "Загальний обсяг даних"
|
||||||
"sent" = "Відправлено"
|
"sent" = "Відправлено"
|
||||||
"received" = "Отримано"
|
"received" = "Отримано"
|
||||||
"xraySwitchVersionDialog" = "Змінити версію Xray"
|
"xraySwitchVersionDialog" = "Ви дійсно хочете змінити версію Xray?"
|
||||||
"xraySwitchVersionDialogDesc" = "Ви впевнені, що бажаєте змінити версію Xray на"
|
"xraySwitchVersionDialogDesc" = "Це змінить версію Xray на #version#."
|
||||||
|
"xraySwitchVersionPopover" = "Xray успішно оновлено"
|
||||||
|
"geofileUpdateDialog" = "Ви дійсно хочете оновити геофайл?"
|
||||||
|
"geofileUpdateDialogDesc" = "Це оновить файл #filename#."
|
||||||
|
"geofileUpdatePopover" = "Геофайл успішно оновлено"
|
||||||
"dontRefresh" = "Інсталяція триває, будь ласка, не оновлюйте цю сторінку"
|
"dontRefresh" = "Інсталяція триває, будь ласка, не оновлюйте цю сторінку"
|
||||||
"logs" = "Журнали"
|
"logs" = "Журнали"
|
||||||
"config" = "Конфігурація"
|
"config" = "Конфігурація"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 Стандартний пароль: {{ .ClientPassword }}\n\nВведіть ваш пароль."
|
"pass_prompt" = "🔑 Стандартний пароль: {{ .ClientPassword }}\n\nВведіть ваш пароль."
|
||||||
"email_prompt" = "📧 Стандартний email: {{ .ClientEmail }}\n\nВведіть ваш email."
|
"email_prompt" = "📧 Стандартний email: {{ .ClientEmail }}\n\nВведіть ваш email."
|
||||||
"comment_prompt" = "💬 Стандартний коментар: {{ .ClientComment }}\n\nВведіть ваш коментар."
|
"comment_prompt" = "💬 Стандартний коментар: {{ .ClientComment }}\n\nВведіть ваш коментар."
|
||||||
"inbound_client_data_id" = "🔄 Вхідні: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафік: {{ .ClientTraffic }}\n📅 Термін придатності: {{ .ClientExp }}\n💬 Коментар: {{ .ClientComment }}\n\nТепер ви можете додати клієнта до вхідних!"
|
"inbound_client_data_id" = "🔄 Вхід: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Електронна пошта: {{ .ClientEmail }}\n📊 Трафік: {{ .ClientTraffic }}\n📅 Дата завершення: {{ .ClientExp }}\n🌐 Обмеження IP: {{ .IpLimit }}\n💬 Коментар: {{ .ClientComment }}\n\nТепер ви можете додати клієнта до вхідного з'єднання!"
|
||||||
"inbound_client_data_pass" = "🔄 Вхідні: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Трафік: {{ .ClientTraffic }}\n📅 Термін придатності: {{ .ClientExp }}\n💬 Коментар: {{ .ClientComment }}\n\nТепер ви можете додати клієнта до вхідних!"
|
"inbound_client_data_pass" = "🔄 Вхід: {{ .InboundRemark }}\n\n🔑 Пароль: {{ .ClientPass }}\n📧 Електронна пошта: {{ .ClientEmail }}\n📊 Трафік: {{ .ClientTraffic }}\n📅 Дата завершення: {{ .ClientExp }}\n🌐 Обмеження IP: {{ .IpLimit }}\n💬 Коментар: {{ .ClientComment }}\n\nТепер ви можете додати клієнта до вхідного з'єднання!"
|
||||||
"cancel" = "❌ Процес скасовано! \n\nВи можете знову розпочати, використовуючи /start у будь-який час. 🔄"
|
"cancel" = "❌ Процес скасовано! \n\nВи можете знову розпочати, використовуючи /start у будь-який час. 🔄"
|
||||||
"error_add_client" = "⚠️ Помилка:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Помилка:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Гаразд, залишу значення за замовчуванням. 😊"
|
"using_default_value" = "Гаразд, залишу значення за замовчуванням. 😊"
|
||||||
"incorrect_input" ="Ваш ввід невірний.\nФрази повинні бути без пробілів.\nПравильний приклад: aaaaaa\nНеправильний приклад: aaa aaa 🚫"
|
"incorrect_input" ="Ваш ввід невірний.\nФрази повинні бути без пробілів.\nПравильний приклад: aaaaaa\nНеправильний приклад: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "Ви впевнені? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 Електронна пошта: {{ .ClientEmail }}\n🏁 Результат: ✅ Успішно"
|
||||||
|
"FailedResetTraffic" = "📧 Електронна пошта: {{ .ClientEmail }}\n🏁 Результат: ❌ Невдача \n\n🛠️ Помилка: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Процес скидання трафіку завершено для всіх клієнтів."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 Пароль"
|
"change_password" = "⚙️🔑 Пароль"
|
||||||
"change_email" = "⚙️📧 Електронна пошта"
|
"change_email" = "⚙️📧 Електронна пошта"
|
||||||
"change_comment" = "⚙️💬 Коментар"
|
"change_comment" = "⚙️💬 Коментар"
|
||||||
|
"ResetAllTraffics" = "Скинути весь трафік"
|
||||||
|
"SortedTrafficUsageReport" = "Відсортований звіт про використання трафіку"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "Tổng dữ liệu"
|
"totalData" = "Tổng dữ liệu"
|
||||||
"sent" = "Đã gửi"
|
"sent" = "Đã gửi"
|
||||||
"received" = "Đã nhận"
|
"received" = "Đã nhận"
|
||||||
"xraySwitchVersionDialog" = "Chuyển đổi Phiên bản Xray"
|
"xraySwitchVersionDialog" = "Bạn có chắc chắn muốn thay đổi phiên bản Xray không?"
|
||||||
"xraySwitchVersionDialogDesc" = "Bạn có chắc chắn muốn chuyển đổi phiên bản Xray sang"
|
"xraySwitchVersionDialogDesc" = "Hành động này sẽ thay đổi phiên bản Xray thành #version#."
|
||||||
|
"xraySwitchVersionPopover" = "Xray đã được cập nhật thành công"
|
||||||
|
"geofileUpdateDialog" = "Bạn có chắc chắn muốn cập nhật geofile không?"
|
||||||
|
"geofileUpdateDialogDesc" = "Hành động này sẽ cập nhật tệp #filename#."
|
||||||
|
"geofileUpdatePopover" = "Geofile đã được cập nhật thành công"
|
||||||
"dontRefresh" = "Đang tiến hành cài đặt, vui lòng không làm mới trang này."
|
"dontRefresh" = "Đang tiến hành cài đặt, vui lòng không làm mới trang này."
|
||||||
"logs" = "Nhật ký"
|
"logs" = "Nhật ký"
|
||||||
"config" = "Cấu hình"
|
"config" = "Cấu hình"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 Mật khẩu mặc định: {{ .ClientPassword }}\n\nVui lòng nhập mật khẩu của bạn."
|
"pass_prompt" = "🔑 Mật khẩu mặc định: {{ .ClientPassword }}\n\nVui lòng nhập mật khẩu của bạn."
|
||||||
"email_prompt" = "📧 Email mặc định: {{ .ClientEmail }}\n\nVui lòng nhập email của bạn."
|
"email_prompt" = "📧 Email mặc định: {{ .ClientEmail }}\n\nVui lòng nhập email của bạn."
|
||||||
"comment_prompt" = "💬 Bình luận mặc định: {{ .ClientComment }}\n\nVui lòng nhập bình luận của bạn."
|
"comment_prompt" = "💬 Bình luận mặc định: {{ .ClientComment }}\n\nVui lòng nhập bình luận của bạn."
|
||||||
"inbound_client_data_id" = "🔄 Vào: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Lưu lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n💬 Bình luận: {{ .ClientComment }}\n\nBạn có thể thêm khách hàng vào vào ngay bây giờ!"
|
"inbound_client_data_id" = "🔄 Kết nối vào: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 Email: {{ .ClientEmail }}\n📊 Dung lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n🌐 Giới hạn IP: {{ .IpLimit }}\n💬 Ghi chú: {{ .ClientComment }}\n\nBây giờ bạn có thể thêm khách hàng vào inbound!"
|
||||||
"inbound_client_data_pass" = "🔄 Vào: {{ .InboundRemark }}\n\n🔑 Mật khẩu: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Lưu lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n💬 Bình luận: {{ .ClientComment }}\n\nBạn có thể thêm khách hàng vào vào ngay bây giờ!"
|
"inbound_client_data_pass" = "🔄 Kết nối vào: {{ .InboundRemark }}\n\n🔑 Mật khẩu: {{ .ClientPass }}\n📧 Email: {{ .ClientEmail }}\n📊 Dung lượng: {{ .ClientTraffic }}\n📅 Ngày hết hạn: {{ .ClientExp }}\n🌐 Giới hạn IP: {{ .IpLimit }}\n💬 Ghi chú: {{ .ClientComment }}\n\nBây giờ bạn có thể thêm khách hàng vào inbound!"
|
||||||
"cancel" = "❌ Quá trình đã bị hủy! \n\nBạn có thể bắt đầu lại bất cứ lúc nào bằng cách nhập /start. 🔄"
|
"cancel" = "❌ Quá trình đã bị hủy! \n\nBạn có thể bắt đầu lại bất cứ lúc nào bằng cách nhập /start. 🔄"
|
||||||
"error_add_client" = "⚠️ Lỗi:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ Lỗi:\n\n {{ .error }}"
|
||||||
"using_default_value" = "Được rồi, tôi sẽ sử dụng giá trị mặc định. 😊"
|
"using_default_value" = "Được rồi, tôi sẽ sử dụng giá trị mặc định. 😊"
|
||||||
"incorrect_input" ="Dữ liệu bạn nhập không hợp lệ.\nCác chuỗi phải liền mạch và không có dấu cách.\nVí dụ đúng: aaaaaa\nVí dụ sai: aaa aaa 🚫"
|
"incorrect_input" ="Dữ liệu bạn nhập không hợp lệ.\nCác chuỗi phải liền mạch và không có dấu cách.\nVí dụ đúng: aaaaaa\nVí dụ sai: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "Bạn có chắc không? 🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Kết quả: ✅ Thành công"
|
||||||
|
"FailedResetTraffic" = "📧 Email: {{ .ClientEmail }}\n🏁 Kết quả: ❌ Thất bại \n\n🛠️ Lỗi: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 Quá trình đặt lại lưu lượng đã hoàn tất cho tất cả khách hàng."
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 Mật Khẩu"
|
"change_password" = "⚙️🔑 Mật Khẩu"
|
||||||
"change_email" = "⚙️📧 Email"
|
"change_email" = "⚙️📧 Email"
|
||||||
"change_comment" = "⚙️💬 Bình Luận"
|
"change_comment" = "⚙️💬 Bình Luận"
|
||||||
|
"ResetAllTraffics" = "Đặt lại tất cả lưu lượng"
|
||||||
|
"SortedTrafficUsageReport" = "Báo cáo sử dụng lưu lượng đã sắp xếp"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "总数据"
|
"totalData" = "总数据"
|
||||||
"sent" = "已发送"
|
"sent" = "已发送"
|
||||||
"received" = "已接收"
|
"received" = "已接收"
|
||||||
"xraySwitchVersionDialog" = "切换 Xray 版本"
|
"xraySwitchVersionDialog" = "您确定要更改Xray版本吗?"
|
||||||
"xraySwitchVersionDialogDesc" = "是否切换 Xray 版本至"
|
"xraySwitchVersionDialogDesc" = "这将把Xray版本更改为#version#。"
|
||||||
|
"xraySwitchVersionPopover" = "Xray 更新成功"
|
||||||
|
"geofileUpdateDialog" = "您确定要更新地理文件吗?"
|
||||||
|
"geofileUpdateDialogDesc" = "这将更新 #filename# 文件。"
|
||||||
|
"geofileUpdatePopover" = "地理文件更新成功"
|
||||||
"dontRefresh" = "安装中,请勿刷新此页面"
|
"dontRefresh" = "安装中,请勿刷新此页面"
|
||||||
"logs" = "日志"
|
"logs" = "日志"
|
||||||
"config" = "配置"
|
"config" = "配置"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 默认密码: {{ .ClientPassword }}\n\n请输入您的密码。"
|
"pass_prompt" = "🔑 默认密码: {{ .ClientPassword }}\n\n请输入您的密码。"
|
||||||
"email_prompt" = "📧 默认邮箱: {{ .ClientEmail }}\n\n请输入您的邮箱。"
|
"email_prompt" = "📧 默认邮箱: {{ .ClientEmail }}\n\n请输入您的邮箱。"
|
||||||
"comment_prompt" = "💬 默认评论: {{ .ClientComment }}\n\n请输入您的评论。"
|
"comment_prompt" = "💬 默认评论: {{ .ClientComment }}\n\n请输入您的评论。"
|
||||||
"inbound_client_data_id" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 过期日期: {{ .ClientExp }}\n💬 评论: {{ .ClientComment }}\n\n您现在可以将客户添加到入站!"
|
"inbound_client_data_id" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日期: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 备注: {{ .ClientComment }}\n\n你现在可以将客户添加到入站了!"
|
||||||
"inbound_client_data_pass" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 密码: {{ .ClientPass }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 过期日期: {{ .ClientExp }}\n💬 评论: {{ .ClientComment }}\n\n您现在可以将客户添加到入站!"
|
"inbound_client_data_pass" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 密码: {{ .ClientPass }}\n📧 邮箱: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日期: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 备注: {{ .ClientComment }}\n\n你现在可以将客户添加到入站了!"
|
||||||
"cancel" = "❌ 进程已取消!\n\n您可以随时使用 /start 重新开始。 🔄"
|
"cancel" = "❌ 进程已取消!\n\n您可以随时使用 /start 重新开始。 🔄"
|
||||||
"error_add_client" = "⚠️ 错误:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ 错误:\n\n {{ .error }}"
|
||||||
"using_default_value" = "好的,我会使用默认值。 😊"
|
"using_default_value" = "好的,我会使用默认值。 😊"
|
||||||
"incorrect_input" ="您的输入无效。\n短语应连续输入,不能有空格。\n正确示例: aaaaaa\n错误示例: aaa aaa 🚫"
|
"incorrect_input" ="您的输入无效。\n短语应连续输入,不能有空格。\n正确示例: aaaaaa\n错误示例: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "你确定吗?🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 邮箱: {{ .ClientEmail }}\n🏁 结果: ✅ 成功"
|
||||||
|
"FailedResetTraffic" = "📧 邮箱: {{ .ClientEmail }}\n🏁 结果: ❌ 失败 \n\n🛠️ 错误: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 所有客户的流量重置已完成。"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 密码"
|
"change_password" = "⚙️🔑 密码"
|
||||||
"change_email" = "⚙️📧 邮箱"
|
"change_email" = "⚙️📧 邮箱"
|
||||||
"change_comment" = "⚙️💬 评论"
|
"change_comment" = "⚙️💬 评论"
|
||||||
|
"ResetAllTraffics" = "重置所有流量"
|
||||||
|
"SortedTrafficUsageReport" = "排序的流量使用报告"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
|
@ -124,8 +124,12 @@
|
||||||
"totalData" = "總數據"
|
"totalData" = "總數據"
|
||||||
"sent" = "已發送"
|
"sent" = "已發送"
|
||||||
"received" = "已接收"
|
"received" = "已接收"
|
||||||
"xraySwitchVersionDialog" = "切換 Xray 版本"
|
"xraySwitchVersionDialog" = "您確定要變更Xray版本嗎?"
|
||||||
"xraySwitchVersionDialogDesc" = "是否切換 Xray 版本至"
|
"xraySwitchVersionDialogDesc" = "這將會把Xray版本變更為#version#。"
|
||||||
|
"xraySwitchVersionPopover" = "Xray 更新成功"
|
||||||
|
"geofileUpdateDialog" = "您確定要更新地理檔案嗎?"
|
||||||
|
"geofileUpdateDialogDesc" = "這將更新 #filename# 檔案。"
|
||||||
|
"geofileUpdatePopover" = "地理檔案更新成功"
|
||||||
"dontRefresh" = "安裝中,請勿重新整理此頁面"
|
"dontRefresh" = "安裝中,請勿重新整理此頁面"
|
||||||
"logs" = "日誌"
|
"logs" = "日誌"
|
||||||
"config" = "配置"
|
"config" = "配置"
|
||||||
|
@ -603,12 +607,16 @@
|
||||||
"pass_prompt" = "🔑 預設密碼: {{ .ClientPassword }}\n\n請輸入您的密碼。"
|
"pass_prompt" = "🔑 預設密碼: {{ .ClientPassword }}\n\n請輸入您的密碼。"
|
||||||
"email_prompt" = "📧 預設電子郵件: {{ .ClientEmail }}\n\n請輸入您的電子郵件。"
|
"email_prompt" = "📧 預設電子郵件: {{ .ClientEmail }}\n\n請輸入您的電子郵件。"
|
||||||
"comment_prompt" = "💬 預設評論: {{ .ClientComment }}\n\n請輸入您的評論。"
|
"comment_prompt" = "💬 預設評論: {{ .ClientComment }}\n\n請輸入您的評論。"
|
||||||
"inbound_client_data_id" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n💬 評論: {{ .ClientComment }}\n\n您現在可以將客戶新增至入站!"
|
"inbound_client_data_id" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 ID: {{ .ClientId }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 備註: {{ .ClientComment }}\n\n你現在可以將客戶加入入站了!"
|
||||||
"inbound_client_data_pass" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 密碼: {{ .ClientPass }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n💬 評論: {{ .ClientComment }}\n\n您現在可以將客戶新增至入站!"
|
"inbound_client_data_pass" = "🔄 入站: {{ .InboundRemark }}\n\n🔑 密碼: {{ .ClientPass }}\n📧 電子郵件: {{ .ClientEmail }}\n📊 流量: {{ .ClientTraffic }}\n📅 到期日: {{ .ClientExp }}\n🌐 IP 限制: {{ .IpLimit }}\n💬 備註: {{ .ClientComment }}\n\n你現在可以將客戶加入入站了!"
|
||||||
"cancel" = "❌ 程序已取消!\n\n您可以隨時使用 /start 重新開始。 🔄"
|
"cancel" = "❌ 程序已取消!\n\n您可以隨時使用 /start 重新開始。 🔄"
|
||||||
"error_add_client" = "⚠️ 錯誤:\n\n {{ .error }}"
|
"error_add_client" = "⚠️ 錯誤:\n\n {{ .error }}"
|
||||||
"using_default_value" = "好的,我會使用預設值。 😊"
|
"using_default_value" = "好的,我會使用預設值。 😊"
|
||||||
"incorrect_input" ="您的輸入無效。\n短語應連續輸入,不能有空格。\n正確示例: aaaaaa\n錯誤示例: aaa aaa 🚫"
|
"incorrect_input" ="您的輸入無效。\n短語應連續輸入,不能有空格。\n正確示例: aaaaaa\n錯誤示例: aaa aaa 🚫"
|
||||||
|
"AreYouSure" = "你確定嗎?🤔"
|
||||||
|
"SuccessResetTraffic" = "📧 電子郵件: {{ .ClientEmail }}\n🏁 結果: ✅ 成功"
|
||||||
|
"FailedResetTraffic" = "📧 電子郵件: {{ .ClientEmail }}\n🏁 結果: ❌ 失敗 \n\n🛠️ 錯誤: [ {{ .ErrorMessage }} ]"
|
||||||
|
"FinishProcess" = "🔚 所有客戶的流量重置已完成。"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.buttons]
|
[tgbot.buttons]
|
||||||
|
@ -653,6 +661,8 @@
|
||||||
"change_password" = "⚙️🔑 密碼"
|
"change_password" = "⚙️🔑 密碼"
|
||||||
"change_email" = "⚙️📧 電子郵件"
|
"change_email" = "⚙️📧 電子郵件"
|
||||||
"change_comment" = "⚙️💬 評論"
|
"change_comment" = "⚙️💬 評論"
|
||||||
|
"ResetAllTraffics" = "重設所有流量"
|
||||||
|
"SortedTrafficUsageReport" = "排序過的流量使用報告"
|
||||||
|
|
||||||
|
|
||||||
[tgbot.answers]
|
[tgbot.answers]
|
||||||
|
|
Loading…
Reference in a new issue