Skip to content

Commit

Permalink
feat(subscription): add settings template for clash
Browse files Browse the repository at this point in the history
  • Loading branch information
M03ED committed Jul 23, 2024
1 parent 4209ef4 commit 94a3f28
Show file tree
Hide file tree
Showing 9 changed files with 269 additions and 128 deletions.
225 changes: 142 additions & 83 deletions app/subscription/clash.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import copy
import json
from random import choice

Expand All @@ -6,7 +7,8 @@
from app.subscription.funcs import get_grpc_gun
from app.templates import render_template
from config import (
CLASH_SUBSCRIPTION_TEMPLATE,
CLASH_SUBSCRIPTION_TEMPLATE,
CLASH_SETTINGS_TEMPLATE,
MUX_TEMPLATE,
USER_AGENT_TEMPLATE,
)
Expand All @@ -22,15 +24,16 @@ def __init__(self):
}
self.proxy_remarks = []
self.mux_template = render_template(MUX_TEMPLATE)
temp_user_agent_data = render_template(USER_AGENT_TEMPLATE)
user_agent_data = json.loads(temp_user_agent_data)
user_agent_data = json.loads(render_template(USER_AGENT_TEMPLATE))

if 'list' in user_agent_data and isinstance(user_agent_data['list'], list):
self.user_agent_list = user_agent_data['list']
else:
self.user_agent_list = []

del temp_user_agent_data, user_agent_data
self.settings = yaml.load(render_template(CLASH_SETTINGS_TEMPLATE), Loader=yaml.SafeLoader)

del user_agent_data

def render(self, reverse=False):
if reverse:
Expand All @@ -44,7 +47,7 @@ def render(self, reverse=False):
Loader=yaml.SafeLoader
),
sort_keys=False,
allow_unicode=True
allow_unicode=True,
)

def __str__(self) -> str:
Expand All @@ -63,6 +66,82 @@ def _remark_validation(self, remark):
return new
c += 1

def http_config(
self,
path="",
host="",
random_user_agent: bool = False,
):
config = copy.deepcopy(self.settings.get("http-opts", {
'headers': {}
}))

if path:
config["path"] = [path]
if host:
config["Host"] = host
if random_user_agent:
if "headers" not in config:
config["headers"] = {}
config["header"]["User-Agent"] = choice(self.user_agent_list)

return config

def ws_config(
self,
path="",
host="",
max_early_data=None,
early_data_header_name="",
is_httpupgrade: bool =False,
random_user_agent: bool = False,
):
config = copy.deepcopy(self.settings.get("ws-opts", {}))
if (host or random_user_agent) and "headers" not in config:
config["headers"] = {}
if path:
config["path"] = path
if host:
config["headers"]["Host"] = host
if random_user_agent:
config["headers"]["User-Agent"] = choice(self.user_agent_list)
if max_early_data:
config["max-early-data"] = max_early_data
config["early-data-header-name"] = early_data_header_name
if is_httpupgrade:
config["v2ray-http-upgrade"] = True
if max_early_data:
config["v2ray-http-upgrade-fast-open"] = True

return config

def grpc_config(self, path=""):
config = copy.deepcopy(self.settings.get("grpc-opts", {}))
if path:
config["grpc-service-name"] = path

return config

def h2_config(self, path="", host=""):
config = copy.deepcopy(self.settings.get("h2-opts", {}))
if path:
config["path"] = path
if host:
config["host"] = [host]

return config

def tcp_config(self, path="", host=""):
config = copy.deepcopy(self.settings.get("tcp-opts", {}))
if path:
config["path"] = [path]
if host:
if "headers" not in config:
config["headers"] = {}
config["headers"]["Host"] = host

return config

def make_node(self,
name: str,
type: str,
Expand All @@ -87,6 +166,11 @@ def make_node(self,
type = 'ss'
if network == 'tcp' and headers == 'http':
network = 'http'
if network == 'httpupgrade':
network = 'ws'
is_httpupgrade = True
else:
is_httpupgrade = False

remark = self._remark_validation(name)
node = {
Expand All @@ -95,7 +179,6 @@ def make_node(self,
'server': server,
'port': port,
'network': network,
f'{network}-opts': {},
'udp': udp
}

Expand All @@ -106,6 +189,7 @@ def make_node(self,
early_data_header_name = "Sec-WebSocket-Protocol"
else:
max_early_data = None
early_data_header_name = ""

if type == 'ss': # shadowsocks
return node
Expand All @@ -121,54 +205,36 @@ def make_node(self,
if ais:
node['skip-cert-verify'] = ais

net_opts = node[f'{network}-opts']

if network == 'http':
if path:
net_opts['method'] = 'GET'
net_opts['path'] = [path]
if host:
net_opts['method'] = 'GET'
net_opts['Host'] = host
if random_user_agent:
net_opts['header'] = {"User-Agent": choice(self.user_agent_list)}

if network == 'ws' or network == 'httpupgrade':
if path:
net_opts['path'] = path
if host or random_user_agent:
net_opts['headers'] = {}
if host:
net_opts['headers']["Host"] = host
if random_user_agent:
net_opts['headers']["User-Agent"] = choice(self.user_agent_list)
if max_early_data:
net_opts['max-early-data'] = max_early_data
net_opts['early-data-header-name'] = early_data_header_name
if network == 'httpupgrade':
net_opts['v2ray-http-upgrade'] = True
if max_early_data:
net_opts['v2ray-http-upgrade-fast-open'] = True

if network == 'grpc' or network == 'gun':
if path:
net_opts['grpc-service-name'] = path
if random_user_agent:
net_opts['header'] = {"User-Agent": choice(self.user_agent_list)}

if network == 'h2':
if path:
net_opts['path'] = path
if host:
net_opts['host'] = [host]

if network == 'tcp':
if path:
net_opts['method'] = 'GET'
net_opts['path'] = [path]
if host:
net_opts['method'] = 'GET'
net_opts['headers'] = {"Host": host}
net_opts = self.http_config(
path=path,
host=host,
random_user_agent=random_user_agent,
)

elif network == 'ws':
net_opts = self.ws_config(
path=path,
host=host,
max_early_data=max_early_data,
early_data_header_name=early_data_header_name,
is_httpupgrade=is_httpupgrade,
random_user_agent=random_user_agent,
)

elif network == 'grpc' or network == 'gun':
net_opts = self.grpc_config(path=path)

elif network == 'h2':
net_opts = self.h2_config(path=path, host=host)

elif network == 'tcp':
net_opts = self.tcp_config(path=path, host=host)

else:
net_opts = {}

node[f'{network}-opts'] = net_opts

mux_json = json.loads(self.mux_template)
mux_config = mux_json["clash"]
Expand All @@ -183,7 +249,7 @@ def add(self, remark: str, address: str, inbound: dict, settings: dict):
# not supported by clash
if inbound['network'] in ("kcp", "splithttp"):
return

node = self.make_node(
name=remark,
type=inbound['protocol'],
Expand All @@ -197,28 +263,28 @@ def add(self, remark: str, address: str, inbound: dict, settings: dict):
headers=inbound['header_type'],
udp=True,
alpn=inbound.get('alpn', ''),
ais=inbound.get('ais', ''),
mux_enable=inbound.get('mux_enable', ''),
ais=inbound.get('ais', False),
mux_enable=inbound.get('mux_enable', False),
random_user_agent=inbound.get("random_user_agent")
)

if inbound['protocol'] == 'vmess':
node['uuid'] = settings['id']
node['alterId'] = 0
node['cipher'] = 'auto'
self.data['proxies'].append(node)
self.proxy_remarks.append(remark)

if inbound['protocol'] == 'trojan':
elif inbound['protocol'] == 'trojan':
node['password'] = settings['password']
self.data['proxies'].append(node)
self.proxy_remarks.append(remark)

if inbound['protocol'] == 'shadowsocks':
elif inbound['protocol'] == 'shadowsocks':
node['password'] = settings['password']
node['cipher'] = settings['method']
self.data['proxies'].append(node)
self.proxy_remarks.append(remark)

else:
return

self.data['proxies'].append(node)
self.proxy_remarks.append(remark)


class ClashMetaConfiguration(ClashConfiguration):
Expand Down Expand Up @@ -269,7 +335,7 @@ def add(self, remark: str, address: str, inbound: dict, settings: dict):
# not supported by clash-meta
if inbound['network'] in ("kcp", "splithttp"):
return

node = self.make_node(
name=remark,
type=inbound['protocol'],
Expand All @@ -286,38 +352,31 @@ def add(self, remark: str, address: str, inbound: dict, settings: dict):
fp=inbound.get('fp', ''),
pbk=inbound.get('pbk', ''),
sid=inbound.get('sid', ''),
ais=inbound.get('ais', ''),
mux_enable=inbound.get('mux_enable', ''),
ais=inbound.get('ais', False),
mux_enable=inbound.get('mux_enable', False),
random_user_agent=inbound.get("random_user_agent")
)

if inbound['protocol'] == 'vmess':
node['uuid'] = settings['id']
node['alterId'] = 0
node['cipher'] = 'auto'
self.data['proxies'].append(node)
self.proxy_remarks.append(remark)

if inbound['protocol'] == 'vless':
elif inbound['protocol'] == 'vless':
node['uuid'] = settings['id']

if inbound['network'] in ('tcp', 'kcp') and inbound['header_type'] != 'http' and inbound['tls'] != 'none':
node['flow'] = settings.get('flow', '')

self.data['proxies'].append(node)
self.proxy_remarks.append(remark)

if inbound['protocol'] == 'trojan':
elif inbound['protocol'] == 'trojan':
node['password'] = settings['password']

if inbound['network'] in ('tcp', 'kcp') and inbound['header_type'] != 'http' and inbound['tls']:
node['flow'] = settings.get('flow', '')

self.data['proxies'].append(node)
self.proxy_remarks.append(remark)

if inbound['protocol'] == 'shadowsocks':
elif inbound['protocol'] == 'shadowsocks':
node['password'] = settings['password']
node['cipher'] = settings['method']
self.data['proxies'].append(node)
self.proxy_remarks.append(remark)

else:
return

self.data['proxies'].append(node)
self.proxy_remarks.append(remark)
11 changes: 4 additions & 7 deletions app/subscription/singbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,18 @@ class SingBoxConfiguration(str):

def __init__(self):
self.proxy_remarks = []
template = render_template(SINGBOX_SUBSCRIPTION_TEMPLATE)
self.config = json.loads(template)
self.config = json.loads(render_template(SINGBOX_SUBSCRIPTION_TEMPLATE))
self.mux_template = render_template(MUX_TEMPLATE)
temp_user_agent_data = render_template(USER_AGENT_TEMPLATE)
user_agent_data = json.loads(temp_user_agent_data)
user_agent_data = json.loads(render_template(USER_AGENT_TEMPLATE))

if 'list' in user_agent_data and isinstance(user_agent_data['list'], list):
self.user_agent_list = user_agent_data['list']
else:
self.user_agent_list = []

temp_settings = render_template(SINGBOX_SETTINGS_TEMPLATE)
self.settings = json.loads(temp_settings)
self.settings = json.loads(render_template(SINGBOX_SETTINGS_TEMPLATE))

del temp_user_agent_data, user_agent_data, temp_settings
del user_agent_data

def _remark_validation(self, remark):
if not remark in self.proxy_remarks:
Expand Down
Loading

0 comments on commit 94a3f28

Please sign in to comment.