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.
- hiddifypanel/VERSION +1 -1
- hiddifypanel/VERSION.py +2 -2
- hiddifypanel/base.py +22 -12
- hiddifypanel/cache.py +2 -51
- hiddifypanel/drivers/wireguard_api.py +24 -5
- hiddifypanel/hutils/convert.py +1 -1
- hiddifypanel/hutils/flask.py +28 -2
- hiddifypanel/hutils/importer/xui.py +6 -7
- hiddifypanel/hutils/network/__init__.py +1 -0
- hiddifypanel/hutils/network/cf_api.py +84 -0
- hiddifypanel/hutils/network/net.py +26 -49
- hiddifypanel/hutils/node/child.py +25 -7
- hiddifypanel/hutils/node/parent.py +7 -7
- hiddifypanel/hutils/node/shared.py +19 -6
- hiddifypanel/hutils/proxy/clash.py +1 -1
- hiddifypanel/hutils/proxy/shared.py +1 -1
- hiddifypanel/hutils/proxy/singbox.py +2 -3
- hiddifypanel/hutils/proxy/xray.py +12 -10
- hiddifypanel/hutils/proxy/xrayjson.py +26 -49
- hiddifypanel/hutils/utils.py +47 -3
- hiddifypanel/models/__init__.py +1 -1
- hiddifypanel/models/admin.py +9 -2
- hiddifypanel/models/base_account.py +3 -1
- hiddifypanel/models/config.py +10 -19
- hiddifypanel/models/config_enum.py +18 -6
- hiddifypanel/models/domain.py +82 -118
- hiddifypanel/models/user.py +44 -24
- hiddifypanel/panel/admin/Actions.py +6 -11
- hiddifypanel/panel/admin/AdminstratorAdmin.py +3 -9
- hiddifypanel/panel/admin/Backup.py +5 -8
- hiddifypanel/panel/admin/Dashboard.py +3 -4
- hiddifypanel/panel/admin/DomainAdmin.py +20 -15
- hiddifypanel/panel/admin/ProxyAdmin.py +3 -10
- hiddifypanel/panel/admin/QuickSetup.py +1 -1
- hiddifypanel/panel/admin/SettingAdmin.py +7 -5
- hiddifypanel/panel/admin/Terminal.py +0 -1
- hiddifypanel/panel/admin/UserAdmin.py +4 -3
- hiddifypanel/panel/admin/templates/model/proxydetail_list.html +6 -0
- hiddifypanel/panel/cli.py +36 -23
- hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +15 -5
- hiddifypanel/panel/commercial/restapi/v1/tgbot.py +7 -4
- hiddifypanel/panel/commercial/restapi/v2/admin/__init__.py +17 -13
- hiddifypanel/panel/commercial/restapi/v2/admin/admin_info_api.py +4 -3
- hiddifypanel/panel/commercial/restapi/v2/admin/admin_user_api.py +28 -10
- hiddifypanel/panel/commercial/restapi/v2/admin/admin_users_api.py +2 -19
- hiddifypanel/panel/commercial/restapi/v2/admin/schema.py +27 -4
- hiddifypanel/panel/commercial/restapi/v2/admin/user_api.py +28 -9
- hiddifypanel/panel/commercial/restapi/v2/admin/users_api.py +1 -21
- hiddifypanel/panel/commercial/restapi/v2/parent/register_api.py +1 -1
- hiddifypanel/panel/commercial/restapi/v2/parent/schema.py +8 -4
- hiddifypanel/panel/commercial/restapi/v2/parent/sync_api.py +19 -3
- hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +48 -42
- hiddifypanel/panel/commercial/telegrambot/Usage.py +1 -1
- hiddifypanel/panel/commercial/telegrambot/admin.py +1 -1
- hiddifypanel/panel/commercial/telegrambot/information.py +1 -1
- hiddifypanel/panel/common.py +5 -11
- hiddifypanel/panel/hiddify.py +9 -20
- hiddifypanel/panel/init_db.py +41 -24
- hiddifypanel/panel/usage.py +38 -9
- hiddifypanel/panel/user/user.py +52 -32
- hiddifypanel/templates/admin-layout.html +2 -2
- hiddifypanel/templates/fake.html +316 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +107 -45
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +102 -36
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +64 -7
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +161 -78
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +63 -6
- hiddifypanel/translations.i18n/en.json +83 -42
- hiddifypanel/translations.i18n/fa.json +73 -32
- hiddifypanel/translations.i18n/pt.json +45 -4
- hiddifypanel/translations.i18n/ru.json +113 -72
- hiddifypanel/translations.i18n/zh.json +44 -3
- {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/METADATA +2 -1
- {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/RECORD +83 -82
- {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/WHEEL +1 -1
- hiddifypanel/panel/cf_api.py +0 -37
- {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-10.20.3.dist-info → hiddifypanel-10.30.0.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
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
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
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"""
|
@@ -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.
|
19
|
+
"Expire time: {}\n".format(user.remaining_days) +
|
20
20
|
"Usage class: {}\n".format(user.mode)
|
21
21
|
)
|
22
22
|
|
hiddifypanel/panel/common.py
CHANGED
@@ -46,12 +46,8 @@ def init_app(app: APIFlask):
|
|
46
46
|
return jsonify({
|
47
47
|
'message': 'Not Found',
|
48
48
|
}), 404
|
49
|
-
|
50
|
-
|
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
|
-
|
87
|
-
|
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
|
|
hiddifypanel/panel/hiddify.py
CHANGED
@@ -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
|
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
|
-
|
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
|
-
|
278
|
-
|
279
|
-
|
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
|
hiddifypanel/panel/init_db.py
CHANGED
@@ -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 "
|
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
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
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=
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
644
|
+
logger.info("no backup found...")
|
628
645
|
return
|
629
646
|
if os.path.isfile(sqlite_db):
|
630
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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()
|
hiddifypanel/panel/usage.py
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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
|
|