hiddifypanel 10.10.20__py3-none-any.whl → 10.11.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +2 -2
  3. hiddifypanel/hutils/__init__.py +3 -0
  4. hiddifypanel/hutils/crypto.py +29 -0
  5. hiddifypanel/hutils/encode.py +4 -0
  6. hiddifypanel/hutils/flask.py +4 -0
  7. hiddifypanel/hutils/github_issue.py +1 -1
  8. hiddifypanel/{models/utils.py → hutils/model.py} +14 -4
  9. hiddifypanel/hutils/network/net.py +46 -2
  10. hiddifypanel/hutils/proxy/__init__.py +4 -0
  11. hiddifypanel/hutils/proxy/clash.py +161 -0
  12. hiddifypanel/hutils/proxy/shared.py +414 -0
  13. hiddifypanel/hutils/proxy/singbox.py +338 -0
  14. hiddifypanel/hutils/proxy/xray.py +561 -0
  15. hiddifypanel/models/admin.py +16 -14
  16. hiddifypanel/models/base_account.py +4 -4
  17. hiddifypanel/models/config.py +1 -1
  18. hiddifypanel/models/proxy.py +17 -17
  19. hiddifypanel/models/user.py +15 -13
  20. hiddifypanel/panel/admin/AdminstratorAdmin.py +1 -1
  21. hiddifypanel/panel/admin/DomainAdmin.py +13 -27
  22. hiddifypanel/panel/admin/ProxyAdmin.py +3 -3
  23. hiddifypanel/panel/admin/SettingAdmin.py +22 -11
  24. hiddifypanel/panel/admin/UserAdmin.py +9 -7
  25. hiddifypanel/panel/cf_api.py +1 -2
  26. hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +5 -6
  27. hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +1 -1
  28. hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +4 -7
  29. hiddifypanel/panel/common.py +5 -3
  30. hiddifypanel/panel/hiddify.py +0 -90
  31. hiddifypanel/panel/init_db.py +14 -9
  32. hiddifypanel/panel/user/__init__.py +0 -1
  33. hiddifypanel/panel/user/templates/all_configs copy.txt +2 -2
  34. hiddifypanel/panel/user/templates/all_configs.txt +2 -2
  35. hiddifypanel/panel/user/templates/base_singbox_config.json.j2 +2 -1
  36. hiddifypanel/panel/user/templates/base_xray_config.json.j2 +125 -0
  37. hiddifypanel/panel/user/templates/clash_config copy.yml +1 -1
  38. hiddifypanel/panel/user/templates/clash_config.yml +4 -4
  39. hiddifypanel/panel/user/templates/clash_proxies.yml +1 -1
  40. hiddifypanel/panel/user/templates/home/all-configs.html +2 -2
  41. hiddifypanel/panel/user/templates/home/all-configs_old.html +1 -1
  42. hiddifypanel/panel/user/templates/home/ios copy.html +2 -2
  43. hiddifypanel/panel/user/user.py +50 -44
  44. hiddifypanel/templates/admin-layout.html +16 -24
  45. hiddifypanel/templates/fake.html +0 -276
  46. hiddifypanel/templates/flaskadmin-layout.html +2 -1
  47. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  48. hiddifypanel/translations/en/LC_MESSAGES/messages.po +16 -9
  49. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  50. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +12 -6
  51. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  52. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +9 -4
  53. hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
  54. hiddifypanel/translations/ru/LC_MESSAGES/messages.po +12 -7
  55. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  56. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +9 -4
  57. hiddifypanel/translations.i18n/en.json +8 -7
  58. hiddifypanel/translations.i18n/fa.json +5 -4
  59. hiddifypanel/translations.i18n/pt.json +3 -2
  60. hiddifypanel/translations.i18n/ru.json +6 -5
  61. hiddifypanel/translations.i18n/zh.json +3 -2
  62. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/METADATA +1 -1
  63. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/RECORD +67 -61
  64. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/WHEEL +1 -1
  65. hiddifypanel/panel/user/link_maker.py +0 -1089
  66. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/LICENSE.md +0 -0
  67. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/entry_points.txt +0 -0
  68. {hiddifypanel-10.10.20.dist-info → hiddifypanel-10.11.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,338 @@
1
+ from flask import render_template, request, g
2
+ import json
3
+
4
+ from hiddifypanel import hutils
5
+ from hiddifypanel.models import ProxyProto, ProxyTransport, Domain, ConfigEnum, hconfig
6
+ from hiddifypanel.panel.hiddify import is_hiddify_next_version
7
+
8
+
9
+ def configs_as_json(domains: list[Domain], **kwargs) -> str:
10
+ ua = hutils.flask.get_user_agent()
11
+ base_config = json.loads(render_template('base_singbox_config.json.j2'))
12
+ allphttp = [p for p in request.args.get("phttp", "").split(',') if p]
13
+ allptls = [p for p in request.args.get("ptls", "").split(',') if p]
14
+
15
+ allp = []
16
+ for d in domains:
17
+ base_config['dns']['rules'][0]['domain'].append(d.domain)
18
+ for pinfo in hutils.proxy.get_valid_proxies(domains):
19
+ sing = to_singbox(pinfo)
20
+ if 'msg' not in sing:
21
+ allp += sing
22
+ base_config['outbounds'] += allp
23
+
24
+ select = {
25
+ "type": "selector",
26
+ "tag": "Select",
27
+ "outbounds": [p['tag'] for p in allp if 'shadowtls-out' not in p['tag']],
28
+ "default": "Auto"
29
+ }
30
+ select['outbounds'].insert(0, "Auto")
31
+ base_config['outbounds'].insert(0, select)
32
+ smart = {
33
+ "type": "urltest",
34
+ "tag": "Auto",
35
+ "outbounds": [p['tag'] for p in allp if 'shadowtls-out' not in p],
36
+ "url": "https://www.gstatic.com/generate_204",
37
+ "interval": "10m",
38
+ "tolerance": 200
39
+ }
40
+ base_config['outbounds'].insert(1, smart)
41
+ res = json.dumps(base_config, indent=4, cls=hutils.proxy.ProxyJsonEncoder)
42
+ # if ua['is_hiddify']:
43
+ # res = res[:-1]+',"experimental": {}}'
44
+ return res
45
+
46
+
47
+ def to_singbox(proxy: dict) -> list[dict] | dict:
48
+ name = proxy['name']
49
+
50
+ all_base = []
51
+ if proxy['l3'] == "kcp":
52
+ return {'name': name, 'msg': "clash does not support kcp", 'type': 'debug'}
53
+
54
+ base = {}
55
+ all_base.append(base)
56
+ # vmess ws
57
+ base["tag"] = f"""{proxy['extra_info']} {proxy["name"]} § {proxy['port']} {proxy["dbdomain"].id}"""
58
+ base["type"] = str(proxy["proto"])
59
+ base["server"] = proxy["server"]
60
+ base["server_port"] = int(proxy["port"])
61
+ # base['alpn'] = proxy['alpn'].split(',')
62
+ if proxy["proto"] == "ssr":
63
+ add_ssr(base, proxy)
64
+ return all_base
65
+ if proxy["proto"] == ProxyProto.wireguard:
66
+ add_wireguard(base, proxy)
67
+ return all_base
68
+
69
+ if proxy["proto"] in ["ss", "v2ray"]:
70
+ add_shadowsocks_base(all_base, proxy)
71
+ return all_base
72
+ if proxy["proto"] == "ssh":
73
+ add_ssh(all_base, proxy)
74
+ return all_base
75
+
76
+ if proxy["proto"] == "trojan":
77
+ base["password"] = proxy["password"]
78
+
79
+ if proxy['proto'] in ['vmess', 'vless']:
80
+ base["uuid"] = proxy["uuid"]
81
+
82
+ if proxy['proto'] in ['vmess', 'vless', 'trojan']:
83
+ add_multiplex(base)
84
+
85
+ add_tls(base, proxy)
86
+
87
+ if g.user_agent.get('is_hiddify'):
88
+ add_tls_tricks(base, proxy)
89
+
90
+ if proxy.get('flow'):
91
+ base["flow"] = proxy['flow']
92
+ # base["flow-show"] = True
93
+
94
+ if proxy["proto"] == "vmess":
95
+ base["alter_id"] = 0
96
+ base["security"] = proxy["cipher"]
97
+
98
+ # base["udp"] = True
99
+ if proxy["proto"] in ["vmess", "vless"]:
100
+ base["packet_encoding"] = "xudp" # udp packet encoding
101
+
102
+ if proxy["proto"] == "tuic":
103
+ add_tuic(base, proxy)
104
+ elif proxy["proto"] == "hysteria2":
105
+ add_hysteria(base, proxy)
106
+ else:
107
+ add_transport(base, proxy)
108
+
109
+ return all_base
110
+
111
+
112
+ def add_multiplex(base: dict):
113
+ if not hconfig(ConfigEnum.mux_enable):
114
+ return
115
+ base['multiplex'] = {
116
+ "enabled": True,
117
+ "protocol": hconfig(ConfigEnum.mux_protocol),
118
+ "padding": hconfig(ConfigEnum.mux_padding_enable)
119
+ }
120
+ # Conflicts: max_streams with max_connections and min_streams
121
+ mux_max_streams = int(hconfig(ConfigEnum.mux_max_streams))
122
+ if mux_max_streams and mux_max_streams != 0:
123
+ base['multiplex']['max_streams'] = mux_max_streams
124
+ else:
125
+ base['multiplex']['max_connections'] = int(hconfig(ConfigEnum.mux_max_connections))
126
+ base['multiplex']['min_streams'] = int(hconfig(ConfigEnum.mux_min_streams))
127
+
128
+ add_tcp_brutal(base)
129
+
130
+
131
+ def add_tcp_brutal(base: dict):
132
+ if 'multiplex' in base:
133
+ base['multiplex']['brutal'] = {
134
+ "enabled": hconfig(ConfigEnum.mux_brutal_enable),
135
+ "up_mbps": int(hconfig(ConfigEnum.mux_brutal_up_mbps)),
136
+ "down_mbps": int(hconfig(ConfigEnum.mux_brutal_down_mbps))
137
+ }
138
+
139
+
140
+ def add_udp_over_tcp(base: dict):
141
+ base['udp_over_tcp'] = {
142
+ "enabled": True,
143
+ "version": 2
144
+ }
145
+
146
+
147
+ def add_tls(base: dict, proxy: dict):
148
+ if not ("tls" in proxy["l3"] or "reality" in proxy["l3"]):
149
+ return
150
+ base["tls"] = {
151
+ "enabled": True,
152
+ "server_name": proxy["sni"]
153
+ }
154
+ if proxy['proto'] not in ["tuic", "hysteria2"]:
155
+ base["tls"]["utls"] = {
156
+ "enabled": True,
157
+ "fingerprint": proxy.get('fingerprint', 'none')
158
+ }
159
+
160
+ if "reality" in proxy["l3"]:
161
+ base["tls"]["reality"] = {
162
+ "enabled": True,
163
+ "public_key": proxy['reality_pbk'],
164
+ "short_id": proxy['reality_short_id']
165
+ }
166
+ base["tls"]['insecure'] = proxy['allow_insecure'] or (proxy["mode"] == "Fake")
167
+ base["tls"]["alpn"] = proxy['alpn'].split(',')
168
+ # base['ech'] = {
169
+ # "enabled": True,
170
+ # }
171
+
172
+
173
+ def add_tls_tricks(base: dict, proxy: dict):
174
+ if proxy.get('tls_fragment_enable'):
175
+ base['tls_fragment'] = {
176
+ 'enabled': True,
177
+ 'size': proxy["tls_fragment_size"],
178
+ 'sleep': proxy["tls_fragment_sleep"]
179
+ }
180
+
181
+ if 'tls' in base:
182
+ if proxy.get("tls_padding_enable") or proxy.get("tls_mixed_case"):
183
+ base['tls']['tls_tricks'] = {}
184
+ if proxy.get("tls_padding_enable"):
185
+ base['tls']['tls_tricks']['padding_size'] = proxy["tls_padding_length"]
186
+
187
+ if proxy.get("tls_mixed_case"):
188
+ base['tls']['tls_tricks']['mixedcase_sni'] = True
189
+
190
+
191
+ def add_transport(base: dict, proxy: dict):
192
+ if proxy['l3'] == 'reality' and proxy['transport'] not in ["grpc"]:
193
+ return
194
+ base["transport"] = {}
195
+ if proxy['transport'] in ["ws", "WS"]:
196
+ base["transport"] = {
197
+ "type": "ws",
198
+ "path": proxy["path"],
199
+ "early_data_header_name": "Sec-WebSocket-Protocol"
200
+ }
201
+ if "host" in proxy:
202
+ base["transport"]["headers"] = {"Host": proxy["host"]}
203
+
204
+ if proxy['transport'] in [ProxyTransport.httpupgrade]:
205
+ base["transport"] = {
206
+ "type": "httpupgrade",
207
+ "path": proxy["path"]
208
+ }
209
+ if "host" in proxy:
210
+ base["transport"]["headers"] = {"Host": proxy["host"]}
211
+
212
+ if proxy["transport"] in ["tcp", "h2"]:
213
+ base["transport"] = {
214
+ "type": "http",
215
+ "path": proxy.get("path", ""),
216
+ "idle_timeout": "15s",
217
+ "ping_timeout": "15s"
218
+ # "method": "",
219
+ # "headers": {},
220
+ }
221
+
222
+ if 'host' in proxy:
223
+ base["transport"]["host"] = [proxy["host"]]
224
+
225
+ if proxy["transport"] == "grpc":
226
+ base["transport"] = {
227
+ "type": "grpc",
228
+ "service_name": proxy["grpc_service_name"],
229
+ "idle_timeout": "115s",
230
+ "ping_timeout": "15s",
231
+ # "permit_without_stream": false
232
+ }
233
+
234
+
235
+ def add_ssr(base: dict, proxy: dict):
236
+
237
+ base["method"] = proxy["cipher"]
238
+ base["password"] = proxy["uuid"]
239
+ # base["udp"] = True
240
+ base["obfs"] = proxy["ssr-obfs"]
241
+ base["protocol"] = proxy["ssr-protocol"]
242
+ base["protocol-param"] = proxy["fakedomain"]
243
+
244
+
245
+ def add_wireguard(base: dict, proxy: dict):
246
+
247
+ base["local_address"] = f'{proxy["wg_ipv4"]}/32'
248
+ base["private_key"] = proxy["wg_pk"]
249
+ base["peer_public_key"] = proxy["wg_server_pub"]
250
+
251
+ base["pre_shared_key"] = proxy["wg_psk"]
252
+
253
+ base["mtu"] = 1380
254
+ if g.user_agent.get('is_hiddify') and is_hiddify_next_version(0, 15, 0):
255
+ base["fake_packets"] = proxy["wg_noise_trick"]
256
+
257
+
258
+ def add_shadowsocks_base(all_base: list[dict], proxy: dict):
259
+ base = all_base[0]
260
+ base["type"] = "shadowsocks"
261
+ base["method"] = proxy["cipher"]
262
+ base["password"] = proxy["password"]
263
+ add_udp_over_tcp(base)
264
+ add_multiplex(base)
265
+ if proxy["transport"] == "faketls":
266
+ base["plugin"] = "obfs-local"
267
+ base["plugin_opts"] = f'obfs=tls;obfs-host={proxy["fakedomain"]}'
268
+ if proxy['proto'] == 'v2ray':
269
+ base["plugin"] = "v2ray-plugin"
270
+ # "skip-cert-verify": proxy["mode"] == "Fake" or proxy['allow_insecure'],
271
+ base["plugin_opts"] = f'mode=websocket;path={proxy["path"]};host={proxy["host"]};tls'
272
+
273
+ if proxy["transport"] == "shadowtls":
274
+ base['detour'] = base['tag'] + "_shadowtls-out §hide§"
275
+
276
+ shadowtls_base = {
277
+ "type": "shadowtls",
278
+ "tag": base['detour'],
279
+ "server": base['server'],
280
+ "server_port": base['server_port'],
281
+ "version": 3,
282
+ "password": proxy["shared_secret"],
283
+ "tls": {
284
+ "enabled": True,
285
+ "server_name": proxy["fakedomain"],
286
+ "utls": {
287
+ "enabled": True,
288
+ "fingerprint": proxy.get('fingerprint', 'none')
289
+ },
290
+ # "alpn": proxy['alpn'].split(',')
291
+ }
292
+ }
293
+ # add_utls(shadowtls_base)
294
+ del base['server']
295
+ del base['server_port']
296
+ all_base.append(shadowtls_base)
297
+
298
+
299
+ def add_ssh(all_base: list[dict], proxy: dict):
300
+ base = all_base[0]
301
+ # base["client_version"]= "{{ssh_client_version}}"
302
+ base["user"] = proxy['uuid']
303
+ base["private_key"] = proxy['private_key'] # .replace('\n', '\\n')
304
+
305
+ base["host_key"] = proxy.get('host_key', [])
306
+
307
+ socks_front = {
308
+ "type": "socks",
309
+ "tag": base['tag'] + "+UDP",
310
+ "server": "127.0.0.1",
311
+ "server_port": 2000,
312
+ "version": "5",
313
+ "udp_over_tcp": True,
314
+ "network": "tcp",
315
+ "detour": base['tag']
316
+ }
317
+ all_base.append(socks_front)
318
+
319
+
320
+ def add_tuic(base: dict, proxy: dict):
321
+ base['congestion_control'] = "cubic"
322
+ base['udp_relay_mode'] = 'native'
323
+ base['zero_rtt_handshake'] = True
324
+ base['heartbeat'] = "10s"
325
+ base['password'] = proxy['uuid']
326
+ base['uuid'] = proxy['uuid']
327
+
328
+
329
+ def add_hysteria(base: dict, proxy: dict):
330
+ base['up_mbps'] = int(hconfig(ConfigEnum.hysteria_up_mbps))
331
+ base['down_mbps'] = int(hconfig(ConfigEnum.hysteria_down_mbps))
332
+ # TODO: check the obfs should be empty or not exists at all
333
+ if hconfig(ConfigEnum.hysteria_obfs_enable):
334
+ base['obfs'] = {
335
+ "type": "salamander",
336
+ "password": hconfig(ConfigEnum.proxy_path)
337
+ }
338
+ base['password'] = proxy['uuid']