hiddifypanel 9.0.0.dev90__py3-none-any.whl → 10.5.0.dev0__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/auth.py +30 -9
- hiddifypanel/base.py +60 -52
- hiddifypanel/cache.py +43 -25
- hiddifypanel/database.py +9 -0
- hiddifypanel/drivers/abstract_driver.py +2 -0
- hiddifypanel/drivers/singbox_api.py +17 -15
- hiddifypanel/drivers/ssh_liberty_bridge_api.py +3 -1
- hiddifypanel/drivers/user_driver.py +12 -6
- hiddifypanel/drivers/wireguard_api.py +7 -2
- hiddifypanel/drivers/xray_api.py +14 -9
- hiddifypanel/hutils/__init__.py +4 -0
- hiddifypanel/hutils/convert.py +13 -2
- hiddifypanel/hutils/crypto.py +48 -0
- hiddifypanel/hutils/encode.py +4 -1
- hiddifypanel/hutils/flask.py +38 -5
- hiddifypanel/hutils/github_issue.py +1 -1
- hiddifypanel/hutils/importer/xui.py +5 -2
- hiddifypanel/{models/utils.py → hutils/model.py} +14 -4
- hiddifypanel/hutils/network/auto_ip_selector.py +2 -0
- hiddifypanel/hutils/network/net.py +46 -2
- hiddifypanel/hutils/node/__init__.py +3 -0
- hiddifypanel/hutils/node/api_client.py +76 -0
- hiddifypanel/hutils/node/child.py +147 -0
- hiddifypanel/hutils/node/parent.py +100 -0
- hiddifypanel/hutils/node/shared.py +65 -0
- hiddifypanel/hutils/proxy/__init__.py +5 -0
- hiddifypanel/hutils/proxy/clash.py +161 -0
- hiddifypanel/hutils/proxy/shared.py +434 -0
- hiddifypanel/hutils/proxy/singbox.py +339 -0
- hiddifypanel/hutils/proxy/xray.py +235 -0
- hiddifypanel/hutils/proxy/xrayjson.py +391 -0
- hiddifypanel/hutils/random.py +4 -0
- hiddifypanel/hutils/utils.py +4 -1
- hiddifypanel/models/__init__.py +2 -2
- hiddifypanel/models/admin.py +31 -17
- hiddifypanel/models/base_account.py +7 -7
- hiddifypanel/models/child.py +30 -16
- hiddifypanel/models/config.py +45 -16
- hiddifypanel/models/config_enum.py +68 -17
- hiddifypanel/models/domain.py +28 -20
- hiddifypanel/models/parent_domain.py +2 -2
- hiddifypanel/models/proxy.py +29 -20
- hiddifypanel/models/report.py +2 -3
- hiddifypanel/models/usage.py +2 -2
- hiddifypanel/models/user.py +33 -22
- hiddifypanel/panel/admin/Actions.py +13 -19
- hiddifypanel/panel/admin/AdminstratorAdmin.py +14 -3
- hiddifypanel/panel/admin/Dashboard.py +5 -10
- hiddifypanel/panel/admin/DomainAdmin.py +35 -48
- hiddifypanel/panel/admin/NodeAdmin.py +6 -2
- hiddifypanel/panel/admin/ProxyAdmin.py +6 -5
- hiddifypanel/panel/admin/QuickSetup.py +21 -20
- hiddifypanel/panel/admin/SettingAdmin.py +107 -62
- hiddifypanel/panel/admin/UserAdmin.py +22 -21
- hiddifypanel/panel/admin/templates/index.html +1 -1
- hiddifypanel/panel/admin/templates/model/user_list.html +44 -20
- hiddifypanel/panel/admin/templates/parent_dash.html +2 -4
- hiddifypanel/panel/admin/templates/result.html +2 -3
- hiddifypanel/panel/cf_api.py +1 -2
- hiddifypanel/panel/cli.py +16 -16
- hiddifypanel/panel/commercial/ProxyDetailsAdmin.py +16 -12
- hiddifypanel/panel/commercial/__init__.py +7 -5
- hiddifypanel/panel/commercial/restapi/v1/__init__.py +1 -1
- hiddifypanel/panel/commercial/restapi/v1/tgbot.py +1 -1
- hiddifypanel/panel/commercial/restapi/v1/tgmsg.py +14 -10
- hiddifypanel/panel/commercial/restapi/v2/admin/__init__.py +0 -5
- hiddifypanel/panel/commercial/restapi/v2/admin/admin_info_api.py +2 -2
- hiddifypanel/panel/commercial/restapi/v2/admin/admin_log_api.py +4 -5
- hiddifypanel/panel/commercial/restapi/v2/admin/admin_user_api.py +8 -25
- hiddifypanel/panel/commercial/restapi/v2/admin/admin_users_api.py +4 -4
- hiddifypanel/panel/commercial/restapi/v2/admin/schema.py +157 -0
- hiddifypanel/panel/commercial/restapi/v2/admin/server_status_api.py +3 -3
- hiddifypanel/panel/commercial/restapi/v2/admin/user_api.py +9 -66
- hiddifypanel/panel/commercial/restapi/v2/admin/users_api.py +1 -1
- hiddifypanel/panel/commercial/restapi/v2/child/__init__.py +18 -0
- hiddifypanel/panel/commercial/restapi/v2/child/actions.py +63 -0
- hiddifypanel/panel/commercial/restapi/v2/child/register_parent_api.py +34 -0
- hiddifypanel/panel/commercial/restapi/v2/child/schema.py +7 -0
- hiddifypanel/panel/commercial/restapi/v2/child/sync_parent_api.py +21 -0
- hiddifypanel/panel/commercial/restapi/v2/panel/__init__.py +13 -0
- hiddifypanel/panel/commercial/restapi/v2/panel/info.py +18 -0
- hiddifypanel/panel/commercial/restapi/v2/panel/ping_pong.py +23 -0
- hiddifypanel/panel/commercial/restapi/v2/panel/schema.py +7 -0
- hiddifypanel/panel/commercial/restapi/v2/parent/__init__.py +16 -0
- hiddifypanel/panel/commercial/restapi/v2/parent/register_api.py +65 -0
- hiddifypanel/panel/commercial/restapi/v2/parent/schema.py +115 -0
- hiddifypanel/panel/commercial/restapi/v2/parent/status_api.py +26 -0
- hiddifypanel/panel/commercial/restapi/v2/parent/sync_api.py +53 -0
- hiddifypanel/panel/commercial/restapi/v2/parent/usage_api.py +57 -0
- hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +17 -23
- hiddifypanel/panel/commercial/restapi/v2/user/configs_api.py +23 -26
- hiddifypanel/panel/commercial/telegrambot/admin.py +1 -2
- hiddifypanel/panel/common.py +25 -8
- hiddifypanel/panel/common_bp/login.py +2 -2
- hiddifypanel/panel/hiddify.py +22 -185
- hiddifypanel/panel/init_db.py +102 -55
- hiddifypanel/panel/usage.py +33 -18
- hiddifypanel/panel/user/__init__.py +0 -1
- hiddifypanel/panel/user/templates/all_configs copy.txt +2 -2
- hiddifypanel/panel/user/templates/all_configs.txt +2 -2
- hiddifypanel/panel/user/templates/base_singbox_config.json.j2 +2 -1
- hiddifypanel/panel/user/templates/base_xray_config.json.j2 +125 -0
- hiddifypanel/panel/user/templates/clash_config copy.yml +1 -1
- hiddifypanel/panel/user/templates/clash_config.yml +4 -4
- hiddifypanel/panel/user/templates/clash_proxies.yml +1 -1
- hiddifypanel/panel/user/templates/home/all-configs.html +2 -2
- hiddifypanel/panel/user/templates/home/all-configs_old.html +1 -1
- hiddifypanel/panel/user/templates/home/ios copy.html +2 -2
- hiddifypanel/panel/user/templates/home/usage.html +1 -1
- hiddifypanel/panel/user/templates/new.html +2 -2
- hiddifypanel/panel/user/user.py +56 -50
- hiddifypanel/static/css/custom.css +31 -0
- hiddifypanel/static/images/favicon.ico +0 -0
- hiddifypanel/static/images/hiddify-old.png +0 -0
- hiddifypanel/static/images/hiddify.png +0 -0
- hiddifypanel/static/images/hiddify2.png +0 -0
- hiddifypanel/static/new/assets/{index-1b891a7c.js → index-ccb9873c.js} +56 -56
- hiddifypanel/static/new/assets/index-fa00de9a.css +1 -0
- hiddifypanel/static/new/i18n/en.json +6 -6
- hiddifypanel/static/new/i18n/fa.json +2 -2
- hiddifypanel/templates/admin-layout.html +30 -43
- hiddifypanel/templates/fake.html +0 -4
- hiddifypanel/templates/flaskadmin-layout.html +7 -3
- hiddifypanel/templates/master.html +11 -6
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +2082 -1977
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +2035 -1924
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +1911 -1840
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +2036 -1881
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +1857 -1720
- hiddifypanel/translations.i18n/en.json +992 -933
- hiddifypanel/translations.i18n/fa.json +994 -935
- hiddifypanel/translations.i18n/pt.json +994 -935
- hiddifypanel/translations.i18n/ru.json +994 -935
- hiddifypanel/translations.i18n/zh.json +971 -912
- {hiddifypanel-9.0.0.dev90.dist-info → hiddifypanel-10.5.0.dev0.dist-info}/METADATA +47 -47
- {hiddifypanel-9.0.0.dev90.dist-info → hiddifypanel-10.5.0.dev0.dist-info}/RECORD +147 -120
- {hiddifypanel-9.0.0.dev90.dist-info → hiddifypanel-10.5.0.dev0.dist-info}/WHEEL +1 -1
- hiddifypanel/panel/commercial/restapi/v2/DTO.py +0 -9
- hiddifypanel/panel/commercial/restapi/v2/hello/__init__.py +0 -16
- hiddifypanel/panel/commercial/restapi/v2/hello/hello.py +0 -32
- hiddifypanel/panel/user/link_maker.py +0 -1083
- hiddifypanel/static/new/assets/index-669b32c8.css +0 -1
- {hiddifypanel-9.0.0.dev90.dist-info → hiddifypanel-10.5.0.dev0.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-9.0.0.dev90.dist-info → hiddifypanel-10.5.0.dev0.dist-info}/entry_points.txt +0 -0
- {hiddifypanel-9.0.0.dev90.dist-info → hiddifypanel-10.5.0.dev0.dist-info}/top_level.txt +0 -0
hiddifypanel/panel/init_db.py
CHANGED
@@ -2,28 +2,63 @@ import datetime
|
|
2
2
|
import json
|
3
3
|
import os
|
4
4
|
import random
|
5
|
-
import string
|
6
5
|
import sys
|
7
6
|
import uuid
|
8
7
|
|
9
|
-
from dateutil import relativedelta
|
10
8
|
|
11
9
|
from hiddifypanel import Events, hutils
|
12
10
|
from hiddifypanel.models import *
|
13
|
-
from hiddifypanel.models import ConfigEnum, User, set_hconfig, ChildMode
|
14
11
|
from hiddifypanel.panel import hiddify
|
15
|
-
from hiddifypanel.database import db
|
16
|
-
|
17
|
-
|
12
|
+
from hiddifypanel.database import db, db_execute
|
13
|
+
from hiddifypanel import hutils
|
14
|
+
from sqlalchemy import text
|
18
15
|
from flask import g
|
19
16
|
|
20
|
-
MAX_DB_VERSION =
|
17
|
+
MAX_DB_VERSION = 90
|
18
|
+
|
19
|
+
|
20
|
+
def _v83(child_id):
|
21
|
+
set_hconfig(ConfigEnum.log_level, LogLevel.CRITICAL)
|
22
|
+
|
23
|
+
|
24
|
+
def _v82(child_id):
|
25
|
+
set_hconfig(ConfigEnum.vless_enable, True)
|
26
|
+
set_hconfig(ConfigEnum.trojan_enable, True)
|
27
|
+
set_hconfig(ConfigEnum.reality_enable, True)
|
28
|
+
set_hconfig(ConfigEnum.tcp_enable, True)
|
29
|
+
set_hconfig(ConfigEnum.quic_enable, True)
|
30
|
+
set_hconfig(ConfigEnum.xtls_enable, True)
|
31
|
+
set_hconfig(ConfigEnum.h2_enable, True)
|
32
|
+
|
33
|
+
|
34
|
+
def _v80(child_id):
|
35
|
+
set_hconfig(ConfigEnum.parent_domain, '')
|
36
|
+
set_hconfig(ConfigEnum.parent_admin_proxy_path, '')
|
37
|
+
|
38
|
+
|
39
|
+
def _v79(child_id):
|
40
|
+
set_hconfig(ConfigEnum.panel_mode, PanelMode.standalone)
|
41
|
+
|
42
|
+
|
43
|
+
def _v78(child_id):
|
44
|
+
# equalize panel unique id and root child unique id
|
45
|
+
root_child_unique_id = Child.query.filter(Child.name == "Root").first().unique_id
|
46
|
+
set_hconfig(ConfigEnum.unique_id, root_child_unique_id)
|
47
|
+
|
48
|
+
|
49
|
+
def _v77(child_id):
|
50
|
+
pass
|
51
|
+
|
52
|
+
|
53
|
+
def _v75(child_id):
|
54
|
+
for u in User.query.all():
|
55
|
+
hutils.model.gen_wg_keys(u)
|
21
56
|
|
22
57
|
|
23
58
|
def _v74(child_id):
|
24
59
|
set_hconfig(ConfigEnum.ws_enable, True)
|
25
60
|
set_hconfig(ConfigEnum.grpc_enable, True)
|
26
|
-
set_hconfig(ConfigEnum.httpupgrade_enable,
|
61
|
+
set_hconfig(ConfigEnum.httpupgrade_enable, True)
|
27
62
|
set_hconfig(ConfigEnum.shadowsocks2022_port, hutils.random.get_random_unused_port())
|
28
63
|
set_hconfig(ConfigEnum.shadowsocks2022_method, "2022-blake3-aes-256-gcm")
|
29
64
|
set_hconfig(ConfigEnum.shadowsocks2022_enable, False)
|
@@ -66,12 +101,12 @@ def _v69():
|
|
66
101
|
add_config_if_not_exist(ConfigEnum.wireguard_port, hutils.random.get_random_unused_port())
|
67
102
|
add_config_if_not_exist(ConfigEnum.wireguard_ipv4, "10.90.0.1")
|
68
103
|
add_config_if_not_exist(ConfigEnum.wireguard_ipv6, "fd42:42:90::1")
|
69
|
-
wg_pk, wg_pub, _ =
|
104
|
+
wg_pk, wg_pub, _ = hutils.crypto.get_wg_private_public_psk_pair()
|
70
105
|
add_config_if_not_exist(ConfigEnum.wireguard_private_key, wg_pk)
|
71
106
|
add_config_if_not_exist(ConfigEnum.wireguard_public_key, wg_pub)
|
72
107
|
add_config_if_not_exist(ConfigEnum.wireguard_noise_trick, "5-10")
|
73
108
|
for u in User.query.all():
|
74
|
-
u.wg_pk, u.wg_pub, u.wg_psk =
|
109
|
+
u.wg_pk, u.wg_pub, u.wg_psk = hutils.crypto.get_wg_private_public_psk_pair()
|
75
110
|
|
76
111
|
|
77
112
|
def _v65():
|
@@ -86,10 +121,6 @@ def _v65():
|
|
86
121
|
add_config_if_not_exist(ConfigEnum.mux_brutal_down_mbps, '100')
|
87
122
|
|
88
123
|
|
89
|
-
def _v64():
|
90
|
-
set_hconfig(ConfigEnum.ssh_server_redis_url, "unix:///opt/hiddify-manager/other/redis/run.sock?db=1")
|
91
|
-
|
92
|
-
|
93
124
|
def _v63():
|
94
125
|
add_config_if_not_exist(ConfigEnum.hysteria_enable, True)
|
95
126
|
add_config_if_not_exist(ConfigEnum.hysteria_port, hutils.random.get_random_unused_port())
|
@@ -120,13 +151,13 @@ def _v60():
|
|
120
151
|
def _v59():
|
121
152
|
# set user model username and password
|
122
153
|
for u in User.query.all():
|
123
|
-
|
124
|
-
|
154
|
+
hutils.model.gen_username(u)
|
155
|
+
hutils.model.gen_password(u)
|
125
156
|
|
126
157
|
# set admin model username and password
|
127
158
|
for a in AdminUser.query.all():
|
128
|
-
|
129
|
-
|
159
|
+
hutils.model.gen_username(a)
|
160
|
+
hutils.model.gen_password(a)
|
130
161
|
|
131
162
|
|
132
163
|
def _v57():
|
@@ -164,7 +195,7 @@ def _v50():
|
|
164
195
|
def _v49():
|
165
196
|
|
166
197
|
for u in User.query.all():
|
167
|
-
priv, publ =
|
198
|
+
priv, publ = hutils.crypto.get_ed25519_private_public_pair()
|
168
199
|
u.ed25519_private_key = priv
|
169
200
|
u.ed25519_public_key = publ
|
170
201
|
|
@@ -182,7 +213,7 @@ def _v45():
|
|
182
213
|
|
183
214
|
if not Proxy.query.filter(Proxy.name == "SSH").first():
|
184
215
|
db.session.add(Proxy(l3='ssh', transport='ssh', cdn='direct', proto='ssh', enable=True, name="SSH"))
|
185
|
-
|
216
|
+
|
186
217
|
add_config_if_not_exist(ConfigEnum.ssh_server_port, hutils.random.get_random_unused_port())
|
187
218
|
add_config_if_not_exist(ConfigEnum.ssh_server_enable, False)
|
188
219
|
# def _v43():
|
@@ -224,7 +255,7 @@ def _v33():
|
|
224
255
|
|
225
256
|
def _v31():
|
226
257
|
add_config_if_not_exist(ConfigEnum.reality_short_ids, uuid.uuid4().hex[0:random.randint(1, 8) * 2])
|
227
|
-
key_pair =
|
258
|
+
key_pair = hutils.crypto.generate_x25519_keys()
|
228
259
|
add_config_if_not_exist(ConfigEnum.reality_private_key, key_pair['private_key'])
|
229
260
|
add_config_if_not_exist(ConfigEnum.reality_public_key, key_pair['public_key'])
|
230
261
|
db.session.bulk_save_objects(get_proxy_rows_v1())
|
@@ -370,7 +401,7 @@ def _v7():
|
|
370
401
|
Proxy.query.filter(Proxy.name == 'tls XTLSVision direct trojan').delete()
|
371
402
|
except BaseException:
|
372
403
|
pass
|
373
|
-
add_config_if_not_exist(ConfigEnum.telegram_lib, "
|
404
|
+
add_config_if_not_exist(ConfigEnum.telegram_lib, "erlang")
|
374
405
|
add_config_if_not_exist(ConfigEnum.admin_lang, hconfig(ConfigEnum.lang))
|
375
406
|
add_config_if_not_exist(ConfigEnum.branding_title, "")
|
376
407
|
add_config_if_not_exist(ConfigEnum.branding_site, "")
|
@@ -506,7 +537,7 @@ def make_proxy_rows(cfgs):
|
|
506
537
|
|
507
538
|
def add_config_if_not_exist(key: ConfigEnum, val: str | int, child_id: int | None = None):
|
508
539
|
if child_id is None:
|
509
|
-
child_id = Child.current.id
|
540
|
+
child_id = Child.current().id
|
510
541
|
|
511
542
|
old_val = hconfig(key, child_id)
|
512
543
|
print(key, val, child_id, old_val)
|
@@ -517,15 +548,18 @@ def add_config_if_not_exist(key: ConfigEnum, val: str | int, child_id: int | Non
|
|
517
548
|
def add_column(column):
|
518
549
|
try:
|
519
550
|
column_type = column.type.compile(db.engine.dialect)
|
520
|
-
|
551
|
+
|
552
|
+
db_execute(f'ALTER TABLE {column.table.name} ADD COLUMN {column.name} {column_type}')
|
521
553
|
except BaseException:
|
522
554
|
pass
|
523
555
|
|
524
556
|
|
525
|
-
def execute(query):
|
557
|
+
def execute(query: str):
|
526
558
|
try:
|
527
|
-
|
528
|
-
|
559
|
+
|
560
|
+
db_execute(query)
|
561
|
+
except BaseException as e:
|
562
|
+
print(e)
|
529
563
|
pass
|
530
564
|
|
531
565
|
|
@@ -545,7 +579,8 @@ def add_new_enum_values():
|
|
545
579
|
# Get the values in the enum column in the database
|
546
580
|
# result = db.engine.execute(f"SELECT DISTINCT `{column_name}` FROM {table_name}")
|
547
581
|
# db_values = {row[0] for row in result}
|
548
|
-
|
582
|
+
|
583
|
+
result = db_execute(f"SHOW COLUMNS FROM {table_name} LIKE '{column_name}';")
|
549
584
|
db_values = []
|
550
585
|
|
551
586
|
for row in result:
|
@@ -564,7 +599,7 @@ def add_new_enum_values():
|
|
564
599
|
# Add the new value to the enum column in the database
|
565
600
|
enumstr = ','.join([f"'{a}'" for a in [*existing_values, *old_values]])
|
566
601
|
|
567
|
-
|
602
|
+
db_execute(text(f"ALTER TABLE {table_name} MODIFY COLUMN `{column_name}` ENUM({enumstr});"))
|
568
603
|
|
569
604
|
db.session.commit()
|
570
605
|
|
@@ -618,8 +653,8 @@ def init_db():
|
|
618
653
|
get_hconfigs.invalidate_all()
|
619
654
|
# set_hconfig(ConfigEnum.db_version, 71)
|
620
655
|
# temporary fix
|
621
|
-
|
622
|
-
|
656
|
+
add_column(Child.mode)
|
657
|
+
add_column(Child.name)
|
623
658
|
db_version = int(hconfig(ConfigEnum.db_version) or 0)
|
624
659
|
if db_version == latest_db_version():
|
625
660
|
return
|
@@ -664,32 +699,44 @@ def init_db():
|
|
664
699
|
|
665
700
|
|
666
701
|
def migrate(db_version):
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
702
|
+
for table_name, table_obj in db.metadata.tables.items():
|
703
|
+
for column in table_obj.columns:
|
704
|
+
add_column(column)
|
705
|
+
Events.db_prehook.notify()
|
706
|
+
if db_version < 82:
|
707
|
+
execute('ALTER TABLE child DROP INDEX `name`;')
|
708
|
+
if db_version < 77:
|
709
|
+
execute('ALTER TABLE user_detail DROP COLUMN connected_ips;')
|
710
|
+
execute('update user_detail set connected_devices="" where connected_devices IS NULL')
|
711
|
+
|
712
|
+
if db_version < 70:
|
713
|
+
execute('CREATE INDEX date ON daily_usage (date);')
|
714
|
+
execute('CREATE INDEX username ON user (username);')
|
715
|
+
execute('CREATE INDEX username ON admin_user (username);')
|
716
|
+
execute('CREATE INDEX telegram_id ON user (telegram_id);')
|
717
|
+
execute('CREATE INDEX telegram_id ON admin_user (telegram_id);')
|
718
|
+
|
719
|
+
execute('ALTER TABLE proxy DROP INDEX `name`;')
|
720
|
+
|
721
|
+
execute("ALTER TABLE user MODIFY COLUMN telegram_id BIGINT;")
|
722
|
+
execute("ALTER TABLE admin_user MODIFY COLUMN telegram_id BIGINT;")
|
723
|
+
|
724
|
+
# aaa
|
725
|
+
# # add_column(UserDetail.connected_devices)
|
726
|
+
# add_column(Child.mode)
|
727
|
+
# add_column(Child.name)
|
728
|
+
# add_column(User.lang)
|
729
|
+
# add_column(AdminUser.lang)
|
730
|
+
# add_column(User.username)
|
731
|
+
# add_column(User.password)
|
732
|
+
# add_column(AdminUser.username)
|
733
|
+
# add_column(AdminUser.password)
|
734
|
+
# add_column(User.wg_pk)
|
735
|
+
# add_column(User.wg_pub)
|
736
|
+
# add_column(User.wg_psk)
|
677
737
|
|
678
|
-
|
679
|
-
add_column(Child.name)
|
680
|
-
add_column(User.lang)
|
681
|
-
add_column(AdminUser.lang)
|
682
|
-
add_column(User.username)
|
683
|
-
add_column(User.password)
|
684
|
-
add_column(AdminUser.username)
|
685
|
-
add_column(AdminUser.password)
|
686
|
-
add_column(User.wg_pk)
|
687
|
-
add_column(User.wg_pub)
|
688
|
-
add_column(User.wg_psk)
|
689
|
-
|
690
|
-
add_column(Domain.extra_params)
|
738
|
+
# add_column(Domain.extra_params)
|
691
739
|
|
692
|
-
Events.db_prehook.notify()
|
693
740
|
if db_version < 52:
|
694
741
|
execute(f'update domain set mode="sub_link_only", sub_link_only=false where sub_link_only = true or mode=1 or mode="1"')
|
695
742
|
execute(f'update domain set mode="direct", sub_link_only=false where mode=0 or mode="0"')
|
hiddifypanel/panel/usage.py
CHANGED
@@ -1,34 +1,36 @@
|
|
1
1
|
from flask_babel import lazy_gettext as _
|
2
2
|
from sqlalchemy import func
|
3
|
+
from typing import Dict
|
3
4
|
import datetime
|
4
5
|
|
5
6
|
from hiddifypanel.drivers import user_driver
|
6
7
|
from hiddifypanel.models import *
|
7
8
|
from hiddifypanel.panel import hiddify
|
8
9
|
from hiddifypanel.database import db
|
10
|
+
from hiddifypanel import hutils
|
9
11
|
|
10
12
|
to_gig_d = 1024**3
|
11
13
|
|
12
14
|
|
13
15
|
def update_local_usage():
|
14
16
|
res = user_driver.get_users_usage(reset=True)
|
15
|
-
return
|
17
|
+
return _add_users_usage(res, child_id=0)
|
16
18
|
|
17
19
|
# return {"status": 'success', "comments":res}
|
18
20
|
|
19
21
|
|
20
|
-
def add_users_usage_uuid(uuids_bytes, child_id):
|
21
|
-
|
22
|
+
def add_users_usage_uuid(uuids_bytes: Dict[str, Dict], child_id, sync=False):
|
23
|
+
uuids_bytes = {u: v for u, v in uuids_bytes.items() if v}
|
24
|
+
uuids = uuids_bytes.keys()
|
25
|
+
users = User.query.filter(User.uuid.in_(uuids))
|
22
26
|
dbusers_bytes = {u: uuids_bytes.get(u.uuid, 0) for u in users}
|
23
|
-
|
27
|
+
_add_users_usage(dbusers_bytes, child_id, sync) # type: ignore
|
24
28
|
|
25
29
|
|
26
|
-
def
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
hiddify_api.add_user_usage_to_parent(dbusers_bytes)
|
31
|
-
|
30
|
+
def _add_users_usage(users_usage_data: Dict[User, Dict], child_id, sync=False):
|
31
|
+
'''
|
32
|
+
sync: when enabled, it means we have received usages from the parent panel
|
33
|
+
'''
|
32
34
|
res = {}
|
33
35
|
have_change = False
|
34
36
|
before_enabled_users = user_driver.get_enabled_users()
|
@@ -42,16 +44,16 @@ def add_users_usage(dbusers_bytes, child_id):
|
|
42
44
|
daily_usage[adm.id].online = User.query.filter(User.added_by == adm.id).filter(func.DATE(User.last_online) == today).count()
|
43
45
|
# db.session.commit()
|
44
46
|
userDetails = {p.user_id: p for p in UserDetail.query.filter(UserDetail.child_id == child_id).all()}
|
45
|
-
for user, uinfo in
|
47
|
+
for user, uinfo in users_usage_data.items():
|
46
48
|
usage_bytes = uinfo['usage']
|
47
|
-
|
49
|
+
devices = uinfo['devices']
|
48
50
|
# user_active_before=user.is_active
|
49
51
|
detail = userDetails.get(user.id)
|
50
52
|
if not detail:
|
51
53
|
detail = UserDetail(user_id=user.id, child_id=child_id)
|
52
54
|
detail.current_usage_GB = detail.current_usage_GB or 0
|
53
55
|
db.session.add(detail)
|
54
|
-
detail.
|
56
|
+
detail.connected_devices = devices
|
55
57
|
detail.current_usage_GB = detail.current_usage_GB or 0
|
56
58
|
if not user.last_reset_time or user.user_should_reset():
|
57
59
|
user.last_reset_time = datetime.date.today()
|
@@ -66,11 +68,20 @@ def add_users_usage(dbusers_bytes, child_id):
|
|
66
68
|
if not isinstance(usage_bytes, int) or usage_bytes == 0:
|
67
69
|
res[user.uuid] = "No usage"
|
68
70
|
else:
|
69
|
-
|
71
|
+
if sync:
|
72
|
+
if daily_usage.get(user.added_by, daily_usage[1]).usage != usage_bytes:
|
73
|
+
daily_usage.get(user.added_by, daily_usage[1]).usage = usage_bytes
|
74
|
+
else:
|
75
|
+
daily_usage.get(user.added_by, daily_usage[1]).usage += usage_bytes
|
70
76
|
in_gig = (usage_bytes) / to_gig_d
|
71
77
|
res[user.uuid] = in_gig
|
72
|
-
|
73
|
-
|
78
|
+
if sync:
|
79
|
+
if user.current_usage_GB != in_gig:
|
80
|
+
user.current_usage_GB = in_gig
|
81
|
+
# detail.current_usage_GB = in_gig
|
82
|
+
else:
|
83
|
+
user.current_usage_GB += in_gig
|
84
|
+
detail.current_usage_GB += in_gig
|
74
85
|
user.last_online = datetime.datetime.now()
|
75
86
|
detail.last_online = datetime.datetime.now()
|
76
87
|
|
@@ -83,15 +94,19 @@ def add_users_usage(dbusers_bytes, child_id):
|
|
83
94
|
have_change = True
|
84
95
|
res[user.uuid] = f"{res[user.uuid]} !OUT of USAGE! Client Removed"
|
85
96
|
|
86
|
-
db.session.commit()
|
97
|
+
db.session.commit() # type: ignore
|
87
98
|
if have_change:
|
88
99
|
hiddify.quick_apply_users()
|
89
100
|
|
101
|
+
# sync with the parent
|
102
|
+
if not sync:
|
103
|
+
if hutils.node.is_child():
|
104
|
+
hutils.node.child.sync_users_usage_with_parent()
|
90
105
|
return {"status": 'success', "comments": res}
|
91
106
|
|
92
107
|
|
93
108
|
def send_bot_message(user):
|
94
|
-
if not (hconfig(ConfigEnum.telegram_bot_token)
|
109
|
+
if not (hconfig(ConfigEnum.telegram_bot_token) or not hutils.node.is_parent()):
|
95
110
|
return
|
96
111
|
if not user.telegram_id:
|
97
112
|
return
|
@@ -1,4 +1,4 @@
|
|
1
|
-
{% for type in link_maker.
|
1
|
+
{% for type in link_maker.get_all_proxies(d.child_id,only_enabled=True) %}
|
2
2
|
{% set pinfo=link_maker.proxy_info(type) %}
|
3
3
|
# {{type}} {{domain}}
|
4
4
|
{{pinfo['url']}}
|
@@ -16,7 +16,7 @@
|
|
16
16
|
# HTTP Not Secure
|
17
17
|
# HTTP Not Secure
|
18
18
|
|
19
|
-
{% for type in link_maker.
|
19
|
+
{% for type in link_maker.get_all_proxies(d.child_id,only_enabled=True) %}
|
20
20
|
{% set pinfo=link_maker.proxy_info(type,port=80,security="http") %}
|
21
21
|
{% if pinfo!=None %}
|
22
22
|
# HTTP {{type}} {{domain}}
|
@@ -14,10 +14,10 @@ trojan://1@{{fake_ip_for_sub_link}}?sni=fake_ip_for_sub_link&security=tls#{{user
|
|
14
14
|
####################################
|
15
15
|
## {% if d.has_auto_ip %}Auto {%endif%} {{d.mode}} {{d.alias or d.domain}} {{t}}:{{port}}
|
16
16
|
####################################
|
17
|
-
{% for type in link_maker.
|
17
|
+
{% for type in link_maker.get_all_proxies(d.child_id, only_enabled=True) %}
|
18
18
|
{% set pinfo=link_maker.make_proxy(type,d,phttp=phttp,ptls=ptls) %}
|
19
19
|
{% if 'msg' not in pinfo %}
|
20
|
-
{% set link=link_maker.to_link(pinfo) %}
|
20
|
+
{% set link=link_maker.xray.to_link(pinfo) %}
|
21
21
|
{% if 'msg' not in link %}
|
22
22
|
{{''}}
|
23
23
|
# {{pinfo["name"]}} {{d.alias or d.domain}}
|
@@ -0,0 +1,125 @@
|
|
1
|
+
{
|
2
|
+
"remarks": "{{remarks}}",
|
3
|
+
"log": {
|
4
|
+
"access": "",
|
5
|
+
"error": "",
|
6
|
+
"loglevel": "warning"
|
7
|
+
},
|
8
|
+
"inbounds": [
|
9
|
+
{
|
10
|
+
"tag": "socks",
|
11
|
+
"port": 10808,
|
12
|
+
"listen": "127.0.0.1",
|
13
|
+
"protocol": "socks",
|
14
|
+
"sniffing": {
|
15
|
+
"enabled": true,
|
16
|
+
"destOverride": [
|
17
|
+
"http",
|
18
|
+
"tls"
|
19
|
+
],
|
20
|
+
"routeOnly": false
|
21
|
+
},
|
22
|
+
"settings": {
|
23
|
+
"auth": "noauth",
|
24
|
+
"udp": true,
|
25
|
+
"allowTransparent": false
|
26
|
+
}
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"tag": "http",
|
30
|
+
"port": 10809,
|
31
|
+
"listen": "127.0.0.1",
|
32
|
+
"protocol": "http",
|
33
|
+
"sniffing": {
|
34
|
+
"enabled": true,
|
35
|
+
"destOverride": [
|
36
|
+
"http",
|
37
|
+
"tls"
|
38
|
+
],
|
39
|
+
"routeOnly": false
|
40
|
+
},
|
41
|
+
"settings": {
|
42
|
+
"auth": "noauth",
|
43
|
+
"udp": true,
|
44
|
+
"allowTransparent": false
|
45
|
+
}
|
46
|
+
}
|
47
|
+
],
|
48
|
+
"outbounds": [
|
49
|
+
{
|
50
|
+
"tag": "fragment",
|
51
|
+
"protocol": "freedom",
|
52
|
+
"settings": {
|
53
|
+
"domainStrategy": "AsIs"
|
54
|
+
{% if hconfig(ConfigEnum.tls_fragment_enable) %}
|
55
|
+
,"fragment": {
|
56
|
+
"packets": "tlshello",
|
57
|
+
"length": "{{ hconfig(ConfigEnum.tls_fragment_size) }}",
|
58
|
+
"interval": "{{ hconfig(ConfigEnum.tls_fragment_sleep) }}"
|
59
|
+
}
|
60
|
+
{% endif %}
|
61
|
+
},
|
62
|
+
"streamSettings": {
|
63
|
+
"sockopt": {
|
64
|
+
"tcpNoDelay": true,
|
65
|
+
"tcpKeepAliveIdle": 100
|
66
|
+
}
|
67
|
+
}
|
68
|
+
},
|
69
|
+
{
|
70
|
+
"tag": "direct",
|
71
|
+
"protocol": "freedom",
|
72
|
+
"settings": {}
|
73
|
+
},
|
74
|
+
{
|
75
|
+
"tag": "block",
|
76
|
+
"protocol": "blackhole",
|
77
|
+
"settings": {
|
78
|
+
"response": {
|
79
|
+
"type": "http"
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
],
|
84
|
+
"routing": {
|
85
|
+
"domainStrategy": "AsIs",
|
86
|
+
"rules": [
|
87
|
+
{
|
88
|
+
"type": "field",
|
89
|
+
"inboundTag": [
|
90
|
+
"api"
|
91
|
+
],
|
92
|
+
"outboundTag": "api",
|
93
|
+
"enabled": true
|
94
|
+
},
|
95
|
+
{
|
96
|
+
"id": "5465425548310166497",
|
97
|
+
"type": "field",
|
98
|
+
"outboundTag": "direct",
|
99
|
+
"domain": [
|
100
|
+
"domain:ir",
|
101
|
+
"geosite:cn"
|
102
|
+
],
|
103
|
+
"enabled": true
|
104
|
+
},
|
105
|
+
{
|
106
|
+
"id": "5425034033205580637",
|
107
|
+
"type": "field",
|
108
|
+
"outboundTag": "direct",
|
109
|
+
"ip": [
|
110
|
+
"geoip:private",
|
111
|
+
"geoip:cn",
|
112
|
+
"geoip:ir"
|
113
|
+
],
|
114
|
+
"enabled": true
|
115
|
+
},
|
116
|
+
{
|
117
|
+
"id": "5627785659655799759",
|
118
|
+
"type": "field",
|
119
|
+
"port": "0-65535",
|
120
|
+
"outboundTag": "proxy",
|
121
|
+
"enabled": true
|
122
|
+
}
|
123
|
+
]
|
124
|
+
}
|
125
|
+
}
|
@@ -51,7 +51,7 @@ proxy-groups:
|
|
51
51
|
proxies:
|
52
52
|
- automatic
|
53
53
|
- sequential
|
54
|
-
{{link_maker.get_clash_config_names(meta_or_normal,domains)|indent(6)}}
|
54
|
+
{{link_maker.clash.get_clash_config_names(meta_or_normal,domains)|indent(6)}}
|
55
55
|
|
56
56
|
# use:
|
57
57
|
# %for phttp in hconfigs[ConfigEnum.http_ports].split(',')
|
@@ -88,7 +88,7 @@ proxy-groups:
|
|
88
88
|
url: "http://cp.cloudflare.com"
|
89
89
|
interval: 300
|
90
90
|
proxies:
|
91
|
-
{{link_maker.get_clash_config_names(meta_or_normal,domains)|indent(6)}}
|
91
|
+
{{link_maker.clash.get_clash_config_names(meta_or_normal,domains)|indent(6)}}
|
92
92
|
# use:
|
93
93
|
# %for phttp in hconfigs[ConfigEnum.http_ports].split(',')
|
94
94
|
# - all_proxies_{{phttp}}
|
@@ -99,7 +99,7 @@ proxy-groups:
|
|
99
99
|
|
100
100
|
- name: auto
|
101
101
|
proxies:
|
102
|
-
{{link_maker.get_clash_config_names(meta_or_normal,domains)|indent(6)}}
|
102
|
+
{{link_maker.clash.get_clash_config_names(meta_or_normal,domains)|indent(6)}}
|
103
103
|
# use:
|
104
104
|
# %for phttp in hconfigs[ConfigEnum.http_ports].split(',')
|
105
105
|
# - all_proxies_{{phttp}}
|
@@ -116,7 +116,7 @@ proxy-groups:
|
|
116
116
|
|
117
117
|
|
118
118
|
|
119
|
-
{{link_maker.get_all_clash_configs(meta_or_normal,domains)}}
|
119
|
+
{{link_maker.clash.get_all_clash_configs(meta_or_normal,domains)}}
|
120
120
|
|
121
121
|
# proxy-providers:
|
122
122
|
# %for t in (['http','tls'] if hconfigs[ConfigEnum.http_proxy_enable] else ['tls'])
|
@@ -108,10 +108,10 @@
|
|
108
108
|
<td><span class="badge badge-success">{{_('all')}}</span></td>
|
109
109
|
</tr>
|
110
110
|
|
111
|
-
{% for pinfo in link_maker.
|
111
|
+
{% for pinfo in link_maker.get_valid_proxies(domains) %}
|
112
112
|
<tr>
|
113
113
|
<td>
|
114
|
-
<div class="btn-group"><a href='{{link_maker.to_link(pinfo)}}' class="btn btn-light orig-link">{{pinfo["name"].replace("_", " ")}}</a></div>
|
114
|
+
<div class="btn-group"><a href='{{link_maker.xray.to_link(pinfo)}}' class="btn btn-light orig-link">{{pinfo["name"].replace("_", " ")}}</a></div>
|
115
115
|
</td>
|
116
116
|
<td><span class="badge badge-danger"> {% if pinfo['dbdomain'].has_auto_ip %}Auto {%endif%}{{pinfo["mode"]}}</span></td>
|
117
117
|
<td><span class="badge ltr">{{pinfo['server']}}</span></td>
|
@@ -48,7 +48,7 @@
|
|
48
48
|
<td><span class="badge badge-success">{{_('all')}}</span></td>
|
49
49
|
</tr>
|
50
50
|
|
51
|
-
{% for type in link_maker.
|
51
|
+
{% for type in link_maker.get_all_proxies(only_enabled=True) %}
|
52
52
|
{% for mode in ["tls","http"] %}
|
53
53
|
{% set pinfo=link_maker.proxy_info(type,mode=mode) %}
|
54
54
|
{% if pinfo!=None %}
|
@@ -51,7 +51,7 @@
|
|
51
51
|
سپس کانفیگ مورد نظر را انتخاب و اجرا نمایید.
|
52
52
|
<br>
|
53
53
|
|
54
|
-
{% for type in link_maker.
|
54
|
+
{% for type in link_maker.get_all_proxies(only_enabled=True) %}
|
55
55
|
{% set pinfo=link_maker.proxy_info(type) %}
|
56
56
|
{% if pinfo!=None %}
|
57
57
|
<div class="btn-group"><a href='{{pinfo["url"]}}' class="btn btn-primary orig-link">{{type}}</a></div>
|
@@ -107,7 +107,7 @@
|
|
107
107
|
<br />
|
108
108
|
سپس کانفیگ مورد نظر خود را اعمال کنید:
|
109
109
|
<br />
|
110
|
-
{% for type in link_maker.
|
110
|
+
{% for type in link_maker.get_all_proxies(only_enabled=True) %}
|
111
111
|
{% set pinfo=link_maker.proxy_info(type) %}
|
112
112
|
{% if pinfo!=None %}
|
113
113
|
<div class="btn-group"><a href='{{pinfo["url"]}}' class="btn btn-primary orig-link">{{type}}</a></div>
|
@@ -23,7 +23,7 @@
|
|
23
23
|
{% endif %}
|
24
24
|
{% if not user.is_active %}
|
25
25
|
{{_("User is inactive")}}
|
26
|
-
{% if (user.
|
26
|
+
{% if (user.devices|length)>user.max_ips: %}
|
27
27
|
<br>
|
28
28
|
<i class="fa-solid fa-users-slash text-danger"></i> {{_("Too many Connected IPs")}}
|
29
29
|
{% endif %}
|