hiddifypanel 10.20.3__py3-none-any.whl → 10.30.0__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 (84) hide show
  1. hiddifypanel/VERSION +1 -1
  2. hiddifypanel/VERSION.py +2 -2
  3. hiddifypanel/base.py +22 -12
  4. hiddifypanel/cache.py +2 -51
  5. hiddifypanel/drivers/wireguard_api.py +24 -5
  6. hiddifypanel/hutils/convert.py +1 -1
  7. hiddifypanel/hutils/flask.py +28 -2
  8. hiddifypanel/hutils/importer/xui.py +6 -7
  9. hiddifypanel/hutils/network/__init__.py +1 -0
  10. hiddifypanel/hutils/network/cf_api.py +84 -0
  11. hiddifypanel/hutils/network/net.py +26 -49
  12. hiddifypanel/hutils/node/child.py +25 -7
  13. hiddifypanel/hutils/node/parent.py +7 -7
  14. hiddifypanel/hutils/node/shared.py +19 -6
  15. hiddifypanel/hutils/proxy/clash.py +1 -1
  16. hiddifypanel/hutils/proxy/shared.py +1 -1
  17. hiddifypanel/hutils/proxy/singbox.py +2 -3
  18. hiddifypanel/hutils/proxy/xray.py +12 -10
  19. hiddifypanel/hutils/proxy/xrayjson.py +26 -49
  20. hiddifypanel/hutils/utils.py +47 -3
  21. hiddifypanel/models/__init__.py +1 -1
  22. hiddifypanel/models/admin.py +9 -2
  23. hiddifypanel/models/base_account.py +3 -1
  24. hiddifypanel/models/config.py +10 -19
  25. hiddifypanel/models/config_enum.py +18 -6
  26. hiddifypanel/models/domain.py +82 -118
  27. hiddifypanel/models/user.py +44 -24
  28. hiddifypanel/panel/admin/Actions.py +6 -11
  29. hiddifypanel/panel/admin/AdminstratorAdmin.py +3 -9
  30. hiddifypanel/panel/admin/Backup.py +5 -8
  31. hiddifypanel/panel/admin/Dashboard.py +3 -4
  32. hiddifypanel/panel/admin/DomainAdmin.py +20 -15
  33. hiddifypanel/panel/admin/ProxyAdmin.py +3 -10
  34. hiddifypanel/panel/admin/QuickSetup.py +1 -1
  35. hiddifypanel/panel/admin/SettingAdmin.py +7 -5
  36. hiddifypanel/panel/admin/Terminal.py +0 -1
  37. hiddifypanel/panel/admin/UserAdmin.py +4 -3
  38. hiddifypanel/panel/admin/templates/model/proxydetail_list.html +6 -0
  39. hiddifypanel/panel/cli.py +36 -23
  40. hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +15 -5
  41. hiddifypanel/panel/commercial/restapi/v1/tgbot.py +7 -4
  42. hiddifypanel/panel/commercial/restapi/v2/admin/__init__.py +17 -13
  43. hiddifypanel/panel/commercial/restapi/v2/admin/admin_info_api.py +4 -3
  44. hiddifypanel/panel/commercial/restapi/v2/admin/admin_user_api.py +28 -10
  45. hiddifypanel/panel/commercial/restapi/v2/admin/admin_users_api.py +2 -19
  46. hiddifypanel/panel/commercial/restapi/v2/admin/schema.py +27 -4
  47. hiddifypanel/panel/commercial/restapi/v2/admin/user_api.py +28 -9
  48. hiddifypanel/panel/commercial/restapi/v2/admin/users_api.py +1 -21
  49. hiddifypanel/panel/commercial/restapi/v2/parent/register_api.py +1 -1
  50. hiddifypanel/panel/commercial/restapi/v2/parent/schema.py +8 -4
  51. hiddifypanel/panel/commercial/restapi/v2/parent/sync_api.py +19 -3
  52. hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +48 -42
  53. hiddifypanel/panel/commercial/telegrambot/Usage.py +1 -1
  54. hiddifypanel/panel/commercial/telegrambot/admin.py +1 -1
  55. hiddifypanel/panel/commercial/telegrambot/information.py +1 -1
  56. hiddifypanel/panel/common.py +5 -11
  57. hiddifypanel/panel/hiddify.py +9 -20
  58. hiddifypanel/panel/init_db.py +41 -24
  59. hiddifypanel/panel/usage.py +38 -9
  60. hiddifypanel/panel/user/user.py +52 -32
  61. hiddifypanel/templates/admin-layout.html +2 -2
  62. hiddifypanel/templates/fake.html +316 -0
  63. hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
  64. hiddifypanel/translations/en/LC_MESSAGES/messages.po +107 -45
  65. hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
  66. hiddifypanel/translations/fa/LC_MESSAGES/messages.po +102 -36
  67. hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
  68. hiddifypanel/translations/pt/LC_MESSAGES/messages.po +64 -7
  69. hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
  70. hiddifypanel/translations/ru/LC_MESSAGES/messages.po +161 -78
  71. hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
  72. hiddifypanel/translations/zh/LC_MESSAGES/messages.po +63 -6
  73. hiddifypanel/translations.i18n/en.json +83 -42
  74. hiddifypanel/translations.i18n/fa.json +73 -32
  75. hiddifypanel/translations.i18n/pt.json +45 -4
  76. hiddifypanel/translations.i18n/ru.json +113 -72
  77. hiddifypanel/translations.i18n/zh.json +44 -3
  78. {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/METADATA +2 -1
  79. {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/RECORD +83 -82
  80. {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/WHEEL +1 -1
  81. hiddifypanel/panel/cf_api.py +0 -37
  82. {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/LICENSE.md +0 -0
  83. {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/entry_points.txt +0 -0
  84. {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/top_level.txt +0 -0
@@ -34,11 +34,27 @@ class SyncApi(MethodView):
34
34
 
35
35
  try:
36
36
  logger.info("Syncing domains...")
37
- bulk_register_domains(data['domains'], commit=False, force_child_unique_id=child.unique_id)
37
+ if data.get('domains'):
38
+ logger.info("Inserting domains into database")
39
+ Domain.bulk_register(data['domains'], commit=False, force_child_unique_id=child.unique_id)
40
+ else:
41
+ logger.info("Domains field is empty")
42
+
38
43
  logger.info("Syncing hconfigs...")
39
- bulk_register_configs(data['hconfigs'], commit=False, froce_child_unique_id=child.unique_id)
44
+ if data.get('hconfigs'):
45
+ logger.info("Inserting hconfigs into database")
46
+ bulk_register_configs(data['hconfigs'], commit=False, froce_child_unique_id=child.unique_id)
47
+ else:
48
+ logger.info("Hconfigs field is empty")
49
+
40
50
  logger.info("Syncing proxies...")
41
- Proxy.bulk_register(data['proxies'], commit=False, force_child_unique_id=child.unique_id)
51
+ if data.get('proxies'):
52
+ logger.info("Inserting proxies into database")
53
+ Proxy.bulk_register(data['proxies'], commit=False, force_child_unique_id=child.unique_id)
54
+ else:
55
+ logger.info("Proxies field is empty")
56
+
57
+ logger.info("Commit changes to database")
42
58
  db.session.commit() # type: ignore
43
59
  except Exception as err:
44
60
  with logger.contextualize(error=err):
@@ -50,60 +50,66 @@ class AllConfigsAPI(MethodView):
50
50
  )
51
51
  )
52
52
 
53
- # Add Full Singbox
54
- items.append(
55
- create_item(
56
- "Full Singbox", "ALL", "", "", "", "",
57
- # f"{base_url}full-singbox.json?asn={c['asn']}"
58
- f"{base_url}singbox/?asn={c['asn']}#{config_name}"
53
+ if hconfig(ConfigEnum.sub_full_singbox_enable):
54
+ # Add Full Singbox
55
+ items.append(
56
+ create_item(
57
+ "Full Singbox", "ALL", "", "", "", "",
58
+ # f"{base_url}full-singbox.json?asn={c['asn']}"
59
+ f"{base_url}singbox/?asn={c['asn']}#{config_name}"
60
+ )
59
61
  )
60
- )
61
62
 
62
- # Add Full Xray
63
- items.append(
64
- create_item(
65
- "Full Xray", "ALL", "", "", "", "",
66
- f"{base_url}xray/#{config_name}"
63
+ if hconfig(ConfigEnum.sub_full_xray_json_enable):
64
+ # Add Full Xray
65
+ items.append(
66
+ create_item(
67
+ "Full Xray", "ALL", "", "", "", "",
68
+ f"{base_url}xray/#{config_name}"
69
+ )
67
70
  )
68
- )
69
71
 
70
- # Add Subscription link
71
- items.append(
72
- create_item(
73
- "Subscription link", "ALL", "", "", "", "",
74
- # f"{base_url}all.txt?name={c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}&asn={c['asn']}&mode={c['mode']}"
75
- f"{base_url}sub/?asn={c['asn']}#{config_name}"
72
+ if hconfig(ConfigEnum.sub_full_links_enable):
73
+ # Add Subscription link
74
+ items.append(
75
+ create_item(
76
+ "Subscription link", "ALL", "", "", "", "",
77
+ # f"{base_url}all.txt?name={c['db_domain'].alias or c['db_domain'].domain}-{c['asn']}&asn={c['asn']}&mode={c['mode']}"
78
+ f"{base_url}sub/?asn={c['asn']}#{config_name}"
79
+ )
76
80
  )
77
- )
78
81
 
79
- # Add Subscription link base64
80
- items.append(
81
- create_item(
82
- "Subscription link b64", "ALL", "", "", "", "",
83
- # 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"
84
- f"{base_url}sub64/?asn={c['asn']}#{config_name}"
82
+ if hconfig(ConfigEnum.sub_full_links_b64_enable):
83
+ # Add Subscription link base64
84
+ items.append(
85
+ create_item(
86
+ "Subscription link b64", "ALL", "", "", "", "",
87
+ # 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"
88
+ f"{base_url}sub64/?asn={c['asn']}#{config_name}"
89
+ )
85
90
  )
86
- )
87
- # Add Clash Meta
88
- items.append(
89
- create_item(
90
- "Clash Meta", "ALL", "", "", "", "",
91
- # 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']}"
92
- f"clash://install-config?url={base_url}clashmeta/?asn={c['asn']}#{config_name}"
91
+ if hconfig(ConfigEnum.sub_full_clash_meta_enable):
92
+ # Add Clash Meta
93
+ items.append(
94
+ create_item(
95
+ "Clash Meta", "ALL", "", "", "", "",
96
+ # 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']}"
97
+ f"clash://install-config?url={base_url}clashmeta/?asn={c['asn']}#{config_name}"
98
+ )
93
99
  )
94
- )
95
100
 
96
- # Add Clash
97
- items.append(
98
- create_item(
99
- "Clash", "ALL", "Except VLess", "", "", "",
100
- # 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']}"
101
- f"clash://install-config?url={base_url}clash/?asn={c['asn']}#{config_name}"
101
+ if hconfig(ConfigEnum.sub_full_clash_enable):
102
+ # Add Clash
103
+ items.append(
104
+ create_item(
105
+ "Clash", "ALL", "Except VLess", "", "", "",
106
+ # 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']}"
107
+ f"clash://install-config?url={base_url}clash/?asn={c['asn']}#{config_name}"
108
+ )
102
109
  )
103
- )
104
110
 
105
111
  # Add Singbox: SSh
106
- if hconfig(ConfigEnum.ssh_server_enable):
112
+ if hconfig(ConfigEnum.sub_singbox_ssh_enable) and hconfig(ConfigEnum.ssh_server_enable):
107
113
  items.append(
108
114
  create_item(
109
115
  "Singbox: SSH", "SSH", "", "", "", "",
@@ -57,7 +57,7 @@ def get_usage_msg(uuid, domain=None):
57
57
  expire_rel = user_data['expire_rel']
58
58
  reset_day = user_data['reset_day']
59
59
 
60
- domain = domain or get_panel_domains()[0]
60
+ domain = domain or Domain.get_domains()[0]
61
61
  user_link = hiddify.get_account_panel_link(user, domain.domain)
62
62
  with force_locale(user.lang or hconfig(ConfigEnum.lang)):
63
63
  msg = f"""{_('<a href="%(user_link)s"> %(user)s</a>',user_link=user_link ,user=user.name if user.name != "default" else "")}\n\n"""
@@ -102,7 +102,7 @@ def admin_keyboard_domain(old_action):
102
102
  )
103
103
  return types.InlineKeyboardMarkup(keyboard=[
104
104
  [keyboard(d)]
105
- for d in get_panel_domains()
105
+ for d in Domain.get_domains()
106
106
  ]
107
107
  )
108
108
 
@@ -16,7 +16,7 @@ def prepare_me_info(user):
16
16
  "Your hiddify information is\n" +
17
17
  "UUID: {}\n".format(user.uuid) +
18
18
  "Last online date: {}\n".format(user.last_online) +
19
- "Expire time: {}\n".format(user.expiry_time) +
19
+ "Expire time: {}\n".format(user.remaining_days) +
20
20
  "Usage class: {}\n".format(user.mode)
21
21
  )
22
22
 
@@ -46,12 +46,8 @@ def init_app(app: APIFlask):
46
46
  return jsonify({
47
47
  'message': 'Not Found',
48
48
  }), 404
49
- # print(request.headers)
50
- last_version = hiddify.get_latest_release_version('hiddify-panel') # TODO: add dev update check
51
- if "T" in hiddifypanel.__version__:
52
- has_update = False
53
- else:
54
- has_update = "dev" not in hiddifypanel.__version__ and f'{last_version}' != hiddifypanel.__version__
49
+
50
+ has_update = hutils.utils.is_panel_outdated()
55
51
 
56
52
  if not request.accept_mimetypes.accept_html:
57
53
  if has_update:
@@ -68,6 +64,7 @@ def init_app(app: APIFlask):
68
64
 
69
65
  # Create github issue link
70
66
  issue_link = hutils.github_issue.generate_github_issue_link_for_500_error(e, trace)
67
+ last_version = hiddify.get_latest_release_version('hiddifypanel')
71
68
 
72
69
  return render_template('500.html', error=e, trace=trace, has_update=has_update, last_version=last_version, issue_link=issue_link), 500
73
70
 
@@ -83,11 +80,8 @@ def init_app(app: APIFlask):
83
80
  # Create github issue link
84
81
  issue_link = hutils.github_issue.generate_github_issue_link_for_500_error(e, trace)
85
82
 
86
- last_version = hiddify.get_latest_release_version('hiddify-panel') # TODO: add dev update check
87
- if "T" in hiddifypanel.__version__:
88
- has_update = False
89
- else:
90
- has_update = "dev" not in hiddifypanel.__version__ and f'{last_version}' != hiddifypanel.__version__
83
+ has_update = hutils.utils.is_panel_outdated()
84
+ last_version = hiddify.get_latest_release_version('hiddifypanel')
91
85
 
92
86
  return render_template('500.html', error=e, trace=trace, has_update=has_update, last_version=last_version, issue_link=issue_link), 500
93
87
 
@@ -82,7 +82,9 @@ def get_html_user_link(model: BaseAccount, domain: Domain):
82
82
  if "*" in d:
83
83
  d = d.replace("*", hutils.random.get_random_string(5, 15))
84
84
 
85
- link = f'{get_account_panel_link(model, d)}#{hutils.encode.unicode_slug(model.name)}'
85
+ # for showing child/node link (we send child_id to get_account_panel_link to get domain proxy path correctly)
86
+ d_child_id = domain.child_id
87
+ link = f'{get_account_panel_link(model, d,child_id=d_child_id)}#{hutils.encode.unicode_slug(model.name)}'
86
88
 
87
89
  text = domain.alias or domain.domain
88
90
  color_cls = 'info'
@@ -224,7 +226,7 @@ def set_db_from_json(json_data, override_child_unique_id=True, set_users=True, s
224
226
  if set_users and 'users' in json_data:
225
227
  User.bulk_register(json_data['users'], commit=False, remove=remove_users)
226
228
  if set_domains and 'domains' in json_data:
227
- bulk_register_domains(json_data['domains'], commit=False, remove=remove_domains)
229
+ Domain.bulk_register(json_data['domains'], commit=False, remove=remove_domains)
228
230
 
229
231
  if set_settings and 'hconfigs' in json_data:
230
232
  bulk_register_configs(json_data["hconfigs"], commit=True, override_unique_id=override_unique_id)
@@ -274,9 +276,11 @@ def get_account_panel_link(account: BaseAccount, host: str, is_https: bool = Tru
274
276
  link += str(host)
275
277
  proxy_path = hconfig(ConfigEnum.proxy_path_admin if is_admin else ConfigEnum.proxy_path_client, child_id)
276
278
  link += f'/{proxy_path}/'
277
- if child_id != 0:
278
- child = Child.by_id(child_id)
279
- link += f"{child.id}/"
279
+
280
+ # if child_id != 0:
281
+ # child = Child.by_id(child_id)
282
+ # link += f"{child.id}/"
283
+
280
284
  if basic_auth:
281
285
  link += "l"
282
286
  else:
@@ -332,18 +336,3 @@ def get_backup_child_unique_id(backupdata: dict) -> str:
332
336
  if len(backupdata.get('childs', [])) == 0:
333
337
  return "self"
334
338
  return backupdata['childs'][0]['unique_id']
335
-
336
-
337
- def is_hiddify_next_version(major_v: int = 0, minor_v: int = 0, patch_v: int = 0) -> bool:
338
- '''If the user agent version be equals or higher than parameters returns True'''
339
- if not g.user_agent.get('hiddify_version'):
340
- return False
341
- raw_v = g.user_agent['hiddify_version']
342
- raw_v_len = len(raw_v)
343
- u_major_v = raw_v[0] if raw_v_len > 0 else 0
344
- u_minor_v = raw_v[1] if raw_v_len > 1 else 0
345
- u_patch_v = raw_v[2] if raw_v_len > 2 else 0
346
-
347
- if u_major_v >= major_v and u_minor_v >= minor_v and u_patch_v >= patch_v:
348
- return True
349
- return False
@@ -13,10 +13,28 @@ from hiddifypanel.panel import hiddify
13
13
  from hiddifypanel.database import db, db_execute
14
14
  from flask import g
15
15
  from sqlalchemy import text
16
-
16
+ from loguru import logger
17
17
  MAX_DB_VERSION = 90
18
18
 
19
19
 
20
+ def _v88(child_id):
21
+ pass
22
+
23
+
24
+ def _v86(child_id):
25
+ set_hconfig(ConfigEnum.hiddifycli_enable, True)
26
+
27
+
28
+ def _v85(child_id):
29
+ set_hconfig(ConfigEnum.sub_full_singbox_enable, True)
30
+ set_hconfig(ConfigEnum.sub_singbox_ssh_enable, True)
31
+ set_hconfig(ConfigEnum.sub_full_xray_json_enable, True)
32
+ set_hconfig(ConfigEnum.sub_full_links_enable, True)
33
+ set_hconfig(ConfigEnum.sub_full_links_b64_enable, True)
34
+ set_hconfig(ConfigEnum.sub_full_clash_enable, True)
35
+ set_hconfig(ConfigEnum.sub_full_clash_meta_enable, True)
36
+
37
+
20
38
  def _v84(child_id):
21
39
  # the 2022-blake3-chacha20-poly1305 encryption method doesn't support multiuser config
22
40
  if hconfig(ConfigEnum.shadowsocks2022_method) == '2022-blake3-chacha20-poly1305':
@@ -246,7 +264,7 @@ def _v41():
246
264
 
247
265
  def _v38():
248
266
  add_config_if_not_exist(ConfigEnum.dns_server, "1.1.1.1")
249
- add_config_if_not_exist(ConfigEnum.warp_mode, "all" if hconfig(ConfigEnum.warp_enable) else "none")
267
+ add_config_if_not_exist(ConfigEnum.warp_mode, "all" if hconfig(ConfigEnum.warp_enable) else "disable")
250
268
  add_config_if_not_exist(ConfigEnum.warp_plus_code, '')
251
269
 
252
270
 
@@ -328,17 +346,17 @@ def _v19():
328
346
  add_config_if_not_exist(ConfigEnum.package_mode, "release")
329
347
 
330
348
 
331
- def _v17():
332
- for u in User.query.all():
333
- if u.expiry_time:
334
- if not u.package_days:
335
- if not u.last_reset_time:
336
- u.package_days = (u.expiry_time - datetime.date.today()).days
337
- u.start_date = datetime.date.today()
338
- else:
339
- u.package_days = (u.expiry_time - u.last_reset_time).days
340
- u.start_date = u.last_reset_time
341
- u.expiry_time = None
349
+ # def _v17():
350
+ # for u in User.query.all():
351
+ # if u.expiry_time:
352
+ # if not u.package_days:
353
+ # if not u.last_reset_time:
354
+ # u.package_days = (u.expiry_time - datetime.date.today()).days
355
+ # u.start_date = datetime.date.today()
356
+ # else:
357
+ # u.package_days = (u.expiry_time - u.last_reset_time).days
358
+ # u.start_date = u.last_reset_time
359
+ # u.expiry_time = None
342
360
 
343
361
 
344
362
  def _v1():
@@ -368,7 +386,7 @@ def _v1():
368
386
  BoolConfig(key=ConfigEnum.vmess_enable, value=True),
369
387
  BoolConfig(key=ConfigEnum.http_proxy_enable, value=True),
370
388
  StrConfig(key=ConfigEnum.shared_secret, value=str(uuid.uuid4())),
371
- BoolConfig(key=ConfigEnum.telegram_enable, value=True),
389
+ BoolConfig(key=ConfigEnum.telegram_enable, value=False),
372
390
  # StrConfig(key=ConfigEnum.telegram_secret,value=uuid.uuid4().hex),
373
391
  StrConfig(key=ConfigEnum.telegram_adtag, value=""),
374
392
  StrConfig(key=ConfigEnum.telegram_fakedomain, value=rnd_domains[1]),
@@ -546,7 +564,6 @@ def add_config_if_not_exist(key: ConfigEnum, val: str | int, child_id: int | Non
546
564
  child_id = Child.current().id
547
565
 
548
566
  old_val = hconfig(key, child_id)
549
- hutils.utils.error(f'{key}, {val}, {child_id}, {old_val}')
550
567
  if old_val is None:
551
568
  set_hconfig(key, val)
552
569
 
@@ -565,7 +582,7 @@ def execute(query: str):
565
582
 
566
583
  db_execute(query)
567
584
  except BaseException as e:
568
- hutils.utils.error(e)
585
+ logger.debug(e)
569
586
  pass
570
587
 
571
588
 
@@ -581,7 +598,7 @@ def add_new_enum_values():
581
598
 
582
599
  # Get the existing values in the enum
583
600
  existing_values = [f'{e}' if isinstance(e, ConfigEnum) else e.value for e in enum_class]
584
- # print("existing_values--------------", existing_values)
601
+
585
602
  # Get the values in the enum column in the database
586
603
  # result = db.engine.execute(f"SELECT DISTINCT `{column_name}` FROM {table_name}")
587
604
  # db_values = {row[0] for row in result}
@@ -598,7 +615,7 @@ def add_new_enum_values():
598
615
  # Find the new values that need to be added to the enum column in the database
599
616
  new_values = set(existing_values) - set(db_values)
600
617
  old_values = set(db_values) - set(existing_values)
601
- # print('new_values-=-----------------', new_values)
618
+
602
619
  if len(new_values) == 0 and len(old_values) == 0:
603
620
  continue
604
621
 
@@ -624,14 +641,14 @@ def upgrade_database():
624
641
  if not os.path.isdir(backup_root) or len(os.listdir(backup_root)) == 0:
625
642
  if os.path.isfile(sqlite_db):
626
643
  os.rename(sqlite_db, sqlite_db + ".old")
627
- hutils.utils.error("no backup found...")
644
+ logger.info("no backup found...")
628
645
  return
629
646
  if os.path.isfile(sqlite_db):
630
- hutils.utils.error("Finding Old Version Database... importing configs from latest backup")
647
+ logger.info("Finding Old Version Database... importing configs from latest backup")
631
648
  newest_file = max([(f, os.path.getmtime(os.path.join(backup_root, f)))
632
649
  for f in os.listdir(backup_root) if os.path.isfile(os.path.join(backup_root, f))], key=lambda x: x[1])[0]
633
650
  with open(f'{backup_root}{newest_file}', 'r') as f:
634
- hutils.utils.error(f"importing configs from {newest_file}")
651
+ logger.info(f"importing configs from {newest_file}")
635
652
  json_data = json.load(f)
636
653
  hiddify.set_db_from_json(json_data,
637
654
  set_users=True,
@@ -649,7 +666,7 @@ def upgrade_database():
649
666
  os.rename(sqlite_db, sqlite_db + ".old")
650
667
  set_hconfig(ConfigEnum.db_version, db_version, commit=True)
651
668
 
652
- hutils.utils.error("Upgrading to the new dataset succuess.")
669
+ logger.info("Upgrading to the new dataset succuess.")
653
670
 
654
671
 
655
672
  def init_db():
@@ -682,7 +699,7 @@ def init_db():
682
699
  if not db_action or (start_version == 0 and ver == 10):
683
700
  continue
684
701
 
685
- hutils.utils.error(f"Updating db from version {db_version} for node {child.id}")
702
+ logger.info(f"Updating db from version {db_version} for node {child.id}")
686
703
 
687
704
  if ver < 70:
688
705
  if child.id != 0:
@@ -692,7 +709,7 @@ def init_db():
692
709
  db_action(child.id)
693
710
 
694
711
  Events.db_init_event.notify(db_version=db_version)
695
- hutils.utils.error(f"Updated successfuly db from version {db_version} to {ver}")
712
+ logger.info(f"Updated successfuly db from version {db_version} to {ver}")
696
713
 
697
714
  db_version = ver
698
715
  db.session.commit()
@@ -27,6 +27,22 @@ def add_users_usage_uuid(uuids_bytes: Dict[str, Dict], child_id, sync=False):
27
27
  _add_users_usage(dbusers_bytes, child_id, sync) # type: ignore
28
28
 
29
29
 
30
+ def _reset_priodic_usage():
31
+ last_usage_check: int = hconfig(ConfigEnum.last_priodic_usage_check) or 0
32
+ import time
33
+ current_time = int(time.time())
34
+ if current_time - last_usage_check < 60 * 60 * 6:
35
+ return
36
+ # reset as soon as possible in the day
37
+ if datetime.datetime.now().hour > 5 and current_time - last_usage_check < 60 * 60 * 24:
38
+ return
39
+
40
+ for user in User.query.filter(User.mode != UserMode.no_reset).all():
41
+ if user.user_should_reset():
42
+ user.reset_usage(commit=False)
43
+ set_hconfig(ConfigEnum.last_priodic_usage_check, current_time)
44
+
45
+
30
46
  def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
31
47
  '''
32
48
  sync: when enabled, it means we have received usages from the parent panel
@@ -42,39 +58,43 @@ def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
42
58
  daily_usage[adm.id] = DailyUsage(admin_id=adm.id, child_id=child_id)
43
59
  db.session.add(daily_usage[adm.id])
44
60
  daily_usage[adm.id].online = User.query.filter(User.added_by == adm.id).filter(func.DATE(User.last_online) == today).count()
45
- # db.session.commit()
61
+
62
+ _reset_priodic_usage()
63
+
46
64
  userDetails = {p.user_id: p for p in UserDetail.query.filter(UserDetail.child_id == child_id).all()}
47
65
  for user, uinfo in users_usage_data.items():
48
66
  usage_bytes = uinfo['usage']
49
67
  devices = uinfo['devices']
50
- # user_active_before=user.is_active
68
+
69
+ # UserDetails things
51
70
  detail = userDetails.get(user.id)
52
71
  if not detail:
53
72
  detail = UserDetail(user_id=user.id, child_id=child_id)
54
- detail.current_usage_GB = detail.current_usage_GB or 0
55
73
  db.session.add(detail)
56
74
  detail.connected_devices = devices
57
75
  detail.current_usage_GB = detail.current_usage_GB or 0
58
- if not user.last_reset_time or user.user_should_reset():
59
- user.last_reset_time = datetime.date.today()
60
- user.current_usage_GB = 0
61
- detail.current_usage_GB = 0
62
76
 
77
+ # Enable the user if isn't already
63
78
  if not before_enabled_users[user.uuid] and user.is_active:
64
79
  print(f"Enabling disabled client {user.uuid} ")
65
80
  user_driver.add_client(user)
66
81
  send_bot_message(user)
67
82
  have_change = True
83
+
84
+ # Check if there's new usage value
68
85
  if not isinstance(usage_bytes, int) or usage_bytes == 0:
69
86
  res[user.uuid] = "No usage"
70
87
  else:
88
+ # Set new daily usage of the user
71
89
  if sync:
72
90
  if daily_usage.get(user.added_by, daily_usage[1]).usage != usage_bytes:
73
91
  daily_usage.get(user.added_by, daily_usage[1]).usage = usage_bytes
74
92
  else:
75
93
  daily_usage.get(user.added_by, daily_usage[1]).usage += usage_bytes
94
+
76
95
  in_gig = (usage_bytes) / to_gig_d
77
- res[user.uuid] = in_gig
96
+
97
+ # Set new current usage of the user
78
98
  if sync:
79
99
  if user.current_usage_GB != in_gig:
80
100
  user.current_usage_GB = in_gig
@@ -82,12 +102,18 @@ def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
82
102
  else:
83
103
  user.current_usage_GB += in_gig
84
104
  detail.current_usage_GB += in_gig
105
+
106
+ # Change last online time of the user
85
107
  user.last_online = datetime.datetime.now()
86
108
  detail.last_online = datetime.datetime.now()
87
109
 
110
+ # Set start date of user to the current datetime if it hasn't been set already
88
111
  if user.start_date is None:
89
112
  user.start_date = datetime.date.today()
90
113
 
114
+ res[user.uuid] = in_gig
115
+
116
+ # Remove user from drivers(singbox, xray, wireguard etc.) if they're inactive
91
117
  if before_enabled_users[user.uuid] and not user.is_active:
92
118
  print(f"Removing enabled client {user.uuid} ")
93
119
  user_driver.remove_client(user)
@@ -95,13 +121,16 @@ def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
95
121
  res[user.uuid] = f"{res[user.uuid]} !OUT of USAGE! Client Removed"
96
122
 
97
123
  db.session.commit() # type: ignore
124
+
125
+ # Apply the changes to the drivers
98
126
  if have_change:
99
127
  hiddify.quick_apply_users()
100
128
 
101
- # sync with the parent
129
+ # Sync the new data with the parent node if the data has not been set by the parent node itself and the current panel is a child panel
102
130
  if not sync:
103
131
  if hutils.node.is_child():
104
132
  hutils.node.child.sync_users_usage_with_parent()
133
+
105
134
  return {"status": 'success', "comments": res}
106
135
 
107
136