hiddifypanel 9.0.0.dev60__py3-none-any.whl → 9.0.0.dev61__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.
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +2 -2
- hiddifypanel/base.py +5 -4
- hiddifypanel/hutils/__init__.py +8 -1
- hiddifypanel/hutils/auth.py +94 -0
- hiddifypanel/hutils/auto_ip_selector.py +1 -1
- hiddifypanel/hutils/convert.py +14 -0
- hiddifypanel/hutils/encode.py +11 -0
- hiddifypanel/hutils/flask.py +24 -0
- hiddifypanel/{panel/github_issue_generator.py → hutils/github_issue.py} +104 -14
- hiddifypanel/hutils/json.py +24 -0
- hiddifypanel/hutils/random.py +19 -0
- hiddifypanel/hutils/utils.py +0 -169
- hiddifypanel/models/__init__.py +1 -0
- hiddifypanel/models/admin.py +53 -8
- hiddifypanel/models/base_account.py +31 -169
- hiddifypanel/models/domain.py +2 -2
- hiddifypanel/models/parent_domain.py +1 -0
- hiddifypanel/models/user.py +105 -33
- hiddifypanel/models/utils.py +3 -3
- hiddifypanel/panel/admin/Actions.py +5 -6
- hiddifypanel/panel/admin/Backup.py +5 -5
- hiddifypanel/panel/admin/ChildAdmin.py +3 -3
- hiddifypanel/panel/admin/Dashboard.py +12 -10
- hiddifypanel/panel/admin/DomainAdmin.py +10 -9
- hiddifypanel/panel/admin/ProxyAdmin.py +4 -6
- hiddifypanel/panel/admin/QuickSetup.py +11 -13
- hiddifypanel/panel/admin/SettingAdmin.py +13 -11
- hiddifypanel/panel/admin/UserAdmin.py +13 -12
- hiddifypanel/panel/auth.py +42 -9
- hiddifypanel/panel/auth_back2.py +5 -5
- hiddifypanel/panel/cli.py +1 -0
- hiddifypanel/panel/commercial/ParentDomainAdmin.py +3 -3
- hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +1 -0
- hiddifypanel/panel/commercial/restapi/v1/tgmsg.py +1 -1
- hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +5 -4
- hiddifypanel/panel/commercial/restapi/v2/user/info_api.py +7 -11
- hiddifypanel/panel/commercial/telegrambot/admin.py +1 -0
- hiddifypanel/panel/common.py +10 -86
- hiddifypanel/panel/common_bp/login.py +9 -8
- hiddifypanel/panel/database.py +22 -21
- hiddifypanel/panel/hiddify.py +25 -28
- hiddifypanel/panel/importer/xui.py +2 -2
- hiddifypanel/panel/init_db.py +20 -13
- hiddifypanel/panel/usage.py +2 -1
- hiddifypanel/panel/user/link_maker.py +118 -15
- hiddifypanel/panel/user/user.py +25 -19
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +252 -234
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +280 -228
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +240 -207
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +240 -207
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +779 -2740
- {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/METADATA +2 -1
- {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/RECORD +63 -57
- {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/WHEEL +0 -0
- {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/entry_points.txt +0 -0
- {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
from flask import g, request, render_template
|
2
|
-
from ipaddress import IPv4Address,
|
2
|
+
from ipaddress import IPv4Address, IPv6Address
|
3
3
|
import enum
|
4
4
|
from hiddifypanel import hutils
|
5
5
|
from hiddifypanel.models import *
|
@@ -235,7 +235,7 @@ def to_link(proxy):
|
|
235
235
|
if 'error' in proxy:
|
236
236
|
return proxy
|
237
237
|
orig_name_link = (proxy['extra_info'] + " " + proxy["name"]).strip()
|
238
|
-
name_link =
|
238
|
+
name_link = hutils.encode.url_encode(orig_name_link)
|
239
239
|
if proxy['proto'] == 'vmess':
|
240
240
|
# print(proxy)
|
241
241
|
vmess_type = None
|
@@ -264,12 +264,18 @@ def to_link(proxy):
|
|
264
264
|
vmess_data['pbk'] = proxy['reality_pbk']
|
265
265
|
vmess_data['sid'] = proxy['reality_short_id']
|
266
266
|
|
267
|
-
|
267
|
+
if proxy['cdn'] and g.user_agent.get('is_hiddify'):
|
268
|
+
add_tls_tricks_to_dict(vmess_data)
|
269
|
+
add_mux_to_dict(vmess_data)
|
270
|
+
|
271
|
+
return "vmess://" + hutils.encode.do_base_64(f'{json.dumps(vmess_data,cls=CustomEncoder)}')
|
268
272
|
# return pbase64(f'vmess://{json.dumps(vmess_data)}')
|
269
273
|
if proxy['proto'] == 'ssh':
|
270
|
-
strenssh =
|
274
|
+
strenssh = hutils.encode.do_base_64(f'{proxy["uuid"]}:0:{proxy["private_key"]}::@{proxy["server"]}:{proxy["port"]}')
|
271
275
|
baseurl = f'ssh://{strenssh}#{name_link}'
|
272
|
-
|
276
|
+
hk = hutils.encode.do_base_64(",".join(proxy["host_key"]))
|
277
|
+
pk = hutils.encode.do_base_64(proxy["private_key"])
|
278
|
+
baseurl += f'\nssh://{proxy["uuid"]}@{proxy["server"]}:{proxy["port"]}/?pk={pk}&hk={hk}#{name_link}'
|
273
279
|
|
274
280
|
return baseurl
|
275
281
|
if proxy['proto'] == "ssr":
|
@@ -298,6 +304,14 @@ def to_link(proxy):
|
|
298
304
|
baseurl += f'&sni={proxy["sni"]}&type={proxy["transport"]}'
|
299
305
|
baseurl += f"&alpn={proxy['alpn']}"
|
300
306
|
|
307
|
+
# the ray2sing supports vless, vmess and trojan tls tricks and mux
|
308
|
+
# the vmess handled already
|
309
|
+
|
310
|
+
if proxy['proto'] in {'vless', 'trojan'}:
|
311
|
+
baseurl = add_mux_to_link(baseurl)
|
312
|
+
if proxy['cdn'] and g.user_agent.get('is_hiddify'):
|
313
|
+
baseurl = add_tls_tricks_to_link(baseurl)
|
314
|
+
|
301
315
|
# infos+=f'&alpn={proxy["alpn"]}'
|
302
316
|
baseurl += f'&path={proxy["path"]}' if "path" in proxy else ""
|
303
317
|
baseurl += f'&host={proxy["host"]}' if "host" in proxy else ""
|
@@ -329,6 +343,54 @@ def to_link(proxy):
|
|
329
343
|
return f'{baseurl}&security=none{infos}'
|
330
344
|
return proxy
|
331
345
|
|
346
|
+
# region tls tricks & mux
|
347
|
+
# notice: combining the functions into two function would make code less readable and difficult to maintain
|
348
|
+
|
349
|
+
|
350
|
+
def add_tls_tricks_to_link(link: str) -> str:
|
351
|
+
if hconfig(ConfigEnum.tls_fragment_enable):
|
352
|
+
link += f'&fgsize={hconfig(ConfigEnum.tls_fragment_size)}&fgsleep={hconfig(ConfigEnum.tls_fragment_sleep)}'
|
353
|
+
if hconfig(ConfigEnum.tls_mixed_case):
|
354
|
+
link += '&mc=1'
|
355
|
+
if hconfig(ConfigEnum.tls_padding_enable):
|
356
|
+
link += f'&padsize={hconfig(ConfigEnum.tls_padding_length)}'
|
357
|
+
return link
|
358
|
+
|
359
|
+
|
360
|
+
def add_mux_to_link(link: str) -> str:
|
361
|
+
if hconfig(ConfigEnum.mux_enable):
|
362
|
+
link += f'&mux={hconfig(ConfigEnum.mux_protocol)}&mux_max={hconfig(ConfigEnum.mux_max_connections)}&mux_min={hconfig(ConfigEnum.mux_min_streams)}&mux_pad={hconfig(ConfigEnum.mux_padding_enable)}'
|
363
|
+
if hconfig(ConfigEnum.mux_brutal_enable):
|
364
|
+
link += f'&mux_up={hconfig(ConfigEnum.mux_brutal_up_mbps)}&mux_down={hconfig(ConfigEnum.mux_brutal_down_mbps)}'
|
365
|
+
return link
|
366
|
+
|
367
|
+
|
368
|
+
def add_tls_tricks_to_dict(d: dict):
|
369
|
+
if hconfig(ConfigEnum.tls_fragment_enable):
|
370
|
+
d['fgsize'] = hconfig(ConfigEnum.tls_fragment_size)
|
371
|
+
d['fgsleep'] = hconfig(ConfigEnum.tls_fragment_sleep)
|
372
|
+
if hconfig(ConfigEnum.tls_mixed_case):
|
373
|
+
d['mc'] = 1
|
374
|
+
if hconfig(ConfigEnum.tls_padding_enable):
|
375
|
+
d['padsize'] = hconfig(ConfigEnum.tls_padding_length)
|
376
|
+
|
377
|
+
|
378
|
+
def add_mux_to_dict(d: dict):
|
379
|
+
if hconfig(ConfigEnum.mux_enable):
|
380
|
+
d['mux'] = hconfig(ConfigEnum.mux_protocol)
|
381
|
+
d['mux_max'] = hconfig(ConfigEnum.mux_max_connections)
|
382
|
+
d['mux_min'] = hconfig(ConfigEnum.mux_min_streams)
|
383
|
+
d['mux_pad'] = hconfig(ConfigEnum.mux_padding_enable)
|
384
|
+
# the hiddify next client doesn't support mux max streams
|
385
|
+
# vmess_data['mux_max_streams'] = hconfig(ConfigEnum.mux_max_streams)
|
386
|
+
|
387
|
+
# handle brutal tcp
|
388
|
+
if hconfig(ConfigEnum.mux_brutal_enable):
|
389
|
+
d['mux_up'] = hconfig(ConfigEnum.mux_brutal_up_mbps)
|
390
|
+
d['mux_down'] = hconfig(ConfigEnum.mux_brutal_down_mbps)
|
391
|
+
|
392
|
+
# endregion
|
393
|
+
|
332
394
|
|
333
395
|
def to_clash_yml(proxy):
|
334
396
|
return yaml.dump(to_clash(proxy))
|
@@ -523,6 +585,9 @@ def to_singbox(proxy):
|
|
523
585
|
|
524
586
|
add_singbox_tls(base, proxy)
|
525
587
|
|
588
|
+
if proxy['cdn'] and g.user_agent.get('is_hiddify') and proxy["proto"] in ['vmess', 'vless', 'trojan']:
|
589
|
+
add_singbox_tls_tricks(base)
|
590
|
+
|
526
591
|
if proxy.get('flow'):
|
527
592
|
base["flow"] = proxy['flow']
|
528
593
|
# base["flow-show"] = True
|
@@ -567,15 +632,31 @@ def add_hysteria(base, proxy):
|
|
567
632
|
|
568
633
|
|
569
634
|
def add_singbox_multiplex(base):
|
570
|
-
|
635
|
+
if not hconfig(ConfigEnum.mux_enable):
|
636
|
+
return
|
571
637
|
base['multiplex'] = {
|
572
638
|
"enabled": True,
|
573
|
-
"protocol":
|
574
|
-
"
|
575
|
-
"min_streams": 4,
|
576
|
-
"max_streams": 0,
|
577
|
-
"padding": false
|
639
|
+
"protocol": hconfig(ConfigEnum.mux_protocol),
|
640
|
+
"padding": hconfig(ConfigEnum.mux_padding_enable)
|
578
641
|
}
|
642
|
+
# Conflicts: max_streams with max_connections and min_streams
|
643
|
+
mux_max_streams = int(hconfig(ConfigEnum.mux_max_streams))
|
644
|
+
if mux_max_streams and mux_max_streams != 0:
|
645
|
+
base['multiplex']['max_streams'] = mux_max_streams
|
646
|
+
else:
|
647
|
+
base['multiplex']['max_connections'] = int(hconfig(ConfigEnum.mux_max_connections))
|
648
|
+
base['multiplex']['min_streams'] = int(hconfig(ConfigEnum.mux_min_streams))
|
649
|
+
|
650
|
+
add_singbox_tcp_brutal(base)
|
651
|
+
|
652
|
+
|
653
|
+
def add_singbox_tcp_brutal(base):
|
654
|
+
if 'multiplex' in base:
|
655
|
+
base['multiplex']['brutal'] = {
|
656
|
+
"enabled": hconfig(ConfigEnum.mux_brutal_enable),
|
657
|
+
"up_mbps": int(hconfig(ConfigEnum.mux_brutal_up_mbps)),
|
658
|
+
"down_mbps": int(hconfig(ConfigEnum.mux_brutal_down_mbps))
|
659
|
+
}
|
579
660
|
|
580
661
|
|
581
662
|
def add_singbox_udp_over_tcp(base):
|
@@ -611,6 +692,28 @@ def add_singbox_tls(base, proxy):
|
|
611
692
|
# }
|
612
693
|
|
613
694
|
|
695
|
+
def add_singbox_tls_tricks(base):
|
696
|
+
if hconfig(ConfigEnum.tls_fragment_enable):
|
697
|
+
base['tls_fragment'] = {
|
698
|
+
# 'enable': True,
|
699
|
+
'size': hconfig(ConfigEnum.tls_fragment_size),
|
700
|
+
'sleep': hconfig(ConfigEnum.tls_fragment_sleep)
|
701
|
+
}
|
702
|
+
|
703
|
+
tls_padding_enable = hconfig(ConfigEnum.tls_padding_enable)
|
704
|
+
tls_mixed_case = hconfig(ConfigEnum.tls_mixed_case)
|
705
|
+
if (tls_padding_enable or tls_mixed_case) and 'tls' not in base:
|
706
|
+
base['tls'] = {
|
707
|
+
'tls_tricks': {}
|
708
|
+
}
|
709
|
+
if hconfig(ConfigEnum.tls_padding_enable):
|
710
|
+
base['tls']['tls_tricks'] = {
|
711
|
+
'padding_size': hconfig(ConfigEnum.tls_padding_length)
|
712
|
+
}
|
713
|
+
if hconfig(ConfigEnum.tls_mixed_case):
|
714
|
+
base['tls']['tls_tricks']['mixedcase_sni'] = True
|
715
|
+
|
716
|
+
|
614
717
|
def add_singbox_transport(base, proxy):
|
615
718
|
if proxy['l3'] == 'reality' and proxy['transport'] not in ["grpc"]:
|
616
719
|
return
|
@@ -769,7 +872,7 @@ def make_v2ray_configs(user, user_activate, domains, expire_days, ip_debug, db_d
|
|
769
872
|
# res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{round(user.current_usage_GB,3)}/{user.usage_limit_GB}GB_Remain:{expire_days}days')
|
770
873
|
# else:
|
771
874
|
|
772
|
-
# res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{
|
875
|
+
# res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{hutils.encode.url_encode(profile_title)}')
|
773
876
|
|
774
877
|
name = '⏳' if user_activate else '✖'
|
775
878
|
if user.usage_limit_GB < 1000:
|
@@ -785,7 +888,7 @@ def make_v2ray_configs(user, user_activate, domains, expire_days, ip_debug, db_d
|
|
785
888
|
|
786
889
|
name = name.strip()
|
787
890
|
if len(name) > 3:
|
788
|
-
res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{
|
891
|
+
res.append(f'trojan://1@{fake_ip_for_sub_link}?sni=fake_ip_for_sub_link&security=tls#{hutils.encode.url_encode(name)}')
|
789
892
|
|
790
893
|
if ua['is_browser']:
|
791
894
|
res.append(f'#Hiddify auto ip: {ip_debug}')
|
@@ -793,9 +896,9 @@ def make_v2ray_configs(user, user_activate, domains, expire_days, ip_debug, db_d
|
|
793
896
|
if not user_activate:
|
794
897
|
|
795
898
|
if hconfig(ConfigEnum.lang) == 'fa':
|
796
|
-
res.append('trojan://1@1.1.1.1#'+
|
899
|
+
res.append('trojan://1@1.1.1.1#'+hutils.encode.url_encode('✖بسته شما به پایان رسید'))
|
797
900
|
else:
|
798
|
-
res.append('trojan://1@1.1.1.1#'+
|
901
|
+
res.append('trojan://1@1.1.1.1#'+hutils.encode.url_encode('✖Package_Ended'))
|
799
902
|
return "\n".join(res)
|
800
903
|
|
801
904
|
for pinfo in get_all_validated_proxies(domains):
|
hiddifypanel/panel/user/user.py
CHANGED
@@ -1,19 +1,22 @@
|
|
1
|
+
import user_agents
|
2
|
+
import datetime
|
3
|
+
import random
|
4
|
+
import re
|
1
5
|
|
2
|
-
from flask import
|
6
|
+
from flask import render_template, request, Response, g
|
3
7
|
from apiflask import abort
|
4
|
-
from hiddifypanel.hutils import auto_ip_selector
|
5
|
-
import datetime
|
6
|
-
from hiddifypanel.models import *
|
7
|
-
from hiddifypanel.panel.database import db
|
8
|
-
from hiddifypanel.panel import hiddify
|
9
8
|
from . import link_maker
|
10
9
|
from flask_classful import FlaskView, route
|
11
|
-
import random
|
12
10
|
from urllib.parse import urlparse
|
13
|
-
import user_agents
|
14
11
|
from flask_babelex import gettext as _
|
15
|
-
|
12
|
+
|
13
|
+
|
16
14
|
from hiddifypanel.panel.auth import login_required
|
15
|
+
from hiddifypanel.hutils import auto_ip_selector
|
16
|
+
from hiddifypanel.panel.database import db
|
17
|
+
from hiddifypanel.panel import hiddify
|
18
|
+
from hiddifypanel.models import *
|
19
|
+
from hiddifypanel import hutils
|
17
20
|
|
18
21
|
|
19
22
|
class UserView(FlaskView):
|
@@ -129,6 +132,9 @@ class UserView(FlaskView):
|
|
129
132
|
@ route('/report', methods=["POST"])
|
130
133
|
@login_required(roles={Role.user})
|
131
134
|
def report(self):
|
135
|
+
|
136
|
+
# THE REPORT MODEL IS NOT COMPLETED YET.
|
137
|
+
|
132
138
|
data = request.get_json()
|
133
139
|
user_ip = auto_ip_selector.get_real_user_ip()
|
134
140
|
report = Report()
|
@@ -217,11 +223,11 @@ class UserView(FlaskView):
|
|
217
223
|
if request.method == 'HEAD':
|
218
224
|
resp = ""
|
219
225
|
else:
|
220
|
-
# render_template('all_configs.txt', **c, base64=do_base_64)
|
226
|
+
# render_template('all_configs.txt', **c, base64=hutils.encode.do_base_64)
|
221
227
|
resp = link_maker.make_v2ray_configs(**c)
|
222
228
|
|
223
229
|
if base64:
|
224
|
-
resp = do_base_64(resp)
|
230
|
+
resp = hutils.encode.do_base_64(resp)
|
225
231
|
return add_headers(resp, c)
|
226
232
|
|
227
233
|
@ route("/offline.html")
|
@@ -236,10 +242,10 @@ class UserView(FlaskView):
|
|
236
242
|
return ""
|
237
243
|
|
238
244
|
|
239
|
-
def do_base_64(str):
|
240
|
-
|
241
|
-
|
242
|
-
|
245
|
+
# def do_base_64(str):
|
246
|
+
# import base64
|
247
|
+
# resp = base64.b64encode(f'{str}'.encode("utf-8"))
|
248
|
+
# return resp.decode()
|
243
249
|
|
244
250
|
|
245
251
|
def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
@@ -263,7 +269,7 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
263
269
|
|
264
270
|
if not db_domain:
|
265
271
|
db_domain = DB(domain=domain, show_domains=[])
|
266
|
-
flash(_("This domain does not exist in the panel!" + domain))
|
272
|
+
hutils.flask.flash(_("This domain does not exist in the panel!" + domain))
|
267
273
|
|
268
274
|
if mode == 'multi':
|
269
275
|
domains = Domain.query.all()
|
@@ -301,7 +307,7 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
301
307
|
d.cdn_ip, d.mode == DomainType.auto_cdn_ip, default_asn)
|
302
308
|
# print("autocdn ip mode ", d.cdn_ip)
|
303
309
|
if "*" in d.domain:
|
304
|
-
d.domain = d.domain.replace("*",
|
310
|
+
d.domain = d.domain.replace("*", hutils.random.get_random_string(5, 15))
|
305
311
|
|
306
312
|
package_mode_dic = {
|
307
313
|
UserMode.daily: 1,
|
@@ -354,7 +360,7 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
|
|
354
360
|
"asn": asn,
|
355
361
|
"country": auto_ip_selector.get_country(user_ip),
|
356
362
|
'has_auto_cdn': has_auto_cdn,
|
357
|
-
'profile_url': hiddify.get_account_panel_link(
|
363
|
+
'profile_url': hiddify.get_account_panel_link(user, domain)
|
358
364
|
}
|
359
365
|
|
360
366
|
|
@@ -369,6 +375,6 @@ def add_headers(res, c):
|
|
369
375
|
resp.headers['profile-update-interval'] = 1
|
370
376
|
# resp.headers['content-disposition']=f'attachment; filename="{c["db_domain"].alias or c["db_domain"].domain} {c["user"].name}"'
|
371
377
|
|
372
|
-
resp.headers['profile-title'] = 'base64:'+do_base_64(c['profile_title'])
|
378
|
+
resp.headers['profile-title'] = 'base64:'+hutils.encode.do_base_64(c['profile_title'])
|
373
379
|
|
374
380
|
return resp
|
Binary file
|