1
0
Alireza Ahmadi 1 жил өмнө
parent
commit
c980a06969

+ 29 - 11
sub/subService.go

@@ -19,6 +19,7 @@ import (
 type SubService struct {
 	address        string
 	showInfo       bool
+	remarkModel    string
 	inboundService service.InboundService
 	settingService service.SettingService
 }
@@ -34,6 +35,10 @@ func (s *SubService) GetSubs(subId string, host string, showInfo bool) ([]string
 	if err != nil {
 		return nil, nil, err
 	}
+	s.remarkModel, err = s.settingService.GetRemarkModel()
+	if err != nil {
+		s.remarkModel = "-ieo"
+	}
 	for _, inbound := range inbounds {
 		clients, err := s.inboundService.GetClients(inbound)
 		if err != nil {
@@ -857,17 +862,30 @@ func (s *SubService) genShadowsocksLink(inbound *model.Inbound, email string) st
 }
 
 func (s *SubService) genRemark(inbound *model.Inbound, email string, extra string) string {
-	var remark []string
+	separationChar := string(s.remarkModel[0])
+	orderChars := s.remarkModel[1:]
+	orders := map[byte]string{
+		'i': "",
+		'e': "",
+		'o': "",
+	}
 	if len(email) > 0 {
-		if len(inbound.Remark) > 0 {
-			remark = append(remark, inbound.Remark)
-		}
-		remark = append(remark, email)
-		if len(extra) > 0 {
-			remark = append(remark, extra)
+		orders['e'] = email
+	}
+	if len(inbound.Remark) > 0 {
+		orders['i'] = inbound.Remark
+	}
+	if len(extra) > 0 {
+		orders['e'] = extra
+	}
+
+	var remark []string
+	for i := 0; i < len(orderChars); i++ {
+		char := orderChars[i]
+		order, exists := orders[char]
+		if exists && order != "" {
+			remark = append(remark, order)
 		}
-	} else {
-		return inbound.Remark
 	}
 
 	if s.showInfo {
@@ -884,7 +902,7 @@ func (s *SubService) genRemark(inbound *model.Inbound, email string, extra strin
 		// Get remained days
 		if statsExist {
 			if !stats.Enable {
-				return fmt.Sprintf("⛔️N/A-%s", strings.Join(remark, "-"))
+				return fmt.Sprintf("⛔️N/A%s%s", separationChar, strings.Join(remark, separationChar))
 			}
 			if vol := stats.Total - (stats.Up + stats.Down); vol > 0 {
 				remark = append(remark, fmt.Sprintf("%s%s", common.FormatTraffic(vol), "📊"))
@@ -898,7 +916,7 @@ func (s *SubService) genRemark(inbound *model.Inbound, email string, extra strin
 			}
 		}
 	}
-	return strings.Join(remark, " : ")
+	return strings.Join(remark, separationChar)
 }
 
 func searchKey(data interface{}, key string) (interface{}, bool) {

+ 2 - 2
web/assets/js/model/dbinbound.js

@@ -137,8 +137,8 @@ class DBInbound {
         }
     }
     
-	get genInboundLinks() {
+	genInboundLinks() {
         const inbound = this.toInbound();
-        return inbound.genInboundLinks(this.remark);
+        return inbound.genInboundLinks(this.remark,remarkModel);
     }
 }

+ 1 - 0
web/assets/js/model/setting.js

@@ -11,6 +11,7 @@ class AllSetting {
         this.pageSize = 0;
         this.expireDiff = "";
         this.trafficDiff = "";
+        this.remarkModel = "-ieo";
         this.tgBotEnable = false;
         this.tgBotToken = "";
         this.tgBotChatId = "";

+ 14 - 6
web/assets/js/model/xray.js

@@ -1566,20 +1566,28 @@ class Inbound extends XrayCommonClass {
         }
     }
 
-    genAllLinks(remark='', client){
+    genAllLinks(remark='', remarkModel = '-ieo', client){
         let result = [];
         let email = client ? client.email : '';
         let addr = !ObjectUtil.isEmpty(this.listen) && this.listen !== "0.0.0.0" ? this.listen : location.hostname;
-        let port = this.port
+        let port = this.port;
+        const separationChar = remarkModel.charAt(0);
+        const orderChars = remarkModel.slice(1);
+        let orders = {
+            'i': remark,
+            'e': client ? client.email : '',
+            'o': '',
+          };
         if(ObjectUtil.isArrEmpty(this.stream.externalProxy)){
-            let r = [remark, email].filter(x => x.length > 0).join('-');
+            let r = orderChars.split('').map(char => orders[char]).filter(x => x.length > 0).join(separationChar);
             result.push({
                 remark: r,
                 link: this.genLink(addr, port, 'same', r, client)
             });
         } else {
             this.stream.externalProxy.forEach((ep) => {
-                let r = [remark, email, ep.remark].filter(x => x.length > 0).join('-')
+                orders['o'] = ep.remark;
+                let r = orderChars.split('').map(char => orders[char]).filter(x => x.length > 0).join(separationChar);
                 result.push({
                     remark: r,
                     link: this.genLink(ep.dest, ep.port, ep.forceTls, r, client)
@@ -1589,11 +1597,11 @@ class Inbound extends XrayCommonClass {
         return result;
     }
 
-    genInboundLinks(remark = '') {
+    genInboundLinks(remark = '', remarkModel = '-ieo') {
         if(this.clients){
            let links = [];
            this.clients.forEach((client) => {
-                genAllLinks(remark,client).forEach(l => {
+                genAllLinks(remark,remarkModel,client).forEach(l => {
                     links.push(l.link);
                 })
             });

+ 1 - 0
web/entity/entity.go

@@ -25,6 +25,7 @@ type AllSetting struct {
 	PageSize         int    `json:"pageSize" form:"pageSize"`
 	ExpireDiff       int    `json:"expireDiff" form:"expireDiff"`
 	TrafficDiff      int    `json:"trafficDiff" form:"trafficDiff"`
+	RemarkModel      string `json:"remarkModel" form:"remarkModel"`
 	TgBotEnable      bool   `json:"tgBotEnable" form:"tgBotEnable"`
 	TgBotToken       string `json:"tgBotToken" form:"tgBotToken"`
 	TgBotChatId      string `json:"tgBotChatId" form:"tgBotChatId"`

+ 1 - 1
web/html/common/qrcode_modal.html

@@ -35,7 +35,7 @@
             this.client = client;
             this.subId = '';
             this.qrcodes = [];
-            this.inbound.genAllLinks(this.dbInbound.remark, client).forEach(l => {
+            this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, client).forEach(l => {
                 this.qrcodes.push({
                     remark: l.remark,
                     link: l.link

+ 1 - 1
web/html/xui/inbound_info_modal.html

@@ -264,7 +264,7 @@
             this.clientSettings = this.inbound.clients ? this.inbound.clients[index] : null;
             this.isExpired = this.inbound.clients ? this.inbound.isExpiry(index): this.dbInbound.isExpiry;
             this.clientStats = this.inbound.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : [];
-            this.links = this.inbound.genAllLinks(this.dbInbound.remark, this.clientSettings);
+            this.links = this.inbound.genAllLinks(this.dbInbound.remark, app.remarkModel, this.clientSettings);
             if (this.clientSettings) {
                 if (this.clientSettings.subId) {
                     this.subLink = this.genSubLink(this.clientSettings.subId);

+ 3 - 1
web/html/xui/inbounds.html

@@ -556,6 +556,7 @@
                 enable : false,
                 subURI : ''
             },
+            remarkModel: '-ieo',
             tgBotEnable: false,
             pageSize: 0,
             isMobile: window.innerWidth <= 768,
@@ -600,6 +601,7 @@
                         subURI: subURI
                     };
                     this.pageSize = pageSize;
+                    this.remarkModel = remarkModel;
                 }
             },
             setInbounds(dbInbounds) {
@@ -1191,7 +1193,7 @@
             exportAllLinks() {
                 let copyText = [];
                 for (const dbInbound of this.dbInbounds) {
-                    copyText.push(dbInbound.genInboundLinks);
+                    copyText.push(dbInbound.genInboundLinks(this.remarkModel));
                 }
                 txtModal.show('{{ i18n "pages.inbounds.export"}}', copyText.join('\r\n'), 'All-Inbounds');
             },

+ 48 - 0
web/html/xui/settings.html

@@ -105,6 +105,28 @@
                     <a-tabs default-active-key="1">
                         <a-tab-pane key="1" tab='{{ i18n "pages.settings.panelSettings"}}'>
                             <a-list item-layout="horizontal">
+                                <a-list-item>
+                                    <a-row style="padding: 20px">
+                                        <a-col :lg="24" :xl="12">
+                                            <a-list-item-meta title='{{ i18n "pages.settings.remarkModel"}}'>
+                                                <template slot="description">{{ i18n "pages.settings.sampleRemark"}}: <i>#[[ remarkSample ]]</i></template>
+                                            </a-list-item-meta>
+                                        </a-col>
+                                        <a-col :lg="24" :xl="12">
+                                            <a-input-group style="width: 100%;">
+                                                <a-select style="padding-right: .5rem; min-width: 80%; width: auto;"
+                                                    mode="multiple"
+                                                    v-model="remarkModel"
+                                                    :dropdown-class-name="themeSwitcher.currentTheme">
+                                                    <a-select-option v-for="(value, key) in remarkModels" :value="key">[[ value ]]</a-select-option>
+                                                </a-select>
+                                                <a-select style="width: 20%;" v-model="remarkSeparator" :dropdown-class-name="themeSwitcher.currentTheme">
+                                                    <a-select-option v-for="key in remarkSeparators" :value="key">[[ key ]]</a-select-option>
+                                                </a-select>
+                                            </a-input-group>
+                                        </a-col>
+                                    </a-row>
+                                </a-list-item>
                                 <setting-list-item type="text" title='{{ i18n "pages.settings.panelListeningIP"}}' desc='{{ i18n "pages.settings.panelListeningIPDesc"}}' v-model="allSetting.webListen"></setting-list-item>
                                 <setting-list-item type="text" title='{{ i18n "pages.settings.panelListeningDomain"}}' desc='{{ i18n "pages.settings.panelListeningDomainDesc"}}' v-model="allSetting.webDomain"></setting-list-item>
                                 <setting-list-item type="number" title='{{ i18n "pages.settings.panelPort"}}' desc='{{ i18n "pages.settings.panelPortDesc"}}' v-model="allSetting.webPort" :min="0"></setting-list-item>
@@ -272,6 +294,31 @@
             saveBtnDisable: true,
             user: {},
             lang: getLang(),
+            showAlert: false,
+            remarkModels: {i:'Inbound',e:'Email',o:'Other'},
+            remarkSeparators: [' ','-','_','@',':','~','|',',','.','/'],
+            remarkSample: '',
+            get remarkModel() {
+                rm = this.allSetting.remarkModel;
+                return rm.length>1 ? rm.substring(1).split('') : [];
+            },
+            set remarkModel(value) {
+                rs = this.allSetting.remarkModel[0];
+                this.allSetting.remarkModel = rs + value.join('');
+                this.changeRemarkSample();
+            },
+            get remarkSeparator() {
+                return this.allSetting.remarkModel.length > 1 ? this.allSetting.remarkModel.charAt(0) : '-';
+            },
+            set remarkSeparator(value) {
+                this.allSetting.remarkModel = value + this.allSetting.remarkModel.substring(1);
+                this.changeRemarkSample();
+            },
+            changeRemarkSample(){
+                sample = []
+                this.remarkModel.forEach(r => sample.push(this.remarkModels[r]));
+                this.remarkSample = sample.length == 0 ? '' : sample.join(this.remarkSeparator);
+            }            
         },
         methods: {
             loading(spinning = true) {
@@ -284,6 +331,7 @@
                 if (msg.success) {
                     this.oldAllSetting = new AllSetting(msg.obj);
                     this.allSetting = new AllSetting(msg.obj);
+                    app.changeRemarkSample();
                     this.saveBtnDisable = true;
                 }
                 await this.fetchUserSecret();

+ 6 - 0
web/service/setting.go

@@ -34,6 +34,7 @@ var defaultValueMap = map[string]string{
 	"pageSize":           "0",
 	"expireDiff":         "0",
 	"trafficDiff":        "0",
+	"remarkModel":        "-ieo",
 	"timeLocation":       "Asia/Tehran",
 	"tgBotEnable":        "false",
 	"tgBotToken":         "",
@@ -311,6 +312,10 @@ func (s *SettingService) GetSessionMaxAge() (int, error) {
 	return s.getInt("sessionMaxAge")
 }
 
+func (s *SettingService) GetRemarkModel() (string, error) {
+	return s.getString("remarkModel")
+}
+
 func (s *SettingService) GetSecretStatus() (bool, error) {
 	return s.getBool("secretEnable")
 }
@@ -457,6 +462,7 @@ func (s *SettingService) GetDefaultSettings(host string) (interface{}, error) {
 		"tgBotEnable": func() (interface{}, error) { return s.GetTgbotenabled() },
 		"subEnable":   func() (interface{}, error) { return s.GetSubEnable() },
 		"subURI":      func() (interface{}, error) { return s.GetSubURI() },
+		"remarkModel": func() (interface{}, error) { return s.GetRemarkModel() },
 	}
 
 	result := make(map[string]interface{})

+ 2 - 0
web/translation/translate.en_US.toml

@@ -245,6 +245,8 @@
 "panelUrlPathDesc" = "Must start with '/' and end with."
 "pageSize" = "Pagination size"
 "pageSizeDesc" = "Define page size for inbounds table. Set 0 to disable"
+"remarkModel" = "Remark Model and Seperation charachter"
+"sampleRemark" = "Sample remark"
 "oldUsername" = "Current Username"
 "currentPassword" = "Current Password"
 "newUsername" = "New Username"

+ 2 - 0
web/translation/translate.es_ES.toml

@@ -245,6 +245,8 @@
 "panelUrlPathDesc" = "Debe empezar con '/' y terminar con."
 "pageSize" = "Tamaño de paginación"
 "pageSizeDesc" = "Defina el tamaño de página para la tabla de entradas. Establezca 0 para desactivar"
+"remarkModel" = "Modelo de observación y carácter de separación"
+"sampleRemark" = "Observación de muestra"
 "oldUsername" = "Nombre de Usuario Actual"
 "currentPassword" = "Contraseña Actual"
 "newUsername" = "Nuevo Nombre de Usuario"

+ 2 - 0
web/translation/translate.fa_IR.toml

@@ -245,6 +245,8 @@
 "panelUrlPathDesc" = "باید با '/' شروع شود و با '/' تمام شود"
 "pageSize" = "اندازه صفحه بندی جدول"
 "pageSizeDesc" = "اندازه صفحه را برای جدول سرویس ها تعریف کنید. 0: غیرفعال"
+"remarkModel" = "نام کانفیگ و جداکننده"
+"sampleRemark" = "نمونه نام"
 "oldUsername" = "نام کاربری فعلی"
 "currentPassword" = "رمز عبور فعلی"
 "newUsername" = "نام کاربری جدید"

+ 2 - 0
web/translation/translate.ru_RU.toml

@@ -245,6 +245,8 @@
 "panelUrlPathDesc" = "Должен начинаться с '/' и заканчиваться на"
 "pageSize" = "Размер нумерации страниц"
 "pageSizeDesc" = "Определить размер страницы для входящей таблицы. Установите 0, чтобы отключить"
+"remarkModel" = "Модель примечания и символ разделения"
+"sampleRemark" = "Пример замечания"
 "oldUsername" = "Текущее имя пользователя"
 "currentPassword" = "Текущий пароль"
 "newUsername" = "Новое имя пользователя"

+ 2 - 0
web/translation/translate.vi_VN.toml

@@ -245,6 +245,8 @@
 "panelUrlPathDesc" = "Phải bắt đầu bằng '/' và kết thúc bằng."
 "pageSize" = "Kích thước phân trang"
 "pageSizeDesc" = "Xác định kích thước trang cho bảng gửi đến. Đặt 0 để tắt"
+"remarkModel" = "Ghi chú mô hình và ký tự phân tách"
+"sampleRemark" = "Nhận xét mẫu"
 "oldUsername" = "Tên người dùng hiện tại"
 "currentPassword" = "Mật khẩu hiện tại"
 "newUsername" = "Tên người dùng mới"

+ 2 - 0
web/translation/translate.zh_Hans.toml

@@ -245,6 +245,8 @@
 "panelUrlPathDesc" = "必须以 '/' 开头,以 '/' 结尾"
 "pageSize" = "分页大小"
 "pageSizeDesc" = "定义入站表的页面大小。设置 0 表示禁用"
+"remarkModel" = "备注模型和分隔符"
+"sampleRemark" = "备注示例"
 "oldUsername" = "原用户名"
 "currentPassword" = "原密码"
 "newUsername" = "新用户名"