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.
Files changed (63) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +2 -2
  3. hiddifypanel/base.py +5 -4
  4. hiddifypanel/hutils/__init__.py +8 -1
  5. hiddifypanel/hutils/auth.py +94 -0
  6. hiddifypanel/hutils/auto_ip_selector.py +1 -1
  7. hiddifypanel/hutils/convert.py +14 -0
  8. hiddifypanel/hutils/encode.py +11 -0
  9. hiddifypanel/hutils/flask.py +24 -0
  10. hiddifypanel/{panel/github_issue_generator.py → hutils/github_issue.py} +104 -14
  11. hiddifypanel/hutils/json.py +24 -0
  12. hiddifypanel/hutils/random.py +19 -0
  13. hiddifypanel/hutils/utils.py +0 -169
  14. hiddifypanel/models/__init__.py +1 -0
  15. hiddifypanel/models/admin.py +53 -8
  16. hiddifypanel/models/base_account.py +31 -169
  17. hiddifypanel/models/domain.py +2 -2
  18. hiddifypanel/models/parent_domain.py +1 -0
  19. hiddifypanel/models/user.py +105 -33
  20. hiddifypanel/models/utils.py +3 -3
  21. hiddifypanel/panel/admin/Actions.py +5 -6
  22. hiddifypanel/panel/admin/Backup.py +5 -5
  23. hiddifypanel/panel/admin/ChildAdmin.py +3 -3
  24. hiddifypanel/panel/admin/Dashboard.py +12 -10
  25. hiddifypanel/panel/admin/DomainAdmin.py +10 -9
  26. hiddifypanel/panel/admin/ProxyAdmin.py +4 -6
  27. hiddifypanel/panel/admin/QuickSetup.py +11 -13
  28. hiddifypanel/panel/admin/SettingAdmin.py +13 -11
  29. hiddifypanel/panel/admin/UserAdmin.py +13 -12
  30. hiddifypanel/panel/auth.py +42 -9
  31. hiddifypanel/panel/auth_back2.py +5 -5
  32. hiddifypanel/panel/cli.py +1 -0
  33. hiddifypanel/panel/commercial/ParentDomainAdmin.py +3 -3
  34. hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +1 -0
  35. hiddifypanel/panel/commercial/restapi/v1/tgmsg.py +1 -1
  36. hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +5 -4
  37. hiddifypanel/panel/commercial/restapi/v2/user/info_api.py +7 -11
  38. hiddifypanel/panel/commercial/telegrambot/admin.py +1 -0
  39. hiddifypanel/panel/common.py +10 -86
  40. hiddifypanel/panel/common_bp/login.py +9 -8
  41. hiddifypanel/panel/database.py +22 -21
  42. hiddifypanel/panel/hiddify.py +25 -28
  43. hiddifypanel/panel/importer/xui.py +2 -2
  44. hiddifypanel/panel/init_db.py +20 -13
  45. hiddifypanel/panel/usage.py +2 -1
  46. hiddifypanel/panel/user/link_maker.py +118 -15
  47. hiddifypanel/panel/user/user.py +25 -19
  48. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  49. hiddifypanel/translations/en/LC_MESSAGES/messages.po +252 -234
  50. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  51. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +280 -228
  52. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  53. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +240 -207
  54. hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
  55. hiddifypanel/translations/ru/LC_MESSAGES/messages.po +240 -207
  56. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  57. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +779 -2740
  58. {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/METADATA +2 -1
  59. {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/RECORD +63 -57
  60. {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/LICENSE.md +0 -0
  61. {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/WHEEL +0 -0
  62. {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/entry_points.txt +0 -0
  63. {hiddifypanel-9.0.0.dev60.dist-info → hiddifypanel-9.0.0.dev61.dist-info}/top_level.txt +0 -0
@@ -4,6 +4,7 @@ from apiflask import Schema
4
4
  from apiflask.fields import Integer, String, Float, URL, Enum
5
5
  from flask import g, request
6
6
  from flask import current_app as app
7
+ from hiddifypanel import hutils
7
8
  from hiddifypanel.panel.auth import login_required
8
9
  import hiddifypanel.panel.auth as auth
9
10
  from flask_babelex import gettext as _
@@ -55,11 +56,11 @@ class InfoAPI(MethodView):
55
56
  dto.profile_remaining_days = g.account.remaining_days()
56
57
  dto.profile_reset_days = g.account.days_to_reset()
57
58
  dto.telegram_bot_url = f"https://t.me/{c['bot'].username}?start={g.account.uuid}" if c['bot'] else ""
58
- dto.telegram_id = c['user'].telegram_id or 0
59
+ dto.telegram_id = c['user'].telegram_id
59
60
 
60
61
  dto.doh = f"https://{request.host}/{g.proxy_path}/dns/dns-query"
61
62
  dto.lang = (c['user'].lang) or Lang(hconfig(ConfigEnum.lang))
62
- dto.brand_icon_url = "" if hconfig(ConfigEnum.branding_title) else hiddify.static_url_for(filename="images/hiddify.png")
63
+ dto.brand_icon_url = "" if hconfig(ConfigEnum.branding_title) else hutils.flask.static_url_for(filename="images/hiddify.png")
63
64
  # with force_locale("fa"):
64
65
  dto.admin_message_html = hconfig(ConfigEnum.branding_freetext) or _("Join our Hiddify Telegram channel to get the latest updates on Hiddify.")
65
66
  if not hconfig(ConfigEnum.branding_freetext) and auth.admin_session_is_exist():
@@ -69,16 +70,11 @@ class InfoAPI(MethodView):
69
70
  return dto
70
71
 
71
72
  @app.input(UserInfoChangableSchema, arg_name='data')
72
- def patch(self, data):
73
- if data['telegram_id']:
74
- try:
75
- tg_id = int(data['telegram_id'])
76
- except:
77
- return {'message': 'The telegram id field is invalid'}
78
-
73
+ def patch(self, data: UserInfoChangableSchema):
74
+ if data['telegram_id'] and hutils.convert.is_int(data['telegram_id']):
79
75
  user = User.by_uuid(g.account.uuid)
80
- if user.telegram_id != tg_id:
81
- user.telegram_id = tg_id
76
+ if user.telegram_id != data['telegram_id']:
77
+ user.telegram_id = data['telegram_id']
82
78
  db.session.commit()
83
79
 
84
80
  if data['language']:
@@ -1,3 +1,4 @@
1
+ from hiddifypanel.panel import hiddify
1
2
  from . import bot
2
3
 
3
4
  from telebot import types
@@ -6,11 +6,10 @@ from flask import g, send_from_directory, session
6
6
  from flask_babelex import gettext as _
7
7
  import hiddifypanel
8
8
  from hiddifypanel.models import *
9
- from hiddifypanel.panel import hiddify, github_issue_generator
10
- from sys import version as python_version
11
- from platform import platform
12
- import hiddifypanel.hutils as hutils
9
+ from hiddifypanel.panel import hiddify
10
+ from hiddifypanel import hutils
13
11
  import hiddifypanel.panel.auth as auth
12
+ from hiddifypanel.panel.auth import current_account
14
13
  from apiflask import APIFlask, HTTPError, abort
15
14
 
16
15
 
@@ -48,7 +47,7 @@ def init_app(app: APIFlask):
48
47
  trace = traceback.format_exc()
49
48
 
50
49
  # Create github issue link
51
- issue_link = generate_github_issue_link_for_500_error(e, trace)
50
+ issue_link = hutils.github_issue.generate_github_issue_link_for_500_error(e, trace)
52
51
 
53
52
  return render_template('500.html', error=e, trace=trace, has_update=has_update, last_version=last_version, issue_link=issue_link), 500
54
53
 
@@ -61,7 +60,7 @@ def init_app(app: APIFlask):
61
60
  trace = traceback.format_exc()
62
61
 
63
62
  # Create github issue link
64
- issue_link = generate_github_issue_link_for_500_error(e, trace)
63
+ issue_link = hutils.github_issue.generate_github_issue_link_for_500_error(e, trace)
65
64
 
66
65
  last_version = hiddify.get_latest_release_version('hiddify-panel') # TODO: add dev update check
67
66
  if "T" in hiddifypanel.__version__:
@@ -75,16 +74,6 @@ def init_app(app: APIFlask):
75
74
 
76
75
  return render_template('error.html', error=e), e.status_code
77
76
 
78
- def generate_github_issue_link(title, issue_body):
79
- opts = {
80
- "user": 'hiddify',
81
- "repo": 'Hiddify-Manager',
82
- "title": title,
83
- "body": issue_body,
84
- }
85
- issue_link = str(github_issue_generator.IssueUrl(opts).get_url())
86
- return issue_link
87
-
88
77
  # @app.spec_processor
89
78
  # def set_default_path_values(spec):
90
79
  # # for path in spec['paths'].values():
@@ -100,7 +89,7 @@ def init_app(app: APIFlask):
100
89
  @app.url_defaults
101
90
  def add_proxy_path_user(endpoint, values):
102
91
  if 'proxy_path' not in values:
103
- if hasattr(g, 'account') and isinstance(g.account, AdminUser):
92
+ if hiddify.is_admin_role(g.account):
104
93
  values['proxy_path'] = hconfig(ConfigEnum.proxy_path_admin)
105
94
  # elif 'static' in endpoint:
106
95
  # values['proxy_path'] = hconfig(ConfigEnum.proxy_path)
@@ -144,7 +133,7 @@ def init_app(app: APIFlask):
144
133
  # if user_agent.is_bot:
145
134
  # abort(400, "invalid")
146
135
 
147
- # uuid = hutils.utils.get_uuid_from_url_path(request.path)
136
+ # uuid = hutils.auth.get_uuid_from_url_path(request.path)
148
137
  # account = User.by_uuid(uuid) or AdminUser.by_uuid(uuid) or abort(400, 'invalid request2')
149
138
 
150
139
  # admin_proxy_path = hconfig(ConfigEnum.proxy_path_admin)
@@ -161,7 +150,7 @@ def init_app(app: APIFlask):
161
150
  # else:
162
151
  # return abort(400, 'invalid request 1')
163
152
 
164
- # new_link = hutils.utils.add_basic_auth_to_url(new_link, account.username, account.password)
153
+ # new_link = hutils.auth.add_basic_auth_to_url(new_link, account.username, account.password)
165
154
 
166
155
  # if user_agent.browser:
167
156
  # return render_template('redirect_to_new_format.html', new_link=new_link)
@@ -171,6 +160,7 @@ def init_app(app: APIFlask):
171
160
  # return redirect(new_link, 302)
172
161
  @app.before_request
173
162
  def set_default_values():
163
+ g.account = current_account
174
164
  g.user_agent = hiddify.get_user_agent()
175
165
 
176
166
  @app.before_request
@@ -216,70 +206,4 @@ def init_app(app: APIFlask):
216
206
  else:
217
207
  g.bot = None
218
208
 
219
- def github_issue_details():
220
- details = {
221
- 'hiddify_version': f'{hiddifypanel.__version__}',
222
- 'python_version': f'{python_version}',
223
- 'os_details': f'{platform()}',
224
- 'user_agent': request.user_agent
225
- }
226
- return details
227
-
228
- def generate_github_issue_link_for_500_error(error, traceback, remove_sensetive_data=True, remove_unrelated_traceback_datails=True):
229
-
230
- def remove_sensetive_data_from_github_issue_link(issue_link):
231
- if hasattr(g, 'account') and hasattr(g.account, 'uuid') and g.account.uuid:
232
- issue_link.replace(f'{g.account.uuid}', '*******************')
233
-
234
- issue_link.replace(request.host, '**********')
235
- issue_link.replace(hconfig(ConfigEnum.proxy_path), '**********')
236
- issue_link.replace(hconfig(ConfigEnum.proxy_path_admin), '**********')
237
- issue_link.replace(hconfig(ConfigEnum.proxy_path_client), '**********')
238
-
239
- def remove_unrelated_traceback_details(stacktrace: str):
240
- lines = stacktrace.splitlines()
241
- if len(lines) < 1:
242
- return ""
243
-
244
- output = ''
245
- skip_next_line = False
246
- for i, line in enumerate(lines):
247
- if i == 0:
248
- output += line + '\n'
249
- continue
250
- if skip_next_line == True:
251
- skip_next_line = False
252
- continue
253
- if line.strip().startswith('File'):
254
- if 'hiddify' in line.lower():
255
- output += line + '\n'
256
- if len(lines) > i+1:
257
- output += lines[i + 1] + '\n'
258
- skip_next_line = True
259
-
260
- return output
261
-
262
- if remove_unrelated_traceback_datails:
263
- traceback = remove_unrelated_traceback_details(traceback)
264
-
265
- issue_details = github_issue_details()
266
-
267
- issue_body = render_template('github_issue_body.j2', issue_details=issue_details, error=error, traceback=traceback)
268
-
269
- # Create github issue link
270
- issue_link = generate_github_issue_link(f"Internal server error: {error.name if hasattr(error,'name') and error.name != None and error.name else 'Unknown'}", issue_body)
271
-
272
- if remove_sensetive_data:
273
- remove_sensetive_data_from_github_issue_link(issue_link)
274
-
275
- return issue_link
276
-
277
- def generate_github_issue_link_for_admin_sidebar():
278
-
279
- issue_body = render_template('github_issue_body.j2', issue_details=github_issue_details())
280
-
281
- # Create github issue link
282
- issue_link = generate_github_issue_link('Please fill the title properly', issue_body)
283
- return issue_link
284
-
285
- app.jinja_env.globals['generate_github_issue_link_for_admin_sidebar'] = generate_github_issue_link_for_admin_sidebar
209
+ app.jinja_env.globals['generate_github_issue_link_for_admin_sidebar'] = hutils.github_issue.generate_github_issue_link_for_admin_sidebar
@@ -1,4 +1,5 @@
1
1
  from flask_classful import FlaskView, route
2
+ from hiddifypanel import hutils
2
3
  from hiddifypanel.panel.auth import login_required, current_account, login_user, logout_user, login_by_uuid
3
4
  from flask import redirect, request, g, url_for, render_template, flash, jsonify
4
5
  from flask import current_app as app
@@ -54,7 +55,7 @@ class LoginView(FlaskView):
54
55
  uuid = form.secret_textbox.data.strip()
55
56
  if login_by_uuid(uuid, hiddify.is_admin_proxy_path()):
56
57
  return redirect(f'/{g.proxy_path}/')
57
- flash(_('config.validation-error'), 'danger')
58
+ hutils.flask.flash(_('config.validation-error'), 'danger') # type: ignore
58
59
  return render_template('login.html', form=LoginForm())
59
60
 
60
61
  @route("/l/")
@@ -66,10 +67,10 @@ class LoginView(FlaskView):
66
67
 
67
68
  loginurl = url_for('common_bp.LoginView:index', next=redirect_arg, user=username)
68
69
  if g.user_agent['is_browser'] and request.headers.get('Authorization') or (current_account and len(username) > 0 and current_account.username != username):
69
- flash(_('Incorrect Password'), 'error')
70
+ hutils.flask.flash(_('Incorrect Password'), 'error') # type: ignore
70
71
  logout_user()
71
- g.account = None
72
- # flash(request.authorization.username, 'error')
72
+ g.__account_store = None
73
+ # hutils.flask.flash(request.authorization.username, 'error')
73
74
  return redirect(loginurl)
74
75
 
75
76
  return render_template("redirect.html", url=loginurl), 401
@@ -90,13 +91,13 @@ class LoginView(FlaskView):
90
91
 
91
92
  # def uuid(self, uuid, path=''):
92
93
  # proxy_path = hiddify.get_proxy_path_from_url(request.url)
93
- # g.account = None
94
+ # g.__account_store = None
94
95
  # uuid = str(uuid)
95
96
  # if proxy_path == hconfig(ConfigEnum.proxy_path_client):
96
- # g.account = User.by_uuid(uuid)
97
+ # g.__account_store = User.by_uuid(uuid)
97
98
  # path = f'client/{path}'
98
99
  # elif proxy_path == hconfig(ConfigEnum.proxy_path_admin):
99
- # g.account = AdminUser.by_uuid(uuid)
100
+ # g.__account_store = AdminUser.by_uuid(uuid)
100
101
  # if not g.account:
101
102
  # abort(403)
102
103
  # if not g.user_agent['is_browser'] and proxy_path == hconfig(ConfigEnum.proxy_path_client):
@@ -134,7 +135,7 @@ class LoginView(FlaskView):
134
135
  "orientation": "any",
135
136
  "icons": [
136
137
  {
137
- "src": hiddify.static_url_for(filename='images/hiddify-dark.png'),
138
+ "src": hutils.flask.static_url_for(filename='images/hiddify-dark.png'),
138
139
  "sizes": "512x512",
139
140
  "type": "image/png",
140
141
  "purpose": "maskable any"
@@ -6,7 +6,8 @@ import re
6
6
  import os
7
7
 
8
8
  db = SQLAlchemy()
9
- db.UUID = UUIDType
9
+ db.UUID = UUIDType # type: ignore
10
+
10
11
 
11
12
  def init_app(app):
12
13
  app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
@@ -14,23 +15,23 @@ def init_app(app):
14
15
 
15
16
  # db.create_all(app)
16
17
  # app.jinja_env.globals['get_locale'] = get_locale
17
- def init_migration(app):
18
- migrate = flask_migrate.Migrate(app,db)
19
- if os.path.isdir(migrate.directory):
20
- return
21
- flask_migrate.init()
22
- def migrate():
23
- try_again = False
24
- try:
25
- # run flask_migrate.migrate function without its decorator to catch function error in try statement
26
- flask_migrate.migrate.__wrapped__()
27
- except Exception as err:
28
- err_str = str(err)
29
- if err_str == 'Target database is not up to date.':
30
- flask_migrate.stamp()
31
- elif err_str.startswith("Can't locate revision identified by"):
32
- rev_id = re.findall(" '(.*)'$",err_str)[0].replace("'","'").strip()
33
- flask_migrate.revision(rev_id=rev_id)
34
- finally:
35
- if try_again:
36
- flask_migrate.migrate()
18
+ # def init_migration(app):
19
+ # migrate = flask_migrate.Migrate(app,db)
20
+ # if os.path.isdir(migrate.directory):
21
+ # return
22
+ # flask_migrate.init()
23
+ # def migrate():
24
+ # try_again = False
25
+ # try:
26
+ # # run flask_migrate.migrate function without its decorator to catch function error in try statement
27
+ # flask_migrate.migrate.__wrapped__()
28
+ # except Exception as err:
29
+ # err_str = str(err)
30
+ # if err_str == 'Target database is not up to date.':
31
+ # flask_migrate.stamp()
32
+ # elif err_str.startswith("Can't locate revision identified by"):
33
+ # rev_id = re.findall(" '(.*)'$",err_str)[0].replace("'","'").strip()
34
+ # flask_migrate.revision(rev_id=rev_id)
35
+ # finally:
36
+ # if try_again:
37
+ # flask_migrate.migrate()
@@ -1,18 +1,22 @@
1
1
  import glob
2
+ import random
3
+ import socket
4
+ import ssl
5
+ import time
2
6
  import uuid
3
7
  import user_agents
4
8
  import json
5
9
  import subprocess
6
10
  import psutil
11
+ from datetime import datetime
7
12
  from typing import Tuple
8
13
  from cryptography.hazmat.primitives import serialization
9
14
  from cryptography.hazmat.primitives.asymmetric import x25519
10
- from flask import current_app, g, jsonify, request
15
+ from flask import current_app, g, request, Markup # type: ignore
11
16
  from flask_babelex import gettext as __
12
17
  from flask_babelex import lazy_gettext as _
13
18
  from wtforms.validators import ValidationError
14
19
  from apiflask import abort as apiflask_abort
15
- from apiflask import abort
16
20
 
17
21
  from datetime import timedelta
18
22
  from babel.dates import format_timedelta as babel_format_timedelta
@@ -57,7 +61,7 @@ def add_short_link_imp(link: str, period_min: int = 5) -> Tuple[str, datetime]:
57
61
  if link in line:
58
62
  return re.search(pattern, line).group(1), datetime.now() + timedelta(minutes=period_min)
59
63
 
60
- short_code = get_random_string(6, 10).lower()
64
+ short_code = hutils.random.get_random_string(6, 10).lower()
61
65
  # exec_command(
62
66
  # f'sudo /opt/hiddify-manager/nginx/add2shortlink.sh {link} {short_code} {period_min} &')
63
67
 
@@ -172,6 +176,8 @@ def is_login_call() -> bool:
172
176
 
173
177
 
174
178
  def is_admin_role(role: Role):
179
+ if not role:
180
+ return False
175
181
  if role in {Role.super_admin, Role.admin, Role.agent}:
176
182
  return True
177
183
  return False
@@ -202,18 +208,18 @@ def proxy_path_validator(proxy_path):
202
208
  return
203
209
 
204
210
  if proxy_path not in [admin_proxy_path, deprecated_path, client_proxy_path]:
205
- abort(400, 'invalid request')
211
+ apiflask_abort(400, 'invalid request')
206
212
 
207
213
  if is_admin_panel_call() and proxy_path != admin_proxy_path:
208
- abort(400, 'invalid request')
214
+ apiflask_abort(400, 'invalid request')
209
215
  if is_user_panel_call() and proxy_path != client_proxy_path:
210
- abort(400, 'invalid request')
216
+ apiflask_abort(400, 'invalid request')
211
217
 
212
218
  if is_api_call(request.path):
213
219
  if is_admin_api_call() and proxy_path != admin_proxy_path:
214
- return apiflask_abort(400, Markup(f"Invalid Proxy Path <a href=/{admin_proxy_path}/admin>Admin Panel</a>")) if dbg_mode else abort(400, 'invalid request')
220
+ return apiflask_abort(400, Markup(f"Invalid Proxy Path <a href=/{admin_proxy_path}/admin>Admin Panel</a>")) if dbg_mode else apiflask_abort(400, 'invalid request')
215
221
  if is_user_api_call() and proxy_path != client_proxy_path:
216
- return apiflask_abort(400, Markup(f"Invalid Proxy Path <a href=/{client_proxy_path}/admin>User Panel</a>")) if dbg_mode else abort(400, 'invalid request')
222
+ return apiflask_abort(400, Markup(f"Invalid Proxy Path <a href=/{client_proxy_path}/admin>User Panel</a>")) if dbg_mode else apiflask_abort(400, 'invalid request')
217
223
 
218
224
 
219
225
  def asset_url(path) -> str:
@@ -271,17 +277,6 @@ def quick_apply_users():
271
277
  return {"status": 'success'}
272
278
 
273
279
 
274
- def flash_config_success(restart_mode='', domain_changed=True):
275
- if restart_mode:
276
- url = url_for('admin.Actions:reinstall', complete_install=restart_mode ==
277
- 'reinstall', domain_changed=domain_changed)
278
- apply_btn = f"<a href='{url}' class='btn btn-primary form_post'>" + \
279
- _("admin.config.apply_configs")+"</a>"
280
- flash((_('config.validation-success', link=apply_btn)), 'success')
281
- else:
282
- flash((_('config.validation-success-no-reset')), 'success')
283
-
284
-
285
280
  # Importing socket library
286
281
 
287
282
  # Function to display hostname and
@@ -333,7 +328,7 @@ def get_html_user_link(model: BaseAccount, domain: Domain):
333
328
  res = ""
334
329
  d = domain.domain
335
330
  if "*" in d:
336
- d = d.replace("*", get_random_string(5, 15))
331
+ d = d.replace("*", hutils.random.get_random_string(5, 15))
337
332
 
338
333
  link = get_account_panel_link(model, d)+f"#{model.name}"
339
334
 
@@ -380,7 +375,7 @@ def check_need_reset(old_configs, do=False):
380
375
  if old_configs[ConfigEnum.package_mode] != hconfig(ConfigEnum.package_mode):
381
376
  return reinstall_action(do_update=True)
382
377
  if not (do and restart_mode == 'reinstall'):
383
- return flash_config_success(restart_mode=restart_mode, domain_changed=False)
378
+ return hutils.flask.flash_config_success(restart_mode=restart_mode, domain_changed=False)
384
379
 
385
380
  return reinstall_action(complete_install=True, domain_changed=domain_changed)
386
381
 
@@ -649,9 +644,12 @@ def get_random_domains(count=1, retry=3):
649
644
  return random.sample(defdomains, count)
650
645
  return get_random_domains(count, retry-1)
651
646
 
647
+ # not used
648
+
652
649
 
653
650
  def is_domain_support_tls_13(domain):
654
651
  context = ssl.create_default_context()
652
+ port = 433
655
653
  with socket.create_connection((domain, port)) as sock:
656
654
  with context.wrap_socket(sock, server_hostname=domain) as ssock:
657
655
  return ssock.version() == "TLSv1.3"
@@ -694,8 +692,8 @@ def debug_flash_if_not_in_the_same_asn(domain):
694
692
  # country_ipv4= ipcountry.get(ipv4)
695
693
  # country_dip= ipcountry.get(dip)
696
694
  if asn_ipv4.get('autonomous_system_organization') != asn_dip.get('autonomous_system_organization'):
697
- flash(_("selected domain for REALITY is not in the same ASN. To better use of the protocol, it is better to find a domain in the same ASN.") +
698
- f"<br> Server ASN={asn_ipv4.get('autonomous_system_organization','unknown')}<br>{domain}_ASN={asn_dip.get('autonomous_system_organization','unknown')}", "warning")
695
+ hutils.flask.flash(_("selected domain for REALITY is not in the same ASN. To better use of the protocol, it is better to find a domain in the same ASN.") +
696
+ f"<br> Server ASN={asn_ipv4.get('autonomous_system_organization','unknown')}<br>{domain}_ASN={asn_dip.get('autonomous_system_organization','unknown')}", "warning")
699
697
  except:
700
698
  pass
701
699
 
@@ -789,10 +787,10 @@ def get_ed25519_private_public_pair():
789
787
  return priv_bytes.decode(), pub_bytes.decode()
790
788
 
791
789
 
792
- def do_base_64(str):
793
- import base64
794
- resp = base64.b64encode(f'{str}'.encode("utf-8"))
795
- return resp.decode()
790
+ # def do_base_64(str):
791
+ # import base64
792
+ # resp = base64.b64encode(f'{str}'.encode("utf-8"))
793
+ # return resp.decode()
796
794
 
797
795
 
798
796
  def get_user_agent():
@@ -855,7 +853,6 @@ def __parse_user_agent(ua):
855
853
 
856
854
  def is_ssh_password_authentication_enabled():
857
855
  if os.path.isfile('/etc/ssh/sshd_config'):
858
- content = ''
859
856
  with open('/etc/ssh/sshd_config', 'r') as f:
860
857
  for line in f.readlines():
861
858
  line = line.strip()
@@ -4,7 +4,7 @@ from typing import Any, Dict, List, Tuple
4
4
  import uuid as uuid_mod
5
5
  from datetime import datetime
6
6
  from dateutil.relativedelta import relativedelta
7
- import hiddifypanel.hutils.utils as utils
7
+ from hiddifypanel import hutils
8
8
  from hiddifypanel.models.admin import AdminUser
9
9
  from hiddifypanel.models.user import User, UserMode
10
10
  from hiddifypanel.models.domain import Domain, DomainType
@@ -63,7 +63,7 @@ def __get_users(db, x_ui_inbounds):
63
63
  def __create_hiddify_user_from_xui_values(id: str, values: Dict[str, Any]) -> User:
64
64
  user = User()
65
65
  user.name = values['name']
66
- user.uuid = id if utils.is_uuid_valid(id, 4) else uuid_mod.uuid4()
66
+ user.uuid = id if hutils.auth.is_uuid_valid(id, 4) else uuid_mod.uuid4()
67
67
 
68
68
  if str(values['expiry_time']) == '0':
69
69
  user.expiry_time = datetime.now() + relativedelta(years=10)
@@ -12,7 +12,7 @@ from hiddifypanel import Events, hutils
12
12
  from hiddifypanel.models import *
13
13
  from hiddifypanel.panel import hiddify
14
14
  from hiddifypanel.panel.database import db
15
- from hiddifypanel.panel.hiddify import get_random_domains, get_random_string
15
+ from hiddifypanel.panel.hiddify import get_random_domains
16
16
  import hiddifypanel.models.utils as model_utils
17
17
 
18
18
  MAX_DB_VERSION = 70
@@ -26,7 +26,12 @@ def init_db():
26
26
  hconfig.invalidate_all()
27
27
  get_hconfigs.invalidate_all()
28
28
  db_version = int(hconfig(ConfigEnum.db_version) or 0)
29
+ if db_version == latest_db_version():
30
+ return
31
+ execute("alter table user alter column telegram_id int;")
32
+ execute("alter table admin_user alter column telegram_id int;")
29
33
  add_column(User.lang)
34
+ add_column(AdminUser.lang)
30
35
  add_column(User.username)
31
36
  add_column(User.password)
32
37
  add_column(AdminUser.username)
@@ -34,8 +39,6 @@ def init_db():
34
39
 
35
40
  add_column(Domain.extra_params)
36
41
 
37
- if db_version == latest_db_version():
38
- return
39
42
  Events.db_prehook.notify()
40
43
  if db_version < 52:
41
44
  execute(f'update domain set mode="sub_link_only", sub_link_only=false where sub_link_only = true or mode=1 or mode="1"')
@@ -148,6 +151,10 @@ def init_db():
148
151
  # add_config_if_not_exist(ConfigEnum.hysteria_enable, True)
149
152
  # add_config_if_not_exist(ConfigEnum.hysteria_port, random.randint(5000, 20000))
150
153
 
154
+ def _v67():
155
+ pass
156
+
157
+
151
158
  def _v65():
152
159
  add_config_if_not_exist(ConfigEnum.mux_enable, False)
153
160
  add_config_if_not_exist(ConfigEnum.mux_protocol, 'smux')
@@ -187,8 +194,8 @@ def _v61():
187
194
 
188
195
 
189
196
  def _v60():
190
- add_config_if_not_exist(ConfigEnum.proxy_path_admin, get_random_string())
191
- add_config_if_not_exist(ConfigEnum.proxy_path_client, get_random_string())
197
+ add_config_if_not_exist(ConfigEnum.proxy_path_admin, hutils.random.get_random_string())
198
+ add_config_if_not_exist(ConfigEnum.proxy_path_client, hutils.random.get_random_string())
192
199
 
193
200
 
194
201
  def _v59():
@@ -354,13 +361,13 @@ def _v20():
354
361
 
355
362
 
356
363
  def _v19():
357
- set_hconfig(ConfigEnum.path_trojan, get_random_string(7, 15))
358
- set_hconfig(ConfigEnum.path_vless, get_random_string(7, 15))
359
- set_hconfig(ConfigEnum.path_vmess, get_random_string(7, 15))
360
- set_hconfig(ConfigEnum.path_ss, get_random_string(7, 15))
361
- set_hconfig(ConfigEnum.path_grpc, get_random_string(7, 15))
362
- set_hconfig(ConfigEnum.path_tcp, get_random_string(7, 15))
363
- set_hconfig(ConfigEnum.path_ws, get_random_string(7, 15))
364
+ set_hconfig(ConfigEnum.path_trojan, hutils.random.get_random_string(7, 15))
365
+ set_hconfig(ConfigEnum.path_vless, hutils.random.get_random_string(7, 15))
366
+ set_hconfig(ConfigEnum.path_vmess, hutils.random.get_random_string(7, 15))
367
+ set_hconfig(ConfigEnum.path_ss, hutils.random.get_random_string(7, 15))
368
+ set_hconfig(ConfigEnum.path_grpc, hutils.random.get_random_string(7, 15))
369
+ set_hconfig(ConfigEnum.path_tcp, hutils.random.get_random_string(7, 15))
370
+ set_hconfig(ConfigEnum.path_ws, hutils.random.get_random_string(7, 15))
364
371
  add_config_if_not_exist(ConfigEnum.tuic_enable, False)
365
372
  add_config_if_not_exist(ConfigEnum.shadowtls_enable, False)
366
373
  add_config_if_not_exist(ConfigEnum.shadowtls_fakedomain, "en.wikipedia.org")
@@ -395,7 +402,7 @@ def _v1():
395
402
  StrConfig(key=ConfigEnum.tls_ports, value="443"),
396
403
  BoolConfig(key=ConfigEnum.first_setup, value=True),
397
404
  StrConfig(key=ConfigEnum.decoy_domain, value=hiddify.get_random_decoy_domain()),
398
- StrConfig(key=ConfigEnum.proxy_path, value=get_random_string()),
405
+ StrConfig(key=ConfigEnum.proxy_path, value=hutils.random.get_random_string()),
399
406
  BoolConfig(key=ConfigEnum.firewall, value=False),
400
407
  BoolConfig(key=ConfigEnum.netdata, value=True),
401
408
  StrConfig(key=ConfigEnum.lang, value='en'),
@@ -19,6 +19,7 @@ def update_local_usage():
19
19
 
20
20
 
21
21
  def add_users_usage_uuid(uuids_bytes, child_id):
22
+ # WHAT IS THE "keys" function WHY ?????
22
23
  users = User.query.filter(User.uuid.in_(keys(uuids_bytes)))
23
24
  dbusers_bytes = {u: uuids_bytes.get(u.uuid, 0) for u in users}
24
25
  add_users_usage(dbusers_bytes, child_id)
@@ -100,6 +101,6 @@ def send_bot_message(user):
100
101
  try:
101
102
  msg = Usage.get_usage_msg(user.uuid)
102
103
  msg = _("User activated!") if user.is_active else _("Package ended!")+"\n"+msg
103
- bot.send_message(user.telegram_id, msg, reply_markup=Usage.user_keyboard(uuid))
104
+ bot.send_message(user.telegram_id, msg, reply_markup=Usage.user_keyboard(user.uuid))
104
105
  except:
105
106
  pass