From 9097ab3e49dbd2fb6adbd2e23a4b7e0915243ae6 Mon Sep 17 00:00:00 2001 From: xx10n3ly Date: Wed, 22 Nov 2023 22:23:53 +0800 Subject: [PATCH 1/2] add only proxy and proxy group --- logs/.gitignore | 2 ++ services/subscription.py | 12 +++++++++--- services/web_service.py | 14 ++++++++++++++ templates/index.html | 19 +++++++++++++++++++ 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 logs/.gitignore diff --git a/logs/.gitignore b/logs/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/logs/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/services/subscription.py b/services/subscription.py index a0d4ef3..467cefe 100644 --- a/services/subscription.py +++ b/services/subscription.py @@ -12,7 +12,7 @@ CLASH = json.load(open("./config/clash.json", "r", encoding="utf8")) -def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__name__), best=False): +def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__name__), best=False, only_proxies=False): """ Generate Clash subscription file :param account: @@ -30,11 +30,13 @@ def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__n user_config = [] # Use len() instead of RANDOM_COUNT because the entrypoints may be less than RANDOM_COUNT + j = 1 for i in range(len(random_points)): point = random_points[i] user_config.append( { - "name": f"{fake.emoji()} CF-{fake.color_name()}", + # "name": f"{fake.emoji()} CF-{fake.color_name()}", + "name": f"CF-WARP-{j}", "type": "wireguard", "server": point.ip, "port": point.port, @@ -44,13 +46,17 @@ def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__n "remote-dns-resolve": False, "udp": False }) + j += 1 clashJSON = copy.deepcopy(CLASH) clashJSON["proxies"] = user_config for proxyGroup in clashJSON["proxy-groups"]: proxyGroup["proxies"] += [proxy["name"] for proxy in user_config] # Generate YAML file - clashYAML = yaml.dump(clashJSON, allow_unicode=True) + if only_proxies: + clashYAML = yaml.dump({'proxies': clashJSON['proxies'], 'proxy-groups': clashJSON['proxy-groups']}, allow_unicode=True) + else: + clashYAML = yaml.dump(clashJSON, allow_unicode=True) return clashYAML diff --git a/services/web_service.py b/services/web_service.py index 281e646..0bdfc08 100644 --- a/services/web_service.py +++ b/services/web_service.py @@ -127,6 +127,20 @@ def http_wireguard(): return response + @app.route('/api/only_proxies', methods=['GET']) + @rate_limit() + @authorized() + def only_proxies(): + account = getCurrentAccount(logger) + best = request.args.get('best') or False + fileData = generate_Clash_subFile(account, logger, best=best, only_proxies=True) + + response = make_response(fileData) + # response.headers = headers + + return response + + def create_app(app_name: str = "web", logger: logging.Logger = None) -> Flask: if logger is None: diff --git a/templates/index.html b/templates/index.html index f714840..eeacfc3 100644 --- a/templates/index.html +++ b/templates/index.html @@ -112,6 +112,9 @@

Clash

Wireguard

+

Only Proxies & Proxies Group

+ + 点击复制节点信息

账户信息

点击查看 @@ -148,6 +151,8 @@

账户信息

width: 200, height: 200 }); + const url = baseUrl + "only_proxies?" + queryParams.toString(); + getOnlyProxy(url) } function copyText(elem) { @@ -167,6 +172,20 @@

账户信息

}, 1000); } + function getOnlyProxy(url) { + const xhr = new XMLHttpRequest(); + xhr.open('GET', url) + xhr.send() + xhr.onload = function() { + if (xhr.status != 200) { + showToast(`Error ${xhr.status}: ${xhr.statusText}`) + } else { + document.getElementById('proxy_info').textContent = ''; + document.getElementById('proxy_info').textContent = xhr.response; + } + } + } + generateLink() From 53b0de6b8edd567c522cab41938b65b374c61c9a Mon Sep 17 00:00:00 2001 From: vvbbnn00 Date: Fri, 24 Nov 2023 03:33:49 +0800 Subject: [PATCH 2/2] Add option `only_proxies` and `random_name`. - `only_proxies`: This option determines whether the API returns built-in Clash rules. - `random_name`: This option controls whether the API generates random node names. When set to false, the node name will take the form of `CF-WARP-1`. --- services/subscription.py | 17 +++++++++----- services/web_service.py | 18 +++++++++++---- templates/index.html | 48 +++++++++++++++++++++++++--------------- 3 files changed, 55 insertions(+), 28 deletions(-) diff --git a/services/subscription.py b/services/subscription.py index 467cefe..3945914 100644 --- a/services/subscription.py +++ b/services/subscription.py @@ -12,9 +12,15 @@ CLASH = json.load(open("./config/clash.json", "r", encoding="utf8")) -def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__name__), best=False, only_proxies=False): +def generate_Clash_subFile(account: Account = None, + logger=logging.getLogger(__name__), + best=False, + only_proxies=False, + random_name=False): """ Generate Clash subscription file + :param random_name: Whether to use random name + :param only_proxies: If this is True, only generate proxies :param account: :param logger: :param best: Whether to use the best entrypoints @@ -30,13 +36,12 @@ def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__n user_config = [] # Use len() instead of RANDOM_COUNT because the entrypoints may be less than RANDOM_COUNT - j = 1 for i in range(len(random_points)): point = random_points[i] + name = f"{fake.emoji()} CF-{fake.color_name()}" if random_name else f"CF-WARP-{i + 1}" user_config.append( { - # "name": f"{fake.emoji()} CF-{fake.color_name()}", - "name": f"CF-WARP-{j}", + "name": name, "type": "wireguard", "server": point.ip, "port": point.port, @@ -46,7 +51,6 @@ def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__n "remote-dns-resolve": False, "udp": False }) - j += 1 clashJSON = copy.deepcopy(CLASH) clashJSON["proxies"] = user_config for proxyGroup in clashJSON["proxy-groups"]: @@ -54,7 +58,8 @@ def generate_Clash_subFile(account: Account = None, logger=logging.getLogger(__n # Generate YAML file if only_proxies: - clashYAML = yaml.dump({'proxies': clashJSON['proxies'], 'proxy-groups': clashJSON['proxy-groups']}, allow_unicode=True) + clashYAML = yaml.dump({'proxies': clashJSON['proxies'], 'proxy-groups': clashJSON['proxy-groups']}, + allow_unicode=True) else: clashYAML = yaml.dump(clashJSON, allow_unicode=True) return clashYAML diff --git a/services/web_service.py b/services/web_service.py index 0bdfc08..9f40c78 100644 --- a/services/web_service.py +++ b/services/web_service.py @@ -96,7 +96,9 @@ def http_account(): def http_clash(): account = getCurrentAccount(logger) best = request.args.get('best') or False - fileData = generate_Clash_subFile(account, logger, best=best) + random_name = request.args.get('randomName').lower() == "true" or False + + fileData = generate_Clash_subFile(account, logger, best=best, random_name=random_name) headers = { 'Content-Type': 'application/x-yaml; charset=utf-8', @@ -115,6 +117,7 @@ def http_clash(): def http_wireguard(): account = getCurrentAccount(logger) best = request.args.get('best') or False + fileData = generate_Wireguard_subFile(account, logger, best=best) headers = { @@ -133,13 +136,20 @@ def http_wireguard(): def only_proxies(): account = getCurrentAccount(logger) best = request.args.get('best') or False - fileData = generate_Clash_subFile(account, logger, best=best, only_proxies=True) + random_name = request.args.get('randomName').lower() == "true" or False + + fileData = generate_Clash_subFile(account, logger, best=best, only_proxies=True, random_name=random_name) response = make_response(fileData) - # response.headers = headers + headers = { + 'Content-Type': 'application/x-yaml; charset=utf-8', + 'Content-Disposition': f'attachment; filename=Clash-{fake.color_name()}.yaml', + "Subscription-Userinfo": f"upload=0; download={account.usage}; total={account.quota}; expire=253388144714" + } + + response.headers = headers return response - def create_app(app_name: str = "web", logger: logging.Logger = None) -> Flask: diff --git a/templates/index.html b/templates/index.html index eeacfc3..5fb7d5d 100644 --- a/templates/index.html +++ b/templates/index.html @@ -73,7 +73,7 @@ left: 50%; transform: translateX(-50%); padding: 10px 20px; - background-color: rgba(110, 255, 114, 0.8); + background-color: rgba(110, 255, 114); color: #4caf50; border-radius: 4px; font-size: 16px; @@ -85,6 +85,12 @@ .show { opacity: 1; } + + .tip { + color: #666; + font-size: 14px; + margin-bottom: 10px; + } @@ -104,6 +110,9 @@

WARP Clash 订阅地址生成器

+
@@ -113,8 +122,12 @@

Clash

Wireguard

Only Proxies & Proxies Group

- - 点击复制节点信息 +
+ 该链接仅包含节点信息,不包含规则信息,适用于自定义规则的用户。 +
+ + 点击复制节点信息 +

账户信息

点击查看
@@ -131,9 +144,11 @@

账户信息

function generateLink() { const password = document.getElementById('passwordInput').value; const best = document.getElementById('alwaysBest').checked; + const randomName = document.getElementById('randomName').checked; const baseUrl = location.protocol + '//' + location.host + '/api/'; const queryParams = new URLSearchParams({ - best + best, + randomName }); if (password.length) { @@ -143,6 +158,7 @@

账户信息

document.getElementById('subscriptionLink').textContent = baseUrl + "clash?" + queryParams.toString(); document.getElementById('WireguardLink').textContent = baseUrl + "wireguard?" + queryParams.toString(); document.getElementById('AccountLink').href = baseUrl + "account?" + queryParams.toString(); + document.getElementById('onlyProxyLink').textContent = baseUrl + "only_proxies?" + queryParams.toString(); const qrcodeContainer = document.getElementById('qrcode'); qrcodeContainer.innerHTML = ''; @@ -151,8 +167,6 @@

账户信息

width: 200, height: 200 }); - const url = baseUrl + "only_proxies?" + queryParams.toString(); - getOnlyProxy(url) } function copyText(elem) { @@ -172,18 +186,16 @@

账户信息

}, 1000); } - function getOnlyProxy(url) { - const xhr = new XMLHttpRequest(); - xhr.open('GET', url) - xhr.send() - xhr.onload = function() { - if (xhr.status != 200) { - showToast(`Error ${xhr.status}: ${xhr.statusText}`) - } else { - document.getElementById('proxy_info').textContent = ''; - document.getElementById('proxy_info').textContent = xhr.response; - } - } + function getOnlyProxy() { + const url = document.getElementById('onlyProxyLink').textContent; + fetch(url, { + method: 'GET', + }).then(res => res.text()).then(res => { + document.getElementById('onlyProxyInfo').textContent = res; + copyText('onlyProxyInfo'); + }).catch(err => { + showToast(`Error ${err.status}: ${err.statusText}`) + }); } generateLink()