Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/MHSanaei/3x-ui.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/assets/js/model/setting.js3
-rw-r--r--web/assets/js/subscription.js7
-rw-r--r--web/entity/entity.go10
-rw-r--r--web/html/settings.html4
-rw-r--r--web/html/settings/panel/subscription/general.html86
-rw-r--r--web/html/settings/panel/subscription/json.html26
-rw-r--r--web/html/settings/panel/subscription/subpage.html17
-rw-r--r--web/service/setting.go39
8 files changed, 152 insertions, 40 deletions
diff --git a/web/assets/js/model/setting.js b/web/assets/js/model/setting.js
index af80a63e..d61d4b8e 100644
--- a/web/assets/js/model/setting.js
+++ b/web/assets/js/model/setting.js
@@ -38,6 +38,8 @@ class AllSetting {
this.subPort = 2096;
this.subPath = "/sub/";
this.subJsonPath = "/json/";
+ this.subClashEnable = true;
+ this.subClashPath = "/clash/";
this.subDomain = "";
this.externalTrafficInformEnable = false;
this.externalTrafficInformURI = "";
@@ -48,6 +50,7 @@ class AllSetting {
this.subShowInfo = true;
this.subURI = "";
this.subJsonURI = "";
+ this.subClashURI = "";
this.subJsonFragment = "";
this.subJsonNoises = "";
this.subJsonMux = "";
diff --git a/web/assets/js/subscription.js b/web/assets/js/subscription.js
index 228dcfa0..d08bfd28 100644
--- a/web/assets/js/subscription.js
+++ b/web/assets/js/subscription.js
@@ -9,6 +9,7 @@
sId: el.getAttribute('data-sid') || '',
subUrl: el.getAttribute('data-sub-url') || '',
subJsonUrl: el.getAttribute('data-subjson-url') || '',
+ subClashUrl: el.getAttribute('data-subclash-url') || '',
download: el.getAttribute('data-download') || '',
upload: el.getAttribute('data-upload') || '',
used: el.getAttribute('data-used') || '',
@@ -98,13 +99,19 @@
this.lang = LanguageManager.getLanguage();
const tpl = document.getElementById('subscription-data');
const sj = tpl ? tpl.getAttribute('data-subjson-url') : '';
+ const sc = tpl ? tpl.getAttribute('data-subclash-url') : '';
if (sj) this.app.subJsonUrl = sj;
+ if (sc) this.app.subClashUrl = sc;
drawQR(this.app.subUrl);
try {
const elJson = document.getElementById('qrcode-subjson');
if (elJson && this.app.subJsonUrl) {
new QRious({ element: elJson, value: this.app.subJsonUrl, size: 220 });
}
+ const elClash = document.getElementById('qrcode-subclash');
+ if (elClash && this.app.subClashUrl) {
+ new QRious({ element: elClash, value: this.app.subClashUrl, size: 220 });
+ }
} catch (e) { /* ignore */ }
this._onResize = () => { this.viewportWidth = window.innerWidth; };
window.addEventListener('resize', this._onResize);
diff --git a/web/entity/entity.go b/web/entity/entity.go
index 40294925..14353cf0 100644
--- a/web/entity/entity.go
+++ b/web/entity/entity.go
@@ -76,6 +76,9 @@ type AllSetting struct {
SubURI string `json:"subURI" form:"subURI"` // Subscription server URI
SubJsonPath string `json:"subJsonPath" form:"subJsonPath"` // Path for JSON subscription endpoint
SubJsonURI string `json:"subJsonURI" form:"subJsonURI"` // JSON subscription server URI
+ SubClashEnable bool `json:"subClashEnable" form:"subClashEnable"` // Enable Clash/Mihomo subscription endpoint
+ SubClashPath string `json:"subClashPath" form:"subClashPath"` // Path for Clash/Mihomo subscription endpoint
+ SubClashURI string `json:"subClashURI" form:"subClashURI"` // Clash/Mihomo subscription server URI
SubJsonFragment string `json:"subJsonFragment" form:"subJsonFragment"` // JSON subscription fragment configuration
SubJsonNoises string `json:"subJsonNoises" form:"subJsonNoises"` // JSON subscription noise configuration
SubJsonMux string `json:"subJsonMux" form:"subJsonMux"` // JSON subscription mux configuration
@@ -168,6 +171,13 @@ func (s *AllSetting) CheckValid() error {
s.SubJsonPath += "/"
}
+ if !strings.HasPrefix(s.SubClashPath, "/") {
+ s.SubClashPath = "/" + s.SubClashPath
+ }
+ if !strings.HasSuffix(s.SubClashPath, "/") {
+ s.SubClashPath += "/"
+ }
+
_, err := time.LoadLocation(s.TimeLocation)
if err != nil {
return common.NewError("time location not exist:", s.TimeLocation)
diff --git a/web/html/settings.html b/web/html/settings.html
index 48aad524..441e62de 100644
--- a/web/html/settings.html
+++ b/web/html/settings.html
@@ -79,10 +79,10 @@
</template>
{{ template "settings/panel/subscription/general" . }}
</a-tab-pane>
- <a-tab-pane key="5" v-if="allSetting.subJsonEnable" :style="{ paddingTop: '20px' }">
+ <a-tab-pane key="5" v-if="allSetting.subJsonEnable || allSetting.subClashEnable" :style="{ paddingTop: '20px' }">
<template #tab>
<a-icon type="code"></a-icon>
- <span>{{ i18n "pages.settings.subSettings" }} (JSON)</span>
+ <span>{{ i18n "pages.settings.subSettings" }} (Formats)</span>
</template>
{{ template "settings/panel/subscription/json" . }}
</a-tab-pane>
diff --git a/web/html/settings/panel/subscription/general.html b/web/html/settings/panel/subscription/general.html
index 5d83aa37..725a9359 100644
--- a/web/html/settings/panel/subscription/general.html
+++ b/web/html/settings/panel/subscription/general.html
@@ -3,43 +3,58 @@
<a-collapse-panel key="1" header='{{ i18n "pages.xray.generalConfigs"}}'>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subEnable"}}</template>
- <template #description>{{ i18n "pages.settings.subEnableDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subEnableDesc"}}</template>
<template #control>
<a-switch v-model="allSetting.subEnable"></a-switch>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>JSON Subscription</template>
- <template #description>{{ i18n "pages.settings.subJsonEnable"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subJsonEnable"}}</template>
<template #control>
<a-switch v-model="allSetting.subJsonEnable"></a-switch>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
+ <template #title>Clash / Mihomo Subscription</template>
+ <template #description>Enable direct Clash and Mihomo YAML
+ subscriptions.</template>
+ <template #control>
+ <a-switch v-model="allSetting.subClashEnable"></a-switch>
+ </template>
+ </a-setting-list-item>
+ <a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subListen"}}</template>
- <template #description>{{ i18n "pages.settings.subListenDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subListenDesc"}}</template>
<template #control>
<a-input type="text" v-model="allSetting.subListen"></a-input>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subDomain"}}</template>
- <template #description>{{ i18n "pages.settings.subDomainDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subDomainDesc"}}</template>
<template #control>
<a-input type="text" v-model="allSetting.subDomain"></a-input>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subPort"}}</template>
- <template #description>{{ i18n "pages.settings.subPortDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subPortDesc"}}</template>
<template #control>
- <a-input-number v-model="allSetting.subPort" :min="1" :min="65535"
+ <a-input-number v-model="allSetting.subPort" :min="1"
+ :min="65535"
:style="{ width: '100%' }"></a-input-number>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subPath"}}</template>
- <template #description>{{ i18n "pages.settings.subPathDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subPathDesc"}}</template>
<template #control>
<a-input type="text" v-model="allSetting.subPath"
@input="allSetting.subPath = ((typeof $event === 'string' ? $event : ($event && $event.target ? $event.target.value : '')) || '').replace(/[:*]/g, '')"
@@ -49,9 +64,11 @@
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subURI"}}</template>
- <template #description>{{ i18n "pages.settings.subURIDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subURIDesc"}}</template>
<template #control>
- <a-input type="text" placeholder="(http|https)://domain[:port]/path/"
+ <a-input type="text"
+ placeholder="(http|https)://domain[:port]/path/"
v-model="allSetting.subURI"></a-input>
</template>
</a-setting-list-item>
@@ -59,14 +76,16 @@
<a-collapse-panel key="2" header='{{ i18n "pages.settings.information" }}'>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subEncrypt"}}</template>
- <template #description>{{ i18n "pages.settings.subEncryptDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subEncryptDesc"}}</template>
<template #control>
<a-switch v-model="allSetting.subEncrypt"></a-switch>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subShowInfo"}}</template>
- <template #description>{{ i18n "pages.settings.subShowInfoDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subShowInfoDesc"}}</template>
<template #control>
<a-switch v-model="allSetting.subShowInfo"></a-switch>
</template>
@@ -74,59 +93,72 @@
<a-divider>{{ i18n "pages.xray.basicTemplate"}}</a-divider>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subTitle"}}</template>
- <template #description>{{ i18n "pages.settings.subTitleDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subTitleDesc"}}</template>
<template #control>
<a-input type="text" v-model="allSetting.subTitle"></a-input>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subSupportUrl"}}</template>
- <template #description>{{ i18n "pages.settings.subSupportUrlDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subSupportUrlDesc"}}</template>
<template #control>
- <a-input type="text" v-model="allSetting.subSupportUrl" placeholder="https://example.com"></a-input>
+ <a-input type="text" v-model="allSetting.subSupportUrl"
+ placeholder="https://example.com"></a-input>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subProfileUrl"}}</template>
- <template #description>{{ i18n "pages.settings.subProfileUrlDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subProfileUrlDesc"}}</template>
<template #control>
- <a-input type="text" v-model="allSetting.subProfileUrl" placeholder="https://example.com"></a-input>
+ <a-input type="text" v-model="allSetting.subProfileUrl"
+ placeholder="https://example.com"></a-input>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subAnnounce"}}</template>
- <template #description>{{ i18n "pages.settings.subAnnounceDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subAnnounceDesc"}}</template>
<template #control>
<a-textarea v-model="allSetting.subAnnounce"></a-textarea>
</template>
</a-setting-list-item>
<a-divider>{{ i18n "pages.xray.advancedTemplate"}} (Happ)</a-divider>
<a-setting-list-item paddings="small">
- <template #title>{{ i18n "pages.settings.subEnableRouting"}}</template>
- <template #description>{{ i18n "pages.settings.subEnableRoutingDesc"}}</template>
+ <template #title>{{ i18n
+ "pages.settings.subEnableRouting"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subEnableRoutingDesc"}}</template>
<template #control>
<a-switch v-model="allSetting.subEnableRouting"></a-switch>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
- <template #title>{{ i18n "pages.settings.subRoutingRules"}}</template>
- <template #description>{{ i18n "pages.settings.subRoutingRulesDesc"}}</template>
+ <template #title>{{ i18n
+ "pages.settings.subRoutingRules"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subRoutingRulesDesc"}}</template>
<template #control>
- <a-textarea v-model="allSetting.subRoutingRules" placeholder="happ://routing/add/..."></a-textarea>
+ <a-textarea v-model="allSetting.subRoutingRules"
+ placeholder="happ://routing/add/..."></a-textarea>
</template>
</a-setting-list-item>
</a-collapse-panel>
<a-collapse-panel key="3" header='{{ i18n "pages.settings.certs" }}'>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subCertPath"}}</template>
- <template #description>{{ i18n "pages.settings.subCertPathDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subCertPathDesc"}}</template>
<template #control>
<a-input type="text" v-model="allSetting.subCertFile"></a-input>
</template>
</a-setting-list-item>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subKeyPath"}}</template>
- <template #description>{{ i18n "pages.settings.subKeyPathDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subKeyPathDesc"}}</template>
<template #control>
<a-input type="text" v-model="allSetting.subKeyFile"></a-input>
</template>
@@ -135,9 +167,11 @@
<a-collapse-panel key="4" header='{{ i18n "pages.settings.intervals"}}'>
<a-setting-list-item paddings="small">
<template #title>{{ i18n "pages.settings.subUpdates"}}</template>
- <template #description>{{ i18n "pages.settings.subUpdatesDesc"}}</template>
+ <template #description>{{ i18n
+ "pages.settings.subUpdatesDesc"}}</template>
<template #control>
- <a-input-number :min="1" v-model="allSetting.subUpdates" :style="{ width: '100%' }"></a-input-number>
+ <a-input-number :min="1" v-model="allSetting.subUpdates"
+ :style="{ width: '100%' }"></a-input-number>
</template>
</a-setting-list-item>
</a-collapse-panel>
diff --git a/web/html/settings/panel/subscription/json.html b/web/html/settings/panel/subscription/json.html
index e8642305..9b83571a 100644
--- a/web/html/settings/panel/subscription/json.html
+++ b/web/html/settings/panel/subscription/json.html
@@ -1,8 +1,8 @@
{{define "settings/panel/subscription/json"}}
<a-collapse default-active-key="1">
<a-collapse-panel key="1" header='{{ i18n "pages.xray.generalConfigs"}}'>
- <a-setting-list-item paddings="small">
- <template #title>{{ i18n "pages.settings.subPath"}}</template>
+ <a-setting-list-item paddings="small" v-if="allSetting.subJsonEnable">
+ <template #title>{{ i18n "pages.settings.subPath"}} (JSON)</template>
<template #description>{{ i18n "pages.settings.subPathDesc"}}</template>
<template #control>
<a-input type="text" v-model="allSetting.subJsonPath"
@@ -11,14 +11,32 @@
placeholder="/json/"></a-input>
</template>
</a-setting-list-item>
- <a-setting-list-item paddings="small">
- <template #title>{{ i18n "pages.settings.subURI"}}</template>
+ <a-setting-list-item paddings="small" v-if="allSetting.subJsonEnable">
+ <template #title>{{ i18n "pages.settings.subURI"}} (JSON)</template>
<template #description>{{ i18n "pages.settings.subURIDesc"}}</template>
<template #control>
<a-input type="text" placeholder="(http|https)://domain[:port]/path/"
v-model="allSetting.subJsonURI"></a-input>
</template>
</a-setting-list-item>
+ <a-setting-list-item paddings="small" v-if="allSetting.subClashEnable">
+ <template #title>{{ i18n "pages.settings.subPath"}} (Clash)</template>
+ <template #description>{{ i18n "pages.settings.subPathDesc"}}</template>
+ <template #control>
+ <a-input type="text" v-model="allSetting.subClashPath"
+ @input="allSetting.subClashPath = ((typeof $event === 'string' ? $event : ($event && $event.target ? $event.target.value : '')) || '').replace(/[:*]/g, '')"
+ @blur="allSetting.subClashPath = (p => { p = p || '/'; if (!p.startsWith('/')) p='/' + p; if (!p.endsWith('/')) p += '/'; return p.replace(/\/+/g,'/'); })(allSetting.subClashPath)"
+ placeholder="/clash/"></a-input>
+ </template>
+ </a-setting-list-item>
+ <a-setting-list-item paddings="small" v-if="allSetting.subClashEnable">
+ <template #title>{{ i18n "pages.settings.subURI"}} (Clash)</template>
+ <template #description>{{ i18n "pages.settings.subURIDesc"}}</template>
+ <template #control>
+ <a-input type="text" placeholder="(http|https)://domain[:port]/path/"
+ v-model="allSetting.subClashURI"></a-input>
+ </template>
+ </a-setting-list-item>
</a-collapse-panel>
<a-collapse-panel key="2" header='{{ i18n "pages.settings.fragment"}}'>
<a-setting-list-item paddings="small">
diff --git a/web/html/settings/panel/subscription/subpage.html b/web/html/settings/panel/subscription/subpage.html
index 794c67c3..64c1224d 100644
--- a/web/html/settings/panel/subscription/subpage.html
+++ b/web/html/settings/panel/subscription/subpage.html
@@ -83,7 +83,7 @@
<a-form-item>
<a-space direction="vertical" align="center">
<a-row type="flex" :gutter="[8,8]" justify="center" style="width:100%">
- <a-col :xs="24" :sm="app.subJsonUrl ? 12 : 24" style="text-align:center;">
+ <a-col :xs="24" :sm="app.subJsonUrl || app.subClashUrl ? 12 : 24" style="text-align:center;">
<tr-qr-box class="qr-box">
<a-tag color="purple" class="qr-tag">
<span>{{ i18n
@@ -112,6 +112,19 @@
</tr-qr-bg>
</tr-qr-box>
</a-col>
+ <a-col v-if="app.subClashUrl" :xs="24" :sm="12" style="text-align:center;">
+ <tr-qr-box class="qr-box">
+ <a-tag color="purple" class="qr-tag">
+ <span>Clash / Mihomo</span>
+ </a-tag>
+ <tr-qr-bg class="qr-bg-sub">
+ <tr-qr-bg-inner class="qr-bg-sub-inner">
+ <canvas id="qrcode-subclash" class="qr-cv" title='{{ i18n "copy" }}'
+ @click="copy(app.subClashUrl)"></canvas>
+ </tr-qr-bg-inner>
+ </tr-qr-bg>
+ </tr-qr-box>
+ </a-col>
</a-row>
</a-space>
</a-form-item>
@@ -242,7 +255,7 @@
</a-layout>
<!-- Bootstrap data for external JS -->
-<template id="subscription-data" data-sid="{{ .sId }}" data-sub-url="{{ .subUrl }}" data-subjson-url="{{ .subJsonUrl }}"
+<template id="subscription-data" data-sid="{{ .sId }}" data-sub-url="{{ .subUrl }}" data-subjson-url="{{ .subJsonUrl }}" data-subclash-url="{{ .subClashUrl }}"
data-download="{{ .download }}" data-upload="{{ .upload }}" data-used="{{ .used }}" data-total="{{ .total }}"
data-remained="{{ .remained }}" data-expire="{{ .expire }}" data-lastonline="{{ .lastOnline }}"
data-downloadbyte="{{ .downloadByte }}" data-uploadbyte="{{ .uploadByte }}" data-totalbyte="{{ .totalByte }}"
diff --git a/web/service/setting.go b/web/service/setting.go
index 5c93e9fd..7027d466 100644
--- a/web/service/setting.go
+++ b/web/service/setting.go
@@ -71,6 +71,9 @@ var defaultValueMap = map[string]string{
"subURI": "",
"subJsonPath": "/json/",
"subJsonURI": "",
+ "subClashEnable": "true",
+ "subClashPath": "/clash/",
+ "subClashURI": "",
"subJsonFragment": "",
"subJsonNoises": "",
"subJsonMux": "",
@@ -555,6 +558,18 @@ func (s *SettingService) GetSubJsonURI() (string, error) {
return s.getString("subJsonURI")
}
+func (s *SettingService) GetSubClashEnable() (bool, error) {
+ return s.getBool("subClashEnable")
+}
+
+func (s *SettingService) GetSubClashPath() (string, error) {
+ return s.getString("subClashPath")
+}
+
+func (s *SettingService) GetSubClashURI() (string, error) {
+ return s.getString("subClashURI")
+}
+
func (s *SettingService) GetSubJsonFragment() (string, error) {
return s.getString("subJsonFragment")
}
@@ -750,11 +765,13 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
"defaultKey": func() (any, error) { return s.GetKeyFile() },
"tgBotEnable": func() (any, error) { return s.GetTgbotEnabled() },
"subEnable": func() (any, error) { return s.GetSubEnable() },
- "subJsonEnable": func() (any, error) { return s.GetSubJsonEnable() },
- "subTitle": func() (any, error) { return s.GetSubTitle() },
- "subURI": func() (any, error) { return s.GetSubURI() },
- "subJsonURI": func() (any, error) { return s.GetSubJsonURI() },
- "remarkModel": func() (any, error) { return s.GetRemarkModel() },
+ "subJsonEnable": func() (any, error) { return s.GetSubJsonEnable() },
+ "subClashEnable": func() (any, error) { return s.GetSubClashEnable() },
+ "subTitle": func() (any, error) { return s.GetSubTitle() },
+ "subURI": func() (any, error) { return s.GetSubURI() },
+ "subJsonURI": func() (any, error) { return s.GetSubJsonURI() },
+ "subClashURI": func() (any, error) { return s.GetSubClashURI() },
+ "remarkModel": func() (any, error) { return s.GetRemarkModel() },
"datepicker": func() (any, error) { return s.GetDatepicker() },
"ipLimitEnable": func() (any, error) { return s.GetIpLimitEnable() },
}
@@ -776,12 +793,19 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
subJsonEnable = b
}
}
- if (subEnable && result["subURI"].(string) == "") || (subJsonEnable && result["subJsonURI"].(string) == "") {
+ subClashEnable := false
+ if v, ok := result["subClashEnable"]; ok {
+ if b, ok2 := v.(bool); ok2 {
+ subClashEnable = b
+ }
+ }
+ if (subEnable && result["subURI"].(string) == "") || (subJsonEnable && result["subJsonURI"].(string) == "") || (subClashEnable && result["subClashURI"].(string) == "") {
subURI := ""
subTitle, _ := s.GetSubTitle()
subPort, _ := s.GetSubPort()
subPath, _ := s.GetSubPath()
subJsonPath, _ := s.GetSubJsonPath()
+ subClashPath, _ := s.GetSubClashPath()
subDomain, _ := s.GetSubDomain()
subKeyFile, _ := s.GetSubKeyFile()
subCertFile, _ := s.GetSubCertFile()
@@ -811,6 +835,9 @@ func (s *SettingService) GetDefaultSettings(host string) (any, error) {
if subJsonEnable && result["subJsonURI"].(string) == "" {
result["subJsonURI"] = subURI + subJsonPath
}
+ if subClashEnable && result["subClashURI"].(string) == "" {
+ result["subClashURI"] = subURI + subClashPath
+ }
}
return result, nil