[feature] customizable remark #692

This commit is contained in:
Alireza Ahmadi
2023-12-08 00:44:36 +01:00
parent fd64ae5c85
commit 5725420197
10 changed files with 108 additions and 27 deletions

View File

@@ -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 {
@@ -793,17 +798,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)
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)
}
remark = append(remark, email)
if len(extra) > 0 {
remark = append(remark, extra)
}
} else {
return inbound.Remark
}
if s.showInfo {
@@ -820,7 +838,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), "📊"))
@@ -834,7 +852,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) {

View File

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

View File

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

View File

@@ -1352,20 +1352,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)
@@ -1375,11 +1383,11 @@ class Inbound extends XrayCommonClass {
return result;
}
genInboundLinks(remark = '') {
genInboundLinks(remark = '', remarkModel = '-ieo') {
if(this.clients){
let links = [];
this.clients.forEach((client) => {
this.genAllLinks(remark,client).forEach(l => {
this.genAllLinks(remark,remarkModel,client).forEach(l => {
links.push(l.link);
})
});

View File

@@ -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"`

View File

@@ -32,7 +32,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

View File

@@ -263,7 +263,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);

View File

@@ -554,6 +554,7 @@
enable : false,
subURI : ''
},
remarkModel: '-ieo',
tgBotEnable: false,
showAlert: false,
pageSize: 0,
@@ -599,6 +600,7 @@
subURI: subURI
};
this.pageSize = pageSize;
this.remarkModel = remarkModel;
}
},
setInbounds(dbInbounds) {
@@ -1173,7 +1175,7 @@
inboundLinks(dbInboundId) {
dbInbound = this.dbInbounds.find(row => row.id === dbInboundId);
newDbInbound = this.checkFallback(dbInbound);
txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks, newDbInbound.remark);
txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks(this.remarkModel), newDbInbound.remark);
},
importInbound() {
promptModal.open({
@@ -1190,7 +1192,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');
},

View File

@@ -77,6 +77,28 @@
<a-tabs default-active-key="1">
<a-tab-pane key="1" tab='{{ i18n "pages.settings.panelConfig"}}'>
<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.number="allSetting.webPort"></setting-list-item>
@@ -93,7 +115,6 @@
<a-col :lg="24" :xl="12">
<a-list-item-meta title="Language"/>
</a-col>
<a-col :lg="24" :xl="12">
<template>
<a-select
@@ -171,8 +192,7 @@
ref="selectBotLang"
v-model="allSetting.tgLang"
style="width: 100%"
:dropdown-class-name="themeSwitcher.currentTheme"
>
:dropdown-class-name="themeSwitcher.currentTheme">
<a-select-option :value="l.value" :label="l.value" v-for="l in supportLangs">
<span role="img" aria-label="l.name" v-text="l.icon"></span>
&nbsp;&nbsp;<span v-text="l.name"></span>
@@ -224,7 +244,31 @@
saveBtnDisable: true,
user: {},
lang: getLang(),
showAlert: false
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) {
@@ -237,6 +281,7 @@
if (msg.success) {
this.oldAllSetting = new AllSetting(msg.obj);
this.allSetting = new AllSetting(msg.obj);
app.changeRemarkSample();
this.saveBtnDisable = true;
}
},

View File

@@ -34,6 +34,7 @@ var defaultValueMap = map[string]string{
"pageSize": "0",
"expireDiff": "0",
"trafficDiff": "0",
"remarkModel": "-ieo",
"timeLocation": "Asia/Tehran",
"tgBotEnable": "false",
"tgBotToken": "",
@@ -295,6 +296,10 @@ func (s *SettingService) GetSessionMaxAge() (int, error) {
return s.getInt("sessionMaxAge")
}
func (s *SettingService) GetRemarkModel() (string, error) {
return s.getString("remarkModel")
}
func (s *SettingService) GetSecret() ([]byte, error) {
secret, err := s.getString("secret")
if secret == defaultValueMap["secret"] {
@@ -433,6 +438,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{})