hiddifypanel 10.80.12.dev1__py3-none-any.whl → 10.85.0b2__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 +3 -3
- hiddifypanel/apps/asgi_app.py +1 -1
- hiddifypanel/apps/celery_app.py +2 -2
- hiddifypanel/apps/celery_app_flask.py +3 -0
- hiddifypanel/apps/wsgi_app.py +1 -1
- hiddifypanel/base.py +5 -5
- hiddifypanel/celery.py +68 -1
- hiddifypanel/database.py +62 -5
- hiddifypanel/drivers/singbox_api.py +2 -1
- hiddifypanel/drivers/user_driver.py +4 -1
- hiddifypanel/hutils/__init__.py +46 -14
- hiddifypanel/hutils/crypto.py +2 -1
- hiddifypanel/hutils/encode.py +1 -2
- hiddifypanel/hutils/flask.py +1 -1
- hiddifypanel/hutils/network/auto_ip_selector.py +15 -12
- hiddifypanel/hutils/network/cf_api.py +7 -2
- hiddifypanel/hutils/proxy/xrayjson.py +1 -0
- hiddifypanel/hutils/system.py +9 -8
- hiddifypanel/hutils/utils.py +2 -1
- hiddifypanel/models/admin.py +7 -5
- hiddifypanel/models/base_account.py +3 -3
- hiddifypanel/models/child.py +4 -4
- hiddifypanel/models/config.py +5 -5
- hiddifypanel/models/config_enum.py +3 -1
- hiddifypanel/models/domain.py +5 -5
- hiddifypanel/models/proxy.py +4 -2
- hiddifypanel/models/report.py +3 -3
- hiddifypanel/models/usage.py +2 -2
- hiddifypanel/models/user.py +3 -3
- hiddifypanel/panel/admin/templates/index.html +6 -6
- hiddifypanel/panel/cli.py +1 -1
- hiddifypanel/panel/commercial/restapi/v1/tgbot.py +2 -3
- hiddifypanel/panel/commercial/restapi/v2/user/apps_api.py +76 -6
- hiddifypanel/panel/common.py +5 -1
- hiddifypanel/panel/common_bp/login.py +3 -2
- hiddifypanel/panel/hiddify.py +9 -9
- hiddifypanel/panel/hlogger.py +3 -1
- hiddifypanel/panel/init_db.py +71 -87
- hiddifypanel/panel/run_commander.py +3 -4
- hiddifypanel/panel/usage.py +10 -9
- hiddifypanel/panel/user/templates/base_singbox_config.json.j2 +19 -34
- hiddifypanel/panel/user/templates/base_xray_config.json.j2 +4 -2
- hiddifypanel/panel/user/templates/clash_config.yml +33 -3
- hiddifypanel/static/apps-icon/clash_verge_rev.ico +0 -0
- hiddifypanel/static/apps-icon/cmfa.ico +0 -0
- hiddifypanel/templates/master.html +1 -1
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +37 -1
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +37 -1
- hiddifypanel/translations/my/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/my/LC_MESSAGES/messages.po +0 -2
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +37 -1
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +37 -1
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +37 -1
- hiddifypanel/translations.i18n/en.json +17 -1
- hiddifypanel/translations.i18n/fa.json +17 -1
- hiddifypanel/translations.i18n/fr.json +1 -0
- hiddifypanel/translations.i18n/my.json +4 -0
- hiddifypanel/translations.i18n/pt.json +17 -1
- hiddifypanel/translations.i18n/ru.json +17 -1
- hiddifypanel/translations.i18n/zh.json +17 -1
- hiddifypanel-10.85.0b2.dist-info/METADATA +331 -0
- {hiddifypanel-10.80.12.dev1.dist-info → hiddifypanel-10.85.0b2.dist-info}/RECORD +120 -116
- {hiddifypanel-10.80.12.dev1.dist-info → hiddifypanel-10.85.0b2.dist-info}/WHEEL +2 -1
- hiddifypanel-10.85.0b2.dist-info/entry_points.txt +2 -0
- hiddifypanel-10.85.0b2.dist-info/top_level.txt +1 -0
- hiddifypanel-10.80.12.dev1.dist-info/METADATA +0 -137
- hiddifypanel-10.80.12.dev1.dist-info/entry_points.txt +0 -3
- {hiddifypanel-10.80.12.dev1.dist-info → hiddifypanel-10.85.0b2.dist-info/licenses}/LICENSE.md +0 -0
hiddifypanel/models/domain.py
CHANGED
@@ -3,10 +3,10 @@ import ipaddress
|
|
3
3
|
import re
|
4
4
|
from typing import Dict, List
|
5
5
|
from flask import request
|
6
|
-
|
6
|
+
|
7
7
|
from sqlalchemy.orm import backref
|
8
8
|
from strenum import StrEnum
|
9
|
-
|
9
|
+
|
10
10
|
|
11
11
|
|
12
12
|
from hiddifypanel.database import db
|
@@ -37,7 +37,7 @@ ShowDomain = db.Table('show_domain',
|
|
37
37
|
)
|
38
38
|
|
39
39
|
|
40
|
-
class Domain(db.Model
|
40
|
+
class Domain(db.Model):
|
41
41
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
42
42
|
child_id = db.Column(db.Integer, db.ForeignKey('child.id'), default=0)
|
43
43
|
domain = db.Column(db.String(200), nullable=True, unique=False)
|
@@ -161,9 +161,9 @@ class Domain(db.Model, SerializerMixin):
|
|
161
161
|
def get_domains(cls, always_add_ip=False, always_add_all_domains=False) -> List['Domain']:
|
162
162
|
from hiddifypanel import hutils
|
163
163
|
domains = []
|
164
|
-
domains =
|
164
|
+
domains = db.session.query(Domain).filter(Domain.mode == DomainType.sub_link_only, Domain.child_id == Child.current().id).all()
|
165
165
|
if not len(domains) or always_add_all_domains:
|
166
|
-
domains =
|
166
|
+
domains = db.session.query(Domain).filter(Domain.mode.notin_([DomainType.fake, DomainType.reality])).all()
|
167
167
|
|
168
168
|
if len(domains) == 0 and request:
|
169
169
|
domains = [Domain(domain=request.host)] # type: ignore
|
hiddifypanel/models/proxy.py
CHANGED
@@ -4,7 +4,7 @@ from enum import auto
|
|
4
4
|
from sqlalchemy import Column, String, Integer, Boolean, Enum, ForeignKey
|
5
5
|
|
6
6
|
from hiddifypanel.database import db
|
7
|
-
|
7
|
+
|
8
8
|
|
9
9
|
|
10
10
|
class ProxyTransport(StrEnum):
|
@@ -59,7 +59,7 @@ class ProxyL3(StrEnum):
|
|
59
59
|
custom = auto()
|
60
60
|
|
61
61
|
|
62
|
-
class Proxy(db.Model
|
62
|
+
class Proxy(db.Model): # type: ignore
|
63
63
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
64
64
|
child_id = Column(Integer, ForeignKey('child.id'), default=0)
|
65
65
|
name = Column(String(200), nullable=False, unique=False)
|
@@ -96,6 +96,8 @@ class Proxy(db.Model, SerializerMixin): # type: ignore
|
|
96
96
|
dbproxy.enable = proxy['enable']
|
97
97
|
dbproxy.name = proxy['name']
|
98
98
|
dbproxy.proto = proxy['proto']
|
99
|
+
if proxy['transport']=="splithttp":
|
100
|
+
proxy['transport']="xhttp"
|
99
101
|
dbproxy.transport = proxy['transport']
|
100
102
|
dbproxy.cdn = proxy['cdn']
|
101
103
|
dbproxy.l3 = proxy['l3']
|
hiddifypanel/models/report.py
CHANGED
@@ -2,10 +2,10 @@ import datetime
|
|
2
2
|
|
3
3
|
|
4
4
|
from hiddifypanel.database import db
|
5
|
-
from sqlalchemy_serializer import SerializerMixin
|
6
5
|
|
7
6
|
|
8
|
-
|
7
|
+
|
8
|
+
class Report(db.Model):
|
9
9
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
10
10
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), default=0, nullable=False)
|
11
11
|
asn_id = db.Column(db.String(200), nullable=False, unique=False)
|
@@ -19,7 +19,7 @@ class Report(db.Model, SerializerMixin):
|
|
19
19
|
details = db.relationship('ReportDetail', cascade="all,delete", backref='report', lazy='dynamic',)
|
20
20
|
|
21
21
|
|
22
|
-
class ReportDetail(db.Model
|
22
|
+
class ReportDetail(db.Model):
|
23
23
|
report_id = db.Column(db.Integer, db.ForeignKey('report.id'), primary_key=True, )
|
24
24
|
proxy_id = db.Column(db.Integer, db.ForeignKey('proxy.id'), primary_key=True, )
|
25
25
|
ping = db.Column(db.Integer, default=-1)
|
hiddifypanel/models/usage.py
CHANGED
@@ -6,10 +6,10 @@ from sqlalchemy import func
|
|
6
6
|
|
7
7
|
|
8
8
|
from hiddifypanel.database import db
|
9
|
-
from sqlalchemy_serializer import SerializerMixin
|
10
9
|
|
11
10
|
|
12
|
-
|
11
|
+
|
12
|
+
class DailyUsage(db.Model):
|
13
13
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
14
14
|
date = db.Column(db.Date, default=datetime.date.today(), index=True)
|
15
15
|
usage = db.Column(db.BigInteger, default=0, nullable=False)
|
hiddifypanel/models/user.py
CHANGED
@@ -11,7 +11,7 @@ from hiddifypanel.database import db
|
|
11
11
|
from hiddifypanel.models import Lang
|
12
12
|
from hiddifypanel.models.base_account import BaseAccount
|
13
13
|
from hiddifypanel.models.admin import AdminUser
|
14
|
-
|
14
|
+
|
15
15
|
|
16
16
|
ONE_GIG = 1024 * 1024 * 1024
|
17
17
|
|
@@ -37,7 +37,7 @@ package_mode_dic = {
|
|
37
37
|
}
|
38
38
|
|
39
39
|
|
40
|
-
class UserDetail(db.Model
|
40
|
+
class UserDetail(db.Model):
|
41
41
|
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
|
42
42
|
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), default=0, nullable=False)
|
43
43
|
child_id = db.Column(db.Integer, db.ForeignKey('child.id'), default=0, nullable=False)
|
@@ -59,7 +59,7 @@ class UserDetail(db.Model, SerializerMixin):
|
|
59
59
|
# return [] if not self.connected_devices else self.connected_devices.split(",")
|
60
60
|
|
61
61
|
|
62
|
-
class User(BaseAccount
|
62
|
+
class User(BaseAccount):
|
63
63
|
"""
|
64
64
|
This is a model class for a user in a database that includes columns for their ID, UUID, name, online status,
|
65
65
|
account expiration date, usage limit, package days, mode, start date, current usage, last reset time, and comment.
|
@@ -126,9 +126,9 @@
|
|
126
126
|
{{info_box("ram","fa-solid fa-memory", _("RAM"),
|
127
127
|
(stats['system']['ram_used']|round(3)) ~ " / " ~ (stats['system']['ram_total']|round(3)) ~ "GB (" ~((stats['system']['ram_used']*100/stats['system']['ram_total'])|int)~" %)",
|
128
128
|
stats['system']['ram_used']*100/stats['system']['ram_total'],
|
129
|
-
('<i class="fa-solid fa-gauge"></i> '|safe) ~ stats['top5']['
|
130
|
-
('<i class="fa-solid fa-gauge"></i> '|safe) ~ stats['top5']['
|
131
|
-
('<i class="fa-solid fa-gauge"></i> '|safe) ~ stats['top5']['
|
129
|
+
('<i class="fa-solid fa-gauge"></i> '|safe) ~ stats['top5']['ram'][0][0] ~ " ‏"|safe ~ ((stats['top5']['ram'][0][1]*100/stats['system']['ram_total'])|int) ~ "% ‏"|safe~
|
130
|
+
('<i class="fa-solid fa-gauge"></i> '|safe) ~ stats['top5']['ram'][1][0] ~ " ‏"|safe ~ ((stats['top5']['ram'][1][1]*100/stats['system']['ram_total'])|int) ~ "% ‏"|safe~
|
131
|
+
('<i class="fa-solid fa-gauge"></i> '|safe) ~ stats['top5']['ram'][2][0] ~ " ‏"|safe ~ ((stats['top5']['ram'][2][1]*100/stats['system']['ram_total'])|int) ~ "% ",
|
132
132
|
coloring=True,
|
133
133
|
color_class="bg-h-pink"
|
134
134
|
)}}
|
@@ -253,9 +253,9 @@
|
|
253
253
|
info_box("ram", "fa-solid fa-memory", "RAM",
|
254
254
|
stats['system']['ram_used'].toFixed(1) + " / " + stats['system']['ram_total'].toFixed(1) + "GB (" + (stats['system']['ram_used'] * 100 / stats['system']['ram_total']).toFixed(0) + " %)",
|
255
255
|
stats['system']['ram_used'] * 100 / stats['system']['ram_total'].toFixed(0),
|
256
|
-
"<i class='fa-solid fa-gauge'></i> " + stats['top5']['
|
257
|
-
" <i class='fa-solid fa-gauge'></i> " + stats['top5']['
|
258
|
-
" <i class='fa-solid fa-gauge'></i> " + stats['top5']['
|
256
|
+
"<i class='fa-solid fa-gauge'></i> " + stats['top5']['ram'][0][0] + " ‏" + (stats['top5']['ram'][0][1] * 100 / stats['system']['ram_total']).toFixed(0) + "% ‏ " +
|
257
|
+
" <i class='fa-solid fa-gauge'></i> " + stats['top5']['ram'][1][0] + " ‏" + (stats['top5']['ram'][1][1] * 100 / stats['system']['ram_total']).toFixed(0) + "% ‏ " +
|
258
|
+
" <i class='fa-solid fa-gauge'></i> " + stats['top5']['ram'][2][0] + " ‏" + (stats['top5']['ram'][2][1] * 100 / stats['system']['ram_total']).toFixed(0) + "% ",
|
259
259
|
true
|
260
260
|
);
|
261
261
|
|
hiddifypanel/panel/cli.py
CHANGED
@@ -47,7 +47,7 @@ def backup_task():
|
|
47
47
|
if not bot.username:
|
48
48
|
register_bot(True)
|
49
49
|
|
50
|
-
for admin in
|
50
|
+
for admin in db.session.query(AdminUser).filter(AdminUser.mode == AdminMode.super_admin, AdminUser.telegram_id is not None,AdminUser.telegram_id!=0).all():
|
51
51
|
caption = ("Backup \n" + admin_links())
|
52
52
|
with open(dst, 'rb') as document:
|
53
53
|
try:
|
@@ -63,9 +63,8 @@ def register_bot(set_hook=False, remove_hook=False):
|
|
63
63
|
if set_hook:
|
64
64
|
bot.set_webhook(url=f"https://{domain}/{admin_proxy_path}/{user_secret}/api/v1/tgbot/")
|
65
65
|
except Exception as e:
|
66
|
-
|
67
|
-
|
68
|
-
traceback.print_stack()
|
66
|
+
logger.error(e)
|
67
|
+
|
69
68
|
|
70
69
|
|
71
70
|
def init_app(app):
|
@@ -111,15 +111,17 @@ class AppAPI(MethodView):
|
|
111
111
|
singbox_dto = self.__get_singbox_app_dto()
|
112
112
|
# hiddifyng_dto = self.__get_hiddifyng_app_dto()
|
113
113
|
v2rayng_dto = self.__get_v2rayng_app_dto()
|
114
|
+
cmfa_dto = self.__get_cmfa_app_dto()
|
114
115
|
# hiddify_clash_android_dto = self.__get_hiddify_clash_android_app_dto()
|
115
116
|
nekobox_dto = self.__get_nekobox_app_dto()
|
116
|
-
apps_data += ([hiddify_next_dto, singbox_dto, v2rayng_dto, nekobox_dto])
|
117
|
+
apps_data += ([hiddify_next_dto, singbox_dto, v2rayng_dto, cmfa_dto, nekobox_dto])
|
117
118
|
case Platform.windows:
|
118
119
|
hiddify_next_dto = self.__get_hiddify_next_app_dto()
|
120
|
+
clash_verge_rev_dto = self.__get_clash_verge_rev_app_dto()
|
119
121
|
# hiddify_clash_dto = self.__get_hiddify_clash_desktop_app_dto()
|
120
122
|
# hiddifyn_dto = self.__get_hiddifyn_app_dto()
|
121
123
|
v2rayn_dto = self.__get_v2rayn_app_dto()
|
122
|
-
apps_data += ([hiddify_next_dto, v2rayn_dto])
|
124
|
+
apps_data += ([hiddify_next_dto, v2rayn_dto, clash_verge_rev_dto ])
|
123
125
|
case Platform.ios:
|
124
126
|
hiddify_next_dto = self.__get_hiddify_next_app_dto()
|
125
127
|
singbox_dto = self.__get_singbox_app_dto()
|
@@ -131,13 +133,15 @@ class AppAPI(MethodView):
|
|
131
133
|
apps_data += ([hiddify_next_dto, singbox_dto, streisand_dto, stash_dto, shadowrocket_dto, foxray_dto, loon_dto])
|
132
134
|
case Platform.linux:
|
133
135
|
hiddify_next_dto = self.__get_hiddify_next_app_dto()
|
136
|
+
clash_verge_rev_dto = self.__get_clash_verge_rev_app_dto()
|
134
137
|
# hiddify_clash_dto = self.__get_hiddify_clash_desktop_app_dto()
|
135
|
-
apps_data += ([hiddify_next_dto])
|
138
|
+
apps_data += ([hiddify_next_dto, clash_verge_rev_dto ])
|
136
139
|
case Platform.mac:
|
137
140
|
hiddify_next_dto = self.__get_hiddify_next_app_dto()
|
138
141
|
singbox_dto = self.__get_singbox_app_dto()
|
142
|
+
clash_verge_rev_dto = self.__get_clash_verge_rev_app_dto()
|
139
143
|
# hiddify_clash_dto = self.__get_hiddify_clash_desktop_app_dto()
|
140
|
-
apps_data += ([hiddify_next_dto, singbox_dto])
|
144
|
+
apps_data += ([hiddify_next_dto, singbox_dto, clash_verge_rev_dto ])
|
141
145
|
|
142
146
|
return apps_data
|
143
147
|
|
@@ -168,11 +172,13 @@ class AppAPI(MethodView):
|
|
168
172
|
stash_app_dto = self.__get_stash_app_dto()
|
169
173
|
# hiddify_clash_app_dto = self.__get_hiddify_clash_desktop_app_dto()
|
170
174
|
singbox_app_dto = self.__get_singbox_app_dto()
|
175
|
+
cmfa_app_dto = self.__get_cmfa_app_dto()
|
176
|
+
clash_verge_rev_app_dto = self.__get_clash_verge_rev_app_dto()
|
171
177
|
hiddify_next_app_dto = self.__get_hiddify_next_app_dto()
|
172
178
|
return [
|
173
179
|
v2rayn_app_dto, v2rayng_app_dto,
|
174
180
|
foxray_app_dto, shadowrocket_app_dto, streisand_app_dto,
|
175
|
-
loon_app_dto, stash_app_dto, singbox_app_dto, hiddify_next_app_dto
|
181
|
+
loon_app_dto, stash_app_dto, singbox_app_dto, cmfa_app_dto, clash_verge_rev_app_dto, hiddify_next_app_dto
|
176
182
|
]
|
177
183
|
|
178
184
|
def __get_app_icon_url(self, app_name):
|
@@ -182,6 +188,10 @@ class AppAPI(MethodView):
|
|
182
188
|
url = base + static_url_for(filename='apps-icon/hiddify_next.ico')
|
183
189
|
elif app_name == _('app.singbox.title'):
|
184
190
|
url = base + static_url_for(filename='apps-icon/singbox.ico')
|
191
|
+
elif app_name == _('app.cmfa.title'):
|
192
|
+
url = base + static_url_for(filename='apps-icon/cmfa.ico')
|
193
|
+
elif app_name == _('app.clash_verge_rev.title'):
|
194
|
+
url = base + static_url_for(filename='apps-icon/clash_verge_rev.ico')
|
185
195
|
elif app_name == _('app.hiddifyn.title'):
|
186
196
|
url = base + static_url_for(filename='apps-icon/hiddifyn.ico')
|
187
197
|
elif app_name == _('app.v2rayng.title'):
|
@@ -356,7 +366,7 @@ class AppAPI(MethodView):
|
|
356
366
|
dto.description = _('app.singbox.description')
|
357
367
|
dto.icon_url = self.__get_app_icon_url(_('app.singbox.title'))
|
358
368
|
dto.guide_url = ''
|
359
|
-
dto.deeplink = f'sing-box://import-remote-profile/?url={self.user_panel_url}'
|
369
|
+
dto.deeplink = f'sing-box://import-remote-profile/?url={self.user_panel_url}#{self.profile_title}'
|
360
370
|
|
361
371
|
# availabe installatoin types
|
362
372
|
installation_types = []
|
@@ -409,6 +419,66 @@ class AppAPI(MethodView):
|
|
409
419
|
dto.install = install_dtos
|
410
420
|
return dto
|
411
421
|
|
422
|
+
def __get_clash_verge_rev_app_dto(self):
|
423
|
+
dto = AppSchema()
|
424
|
+
dto.title = _('app.clash_verge_rev.title')
|
425
|
+
dto.description = _('app.clash_verge_rev.description')
|
426
|
+
dto.icon_url = self.__get_app_icon_url(_('app.clash_verge_rev.title'))
|
427
|
+
dto.guide_url = ''
|
428
|
+
dto.deeplink = f'clash://install-config/?url={self.user_panel_encoded_url}&name={self.profile_title}'
|
429
|
+
|
430
|
+
# availabe installatoin types
|
431
|
+
installation_types = []
|
432
|
+
if self.platform == Platform.all:
|
433
|
+
installation_types = [AppInstallType.setup, AppInstallType.appimage, AppInstallType.dmg]
|
434
|
+
else:
|
435
|
+
match self.platform:
|
436
|
+
case Platform.windows:
|
437
|
+
installation_types = [AppInstallType.setup]
|
438
|
+
case Platform.linux:
|
439
|
+
installation_types = [AppInstallType.appimage]
|
440
|
+
case Platform.mac:
|
441
|
+
installation_types = [AppInstallType.dmg]
|
442
|
+
|
443
|
+
install_dtos = []
|
444
|
+
for install_type in installation_types:
|
445
|
+
install_dto = AppInstall()
|
446
|
+
ins_url = ''
|
447
|
+
match install_type:
|
448
|
+
case AppInstallType.appimage:
|
449
|
+
ins_url = 'https://www.clashverge.dev/install.html#__tabbed_1_2'
|
450
|
+
case AppInstallType.setup:
|
451
|
+
ins_url = 'https://www.clashverge.dev/install.html#__tabbed_1_1'
|
452
|
+
case AppInstallType.dmg:
|
453
|
+
ins_url = 'https://www.clashverge.dev/install.html#__tabbed_1_3'
|
454
|
+
|
455
|
+
install_dto = self.__get_app_install_dto(install_type, ins_url)
|
456
|
+
install_dtos.append(install_dto)
|
457
|
+
|
458
|
+
dto.install = install_dtos
|
459
|
+
return dto
|
460
|
+
|
461
|
+
def __get_cmfa_app_dto(self):
|
462
|
+
dto = AppSchema()
|
463
|
+
dto.title = _('app.cmfa.title')
|
464
|
+
dto.description = _('app.cmfa.description')
|
465
|
+
dto.icon_url = self.__get_app_icon_url(_('app.cmfa.title'))
|
466
|
+
dto.guide_url = ''
|
467
|
+
dto.deeplink = f'clash://install-config/?url={self.user_panel_encoded_url}&name={self.profile_title}'
|
468
|
+
|
469
|
+
latest_url, version = get_latest_release_url(f'https://github.com/MetaCubeX/ClashMetaForAndroid')
|
470
|
+
ins_url = latest_url.split('releases/')[0] + f'releases/download/{version}/cmfa-{version}-meta-universal-release.apk'
|
471
|
+
def remove_v_from_filename(url):
|
472
|
+
parts = url.split('/')
|
473
|
+
filename = parts[-1]
|
474
|
+
new_filename = filename.replace('cmfa-v', 'cmfa-')
|
475
|
+
parts[-1] = new_filename
|
476
|
+
new_url = '/'.join(parts)
|
477
|
+
return new_url
|
478
|
+
ins_url = remove_v_from_filename(ins_url)
|
479
|
+
dto.install = [self.__get_app_install_dto(AppInstallType.apk, ins_url)]
|
480
|
+
return dto
|
481
|
+
|
412
482
|
def __get_hiddify_next_app_dto(self):
|
413
483
|
dto = AppSchema()
|
414
484
|
dto.title = _('app.hiddify.next.title')
|
hiddifypanel/panel/common.py
CHANGED
@@ -40,7 +40,11 @@ def init_app(app: APIFlask):
|
|
40
40
|
|
41
41
|
@app.errorhandler(Exception)
|
42
42
|
def internal_server_error(e):
|
43
|
-
|
43
|
+
if hasattr(e, 'code') and e.code == 404:
|
44
|
+
logger.error(f'{e} {request.url}')
|
45
|
+
else:
|
46
|
+
logger.exception(e)
|
47
|
+
|
44
48
|
if isinstance(e, Exception):
|
45
49
|
if hutils.flask.is_api_call(request.path):
|
46
50
|
return jsonify({
|
@@ -133,8 +133,9 @@ class LoginView(FlaskView):
|
|
133
133
|
@ route('/<secret_uuid>/manifest.webmanifest')
|
134
134
|
def create_pwa_manifest(self):
|
135
135
|
domain = request.host
|
136
|
-
|
137
|
-
|
136
|
+
admin_call=hutils.flask.is_admin_panel_call()
|
137
|
+
account=AdminUser.by_uuid(g.uuid) if admin_call else User.by_uuid(g.uuid)
|
138
|
+
name = (domain if admin_call else account.name)
|
138
139
|
return jsonify({
|
139
140
|
"name": f"Hiddify {name}",
|
140
141
|
"short_name": f"{name}"[:12],
|
hiddifypanel/panel/hiddify.py
CHANGED
@@ -6,7 +6,7 @@ from typing import Tuple
|
|
6
6
|
from flask import current_app, g
|
7
7
|
from flask_babel import lazy_gettext as _
|
8
8
|
from datetime import timedelta
|
9
|
-
|
9
|
+
import os
|
10
10
|
from hiddifypanel.cache import cache
|
11
11
|
from hiddifypanel.models import *
|
12
12
|
from hiddifypanel.database import db
|
@@ -41,7 +41,7 @@ def add_short_link_imp(link: str, period_min: int = 5) -> Tuple[str, datetime]:
|
|
41
41
|
|
42
42
|
pattern = r"([^/]+)\("
|
43
43
|
|
44
|
-
with open(
|
44
|
+
with open(os.environ['HIDDIFY_CONFIG_PATH'] + "/nginx/parts/short-link.conf", 'r') as f:
|
45
45
|
for line in f:
|
46
46
|
if link in line:
|
47
47
|
return re.search(pattern, line).group(1), datetime.now() + timedelta(minutes=period_min)
|
@@ -146,14 +146,14 @@ def get_child(unique_id):
|
|
146
146
|
|
147
147
|
|
148
148
|
def dump_db_to_dict():
|
149
|
-
return {"childs": [u.to_dict() for u in
|
150
|
-
"users": [u.to_dict() for u in
|
151
|
-
"domains": [u.to_dict() for u in
|
152
|
-
"proxies": [u.to_dict() for u in
|
149
|
+
return {"childs": [u.to_dict() for u in db.session.query(Child).all()],
|
150
|
+
"users": [u.to_dict() for u in db.session.query(User).all()],
|
151
|
+
"domains": [u.to_dict() for u in db.session.query(Domain).all()],
|
152
|
+
"proxies": [u.to_dict() for u in db.session.query(Proxy).all()],
|
153
153
|
# "parent_domains": [] if not hconfig(ConfigEnum.license) else [u.to_dict() for u in ParentDomain.query.all()],
|
154
|
-
'admin_users': [d.to_dict() for d in
|
155
|
-
"hconfigs": [*[u.to_dict() for u in
|
156
|
-
*[u.to_dict() for u in
|
154
|
+
'admin_users': [d.to_dict() for d in db.session.query(AdminUser).all()],
|
155
|
+
"hconfigs": [*[u.to_dict() for u in db.session.query(BoolConfig).all()],
|
156
|
+
*[u.to_dict() for u in db.session.query(StrConfig).all()]]
|
157
157
|
}
|
158
158
|
|
159
159
|
|
hiddifypanel/panel/hlogger.py
CHANGED
@@ -5,6 +5,8 @@ def logger_dynamic_formatter(record) -> str:
|
|
5
5
|
fmt = '<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>'
|
6
6
|
if record['extra']:
|
7
7
|
fmt += ' | <level>{extra}</level>'
|
8
|
+
if record["exception"]:
|
9
|
+
fmt += "{exception}\n"
|
8
10
|
return fmt + '\n'
|
9
11
|
|
10
12
|
def init_app(app):
|
@@ -19,7 +21,7 @@ def init_logger(app, cli):
|
|
19
21
|
|
20
22
|
logger.remove()
|
21
23
|
logger.add(sys.stderr if cli else sys.stdout, format=logger_dynamic_formatter, level=app.config['STDOUT_LOG_LEVEL'],
|
22
|
-
colorize=True, catch=True, enqueue=True, diagnose=
|
24
|
+
colorize=True, catch=True, enqueue=True, diagnose=True, backtrace=True)
|
23
25
|
logger.trace('Logger initiated :)')
|
24
26
|
|
25
27
|
with app.app_context():
|