diff --git a/web/assets/js/model/dbinbound.js b/web/assets/js/model/dbinbound.js index a8810899..7f4f0812 100644 --- a/web/assets/js/model/dbinbound.js +++ b/web/assets/js/model/dbinbound.js @@ -136,14 +136,9 @@ class DBInbound { return false; } } - - genLink(address=this.address, remark=this.remark, clientIndex=0) { - const inbound = this.toInbound(); - return inbound.genLink(address, remark, clientIndex); - } get genInboundLinks() { const inbound = this.toInbound(); - return inbound.genInboundLinks(this.address, this.remark); + return inbound.genInboundLinks(this.remark); } } \ No newline at end of file diff --git a/web/assets/js/model/xray.js b/web/assets/js/model/xray.js index fdaeef97..85cd7e5a 100644 --- a/web/assets/js/model/xray.js +++ b/web/assets/js/model/xray.js @@ -567,14 +567,12 @@ TlsStreamSettings.Settings = class extends XrayCommonClass { this.allowInsecure = allowInsecure; this.fingerprint = fingerprint; this.serverName = serverName; - this.domains = domains; } static fromJson(json = {}) { return new TlsStreamSettings.Settings( json.allowInsecure, json.fingerprint, json.serverName, - json.domains, ); } toJson() { @@ -582,7 +580,6 @@ TlsStreamSettings.Settings = class extends XrayCommonClass { allowInsecure: this.allowInsecure, fingerprint: this.fingerprint, serverName: this.serverName, - domains: this.domains, }; } }; @@ -700,6 +697,7 @@ class SockoptStreamSettings extends XrayCommonClass { class StreamSettings extends XrayCommonClass { constructor(network='tcp', security='none', + externalProxy = [], tlsSettings=new TlsStreamSettings(), realitySettings = new RealityStreamSettings(), tcpSettings=new TcpStreamSettings(), @@ -713,6 +711,7 @@ class StreamSettings extends XrayCommonClass { super(); this.network = network; this.security = security; + this.externalProxy = externalProxy; this.tls = tlsSettings; this.reality = realitySettings; this.tcp = tcpSettings; @@ -757,10 +756,10 @@ class StreamSettings extends XrayCommonClass { } static fromJson(json={}) { - return new StreamSettings( json.network, json.security, + json.externalProxy, TlsStreamSettings.fromJson(json.tlsSettings), RealityStreamSettings.fromJson(json.realitySettings), TcpStreamSettings.fromJson(json.tcpSettings), @@ -778,6 +777,7 @@ class StreamSettings extends XrayCommonClass { return { network: network, security: this.security, + externalProxy: this.externalProxy, tlsSettings: this.isTls ? this.tls.toJson() : undefined, realitySettings: this.isReality ? this.reality.toJson() : undefined, tcpSettings: network === 'tcp' ? this.tcp.toJson() : undefined, @@ -836,6 +836,16 @@ class Inbound extends XrayCommonClass { return this.clientStats; } + get clients() { + switch (this.protocol) { + case Protocols.VMESS: return this.settings.vmesses; + case Protocols.VLESS: return this.settings.vlesses; + case Protocols.TROJAN: return this.settings.trojans; + case Protocols.SHADOWSOCKS: return this.isSSMultiUser ? this.settings.shadowsockses : null; + default: return null; + } + } + get protocol() { return this._protocol; } @@ -844,7 +854,7 @@ class Inbound extends XrayCommonClass { this._protocol = protocol; this.settings = Inbound.Settings.getSettings(protocol); if (protocol === Protocols.TROJAN) { - this.tls = true; + this.stream.isTls = true; } } @@ -950,26 +960,8 @@ class Inbound extends XrayCommonClass { } isExpiry(index) { - switch (this.protocol) { - case Protocols.VMESS: - if(this.settings.vmesses[index].expiryTime > 0) - return this.settings.vmesses[index].expiryTime < new Date().getTime(); - return false - case Protocols.VLESS: - if(this.settings.vlesses[index].expiryTime > 0) - return this.settings.vlesses[index].expiryTime < new Date().getTime(); - return false - case Protocols.TROJAN: - if(this.settings.trojans[index].expiryTime > 0) - return this.settings.trojans[index].expiryTime < new Date().getTime(); - return false - case Protocols.SHADOWSOCKS: - if(this.settings.shadowsockses.length > 0 && this.settings.shadowsockses[index].expiryTime > 0) - return this.settings.shadowsockses[index].expiryTime < new Date().getTime(); - return false - default: - return false; - } + let exp = this.clients[index].expiryTime; + return exp > 0 ? exp < new Date().getTime() : false; } canEnableTls() { @@ -1008,19 +1000,20 @@ class Inbound extends XrayCommonClass { this.sniffing = new Sniffing(); } - genVmessLink(address='', remark='', clientIndex=0) { + genVmessLink(address='', port=this.port, forceTls, remark='', clientId) { if (this.protocol !== Protocols.VMESS) { return ''; } + const security = forceTls == 'same' ? this.stream.security : forceTls; let obj = { v: '2', ps: remark, add: address, - port: this.port, - id: this.settings.vmesses[clientIndex].id, + port: port, + id: clientId, net: this.stream.network, type: 'none', - tls: this.stream.security, + tls: security, }; let network = this.stream.network; if (network === 'tcp') { @@ -1060,8 +1053,8 @@ class Inbound extends XrayCommonClass { } } - if (this.stream.security === 'tls') { - if (!ObjectUtil.isEmpty(this.stream.tls.server)) { + if (security === 'tls') { + if (address == this.listen && port == this.port && !ObjectUtil.isEmpty(this.stream.tls.server)) { obj.add = this.stream.tls.server; } if (!ObjectUtil.isEmpty(this.stream.tls.settings.serverName)){ @@ -1081,11 +1074,10 @@ class Inbound extends XrayCommonClass { return 'vmess://' + base64(JSON.stringify(obj, null, 2)); } - genVLESSLink(address = '', remark='', clientIndex=0) { - const settings = this.settings; - const uuid = settings.vlesses[clientIndex].id; - const port = this.port; + genVLESSLink(address = '', port=this.port, forceTls, remark='', clientId, flow) { + const uuid = clientId; const type = this.stream.network; + const security = forceTls == 'same' ? this.stream.security : forceTls; const params = new Map(); params.set("type", this.stream.network); switch (type) { @@ -1136,25 +1128,27 @@ class Inbound extends XrayCommonClass { break; } - if (this.tls) { + if (security === 'tls') { params.set("security", "tls"); - params.set("fp" , this.stream.tls.settings.fingerprint); - params.set("alpn", this.stream.tls.alpn); - if(this.stream.tls.settings.allowInsecure){ - params.set("allowInsecure", "1"); - } - if (!ObjectUtil.isEmpty(this.stream.tls.server)) { - address = this.stream.tls.server; - } - if (this.stream.tls.settings.serverName !== ''){ - params.set("sni", this.stream.tls.settings.serverName); - } - if (type === "tcp" && this.settings.vlesses[clientIndex].flow.length > 0) { - params.set("flow", this.settings.vlesses[clientIndex].flow); + if (this.stream.isTls){ + params.set("fp" , this.stream.tls.settings.fingerprint); + params.set("alpn", this.stream.tls.alpn); + if(this.stream.tls.settings.allowInsecure){ + params.set("allowInsecure", "1"); + } + if (!ObjectUtil.isEmpty(this.stream.tls.server)) { + address = this.stream.tls.server; + } + if (this.stream.tls.settings.serverName !== ''){ + params.set("sni", this.stream.tls.settings.serverName); + } + if (type == "tcp" && !ObjectUtil.isEmpty(flow)) { + params.set("flow", flow); + } } } - if (this.reality) { + if (security === 'reality') { params.set("security", "reality"); params.set("pbk", this.stream.reality.settings.publicKey); params.set("fp", this.stream.reality.settings.fingerprint); @@ -1164,14 +1158,14 @@ class Inbound extends XrayCommonClass { if (this.stream.reality.shortIds.length > 0) { params.set("sid", this.stream.reality.shortIds.split(",")[0]); } - if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { + if (address == this.listen && port == this.port && !ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { address = this.stream.reality.settings.serverName; } if (!ObjectUtil.isEmpty(this.stream.reality.settings.spiderX)) { params.set("spx", this.stream.reality.settings.spiderX); } - if (this.stream.network === 'tcp' && !ObjectUtil.isEmpty(this.settings.vlesses[clientIndex].flow)) { - params.set("flow", this.settings.vlesses[clientIndex].flow); + if (type == 'tcp' && !ObjectUtil.isEmpty(flow)) { + params.set("flow", flow); } } @@ -1184,9 +1178,8 @@ class Inbound extends XrayCommonClass { return url.toString(); } - genSSLink(address='', remark='', clientIndex = 0) { + genSSLink(address='', port=this.port, remark='', clientPassword) { let settings = this.settings; - const port = this.port; const type = this.stream.network; const params = new Map(); params.set("type", this.stream.network); @@ -1240,9 +1233,9 @@ class Inbound extends XrayCommonClass { let password = new Array(); if (this.isSS2022) password.push(settings.password); - if (this.isSSMultiUser) password.push(settings.shadowsockses[clientIndex].password); + if (this.isSSMultiUser) password.push(clientPassword); - let link = `ss://${safeBase64(settings.method + ':' + password.join(':'))}@${address}:${this.port}`; + let link = `ss://${safeBase64(settings.method + ':' + password.join(':'))}@${address}:${port}`; const url = new URL(link); for (const [key, value] of params) { url.searchParams.set(key, value) @@ -1251,9 +1244,8 @@ class Inbound extends XrayCommonClass { return url.toString(); } - genTrojanLink(address = '', remark = '', clientIndex = 0) { - let settings = this.settings; - const port = this.port; + genTrojanLink(address = '', port=this.port, forceTls, remark = '', clientPassword) { + const security = forceTls == 'same' ? this.stream.security : forceTls; const type = this.stream.network; const params = new Map(); params.set("type", this.stream.network); @@ -1305,22 +1297,24 @@ class Inbound extends XrayCommonClass { break; } - if (this.tls) { + if (security === 'tls') { params.set("security", "tls"); - params.set("fp" , this.stream.tls.settings.fingerprint); - params.set("alpn", this.stream.tls.alpn); - if(this.stream.tls.settings.allowInsecure){ - params.set("allowInsecure", "1"); + if (this.stream.isTls){ + params.set("fp" , this.stream.tls.settings.fingerprint); + params.set("alpn", this.stream.tls.alpn); + if(this.stream.tls.settings.allowInsecure){ + params.set("allowInsecure", "1"); + } + if (address == this.listen && port == this.port && !ObjectUtil.isEmpty(this.stream.tls.server)) { + address = this.stream.tls.server; + } + if (this.stream.tls.settings.serverName !== ''){ + params.set("sni", this.stream.tls.settings.serverName); + } } - if (!ObjectUtil.isEmpty(this.stream.tls.server)) { - address = this.stream.tls.server; - } - if (this.stream.tls.settings.serverName !== ''){ - params.set("sni", this.stream.tls.settings.serverName); - } } - if (this.reality) { + if (security === 'reality') { params.set("security", "reality"); params.set("pbk", this.stream.reality.settings.publicKey); params.set("fp", this.stream.reality.settings.fingerprint); @@ -1330,7 +1324,7 @@ class Inbound extends XrayCommonClass { if (this.stream.reality.shortIds.length > 0) { params.set("sid", this.stream.reality.shortIds.split(",")[0]); } - if (!ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { + if (address == this.listen && port == this.port && !ObjectUtil.isEmpty(this.stream.reality.settings.serverName)) { address = this.stream.reality.settings.serverName; } if (!ObjectUtil.isEmpty(this.stream.reality.settings.spiderX)) { @@ -1338,7 +1332,7 @@ class Inbound extends XrayCommonClass { } } - const link = `trojan://${settings.trojans[clientIndex].password}@${address}:${this.port}`; + const link = `trojan://${clientPassword}@${address}:${port}`; const url = new URL(link); for (const [key, value] of params) { url.searchParams.set(key, value) @@ -1347,38 +1341,62 @@ class Inbound extends XrayCommonClass { return url.toString(); } - genLink(address='', remark='', clientIndex=0) { + genLink(address='', port=this.port, forceTls='same', remark='', client) { switch (this.protocol) { case Protocols.VMESS: - return this.genVmessLink(address, remark, clientIndex); + return this.genVmessLink(address, port, forceTls, remark, client.id); case Protocols.VLESS: - return this.genVLESSLink(address, remark, clientIndex); + return this.genVLESSLink(address, port, forceTls, remark, client.id, client.flow); case Protocols.SHADOWSOCKS: - return this.genSSLink(address, remark, clientIndex); + return this.genSSLink(address, port, remark, this.isSSMultiUser ? client.password : ''); case Protocols.TROJAN: - return this.genTrojanLink(address, remark, clientIndex); + return this.genTrojanLink(address, port, forceTls, remark, client.password); default: return ''; } } - genInboundLinks(address = '', remark = '') { - let link = ''; - switch (this.protocol) { - case Protocols.VMESS: - case Protocols.VLESS: - case Protocols.TROJAN: - case Protocols.SHADOWSOCKS: - JSON.parse(this.settings).clients.forEach((client,index) => { - if(this.tls && !ObjectUtil.isArrEmpty(this.stream.tls.settings.domains)){ - this.stream.tls.settings.domains.forEach((domain) => { - link += this.genLink(domain.domain, [remark, client.email, domain.remark].filter(x => x.length > 0).join('-'), index) + '\r\n'; - }); - } else { - link += this.genLink(address, [remark, client.email].filter(x => x.length > 0).join('-'), index) + '\r\n'; - } + genAllLinks(remark='', client){ + let result = []; + let email = client ? client.email : ''; + let addr = this.listen; + let port = this.port + if(ObjectUtil.isArrEmpty(this.stream.externalProxy)){ + let r = [remark, email].filter(x => x.length > 0).join('-'); + 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('-') + let dest = ep.dest.split(":"); + if(dest.length == 2) { + addr = dest[0]; + port = dest[1]; + } else { + addr = dest[0]; + } + result.push({ + remark: r, + link: this.genLink(addr, port, ep.forceTls, r, client) }); - return link; - default: return ''; + }); + } + return result; + } + + genInboundLinks(remark = '') { + if(this.clients){ + let links = []; + this.clients.forEach((client) => { + genAllLinks(remark,client).forEach(l => { + links.push(l.link); + }) + }); + return links.join('\r\n'); + } else { + if(this.protocol == Protocols.SHADOWSOCKS && !this.isSSMultiUser) return this.genSSLink(this.listen, this.port, remark); + return ''; } } diff --git a/web/html/common/qrcode_modal.html b/web/html/common/qrcode_modal.html index 8c0c13d7..75657301 100644 --- a/web/html/common/qrcode_modal.html +++ b/web/html/common/qrcode_modal.html @@ -19,39 +19,25 @@ const qrModal = { title: '', - clientIndex: 0, - inbound: new Inbound(), dbInbound: new DBInbound(), client: null, qrcodes: [], clipboard: null, visible: false, subId: '', - show: function (title = '', dbInbound = new DBInbound(), clientIndex = 0) { + show: function (title = '', dbInbound, client) { this.title = title; - this.clientIndex = clientIndex; this.dbInbound = dbInbound; this.inbound = dbInbound.toInbound(); - settings = JSON.parse(this.inbound.settings); - this.client = settings.clients[clientIndex]; - remark = [this.dbInbound.remark, ( this.client ? this.client.email : '')].filter(Boolean).join('-'); - address = this.dbInbound.address; + this.client = client; this.subId = ''; this.qrcodes = []; - if (this.inbound.stream.isTls && !ObjectUtil.isArrEmpty(this.inbound.stream.tls.settings.domains)) { - this.inbound.stream.tls.settings.domains.forEach((domain) => { - remarkText = [remark, domain.remark].filter(Boolean).join('-'); - this.qrcodes.push({ - remark: remarkText, - link: this.inbound.genLink(domain.domain, remarkText, clientIndex) - }); - }); - } else { + this.inbound.genAllLinks(this.dbInbound.remark, client).forEach(l => { this.qrcodes.push({ - remark: remark, - link: this.inbound.genLink(address, remark, clientIndex) + remark: l.remark, + link: l.link }); - } + }); this.visible = true; }, close: function () { diff --git a/web/html/xui/client_modal.html b/web/html/xui/client_modal.html index 853b83a7..d85e6d4f 100644 --- a/web/html/xui/client_modal.html +++ b/web/html/xui/client_modal.html @@ -36,7 +36,7 @@ this.isEdit = isEdit; this.dbInbound = new DBInbound(dbInbound); this.inbound = dbInbound.toInbound(); - this.clients = this.getClients(this.inbound.protocol, this.inbound.settings); + this.clients = this.inbound.clients; this.index = index === null ? this.clients.length : index; this.delayedStart = false; if (isEdit){ @@ -50,15 +50,6 @@ this.clientStats = this.dbInbound.clientStats.find(row => row.email === this.clients[this.index].email); this.confirm = confirm; }, - getClients(protocol, clientSettings) { - switch(protocol){ - case Protocols.VMESS: return clientSettings.vmesses; - case Protocols.VLESS: return clientSettings.vlesses; - case Protocols.TROJAN: return clientSettings.trojans; - case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; - default: return null; - } - }, getClientId(protocol, client) { switch(protocol){ case Protocols.TROJAN: return client.password; diff --git a/web/html/xui/form/inbound.html b/web/html/xui/form/inbound.html index 5707d153..e61b1259 100644 --- a/web/html/xui/form/inbound.html +++ b/web/html/xui/form/inbound.html @@ -126,6 +126,7 @@ diff --git a/web/html/xui/form/stream/external_proxy.html b/web/html/xui/form/stream/external_proxy.html new file mode 100644 index 00000000..ef117464 --- /dev/null +++ b/web/html/xui/form/stream/external_proxy.html @@ -0,0 +1,29 @@ +{{define "form/externalProxy"}} + + + + + + + + + + + +
+ + + + + - + +
+
+{{end}} \ No newline at end of file diff --git a/web/html/xui/form/tls_settings.html b/web/html/xui/form/tls_settings.html index 5754b650..3e4781fe 100644 --- a/web/html/xui/form/tls_settings.html +++ b/web/html/xui/form/tls_settings.html @@ -4,9 +4,8 @@ - - - - - - - - - - +
{{ i18n "security" }} - + + {{ i18n "none" }} TLS @@ -64,26 +63,7 @@
Multi Domain - - + -
- - - - - - - - - -
{{ i18n "domainName" }} diff --git a/web/html/xui/inbound_info_modal.html b/web/html/xui/inbound_info_modal.html index 27c90d37..16ced4e5 100644 --- a/web/html/xui/inbound_info_modal.html +++ b/web/html/xui/inbound_info_modal.html @@ -246,7 +246,6 @@ visible: false, inbound: new Inbound(), dbInbound: new DBInbound(), - settings: null, clientSettings: null, clientStats: [], upStats: 0, @@ -261,27 +260,10 @@ this.index = index; this.inbound = dbInbound.toInbound(); this.dbInbound = new DBInbound(dbInbound); - this.settings = JSON.parse(this.inbound.settings); - this.clientSettings = this.settings.clients ? Object.values(this.settings.clients)[index] : null; - this.isExpired = this.inbound.isExpiry(index); - this.clientStats = this.settings.clients ? this.dbInbound.clientStats.find(row => row.email === this.clientSettings.email) : []; - remark = [this.dbInbound.remark, ( this.clientSettings ? this.clientSettings.email : '')].filter(Boolean).join('-'); - address = this.dbInbound.address; - this.links = []; - if (this.inbound.stream.isTls && !ObjectUtil.isArrEmpty(this.inbound.stream.tls.settings.domains)) { - this.inbound.stream.tls.settings.domains.forEach((domain) => { - remarkText = [remark, domain.remark].filter(Boolean).join('-'); - this.links.push({ - remark: remarkText, - link: this.inbound.genLink(domain.domain, remarkText, index) - }); - }); - } else { - this.links.push({ - remark: remark, - link: this.inbound.genLink(address, remark, index) - }); - } + 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); if (this.clientSettings) { if (this.clientSettings.subId) { this.subLink = this.genSubLink(this.clientSettings.subId); diff --git a/web/html/xui/inbound_modal.html b/web/html/xui/inbound_modal.html index dc39b8b8..ca9f4989 100644 --- a/web/html/xui/inbound_modal.html +++ b/web/html/xui/inbound_modal.html @@ -42,15 +42,6 @@ loading(loading) { inModal.confirmLoading = loading; }, - getClients(protocol, clientSettings) { - switch(protocol){ - case Protocols.VMESS: return clientSettings.vmesses; - case Protocols.VLESS: return clientSettings.vlesses; - case Protocols.TROJAN: return clientSettings.trojans; - case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; - default: return null; - } - }, }; new Vue({ @@ -69,7 +60,7 @@ return inModal.isEdit; }, get client() { - return inModal.getClients(this.inbound.protocol, this.inbound.settings)[0]; + return inModal.inbound.clients[0]; }, get delayedExpireDays() { return this.client && this.client.expiryTime < 0 ? this.client.expiryTime / -86400000 : 0; @@ -77,16 +68,18 @@ set delayedExpireDays(days){ this.client.expiryTime = -86400000 * days; }, - get multiDomain() { - return this.inbound.stream.tls.settings.domains.length > 0; + get externalProxy() { + return this.inbound.stream.externalProxy.length > 0; }, - set multiDomain(value) { + set externalProxy(value) { if (value) { - inModal.inbound.stream.tls.server = ""; - inModal.inbound.stream.tls.settings.domains = [{ remark: "", domain: window.location.hostname }]; + inModal.inbound.stream.externalProxy = [{ + forceTls: "same", + dest: window.location.hostname + ":" + inModal.inbound.port, + remark: "" + }]; } else { - inModal.inbound.stream.tls.server = ""; - inModal.inbound.stream.tls.settings.domains = []; + inModal.inbound.stream.externalProxy = []; } } }, diff --git a/web/html/xui/inbounds.html b/web/html/xui/inbounds.html index 7a700a34..86a4eee8 100644 --- a/web/html/xui/inbounds.html +++ b/web/html/xui/inbounds.html @@ -617,7 +617,7 @@ }, getClientCounts(dbInbound, inbound) { let clientCount = 0, active = [], deactive = [], depleted = [], expiring = [], online = []; - clients = this.getClients(dbInbound.protocol, inbound.settings); + clients = inbound.clients; clientStats = dbInbound.clientStats now = new Date().getTime() if (clients) { @@ -967,15 +967,6 @@ this.submit(`/xui/inbound/${dbInboundId}/delClient/${clientId}`); } }, - getClients(protocol, clientSettings) { - switch (protocol) { - case Protocols.VMESS: return clientSettings.vmesses; - case Protocols.VLESS: return clientSettings.vlesses; - case Protocols.TROJAN: return clientSettings.trojans; - case Protocols.SHADOWSOCKS: return clientSettings.shadowsockses; - default: return null; - } - }, getClientId(protocol, client) { switch (protocol) { case Protocols.TROJAN: return client.password; @@ -995,7 +986,7 @@ newDbInbound.listen = rootInbound.listen; newDbInbound.port = rootInbound.port; newInbound = newDbInbound.toInbound(); - newInbound.stream.security = 'tls'; + newInbound.stream.security = rootInbound.stream.security; newInbound.stream.tls = rootInbound.stream.tls; newDbInbound.streamSettings = newInbound.stream.toString(); } @@ -1004,18 +995,15 @@ }, showQrcode(dbInboundId, client) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); - inbound = dbInbound.toInbound(); - clients = this.getClients(dbInbound.protocol, inbound.settings); - index = this.findIndexOfClient(dbInbound.protocol, clients, client); newDbInbound = this.checkFallback(dbInbound); - qrModal.show('{{ i18n "qrCode"}}', newDbInbound, index); + qrModal.show('{{ i18n "qrCode"}}', newDbInbound, client); }, showInfo(dbInboundId, client) { dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); index=0; if (dbInbound.isMultiUser()){ inbound = dbInbound.toInbound(); - clients = this.getClients(dbInbound.protocol, inbound.settings); + clients = inbound.clients; index = this.findIndexOfClient(dbInbound.protocol, clients, client); } newDbInbound = this.checkFallback(dbInbound); @@ -1029,7 +1017,7 @@ this.loading() dbInbound = this.dbInbounds.find(row => row.id === dbInboundId); inbound = dbInbound.toInbound(); - clients = this.getClients(dbInbound.protocol, inbound.settings); + clients = inbound.clients; index = this.findIndexOfClient(dbInbound.protocol, clients, client); clients[index].enable = !clients[index].enable; clientId = this.getClientId(dbInbound.protocol, clients[index]); @@ -1043,15 +1031,7 @@ } }, getInboundClients(dbInbound) { - if (dbInbound.protocol == Protocols.VLESS) { - return dbInbound.toInbound().settings.vlesses; - } else if (dbInbound.protocol == Protocols.VMESS) { - return dbInbound.toInbound().settings.vmesses; - } else if (dbInbound.protocol == Protocols.TROJAN) { - return dbInbound.toInbound().settings.trojans; - } else if (dbInbound.protocol == Protocols.SHADOWSOCKS) { - return dbInbound.toInbound().settings.shadowsockses; - } + return dbInbound.toInbound().clients; }, resetClientTraffic(client, dbInboundId, confirmation = true) { if (confirmation){ @@ -1181,11 +1161,11 @@ txtModal.show('{{ i18n "pages.inbounds.export"}}', newDbInbound.genInboundLinks, newDbInbound.remark); }, exportAllLinks() { - let copyText = ''; + let copyText = []; for (const dbInbound of this.dbInbounds) { - copyText += dbInbound.genInboundLinks; + copyText.push(dbInbound.genInboundLinks); } - txtModal.show('{{ i18n "pages.inbounds.export"}}', copyText, 'All-Inbounds'); + txtModal.show('{{ i18n "pages.inbounds.export"}}', copyText.join('\r\n'), 'All-Inbounds'); }, async startDataRefreshLoop() { while (this.isRefreshEnabled) { diff --git a/web/service/xray.go b/web/service/xray.go index ab434350..3827ba6d 100644 --- a/web/service/xray.go +++ b/web/service/xray.go @@ -133,19 +133,24 @@ func (s *XrayService) GetXrayConfig() (*xray.Config, error) { inbound.Settings = string(modifiedSettings) } - // Unmarshal stream JSON - var stream map[string]interface{} - json.Unmarshal([]byte(inbound.StreamSettings), &stream) + if len(inbound.StreamSettings) > 0 { + // Unmarshal stream JSON + var stream map[string]interface{} + json.Unmarshal([]byte(inbound.StreamSettings), &stream) - // Remove the "settings" field under "tlsSettings" and "realitySettings" - tlsSettings, ok1 := stream["tlsSettings"].(map[string]interface{}) - realitySettings, ok2 := stream["realitySettings"].(map[string]interface{}) - if ok1 || ok2 { - if ok1 { - delete(tlsSettings, "settings") - } else if ok2 { - delete(realitySettings, "settings") + // Remove the "settings" field under "tlsSettings" and "realitySettings" + tlsSettings, ok1 := stream["tlsSettings"].(map[string]interface{}) + realitySettings, ok2 := stream["realitySettings"].(map[string]interface{}) + if ok1 || ok2 { + if ok1 { + delete(tlsSettings, "settings") + } else if ok2 { + delete(realitySettings, "settings") + } } + + delete(stream, "externalProxy") + newStream, err := json.MarshalIndent(stream, "", " ") if err != nil { return nil, err diff --git a/web/translation/translate.en_US.toml b/web/translation/translate.en_US.toml index f0e6619c..66b92219 100644 --- a/web/translation/translate.en_US.toml +++ b/web/translation/translate.en_US.toml @@ -169,6 +169,7 @@ "telegramDesc" = "Use Telegram ID without @ or chat IDs ( you can get it here @userinfobot or use '/id' command in bot )" "subscriptionDesc" = "You can find your sub link on Details, also you can use the same name for several configurations" "info" = "Info" +"same" = "Same" [pages.client] "add" = "Add Client" diff --git a/web/translation/translate.fa_IR.toml b/web/translation/translate.fa_IR.toml index 38e13a5d..841c7475 100644 --- a/web/translation/translate.fa_IR.toml +++ b/web/translation/translate.fa_IR.toml @@ -168,6 +168,7 @@ "telegramDesc" = "از آیدی تلگرام بدون @ یا آیدی چت استفاده کنید (می توانید آن را از اینجا دریافت کنید @userinfobot یا در ربات دستور '/id' را وارد کنید)" "subscriptionDesc" = "می توانید ساب لینک خود را در جزئیات پیدا کنید، همچنین می توانید از همین نام برای چندین کانفیگ استفاده کنید" "info" = "اطلاعات" +"same" = "همسان" [pages.client] "add" = "کاربر جدید" diff --git a/web/translation/translate.ru_RU.toml b/web/translation/translate.ru_RU.toml index 4dd1a292..dad8ea03 100644 --- a/web/translation/translate.ru_RU.toml +++ b/web/translation/translate.ru_RU.toml @@ -169,6 +169,7 @@ "telegramDesc" = "Используйте идентификатор Telegram без символа @ или идентификатора чата (можно получить его здесь @userinfobot или использовать команду '/id' в боте)" "subscriptionDesc" = "вы можете найти свою ссылку подписки в разделе «Подробнее», также вы можете использовать одно и то же имя для нескольких конфигов" "info" = "Информация" +"same" = "Тот же" [pages.client] "add" = "Добавить клиента" diff --git a/web/translation/translate.zh_Hans.toml b/web/translation/translate.zh_Hans.toml index 9cae8bc0..b69a51ee 100644 --- a/web/translation/translate.zh_Hans.toml +++ b/web/translation/translate.zh_Hans.toml @@ -169,6 +169,7 @@ "telegramDesc" = "使用 Telegram ID,不包含 @ 符号或聊天 ID(可以在 @userinfobot 处获取,或在机器人中使用'/id'命令)" "subscriptionDesc" = "您可以在详细信息上找到您的子链接,也可以对多个配置使用相同的名称" "info" = "信息" +"same" = "相同" [pages.client] "add" = "添加客户端"