hiddifypanel 10.80.0__py3-none-any.whl → 10.80.0.dev8__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 +1 -1
- hiddifypanel/base.py +129 -43
- hiddifypanel/cache.py +1 -1
- hiddifypanel/database.py +0 -7
- hiddifypanel/hutils/flask.py +3 -3
- hiddifypanel/hutils/proxy/__init__.py +0 -1
- hiddifypanel/hutils/proxy/clash.py +2 -2
- hiddifypanel/hutils/proxy/shared.py +6 -6
- hiddifypanel/hutils/proxy/singbox.py +1 -1
- hiddifypanel/hutils/proxy/xray.py +2 -2
- hiddifypanel/hutils/proxy/xrayjson.py +7 -10
- hiddifypanel/models/config.py +1 -4
- hiddifypanel/models/config_enum.py +2 -2
- hiddifypanel/models/proxy.py +1 -1
- hiddifypanel/panel/__init__.py +8 -8
- hiddifypanel/panel/admin/AdminstratorAdmin.py +8 -7
- hiddifypanel/panel/admin/DomainAdmin.py +98 -132
- hiddifypanel/panel/admin/QuickSetup.py +8 -8
- hiddifypanel/panel/admin/UserAdmin.py +33 -58
- hiddifypanel/panel/admin/templates/index.html +4 -6
- hiddifypanel/panel/admin/templates/model/user_list.html +3 -11
- hiddifypanel/panel/cli.py +2 -11
- hiddifypanel/panel/commercial/restapi/v1/tgbot.py +1 -19
- hiddifypanel/panel/commercial/restapi/v2/admin/system_actions.py +1 -5
- hiddifypanel/panel/commercial/restapi/v2/admin/user_api.py +1 -2
- hiddifypanel/panel/common.py +1 -1
- hiddifypanel/panel/init_db.py +16 -19
- hiddifypanel/panel/usage.py +3 -13
- hiddifypanel/panel/user/user.py +18 -12
- hiddifypanel/templates/fake.html +320 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/en/LC_MESSAGES/messages.po +13 -82
- hiddifypanel/translations/fa/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/fa/LC_MESSAGES/messages.po +12 -81
- hiddifypanel/translations/pt/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/pt/LC_MESSAGES/messages.po +4 -73
- hiddifypanel/translations/ru/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/ru/LC_MESSAGES/messages.po +9 -79
- hiddifypanel/translations/zh/LC_MESSAGES/messages.mo +0 -0
- hiddifypanel/translations/zh/LC_MESSAGES/messages.po +4 -73
- hiddifypanel/translations.i18n/en.json +7 -50
- hiddifypanel/translations.i18n/fa.json +6 -49
- hiddifypanel/translations.i18n/fr.json +2 -2
- hiddifypanel/translations.i18n/my.json +2 -2
- hiddifypanel/translations.i18n/pt.json +4 -47
- hiddifypanel/translations.i18n/ru.json +7 -50
- hiddifypanel/translations.i18n/zh.json +4 -47
- {hiddifypanel-10.80.0.dist-info → hiddifypanel-10.80.0.dev8.dist-info}/METADATA +6 -13
- {hiddifypanel-10.80.0.dist-info → hiddifypanel-10.80.0.dev8.dist-info}/RECORD +53 -69
- hiddifypanel/apps/__init__.py +0 -0
- hiddifypanel/apps/asgi_app.py +0 -7
- hiddifypanel/apps/celery_app.py +0 -3
- hiddifypanel/apps/wsgi_app.py +0 -5
- hiddifypanel/base_setup.py +0 -82
- hiddifypanel/celery.py +0 -45
- hiddifypanel/hutils/proxy/wireguard.py +0 -34
- hiddifypanel/panel/hlogger.py +0 -32
- hiddifypanel/panel/node/__init__.py +0 -9
- hiddifypanel/panel/node/a.py +0 -14
- hiddifypanel/panel/node/hello.py +0 -14
- hiddifypanel/panel/node/test.proto +0 -13
- hiddifypanel/panel/node/test_grpc.py +0 -40
- hiddifypanel/panel/node/test_pb2.py +0 -40
- hiddifypanel/panel/node/test_pb2.pyi +0 -17
- hiddifypanel/panel/node/test_pb2_grpc.py +0 -97
- {hiddifypanel-10.80.0.dist-info → hiddifypanel-10.80.0.dev8.dist-info}/LICENSE.md +0 -0
- {hiddifypanel-10.80.0.dist-info → hiddifypanel-10.80.0.dev8.dist-info}/WHEEL +0 -0
- {hiddifypanel-10.80.0.dist-info → hiddifypanel-10.80.0.dev8.dist-info}/entry_points.txt +0 -0
hiddifypanel/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
10.80.0
|
1
|
+
10.80.0.dev8
|
hiddifypanel/VERSION.py
CHANGED
@@ -2,5 +2,5 @@ import importlib.metadata
|
|
2
2
|
from datetime import datetime
|
3
3
|
|
4
4
|
__version__ = importlib.metadata.version(__package__ or __name__)
|
5
|
-
__release_time__= datetime.strptime('2024-
|
5
|
+
__release_time__= datetime.strptime('2024-11-10T19:52:20','%Y-%m-%dT%H:%M:%S')
|
6
6
|
is_released_version=True
|
hiddifypanel/base.py
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
from flask import request, g
|
2
2
|
# from hiddifypanel.cache import cache
|
3
|
+
from hiddifypanel.models import *
|
3
4
|
|
4
|
-
|
5
|
+
import flask_bootstrap
|
6
|
+
import hiddifypanel
|
7
|
+
from flask_babel import Babel
|
8
|
+
from flask_session import Session
|
5
9
|
|
6
10
|
import datetime
|
7
11
|
|
@@ -9,54 +13,138 @@ from dotenv import dotenv_values
|
|
9
13
|
import os
|
10
14
|
import sys
|
11
15
|
from apiflask import APIFlask
|
16
|
+
from werkzeug.middleware.proxy_fix import ProxyFix
|
12
17
|
from loguru import logger
|
18
|
+
from hiddifypanel.panel.init_db import init_db
|
19
|
+
|
20
|
+
|
21
|
+
def logger_dynamic_formatter(record) -> str:
|
22
|
+
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>'
|
23
|
+
if record['extra']:
|
24
|
+
fmt += ' | <level>{extra}</level>'
|
25
|
+
return fmt + '\n'
|
13
26
|
|
14
27
|
|
15
|
-
|
28
|
+
def init_logger(app, cli):
|
29
|
+
# configure logger
|
30
|
+
logger.remove()
|
31
|
+
logger.add(sys.stderr if cli else sys.stdout, format=logger_dynamic_formatter, level=app.config['STDOUT_LOG_LEVEL'],
|
32
|
+
colorize=True, catch=True, enqueue=True, diagnose=False, backtrace=True)
|
33
|
+
logger.trace('Logger initiated :)')
|
34
|
+
|
35
|
+
|
36
|
+
# TODO: refactor this function
|
16
37
|
|
17
38
|
def create_app(*args, cli=False, **config):
|
18
39
|
|
19
40
|
app = APIFlask(__name__, static_url_path="/<proxy_path>/static/", instance_relative_config=True, version='2.2.0', title="Hiddify API",
|
20
41
|
openapi_blueprint_url_prefix="/<proxy_path>/api", docs_ui='elements', json_errors=False, enable_openapi=not cli)
|
21
42
|
# app = Flask(__name__, static_url_path="/<proxy_path>/static/", instance_relative_config=True)
|
22
|
-
|
23
|
-
|
43
|
+
|
44
|
+
if not cli:
|
45
|
+
|
46
|
+
from hiddifypanel import auth
|
47
|
+
app.config["PREFERRED_URL_SCHEME"] = "https"
|
48
|
+
app.wsgi_app = ProxyFix(
|
49
|
+
app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1,
|
50
|
+
)
|
51
|
+
app.secret_key="asdsad"
|
52
|
+
app.servers = {
|
53
|
+
'name': 'current',
|
54
|
+
'url': '',
|
55
|
+
} # type: ignore
|
56
|
+
app.info = {
|
57
|
+
'description': 'Hiddify is a free and open source software. It is as it is.',
|
58
|
+
'termsOfService': 'https://hiddify.com',
|
59
|
+
'contact': {
|
60
|
+
'name': 'API Support',
|
61
|
+
'url': 'https://www.hiddify.com/support',
|
62
|
+
'email': 'panel@hiddify.com'
|
63
|
+
},
|
64
|
+
'license': {
|
65
|
+
'name': 'Creative Commons Zero v1.0 Universal',
|
66
|
+
'url': 'https://github.com/hiddify/Hiddify-Manager/blob/main/LICENSE'
|
67
|
+
}
|
68
|
+
}
|
69
|
+
# setup flask server-side session
|
70
|
+
# app.config['APPLICATION_ROOT'] = './'
|
71
|
+
# app.config['SESSION_COOKIE_DOMAIN'] = '/'
|
72
|
+
|
73
|
+
|
74
|
+
app.jinja_env.line_statement_prefix = '%'
|
75
|
+
from hiddifypanel import hutils
|
76
|
+
app.jinja_env.filters['b64encode'] = hutils.encode.do_base_64
|
77
|
+
app.view_functions['admin.static'] = {} # fix bug in apiflask
|
78
|
+
flask_bootstrap.Bootstrap4(app)
|
79
|
+
|
24
80
|
for c, v in dotenv_values(os.environ.get("HIDDIFY_CFG_PATH", 'app.cfg')).items():
|
25
81
|
if v.isdecimal():
|
26
82
|
v = int(v)
|
27
83
|
else:
|
28
84
|
v = True if v.lower() == "true" else (False if v.lower() == "false" else v)
|
29
|
-
app.config[c] = v
|
30
|
-
dyn=FlaskDynaconf(app,settings_files=[os.environ.get("HIDDIFY_CFG_PATH", 'app.cfg')])
|
31
|
-
|
32
|
-
if cli:
|
33
|
-
app.config['EXTENSIONS']=[
|
34
|
-
# "hiddifypanel.cache:init_app",
|
35
|
-
"hiddifypanel.database:init_app",
|
36
|
-
"hiddifypanel.panel.hlogger:init_cli",
|
37
|
-
"hiddifypanel.panel.cli:init_app",
|
38
|
-
"hiddifypanel.celery:init_app",
|
39
|
-
]
|
40
|
-
else:
|
41
|
-
app.config['EXTENSIONS']=[
|
42
|
-
# "hiddifypanel.cache:init_app",
|
43
|
-
"hiddifypanel.database:init_app",
|
44
|
-
"hiddifypanel.panel.hlogger:init_app",
|
45
|
-
"hiddifypanel.base_setup:init_app",
|
46
|
-
"hiddifypanel.panel.common:init_app",
|
47
|
-
"hiddifypanel.panel.common_bp:init_app",
|
48
|
-
"hiddifypanel.panel.admin:init_app",
|
49
|
-
"hiddifypanel.panel.user:init_app",
|
50
|
-
"hiddifypanel.panel.commercial:init_app",
|
51
|
-
"hiddifypanel.panel.node:init_app",
|
52
|
-
"hiddifypanel.celery:init_app",
|
53
|
-
]
|
54
|
-
|
55
85
|
|
86
|
+
app.config[c] = v
|
87
|
+
init_logger(app, cli)
|
88
|
+
hiddifypanel.database.init_app(app)
|
89
|
+
with app.app_context():
|
90
|
+
init_db()
|
91
|
+
logger.add(app.config['HIDDIFY_CONFIG_PATH'] + "/log/system/panel.log", format=logger_dynamic_formatter, level=hconfig(ConfigEnum.log_level),
|
92
|
+
colorize=True, catch=True, enqueue=True, diagnose=False, backtrace=True)
|
93
|
+
|
94
|
+
def get_locale():
|
95
|
+
# Put your logic here. Application can store locale in
|
96
|
+
# user profile, cookie, session, etc.
|
97
|
+
if "admin" in request.base_url:
|
98
|
+
g.locale = hconfig(ConfigEnum.admin_lang) or 'en'
|
99
|
+
else:
|
100
|
+
g.locale = auth.current_account.lang or hconfig(ConfigEnum.lang) or 'en'
|
101
|
+
return g.locale
|
102
|
+
app.jinja_env.globals['get_locale'] = get_locale
|
103
|
+
babel = Babel(app, locale_selector=get_locale)
|
104
|
+
if not cli:
|
105
|
+
app.config['SESSION_TYPE'] = 'redis'
|
106
|
+
from hiddifypanel.cache import redis_client
|
107
|
+
app.config['SESSION_REDIS'] = redis_client
|
108
|
+
app.config['SESSION_PERMANENT'] = True
|
109
|
+
app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=10)
|
110
|
+
app.security_schemes = { # equals to use config SECURITY_SCHEMES
|
111
|
+
'Hiddify-API-Key': {
|
112
|
+
'type': 'apiKey',
|
113
|
+
'in': 'header',
|
114
|
+
'name': 'Hiddify-API-Key',
|
115
|
+
}
|
116
|
+
}
|
117
|
+
Session(app)
|
118
|
+
hiddifypanel.panel.common.init_app(app)
|
119
|
+
hiddifypanel.panel.common_bp.init_app(app)
|
120
|
+
|
121
|
+
from hiddifypanel.panel import user, commercial, admin
|
122
|
+
admin.init_app(app)
|
123
|
+
user.init_app(app)
|
124
|
+
commercial.init_app(app)
|
56
125
|
|
57
126
|
app.config.update(config) # Override with passed config
|
58
|
-
|
59
|
-
app.config
|
127
|
+
# app.config['WTF_CSRF_CHECK_DEFAULT'] = False
|
128
|
+
# app.config['WTF_CSRF_ENABLED'] = False
|
129
|
+
# app.config['BABEL_TRANSLATION_DIRECTORIES'] = '/workspace/Hiddify-Server/hiddify-panel/src/translations.i18n'
|
130
|
+
|
131
|
+
# from flask_wtf.csrf import CSRFProtect
|
132
|
+
|
133
|
+
# csrf = CSRFProtect(app)
|
134
|
+
|
135
|
+
# @app.before_request
|
136
|
+
# def check_csrf():
|
137
|
+
# # if "/admin/user/" in request.base_url:
|
138
|
+
# # return
|
139
|
+
# # if "/admin/domain/" in request.base_url:
|
140
|
+
# # return
|
141
|
+
# # if "/admin/actions/" in request.base_url:
|
142
|
+
# # return
|
143
|
+
# # if "/api/" in request.base_url:
|
144
|
+
# # return
|
145
|
+
# csrf.protect()
|
146
|
+
|
147
|
+
hiddifypanel.panel.cli.init_app(app)
|
60
148
|
return app
|
61
149
|
|
62
150
|
|
@@ -65,18 +153,16 @@ def create_app_wsgi(*args, **kwargs):
|
|
65
153
|
# that doesn't allow **config
|
66
154
|
# to be passed to create_app
|
67
155
|
# https://github.com/pallets/flask/issues/4170
|
68
|
-
cli = ("hiddifypanel" in sys.argv[0]
|
69
|
-
|
156
|
+
cli = ("hiddifypanel" in sys.argv[0]) or (sys.argv[1] in ["update-usage", "all-configs", "admin_links", "admin_path"])
|
70
157
|
app = create_app(cli=cli)
|
71
158
|
return app
|
72
159
|
|
73
160
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
return app.extensions["celery"]
|
161
|
+
# def create_cli_app(*args, **kwargs):
|
162
|
+
# # # workaround for Flask issue
|
163
|
+
# # # that doesn't allow **config
|
164
|
+
# # # to be passed to create_app
|
165
|
+
# # # https://github.com/pallets/flask/issues/4170
|
166
|
+
# # print(kwargs)
|
167
|
+
# app = create_app(*args, cli=True, **kwargs)
|
168
|
+
# return app
|
hiddifypanel/cache.py
CHANGED
@@ -5,7 +5,7 @@ from pickle import dumps, loads
|
|
5
5
|
from loguru import logger
|
6
6
|
|
7
7
|
redis_client = redis.from_url(os.environ["REDIS_URI_MAIN"])
|
8
|
-
|
8
|
+
|
9
9
|
|
10
10
|
class CustomRedisCache(RedisCache):
|
11
11
|
def __init__(self, redis_client, prefix="rc", serializer=compact_dump, deserializer=loads, key_serializer=None, support_cluster=True, exception_handler=None):
|
hiddifypanel/database.py
CHANGED
@@ -6,9 +6,6 @@ import os
|
|
6
6
|
from sqlalchemy import Row, text, Sequence
|
7
7
|
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
9
|
db: SQLAlchemy = SQLAlchemy()
|
13
10
|
db.UUID = UUIDType # type: ignore
|
14
11
|
|
@@ -16,10 +13,6 @@ db.UUID = UUIDType # type: ignore
|
|
16
13
|
def init_app(app):
|
17
14
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
|
18
15
|
db.init_app(app)
|
19
|
-
with app.app_context():
|
20
|
-
from hiddifypanel.panel.init_db import init_db
|
21
|
-
init_db()
|
22
|
-
|
23
16
|
|
24
17
|
|
25
18
|
def db_execute(query: str, return_val: bool = False, commit: bool = False, **params: dict):
|
hiddifypanel/hutils/flask.py
CHANGED
@@ -51,7 +51,7 @@ def hurl_for(endpoint, **values):
|
|
51
51
|
def get_user_agent() -> dict:
|
52
52
|
ua = __parse_user_agent(request.user_agent.string)
|
53
53
|
|
54
|
-
if ua.get('v', 1) <
|
54
|
+
if ua.get('v', 1) < 8:
|
55
55
|
__parse_user_agent.invalidate_all() # type:ignore
|
56
56
|
ua = __parse_user_agent(request.user_agent.string)
|
57
57
|
return ua
|
@@ -66,13 +66,13 @@ def __parse_user_agent(ua: str) -> dict:
|
|
66
66
|
# Example: SFA/1.7.0 (239; sing-box 1.7.0)
|
67
67
|
# Example: HiddifyNext/0.13.6 (android) like ClashMeta v2ray sing-box
|
68
68
|
if ua=="v2rayNG/1.8.23": #temporary fix for xray sub in hiddifynext
|
69
|
-
ua="HiddifyNextX/
|
69
|
+
ua="HiddifyNextX/0.13.6 (android) like ClashMeta v2ray sing-box"
|
70
70
|
uaa = user_agents.parse(ua)
|
71
71
|
|
72
72
|
match = re.search(ua_version_pattern, ua)
|
73
73
|
generic_version = list(map(int, match.group(1).split('.'))) if match else [0, 0, 0]
|
74
74
|
res = {}
|
75
|
-
res['v'] =
|
75
|
+
res['v'] = 8
|
76
76
|
res["is_bot"] = uaa.is_bot
|
77
77
|
res["is_browser"] = re.match('^Mozilla', ua, re.IGNORECASE) and True
|
78
78
|
res['os'] = uaa.os.family
|
@@ -33,7 +33,7 @@ def to_clash(proxy, meta_or_normal):
|
|
33
33
|
|
34
34
|
if proxy['l3'] in ["kcp", ProxyL3.h3_quic]:
|
35
35
|
return {'name': name, 'msg': f"clash does not support {proxy['l3']}", 'type': 'debug'}
|
36
|
-
if proxy['transport'] in [ProxyTransport.
|
36
|
+
if proxy['transport'] in [ProxyTransport.splithttp, ProxyTransport.httpupgrade]:
|
37
37
|
return {'name': name, 'msg': f"clash does not support {proxy['transport']}", 'type': 'debug'}
|
38
38
|
# if proxy['proto'] in [Proxy.shado]:
|
39
39
|
|
@@ -44,7 +44,7 @@ def to_clash(proxy, meta_or_normal):
|
|
44
44
|
return {'name': name, 'msg': f"clash does not support {proxy['proto']}", 'type': 'debug'}
|
45
45
|
if proxy['proto'] in ["vless", 'tuic', 'hysteria2']:
|
46
46
|
return {'name': name, 'msg': f"{proxy['proto']} not supported in clash", 'type': 'debug'}
|
47
|
-
if proxy['transport'] in ["shadowtls", "
|
47
|
+
if proxy['transport'] in ["shadowtls", "splithttp"]:
|
48
48
|
return {'name': name, 'msg': f"{proxy['transport']} not supported in clash", 'type': 'debug'}
|
49
49
|
if proxy['l3'] == ProxyL3.tls_h2 and proxy['proto'] in [ProxyProto.vmess, ProxyProto.vless] and proxy['dbe'].cdn == ProxyCDN.direct:
|
50
50
|
return {'name': name, 'msg': "bug tls_h2 vmess and vless in clash meta", 'type': 'warning'}
|
@@ -134,8 +134,8 @@ def get_proxies(child_id: int = 0, only_enabled=False) -> list['Proxy']:
|
|
134
134
|
proxies = [c for c in proxies if 'trojan' not in c.proto]
|
135
135
|
if not hconfig(ConfigEnum.httpupgrade_enable, child_id):
|
136
136
|
proxies = [c for c in proxies if ProxyTransport.httpupgrade not in c.transport]
|
137
|
-
if not hconfig(ConfigEnum.
|
138
|
-
proxies = [c for c in proxies if ProxyTransport.
|
137
|
+
if not hconfig(ConfigEnum.splithttp_enable, child_id):
|
138
|
+
proxies = [c for c in proxies if ProxyTransport.splithttp not in c.transport]
|
139
139
|
if not hconfig(ConfigEnum.ws_enable, child_id):
|
140
140
|
proxies = [c for c in proxies if ProxyTransport.WS not in c.transport]
|
141
141
|
# if not hconfig(ConfigEnum.xtls_enable, child_id):
|
@@ -189,7 +189,7 @@ def get_valid_proxies(domains: list[Domain]) -> list[dict]:
|
|
189
189
|
noDomainProxies = False
|
190
190
|
if proxy.proto in [ProxyProto.ssh, ProxyProto.wireguard]:
|
191
191
|
noDomainProxies = True
|
192
|
-
if proxy.proto in [ProxyProto.ss] and proxy.transport not in [ProxyTransport.grpc, ProxyTransport.h2, ProxyTransport.WS, ProxyTransport.httpupgrade, ProxyTransport.
|
192
|
+
if proxy.proto in [ProxyProto.ss] and proxy.transport not in [ProxyTransport.grpc, ProxyTransport.h2, ProxyTransport.WS, ProxyTransport.httpupgrade, ProxyTransport.splithttp]:
|
193
193
|
noDomainProxies = True
|
194
194
|
options = []
|
195
195
|
key = f'{proxy.proto}{proxy.transport}{proxy.cdn}{proxy.l3}'
|
@@ -413,9 +413,9 @@ def make_proxy(hconfigs: dict, proxy: Proxy, domain_db: Domain, phttp=80, ptls=4
|
|
413
413
|
base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_httpupgrade]}'
|
414
414
|
base["host"] = domain
|
415
415
|
return base
|
416
|
-
if proxy.transport in [ProxyTransport.
|
417
|
-
base['transport'] = '
|
418
|
-
base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.
|
416
|
+
if proxy.transport in [ProxyTransport.splithttp]:
|
417
|
+
base['transport'] = 'splithttp'
|
418
|
+
base['path'] = f'/{path[base["proto"]]}{hconfigs[ConfigEnum.path_splithttp]}'
|
419
419
|
# if 0 and 'h2' in base['alpn'] or 'h3' in base['alpn']:
|
420
420
|
# base['path'] += "2"
|
421
421
|
# else:
|
@@ -47,7 +47,7 @@ def configs_as_json(domains: list[Domain], **kwargs) -> str:
|
|
47
47
|
def is_xray_proxy(proxy: dict):
|
48
48
|
if g.user_agent.get('is_hiddify_prefere_xray'):
|
49
49
|
return True
|
50
|
-
if proxy['transport'] == ProxyTransport.
|
50
|
+
if proxy['transport'] == ProxyTransport.splithttp:
|
51
51
|
return True
|
52
52
|
return False
|
53
53
|
|
@@ -126,10 +126,10 @@ def to_link(proxy: dict) -> str | dict:
|
|
126
126
|
baseurl += "&encryption=none"
|
127
127
|
if proxy.get('fingerprint', 'none') != 'none':
|
128
128
|
baseurl += "&fp=" + proxy['fingerprint']
|
129
|
-
if proxy.get('transport') in {ProxyTransport.
|
129
|
+
if proxy.get('transport') in {ProxyTransport.splithttp}:
|
130
130
|
baseurl += "&core=xray"
|
131
131
|
if proxy['l3'] != 'quic':
|
132
|
-
if proxy.get('l3') != ProxyL3.reality and (proxy.get('transport') in {ProxyTransport.tcp, ProxyTransport.httpupgrade, ProxyTransport.
|
132
|
+
if proxy.get('l3') != ProxyL3.reality and (proxy.get('transport') in {ProxyTransport.tcp, ProxyTransport.httpupgrade, ProxyTransport.splithttp}) and proxy['proto'] in [ProxyProto.vless, ProxyProto.trojan]:
|
133
133
|
baseurl += '&headerType=http'
|
134
134
|
else:
|
135
135
|
baseurl += '&headerType=None'
|
@@ -50,11 +50,10 @@ def configs_as_json(domains: list[Domain], user: User, expire_days: int, remarks
|
|
50
50
|
unsupported_transport = {}
|
51
51
|
if g.user_agent.get('is_v2rayng'):
|
52
52
|
# TODO: ensure which protocols are not supported in v2rayng
|
53
|
-
unsupported_protos = { ProxyProto.hysteria, ProxyProto.hysteria2,
|
54
|
-
ProxyProto.tuic, ProxyProto.ssr, ProxyProto.ssh}
|
53
|
+
unsupported_protos = {ProxyProto.wireguard, ProxyProto.hysteria, ProxyProto.hysteria2,
|
54
|
+
ProxyProto.tuic, ProxyProto.ss, ProxyProto.ssr, ProxyProto.ssh}
|
55
55
|
if not hutils.flask.is_client_version(hutils.flask.ClientVersion.v2ryang, 1, 8, 18):
|
56
56
|
unsupported_transport = {ProxyTransport.httpupgrade}
|
57
|
-
unsupported_protos.update({ProxyProto.wireguard})
|
58
57
|
|
59
58
|
# multiple outbounds needs multiple whole base config not just one with multiple outbounds (at least for v2rayng)
|
60
59
|
# https://github.com/2dust/v2rayNG/pull/2827#issue-2127534078
|
@@ -136,9 +135,7 @@ def add_wireguard_settings(base: dict, proxy: dict):
|
|
136
135
|
base['settings']['mtu'] = 1380 # optional
|
137
136
|
base['settings']['peers'] = [{
|
138
137
|
'endpoint': f'{proxy["server"]}:{int(proxy["port"])}',
|
139
|
-
'publicKey': proxy["wg_server_pub"]
|
140
|
-
"preSharedKey": proxy['wg_psk']
|
141
|
-
|
138
|
+
'publicKey': proxy["wg_server_pub"]
|
142
139
|
# 'allowedIPs':'', 'preSharedKey':'', 'keepAlive':'' # optionals
|
143
140
|
}]
|
144
141
|
|
@@ -265,9 +262,9 @@ def add_stream_settings(base: dict, proxy: dict):
|
|
265
262
|
if proxy['transport'] == ProxyTransport.httpupgrade:
|
266
263
|
ss['network'] = proxy['transport']
|
267
264
|
add_httpupgrade_stream(ss, proxy)
|
268
|
-
if proxy['transport'] == ProxyTransport.
|
265
|
+
if proxy['transport'] == ProxyTransport.splithttp:
|
269
266
|
ss['network'] = proxy['transport']
|
270
|
-
|
267
|
+
add_splithttp_stream(ss, proxy)
|
271
268
|
if proxy['transport'] == 'ws':
|
272
269
|
ss['network'] = proxy['transport']
|
273
270
|
add_ws_stream(ss, proxy)
|
@@ -341,8 +338,8 @@ def add_httpupgrade_stream(ss: dict, proxy: dict):
|
|
341
338
|
}
|
342
339
|
|
343
340
|
|
344
|
-
def
|
345
|
-
ss['
|
341
|
+
def add_splithttp_stream(ss: dict, proxy: dict):
|
342
|
+
ss['splithttpSettings'] = {
|
346
343
|
'path': proxy['path'],
|
347
344
|
'host': proxy['host'],
|
348
345
|
"headers": {
|
hiddifypanel/models/config.py
CHANGED
@@ -153,10 +153,7 @@ def add_or_update_config(commit: bool = True, child_id: int | None = None, overr
|
|
153
153
|
if child_id is None:
|
154
154
|
child_id = Child.current().id
|
155
155
|
c = config['key']
|
156
|
-
|
157
|
-
ckey = ConfigEnum(c)
|
158
|
-
except:
|
159
|
-
return
|
156
|
+
ckey = ConfigEnum(c)
|
160
157
|
if c == ConfigEnum.unique_id and not override_unique_id:
|
161
158
|
return
|
162
159
|
|
@@ -239,7 +239,7 @@ class ConfigEnum(metaclass=FastEnum):
|
|
239
239
|
ws_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
|
240
240
|
grpc_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
|
241
241
|
httpupgrade_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
|
242
|
-
|
242
|
+
splithttp_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
|
243
243
|
|
244
244
|
vless_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
|
245
245
|
trojan_enable = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config)
|
@@ -262,7 +262,7 @@ class ConfigEnum(metaclass=FastEnum):
|
|
262
262
|
path_v2ray = _StrConfigDscr(ConfigCategory.hidden, ApplyMode.apply_config, hide_in_virtual_child=True) # deprecated
|
263
263
|
path_ss = _StrConfigDscr(ConfigCategory.hidden, ApplyMode.apply_config, hide_in_virtual_child=True)
|
264
264
|
|
265
|
-
|
265
|
+
path_splithttp = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
|
266
266
|
path_httpupgrade = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
|
267
267
|
path_ws = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
|
268
268
|
path_tcp = _StrConfigDscr(ConfigCategory.too_advanced, ApplyMode.apply_config, hide_in_virtual_child=True)
|
hiddifypanel/models/proxy.py
CHANGED
hiddifypanel/panel/__init__.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
#
|
4
|
-
|
5
|
-
#
|
6
|
-
|
7
|
-
#
|
8
|
-
#
|
9
|
-
|
2
|
+
from . import user
|
3
|
+
# from . import admin
|
4
|
+
from . import cli
|
5
|
+
# from .. import database
|
6
|
+
from . import common
|
7
|
+
# from . import commercial
|
8
|
+
# from .. import auth
|
9
|
+
from . import common_bp
|
@@ -143,18 +143,19 @@ class AdminstratorAdmin(AdminLTEModelView):
|
|
143
143
|
""")
|
144
144
|
|
145
145
|
def _max_active_users_formatter(view, context, model, name):
|
146
|
-
|
147
|
-
|
146
|
+
|
147
|
+
actives = [u for u in model.recursive_users_query().all() if u.is_active]
|
148
|
+
u = len(actives)
|
148
149
|
if model.mode == AdminMode.super_admin:
|
149
|
-
return f"{
|
150
|
+
return f"{u} / ∞"
|
150
151
|
t = model.max_active_users
|
151
|
-
rate = round(
|
152
|
-
|
153
|
-
|
152
|
+
rate = round(u * 100 / (t + 0.000001))
|
153
|
+
state = "danger" if u >= t else ('warning' if rate > 80 else 'success')
|
154
|
+
color = "#ff7e7e" if u >= t else ('#ffc107' if rate > 80 else '#9ee150')
|
154
155
|
return Markup(f"""
|
155
156
|
<div class="progress progress-lg position-relative" style="min-width: 100px;">
|
156
157
|
<div class="progress-bar progress-bar-striped" role="progressbar" style="width: {rate}%;background-color: {color};" aria-valuenow="{rate}" aria-valuemin="0" aria-valuemax="100"></div>
|
157
|
-
<span class='badge position-absolute' style="left:auto;right:auto;width: 100%;font-size:1em">{
|
158
|
+
<span class='badge position-absolute' style="left:auto;right:auto;width: 100%;font-size:1em">{u} {_('user.home.usage.from')} {t}</span>
|
158
159
|
|
159
160
|
</div>
|
160
161
|
""")
|