hiddifypanel 9.0.0.dev32__py3-none-any.whl → 9.0.0.dev33__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 (47) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +1 -1
  3. hiddifypanel/models/__init__.py +4 -3
  4. hiddifypanel/models/config.py +5 -5
  5. hiddifypanel/models/parent_domain.py +27 -27
  6. hiddifypanel/models/proxy.py +32 -30
  7. hiddifypanel/models/usage.py +71 -71
  8. hiddifypanel/panel/admin/Actions.py +5 -6
  9. hiddifypanel/panel/admin/AdminstratorAdmin.py +6 -6
  10. hiddifypanel/panel/admin/Backup.py +5 -5
  11. hiddifypanel/panel/admin/ChildAdmin.py +1 -2
  12. hiddifypanel/panel/admin/Dashboard.py +4 -5
  13. hiddifypanel/panel/admin/DomainAdmin.py +1 -1
  14. hiddifypanel/panel/admin/QuickSetup.py +1 -9
  15. hiddifypanel/panel/admin/UserAdmin.py +5 -5
  16. hiddifypanel/panel/admin/templates/parent_dash.html +1 -2
  17. hiddifypanel/panel/admin/templates/result.html +5 -3
  18. hiddifypanel/panel/cli.py +10 -32
  19. hiddifypanel/panel/commercial/ParentDomainAdmin.py +1 -1
  20. hiddifypanel/panel/commercial/restapi/v2/admin/server_status_api.py +5 -5
  21. hiddifypanel/panel/commercial/restapi/v2/user/info_api.py +2 -3
  22. hiddifypanel/panel/commercial/restapi/v2/user/short_api.py +2 -3
  23. hiddifypanel/panel/commercial/telegrambot/Usage.py +1 -1
  24. hiddifypanel/panel/commercial/templates/parent_dash.html +1 -1
  25. hiddifypanel/panel/common.py +3 -3
  26. hiddifypanel/panel/hiddify.py +33 -35
  27. hiddifypanel/panel/user/templates/new.html +2 -3
  28. hiddifypanel/panel/user/user.py +5 -193
  29. hiddifypanel/static/css/custom.css +5 -0
  30. hiddifypanel/static/new/assets/index-c4c80da4.js +1 -1
  31. hiddifypanel/templates/master.html +3 -2
  32. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  33. hiddifypanel/translations/en/LC_MESSAGES/messages.po +90 -94
  34. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  35. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +97 -94
  36. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  37. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +103 -99
  38. hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
  39. hiddifypanel/translations/ru/LC_MESSAGES/messages.po +102 -98
  40. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  41. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +91 -93
  42. {hiddifypanel-9.0.0.dev32.dist-info → hiddifypanel-9.0.0.dev33.dist-info}/METADATA +1 -1
  43. {hiddifypanel-9.0.0.dev32.dist-info → hiddifypanel-9.0.0.dev33.dist-info}/RECORD +47 -47
  44. {hiddifypanel-9.0.0.dev32.dist-info → hiddifypanel-9.0.0.dev33.dist-info}/LICENSE.md +0 -0
  45. {hiddifypanel-9.0.0.dev32.dist-info → hiddifypanel-9.0.0.dev33.dist-info}/WHEEL +0 -0
  46. {hiddifypanel-9.0.0.dev32.dist-info → hiddifypanel-9.0.0.dev33.dist-info}/entry_points.txt +0 -0
  47. {hiddifypanel-9.0.0.dev32.dist-info → hiddifypanel-9.0.0.dev33.dist-info}/top_level.txt +0 -0
hiddifypanel/panel/cli.py CHANGED
@@ -55,34 +55,23 @@ def all_configs():
55
55
  # "parent_domains": [hiddify.parent_domain_dict(u) for u in ParentDomain.query.all()],
56
56
  "hconfigs": get_hconfigs()
57
57
  }
58
- # for d in configs['domains']:
59
-
60
- # # del d['domain']['show_domains']
61
58
 
62
59
  def_user = None if len(User.query.all()) > 1 else User.query.filter(User.name == 'default').first()
63
60
  domains = Domain.query.all()
64
61
  sslip_domains = [d.domain for d in domains if "sslip.io" in d.domain]
65
62
 
66
63
  configs['hconfigs']['first_setup'] = def_user != None and len(sslip_domains) > 0
67
-
68
- # path = f'/{hconfig(ConfigEnum.proxy_path_admin)}/l'
69
- path = f'/{hconfig(ConfigEnum.proxy_path_admin)}/{AdminUser.get_super_admin_uuid()}/'
70
-
71
64
  server_ip = hutils.ip.get_ip(4)
72
- configs['admin_path'] = path
73
65
  owner = AdminUser.get_super_admin()
66
+
67
+ configs['admin_path'] = hiddify.get_account_panel_link(owner, server_ip, is_https=False, prefere_path_only=True)
74
68
  configs['panel_links'] = []
75
- # configs['panel_links'].append(hutils.utils.add_basic_auth_to_url(f'http://{server_ip}{path}', owner.username, owner.password))
76
- configs['panel_links'].append(f'http://{server_ip}{path}')
77
- # configs['panel_links'].append(hutils.utils.add_basic_auth_to_url(f'https://{server_ip}{path}', owner.username, owner.password))
78
- configs['panel_links'].append(f'https://{server_ip}{path}')
69
+ configs['panel_links'].append(hiddify.get_account_panel_link(owner, server_ip, is_https=False))
70
+ configs['panel_links'].append(hiddify.get_account_panel_link(owner, server_ip))
79
71
  domains = get_panel_domains()
80
- # if not any([d for d in domains if 'sslip.io' not in d.domain]):
81
- # configs['panel_links'].append(f"https://{server_ip}{path}")
82
72
 
83
73
  for d in domains:
84
- # configs['panel_links'].append(hutils.utils.add_basic_auth_to_url(f'https://{d.domain}{path}', owner.username, owner.password))
85
- configs['panel_links'].append(f'https://{d.domain}{path}')
74
+ configs['panel_links'].append(hiddify.get_account_panel_link(owner, d.domain))
86
75
 
87
76
  print(json.dumps(configs, indent=4))
88
77
 
@@ -100,34 +89,23 @@ def admin_links():
100
89
  server_ip = hutils.ip.get_ip(4)
101
90
  owner = AdminUser.get_super_admin()
102
91
 
103
- proxy_path = hconfig(ConfigEnum.proxy_path_admin)
104
- # admin_links = f"Not Secure (do not use it - only if others not work):\n {hutils.utils.add_basic_auth_to_url(f'http://{server_ip}/{proxy_path}/', owner.username, owner.password)}\n"
105
- admin_links = f"Not Secure (do not use it - only if others not work):\n http://{server_ip}/{proxy_path}/{owner.uuid}/'\n"
92
+ admin_links = f"Not Secure (do not use it - only if others not work):\n {hiddify.get_account_panel_link(owner, server_ip,is_https=True)}'\n"
106
93
 
107
94
  domains = get_panel_domains()
108
95
  admin_links += f"Secure:\n"
109
96
  if not any([d for d in domains if 'sslip.io' not in d.domain]):
110
- # admin_links += f" (not signed) {hutils.utils.add_basic_auth_to_url(f'https://{server_ip}/{proxy_path}/l', owner.username, owner.password)}\n"
111
- admin_links += f" (not signed) https://{server_ip}/{proxy_path}/{owner.uuid}\n"
97
+ admin_links += f" (not signed) {hiddify.get_account_panel_link(owner, server_ip)}\n"
112
98
 
113
- # domains=[*domains,f'{server_ip}.sslip.io']
114
99
  for d in domains:
115
- # admin_links += f" {hutils.utils.add_basic_auth_to_url(f'https://{d.domain}/{proxy_path}/l', owner.username, owner.password)}\n"
116
- admin_links += f" https://{d.domain}/{proxy_path}/{owner.uuid}/\n"
100
+ admin_links += f" {hiddify.get_account_panel_link(owner, d.domain)}\n"
117
101
 
118
102
  print(admin_links)
119
103
  return admin_links
120
104
 
121
105
 
122
106
  def admin_path():
123
- proxy_path = hconfig(ConfigEnum.proxy_path_admin)
124
- admin = AdminUser.query.filter(AdminUser.mode == AdminMode.super_admin).first()
125
- if not admin:
126
- db.session.add(AdminUser(mode=AdminMode.super_admin))
127
- db.session.commit()
128
- admin = AdminUser.query.filter(AdminUser.mode == AdminMode.super_admin).first()
129
-
130
- print(f"/{proxy_path}/admin/")
107
+ admin = AdminUser.get_super_admin()
108
+ print(hiddify.get_account_panel_link(owner, server_ip, prefere_path_only=True))
131
109
 
132
110
 
133
111
  def hysteria_domain_port():
@@ -64,7 +64,7 @@ class ParentDomainAdmin(AdminLTEModelView):
64
64
  form_columns = ['domain', "alias", 'show_domains']
65
65
 
66
66
  def _domain_admin_link(view, context, model, name):
67
- admin_link = f'https://{model.domain}{hiddify.get_admin_path()}'
67
+ admin_link = hiddify.get_account_panel_link(g.account,model.domain)
68
68
  return Markup(f'<div class="btn-group"><a href="{admin_link}" class="btn btn-xs btn-secondary">' + _("admin link") +
69
69
  f'</a><a href="{admin_link}" class="btn btn-xs btn-info ltr" target="_blank">{model.domain}</a></div>')
70
70
 
@@ -3,10 +3,10 @@ from flask import g
3
3
  from flask.views import MethodView
4
4
  from apiflask.fields import Dict
5
5
  from apiflask import Schema
6
+ from hiddifypanel.models.usage import DailyUsage
6
7
  from hiddifypanel.panel.auth import login_required
7
- from hiddifypanel.models.role import Role
8
+ from hiddifypanel.models import Role, DailyUsage
8
9
  from hiddifypanel.panel import hiddify
9
- from hiddifypanel.models import get_daily_usage_stats
10
10
 
11
11
 
12
12
  class ServerStatus(Schema):
@@ -17,13 +17,13 @@ class ServerStatus(Schema):
17
17
  class AdminServerStatusApi(MethodView):
18
18
  decorators = [login_required({Role.super_admin, Role.admin, Role.agent})]
19
19
 
20
- @app.output(ServerStatus)
20
+ @app.output(ServerStatus) # type: ignore
21
21
  def get(self):
22
22
  dto = ServerStatus()
23
- dto.stats = {
23
+ dto.stats = { # type: ignore
24
24
  'system': hiddify.system_stats(),
25
25
  'top5': hiddify.top_processes()
26
26
  }
27
27
  admin_id = request.args.get("admin_id") or g.account.id
28
- dto.usage_history = get_daily_usage_stats(admin_id)
28
+ dto.usage_history = DailyUsage.get_daily_usage_stats(admin_id) # type: ignore
29
29
  return dto
@@ -47,8 +47,7 @@ class InfoAPI(MethodView):
47
47
  dto = ProfileSchema()
48
48
  # user is exist for sure
49
49
  dto.profile_title = c['user'].name
50
- # dto.profile_url = f"https://{g.account.username}:{g.account.password}@{urlparse(request.base_url).hostname}/{g.proxy_path}/#{g.account.name}"
51
- dto.profile_url = f"https://{urlparse(request.base_url).hostname}/{g.proxy_path}/{g.account.uuid}/"
50
+ dto.profile_url = c['profile_url']
52
51
  dto.profile_usage_current = g.account.current_usage_GB
53
52
  dto.profile_usage_total = g.account.usage_limit_GB
54
53
  dto.profile_remaining_days = g.account.remaining_days()
@@ -59,7 +58,7 @@ class InfoAPI(MethodView):
59
58
  dto.admin_message_url = hconfig(ConfigEnum.branding_site)
60
59
  dto.brand_title = hconfig(ConfigEnum.branding_title)
61
60
  dto.brand_icon_url = ""
62
- dto.doh = f"https://{urlparse(request.base_url).hostname}/{g.proxy_path}/dns/dns-query"
61
+ dto.doh = f"https://{request.host}/{g.proxy_path}/dns/dns-query"
63
62
  dto.lang = c['user'].lang
64
63
  return dto
65
64
 
@@ -23,9 +23,8 @@ class ShortAPI(MethodView):
23
23
 
24
24
  @app.output(ShortSchema)
25
25
  def get(self):
26
- short, expire_in = hiddify.add_short_link(
27
- f'https://{request.host}/{hconfig(ConfigEnum.proxy_path_admin)}/')
28
- full_url = f"https://{urlparse(request.base_url).hostname}/{short}"
26
+ short, expire_in = hiddify.add_short_link(hiddify.get_account_panel_link(g.account, request.host))
27
+ full_url = f"https://{request.host}/{short}"
29
28
  dto = ShortSchema()
30
29
  dto.full_url = full_url
31
30
  dto.short = short
@@ -52,7 +52,7 @@ def get_usage_msg(uuid, domain=None):
52
52
  reset_day = user_data['reset_day']
53
53
 
54
54
  domain = domain or get_panel_domains()[0]
55
- user_link = f"https://{domain.domain}/{hconfig(ConfigEnum.proxy_path_client)}/"
55
+ user_link = hiddify.get_account_panel_link(user,domain.domain)
56
56
  msg = f"""{_('<a href="%(user_link)s"> %(user)s</a>',user_link=user_link ,user=user.name if user.name != "default" else "")}\n\n"""
57
57
 
58
58
  msg += f"""{_('user.home.usage.title')} {round(user.current_usage_GB, 3)}GB <b>{_('user.home.usage.from')}</b> {user.usage_limit_GB}GB {_('user.home.usage.monthly') if user.monthly else ''}\n"""
@@ -8,7 +8,7 @@
8
8
  {% macro admin_btn(child,domain) -%}
9
9
  <div class="btn-group">
10
10
 
11
- <a href="https://{{domain}}/{{hconfig(ConfigEnum.proxy_path_admin,child.id)}}/admin/" class="btn btn-xs btn-{{" success" if child.is_active else "warning" }} orig-link ltr" target="_blank">{{domain}}</a>
11
+ <a href="{hiddify.get_account_panel_link(g.account,domain,child_id=child.id)}" class="btn btn-xs btn-{{" success" if child.is_active else "warning" }} orig-link ltr" target="_blank">{{domain}}</a>
12
12
  </div>
13
13
  {%- endmacro -%}
14
14
 
@@ -104,10 +104,10 @@ def init_app(app: APIFlask):
104
104
  if hasattr(g, 'account') and isinstance(g.account, AdminUser):
105
105
  values['proxy_path'] = hconfig(ConfigEnum.proxy_path_admin)
106
106
  # elif 'static' in endpoint:
107
- # values['proxy_path'] = hconfig(ConfigEnum.proxy_path)
107
+ # values['proxy_path'] = hconfig(ConfigEnum.proxy_path)
108
108
  elif hiddify.is_user_panel_call():
109
109
  values['proxy_path'] = hconfig(ConfigEnum.proxy_path_client)
110
- else:
110
+ elif g.is_admin:
111
111
  values['proxy_path'] = hconfig(ConfigEnum.proxy_path_admin)
112
112
 
113
113
  if hiddify.is_api_v1_call(endpoint=endpoint) and 'admin_uuid' not in values:
@@ -184,7 +184,7 @@ def init_app(app: APIFlask):
184
184
 
185
185
  # validate proxy path
186
186
 
187
- g.proxy_path = hutils.utils.get_proxy_path_from_url(request.url)
187
+ # g.proxy_path = hutils.utils.get_proxy_path_from_url(request.url)
188
188
  hiddify.proxy_path_validator(g.proxy_path)
189
189
 
190
190
  # if g.proxy_path != hconfig(ConfigEnum.proxy_path):
@@ -27,15 +27,15 @@ from hiddifypanel.panel.run_commander import commander, Command
27
27
  to_gig_d = 1000*1000*1000
28
28
 
29
29
 
30
- def add_temporary_access():
31
- random_port = random.randint(30000, 50000)
32
- # exec_command(
33
- # f'sudo /opt/hiddify-manager/hiddify-panel/temporary_access.sh {random_port} &')
30
+ # def add_temporary_access():
31
+ # random_port = random.randint(30000, 50000)
32
+ # # exec_command(
33
+ # # f'sudo /opt/hiddify-manager/hiddify-panel/temporary_access.sh {random_port} &')
34
34
 
35
- # run temporary_access.sh
36
- commander(Command.temporary_access, port=random_port)
37
- temp_admin_link = f"http://{hutils.ip.get_ip(4)}:{random_port}{get_admin_path()}"
38
- g.temp_admin_link = temp_admin_link
35
+ # # run temporary_access.sh
36
+ # commander(Command.temporary_access, port=random_port)
37
+ # temp_admin_link = f"http://{hutils.ip.get_ip(4)}:{random_port}{get_admin_path()}"
38
+ # g.temp_admin_link = temp_admin_link
39
39
 
40
40
 
41
41
  # with user panel url format we don't really need this function
@@ -65,12 +65,6 @@ def add_short_link_imp(link: str, period_min: int = 5) -> Tuple[str, datetime]:
65
65
  return short_code, datetime.now() + timedelta(minutes=period_min)
66
66
 
67
67
 
68
- def get_admin_path():
69
- proxy_path = hconfig(ConfigEnum.proxy_path_admin)
70
- # admin_secret = g.account.uuid or get_super_admin_secret()
71
- return (f"/{proxy_path}/admin/")
72
-
73
-
74
68
  def exec_command(cmd, cwd=None):
75
69
  try:
76
70
  subprocess.Popen(cmd.split(" ")) # run in background
@@ -206,13 +200,7 @@ def is_admin_home_call() -> bool:
206
200
 
207
201
 
208
202
  def is_login_call() -> bool:
209
- # print(request.blueprint)
210
203
  return request.blueprint == 'common_bp'
211
- # base_path = f'{request.host}'
212
- # requested_url = f'{request.host}{request.path}'
213
- # if requested_url == f'{base_path}/{hconfig(ConfigEnum.proxy_path_admin)}/' or requested_url == f'{base_path}/{hconfig(ConfigEnum.proxy_path_client)}/':
214
- # return True
215
- # return False
216
204
 
217
205
 
218
206
  def is_admin_role(role: Role):
@@ -372,21 +360,15 @@ def check_connection_for_domain(domain):
372
360
  return True
373
361
 
374
362
 
375
- def get_user_link(uuid, domain, mode='', username=''):
363
+ def get_html_user_link(model: BaseAccount, domain: Domain):
376
364
  is_cdn = domain.mode == DomainType.cdn if type(domain) == Domain else False
377
365
  res = ""
378
- if mode == "multi":
379
- res += "<div class='btn-group'>"
380
366
  d = domain.domain
381
367
  if "*" in d:
382
368
  d = d.replace("*", get_random_string(5, 15))
383
- proxy_path = hconfig(ConfigEnum.proxy_path_admin) if mode == 'admin' else hconfig(ConfigEnum.proxy_path_client)
384
- # account = AdminUser.query.filter(AdminUser.uuid == uuid).first() if mode == 'admin' else User.query.filter(User.uuid == uuid).first()
385
- # link = f"https://{account.username}:{account.password}@{d}/{proxy_path}/admin/#{username}" if mode == 'admin' else f"https://{account.username}:{account.password}@{d}/{proxy_path}/#{username}"
386
- link = f"https://{d}/{proxy_path}/{uuid}/#{username}"
387
369
 
388
- # if mode == 'new':
389
- # link = f"{link}new"
370
+ link = get_account_panel_link(model, d)+f"#{model.name}"
371
+
390
372
  text = domain.alias or domain.domain
391
373
  color_cls = 'info'
392
374
 
@@ -395,7 +377,7 @@ def get_user_link(uuid, domain, mode='', username=''):
395
377
  color_cls = "success" if auto_cdn else 'warning'
396
378
  text = f'<span class="badge badge-secondary" >{"Auto" if auto_cdn else "CDN"}</span> '+text
397
379
 
398
- res += f"<a target='_blank' data-copy='{link}' href='{link}' class='btn btn-xs btn-{color_cls} ltr copy-link' ><i class='fa-solid fa-arrow-up-right-from-square d-none'></i> {text}</a>"
380
+ res += f"<a target='_blank' data-copy='{link}' href='{link}' class='btn btn-xs btn-{color_cls} ltr share-link' ><i class='fa-solid fa-arrow-up-right-from-square d-none'></i> {text}</a>"
399
381
 
400
382
  return res
401
383
 
@@ -538,11 +520,11 @@ def set_db_from_json(json_data, override_child_id=None, set_users=True, set_doma
538
520
  if set_domains and 'domains' in json_data:
539
521
  bulk_register_domains(json_data['domains'], commit=False, remove=remove_domains, override_child_id=override_child_id)
540
522
  if set_domains and 'parent_domains' in json_data:
541
- bulk_register_parent_domains(json_data['parent_domains'], commit=False, remove=remove_domains)
523
+ ParentDomain.bulk_register(json_data['parent_domains'], commit=False, remove=remove_domains)
542
524
  if set_settings and 'hconfigs' in json_data:
543
525
  bulk_register_configs(json_data["hconfigs"], commit=True, override_child_id=override_child_id, override_unique_id=override_unique_id)
544
526
  if 'proxies' in json_data:
545
- bulk_register_proxies(json_data['proxies'], commit=False, override_child_id=override_child_id)
527
+ Proxy.bulk_register(json_data['proxies'], commit=False, override_child_id=override_child_id)
546
528
 
547
529
  ids_without_parent = get_ids_without_parent({u.id: u.to_dict() for u in AdminUser.query.all()})
548
530
  owner = AdminUser.get_super_admin()
@@ -846,12 +828,12 @@ def do_base_64(str):
846
828
 
847
829
 
848
830
  def get_user_agent():
849
- ua= __parse_user_agent(request.user_agent.string)
831
+ ua = __parse_user_agent(request.user_agent.string)
850
832
 
851
833
  if 'is_bot' not in ua:
852
834
  __parse_user_agent.invalidate_all()
853
- ua= __parse_user_agent(request.user_agent.string)
854
-
835
+ ua = __parse_user_agent(request.user_agent.string)
836
+
855
837
  return ua
856
838
 
857
839
 
@@ -915,3 +897,19 @@ def get_direct_host_or_ip(prefer_version: int):
915
897
  if not direct:
916
898
  direct = hutils.ip.get_ip(socket.AF_INET if prefer_version == socket.AF_INET6 else socket.AF_INET6)
917
899
  return direct
900
+
901
+
902
+ def get_account_panel_link(account: BaseAccount, host: str, is_https: bool = True, prefere_path_only: bool = False, child_id=0):
903
+ basic_auth = False
904
+
905
+ link = ""
906
+ if basic_auth or not prefere_path_only:
907
+ link = "https://" if is_https else "http://"
908
+ if basic_auth:
909
+ link += f'{account.uuid}@'
910
+ link += host
911
+ proxy_path = hconfig(ConfigEnum.proxy_path_admin, child_id) if isinstance(account, AdminUser) else hconfig(ConfigEnum.proxy_path_client, child_id)
912
+ link += f'/{proxy_path}/'
913
+ if not basic_auth:
914
+ link += f'{account.uuid}/'
915
+ return link
@@ -2,8 +2,7 @@
2
2
  <html>
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
- {%set base='https://'+domain+'/'+hconfigs[ConfigEnum.proxy_path_client]+"/"+user.uuid+"/"%}
6
- <meta name="apple-itunes-app" content="app-id=6450534064, app-argument=streisand://import/{{base}}">
5
+ <meta name="apple-itunes-app" content="app-id=6450534064, app-argument=streisand://import/{{profile_url}}">
7
6
 
8
7
  <link rel="icon" type="image/png" href="../static/new/assets/hiddify-logo-7617d937.png" />
9
8
  <link rel="stylesheet" href="node_modules/smartbanner.js/dist/smartbanner.min.css">
@@ -20,7 +19,7 @@
20
19
  <script src="node_modules/smartbanner.js/dist/smartbanner.min.js"></script>
21
20
  <script>
22
21
  window.appVersion = '{{version}}';
23
- window.deepLink = "hiddify://import/{{base}}"
22
+ window.deepLink = "hiddify://import/{{profile_url}}"
24
23
  </script>
25
24
  </body>
26
25
  </html>
@@ -27,187 +27,11 @@ class UserView(FlaskView):
27
27
 
28
28
  return f"<div style='direction:ltr'>https://{urlparse(request.base_url).hostname}/{short}/</a><br><br>"+_("This link will expire in 5 minutes")
29
29
 
30
- @route('/info/')
31
- @route('/info')
32
- # TODO: delete this function and use /me/ api instead
33
- def info(self):
34
- c = get_common_data(g.account.uuid, 'new')
35
- data = {
36
- 'profile_title': c['profile_title'],
37
- 'profile_url': f"https://{g.account.username}:{g.account.password}{urlparse(request.base_url).hostname}/{g.proxy_path}/#{g.account.name}",
38
- 'profile_usage_current': g.account.current_usage_GB,
39
- 'profile_usage_total': g.account.usage_limit_GB,
40
- 'profile_remaining_days': g.account.remaining_days(),
41
- 'profile_reset_days': g.account.days_to_reset(),
42
- 'telegram_bot_url': f"https://t.me/{c['bot'].username}?start={g.account.uuid}" if c['bot'] else "",
43
- 'admin_message_html': hconfig(ConfigEnum.branding_freetext),
44
- 'admin_message_url': hconfig(ConfigEnum.branding_site),
45
- 'brand_title': hconfig(ConfigEnum.branding_title),
46
- 'brand_icon_url': "",
47
- 'doh': f"https://{urlparse(request.base_url).hostname}/{g.proxy_path}/dns/dns-query",
48
- 'def_lang': hconfig(ConfigEnum.lang)
49
- }
50
-
51
- return jsonify(data)
52
-
53
- @route('/mtproxies/')
54
- @route('/mtproxies')
55
- def mtproxies(self):
56
- # get domains
57
- c = get_common_data(g.account.uuid, 'new')
58
- mtproxies = []
59
- # TODO: Remove duplicated domains mapped to a same ipv4 and v6
60
- for d in c['domains']:
61
- if d.mode not in [DomainType.direct, DomainType.relay]:
62
- continue
63
- hexuuid = hconfig(ConfigEnum.shared_secret, d.child_id).replace('-', '')
64
- telegram_faketls_domain_hex = hconfig(ConfigEnum.telegram_fakedomain, d.child_id).encode('utf-8').hex()
65
- server_link = f'tg://proxy?server={d.domain}&port=443&secret=ee{hexuuid}{telegram_faketls_domain_hex}'
66
- mtproxies.append({'title': d.alias or d.domain, 'link': server_link})
67
-
68
- return jsonify(mtproxies)
69
-
70
- @route('/all-configs/')
71
- @route('/all-configs')
72
- def configs(self):
73
- def create_item(name, type, domain, protocol, transport, security, link):
74
- return {
75
- 'name': name,
76
- 'domain': domain,
77
- 'link': link,
78
- # 'tags': set(type, protocol, transport, security),
79
- 'type': type,
80
- 'protocol': protocol,
81
- 'transport': transport,
82
- 'security': security,
83
- }
84
-
85
- items = []
86
- base_url = f"https://{g.account.username}:{g.account.password}{urlparse(request.base_url).hostname}/{g.proxy_path}/"
87
- c = get_common_data(g.account.uuid, 'new')
88
-
89
- # Add Auto
90
- items.append(
91
- create_item(
92
- "Auto", "All", "All", "All", "All", "All",
93
- f"{base_url}sub/?asn={c['asn']}")
94
- )
95
-
96
- # Add Full Singbox
97
- items.append(
98
- create_item(
99
- "Full Singbox", "All", "All", "All", "All", "All",
100
- f"{base_url}full-singbox.json?asn={c['asn']}"
101
- )
102
- )
103
-
104
- # Add Clash Meta
105
- items.append(
106
- create_item(
107
- "Clash Meta", "All", "All", "All", "All", "All",
108
- f"clashmeta://install-config?url={base_url}clash/meta/all.yml&name=mnormal_{c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}-{c['mode']}&asn={c['asn']}&mode={c['mode']}"
109
- )
110
- )
111
-
112
- # Add Clash
113
- items.append(
114
- create_item(
115
- "Clash", "All", "All", "Except VLess", "All", "All",
116
- f"clash://install-config?url={base_url}clash/all.yml&name=new_normal_{c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}-{c['mode']}&asn={c['asn']}&mode={c['mode']}"
117
- )
118
- )
119
-
120
- # Add Singbox: SSh
121
- if hconfig(ConfigEnum.ssh_server_enable):
122
- items.append(
123
- create_item(
124
- "Singbox: SSH", "SSH", "SSH", "SSH", "SSH", "SSH",
125
- f"{base_url}singbox.json?name={c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}&asn={c['asn']}&mode={c['mode']}"
126
- )
127
- )
128
-
129
- # Add Subscription link
130
- items.append(
131
- create_item(
132
- "Subscription link", "All", "All", "All", "All", "All",
133
- f"{base_url}all.txt?name={c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}&asn={c['asn']}&mode={c['mode']}"
134
- )
135
- )
136
-
137
- # Add Subscription link base64
138
- items.append(
139
- create_item(
140
- "Subscription link b64", "All", "All", "All", "All", "All",
141
- f"{base_url}all.txt?name=new_link_{c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}-{c['mode']}&asn={c['asn']}&mode={c['mode']}&base64=True"
142
- )
143
- )
144
-
145
- for pinfo in link_maker.get_all_validated_proxies(c['domains']):
146
- items.append(
147
- create_item(
148
- pinfo["name"].replace("_", " "),
149
- f"{'Auto ' if pinfo['dbdomain'].has_auto_ip else ''}{pinfo['mode']}",
150
- pinfo['server'],
151
- pinfo['proto'],
152
- pinfo['transport'],
153
- pinfo['l3'],
154
- f"{link_maker.to_link(pinfo)}"
155
- )
156
- )
157
-
158
- return jsonify(items)
159
-
160
- # endregion
161
-
162
- @route('/test/')
30
+ @route('/useragent/')
163
31
  @login_required(roles={Role.user})
164
32
  def test(self):
165
33
  ua = request.user_agent.string
166
- if re.match('^Mozilla', ua, re.IGNORECASE):
167
- return "Please do not open here"
168
- conf = self.get_proper_config()
169
-
170
- import json
171
- ua = request.user_agent.string
172
- uaa = user_agents.parse(request.user_agent.string)
173
- with open('ua.txt', 'a') as f:
174
- f.write("\n".join([
175
- f'\n{datetime.datetime.now()} '+("Ok" if conf else "ERROR"),
176
- ua,
177
- f'os={uaa.os.family}-{uaa.os.version}({uaa.os.version_string}) br={uaa.browser.family} v={uaa.browser.version} vs={uaa.browser.version_string} dev={uaa.device.family}-{uaa.device.brand}-{uaa.device.model}',
178
- '\n'
179
- ]))
180
- if conf:
181
- return conf
182
- abort(500)
183
- # @route('/old')
184
- # @route('/old/')
185
- # def index(self):
186
-
187
- # c=get_common_data(g.account_uuid,mode="")
188
- # user_agent = user_agents.parse(request.user_agent.string)
189
-
190
- # return render_template('home/index.html',**c,ua=user_agent)
191
- # @route('/multi/')
192
- # @route('/multi')
193
- # def multi(self):
194
-
195
- # c=get_common_data(g.account_uuid,mode="multi")
196
-
197
- # user_agent = user_agents.parse(request.user_agent.string)
198
-
199
- # return render_template('home/multi.html',**c,ua=user_agent)
200
-
201
- # @route('/')
202
- # # @login_required()
203
- # # login
204
- # def login(self):
205
- # return ""
206
- # # redirect based on authenticated account
207
- # if hiddify.is_admin_proxy_path() and g.account.role in {Role.super_admin, Role.admin, Role.agent}:
208
- # return redirect(url_for('admin.Dashboard:index'))
209
- # elif hiddify.is_client_proxy_path():
210
- # return self.auto_sub()
34
+ return ua
211
35
 
212
36
  def index(self):
213
37
  return self.auto_sub()
@@ -241,14 +65,6 @@ class UserView(FlaskView):
241
65
  if re.match('^(Hiddify|FoXray|Fair|v2rayNG|SagerNet|Shadowrocket|V2Box|Loon|Liberty)', ua, re.IGNORECASE):
242
66
  return self.all_configs(base64=True)
243
67
 
244
- @ route('/auto')
245
- @login_required(roles={Role.user})
246
- def auto_select(self):
247
- c = get_common_data(g.account.uuid, mode="new")
248
- user_agent = user_agents.parse(request.user_agent.string)
249
- # return render_template('home/handle_smart.html', **c)
250
- return render_template('home/auto_page.html', **c, ua=user_agent)
251
-
252
68
  @ route('/new/')
253
69
  @ route('/new')
254
70
  @login_required(roles={Role.user})
@@ -371,11 +187,6 @@ class UserView(FlaskView):
371
187
  # render_template('all_configs.txt', **c, base64=do_base_64)
372
188
  resp = link_maker.make_v2ray_configs(**c)
373
189
 
374
- # res = ""
375
- # for line in resp.split("\n"):
376
- # if "vmess://" in line:
377
- # line = "vmess://"+do_base_64(line.replace("vmess://", ""))
378
- # res += line+"\n"
379
190
  if base64:
380
191
  resp = do_base_64(resp)
381
192
  return add_headers(resp, c)
@@ -383,7 +194,7 @@ class UserView(FlaskView):
383
194
  @login_required(roles={Role.user})
384
195
  @ route("/offline.html")
385
196
  def offline():
386
- return f"Not Connected <a href='/{hconfig(ConfigEnum.proxy_path_client)}/'>click for reload</a>"
197
+ return f"Not Connected <a href='{hiddify.get_account_panel_link(g.account, request.host)}'>click for reload</a>"
387
198
 
388
199
  # backward compatiblity
389
200
  @route("/admin/<path:path>")
@@ -509,7 +320,8 @@ def get_common_data(user_uuid, mode, no_domain=False, filter_domain=None):
509
320
  "ip_debug": auto_ip_selector.get_real_user_ip_debug(user_ip),
510
321
  "asn": asn,
511
322
  "country": auto_ip_selector.get_country(user_ip),
512
- 'has_auto_cdn': has_auto_cdn
323
+ 'has_auto_cdn': has_auto_cdn,
324
+ 'profile_url': hiddify.get_account_panel_link(g.account, domain)
513
325
  }
514
326
 
515
327
 
@@ -528,4 +528,9 @@ pre {
528
528
  .dark-mode .modal {
529
529
  color: white;
530
530
 
531
+ }
532
+
533
+ div#qrcode img {
534
+ padding: 10px;
535
+ background-color: white;
531
536
  }