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/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
10.
|
1
|
+
10.85.0b2
|
hiddifypanel/VERSION.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
import importlib.metadata
|
1
|
+
# import importlib.metadata
|
2
2
|
from datetime import datetime
|
3
3
|
|
4
|
-
__version__ =
|
5
|
-
__release_time__= datetime.strptime('
|
4
|
+
__version__ = '10.85.0b2'
|
5
|
+
__release_time__= datetime.strptime('2025-04-13T22:26:27','%Y-%m-%dT%H:%M:%S')
|
6
6
|
is_released_version=True
|
hiddifypanel/apps/asgi_app.py
CHANGED
hiddifypanel/apps/celery_app.py
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
from hiddifypanel.
|
1
|
+
from hiddifypanel.celery import init_app_no_flask
|
2
2
|
|
3
|
-
celery_app=
|
3
|
+
celery_app=init_app_no_flask()
|
hiddifypanel/apps/wsgi_app.py
CHANGED
hiddifypanel/base.py
CHANGED
@@ -8,13 +8,13 @@ import datetime
|
|
8
8
|
from dotenv import dotenv_values
|
9
9
|
import os
|
10
10
|
import sys
|
11
|
-
from apiflask import APIFlask
|
12
|
-
from loguru import logger
|
13
11
|
|
12
|
+
def create_app(*args, app_mode="web", **config):
|
13
|
+
from apiflask import APIFlask
|
14
|
+
from loguru import logger
|
14
15
|
|
15
|
-
from dynaconf import FlaskDynaconf
|
16
16
|
|
17
|
-
|
17
|
+
from dynaconf import FlaskDynaconf
|
18
18
|
|
19
19
|
app = APIFlask(__name__, static_url_path="/<proxy_path>/static/", instance_relative_config=True, version='2.2.0', title="Hiddify API",
|
20
20
|
openapi_blueprint_url_prefix="/<proxy_path>/api", docs_ui='elements', json_errors=False, enable_openapi=app_mode=="web")
|
@@ -36,7 +36,7 @@ def create_app(*args, app_mode="web", **config):
|
|
36
36
|
]
|
37
37
|
|
38
38
|
if app_mode=="celery":
|
39
|
-
extensions
|
39
|
+
extensions=["hiddifypanel.celery:init_app"]
|
40
40
|
elif app_mode=="cli":
|
41
41
|
extensions.append("hiddifypanel.panel.cli:init_app")
|
42
42
|
else:
|
hiddifypanel/celery.py
CHANGED
@@ -1,5 +1,10 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
1
3
|
from celery import Celery, Task
|
2
4
|
from celery.schedules import crontab
|
5
|
+
from dotenv import dotenv_values
|
6
|
+
from loguru import logger
|
7
|
+
|
3
8
|
|
4
9
|
def init_app(app):
|
5
10
|
class FlaskTask(Task):
|
@@ -42,4 +47,66 @@ def init_app(app):
|
|
42
47
|
)
|
43
48
|
|
44
49
|
celery_app.set_default()
|
45
|
-
return celery_app
|
50
|
+
return celery_app
|
51
|
+
|
52
|
+
|
53
|
+
|
54
|
+
def init_app_no_flask():
|
55
|
+
config={}
|
56
|
+
for c, v in dotenv_values(os.environ.get("HIDDIFY_CFG_PATH", 'app.cfg')).items():
|
57
|
+
if v.isdecimal():
|
58
|
+
v = int(v)
|
59
|
+
else:
|
60
|
+
v = True if v.lower() == "true" else (False if v.lower() == "false" else v)
|
61
|
+
config[c] = v
|
62
|
+
import hiddifypanel.database
|
63
|
+
hiddifypanel.database.init_no_flask()
|
64
|
+
|
65
|
+
from hiddifypanel.panel import init_db
|
66
|
+
if not init_db.is_db_latest():
|
67
|
+
logger.error("The database upgrade is required before proceeding. Terminating the process.")
|
68
|
+
import time
|
69
|
+
time.sleep(20)
|
70
|
+
sys.exit(1)
|
71
|
+
|
72
|
+
celery_app = Celery()
|
73
|
+
|
74
|
+
celery_app.config_from_object(dict(
|
75
|
+
broker_url=config['REDIS_URI_MAIN'],
|
76
|
+
result_backend=config['REDIS_URI_MAIN'],
|
77
|
+
# task_ignore_result=True,
|
78
|
+
))
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
# Calls test('hello') every 10 seconds.
|
83
|
+
from hiddifypanel.panel import usage
|
84
|
+
celery_app.add_periodic_task(60.0, usage.update_local_usage.s(), name='update usage')
|
85
|
+
# celery_app.conf.beat_schedule = {
|
86
|
+
# 'update_usage': {
|
87
|
+
# 'task': 'hiddifypanel.panel.usage.update_local_usage',
|
88
|
+
# 'schedule': 30.0,
|
89
|
+
|
90
|
+
# },
|
91
|
+
# }
|
92
|
+
from hiddifypanel.panel.cli import backup_task
|
93
|
+
celery_app.autodiscover_tasks()
|
94
|
+
# celery_app.add_periodic_task(30.0, backup_task.s(), name='backup task')
|
95
|
+
# celery_app.add_periodic_task(
|
96
|
+
# crontab(hour="*/6", minute=30),
|
97
|
+
# backup_task.delay(),
|
98
|
+
# )
|
99
|
+
|
100
|
+
celery_app.add_periodic_task(
|
101
|
+
crontab(hour="*/6", minute="0"),
|
102
|
+
# crontab(hour="*", minute="*"),
|
103
|
+
backup_task.s(),
|
104
|
+
name="backup_task "
|
105
|
+
)
|
106
|
+
|
107
|
+
celery_app.set_default()
|
108
|
+
|
109
|
+
return celery_app
|
110
|
+
|
111
|
+
|
112
|
+
|
hiddifypanel/database.py
CHANGED
@@ -1,19 +1,75 @@
|
|
1
1
|
from typing import Optional
|
2
|
-
from
|
3
|
-
from
|
2
|
+
from sqlalchemy.orm import sessionmaker
|
3
|
+
from sqlalchemy.orm import as_declarative, declared_attr,relationship
|
4
|
+
import sqlalchemy.orm as sa_orm
|
5
|
+
|
6
|
+
# from sqlalchemy_utils import UUIDType
|
4
7
|
import re
|
5
8
|
import os
|
6
|
-
from sqlalchemy import Row, text, Sequence
|
9
|
+
from sqlalchemy import Row, create_engine, text, Sequence
|
10
|
+
import sqlalchemy as sa
|
11
|
+
|
12
|
+
|
13
|
+
# class SQLAlchemy:
|
14
|
+
|
15
|
+
# def __init__(self):
|
16
|
+
# self.engine = create_engine(os.environ.get("SQLALCHEMY_DATABASE_URI"))
|
17
|
+
# self.session_maker = sessionmaker(bind=self.engine)
|
18
|
+
# self.session=self.session_maker()
|
19
|
+
# @as_declarative()
|
20
|
+
# class Base:
|
21
|
+
# @declared_attr
|
22
|
+
# def __tablename__(cls):
|
23
|
+
# return cls.__name__.lower()
|
24
|
+
|
25
|
+
# @classmethod
|
26
|
+
# @property
|
27
|
+
# def query(cls):
|
28
|
+
# return self.session.query(cls)
|
29
|
+
|
30
|
+
|
31
|
+
# self.Query=sa_orm.Query
|
32
|
+
# self.Model=Base
|
33
|
+
# self.Table=sa.Table
|
34
|
+
# self.Column=sa.Column
|
35
|
+
# self.Integer=sa.Integer
|
36
|
+
# self.ForeignKey=sa.ForeignKey
|
7
37
|
|
38
|
+
# def _set_rel_query(self, kwargs) -> None:
|
39
|
+
# """Apply the extension's :attr:`Query` class as the default for relationships
|
40
|
+
# and backrefs.
|
8
41
|
|
42
|
+
# :meta private:
|
43
|
+
# """
|
44
|
+
# kwargs.setdefault("query_class", self.Query)
|
9
45
|
|
46
|
+
# if "backref" in kwargs:
|
47
|
+
# backref = kwargs["backref"]
|
10
48
|
|
49
|
+
# if isinstance(backref, str):
|
50
|
+
# backref = (backref, {})
|
11
51
|
|
12
|
-
|
13
|
-
db.UUID = UUIDType # type: ignore
|
52
|
+
# backref[1].setdefault("query_class", self.Query)
|
14
53
|
|
54
|
+
|
55
|
+
# def relationship(
|
56
|
+
# self, *args, **kwargs
|
57
|
+
# ) :
|
58
|
+
|
59
|
+
# self._set_rel_query(kwargs)
|
60
|
+
# return sa_orm.relationship(*args, **kwargs)
|
61
|
+
from flask_sqlalchemy import SQLAlchemy
|
62
|
+
|
63
|
+
|
64
|
+
db = SQLAlchemy()
|
65
|
+
# db.UUID = UUIDType # type: ignore
|
66
|
+
|
67
|
+
def init_no_flask():
|
68
|
+
engine = create_engine(os.environ.get("SQLALCHEMY_DATABASE_URI"))
|
69
|
+
db.session = sessionmaker(bind=engine)()
|
15
70
|
|
16
71
|
def init_app(app):
|
72
|
+
|
17
73
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
|
18
74
|
db.init_app(app)
|
19
75
|
with app.app_context():
|
@@ -33,3 +89,4 @@ def db_execute(query: str, return_val: bool = False, commit: bool = False, **par
|
|
33
89
|
# res = connection.execute(text(query), params)
|
34
90
|
# connection.commit()s
|
35
91
|
# return res
|
92
|
+
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import os
|
1
2
|
import xtlsapi
|
2
3
|
from hiddifypanel.models import *
|
3
4
|
from .abstract_driver import DriverABS
|
@@ -15,7 +16,7 @@ class SingboxApi(DriverABS):
|
|
15
16
|
return xtlsapi.SingboxClient('127.0.0.1', 10086)
|
16
17
|
|
17
18
|
def get_enabled_users(self):
|
18
|
-
config_dir =
|
19
|
+
config_dir = os.environ['HIDDIFY_CONFIG_PATH']
|
19
20
|
with open(f"{config_dir}/singbox/configs/01_api.json") as f:
|
20
21
|
json_data = json.load(f)
|
21
22
|
return {u.split("@")[0]: 1 for u in json_data['experimental']['v2ray_api']['stats']['users']}
|
@@ -16,7 +16,10 @@ def enabled_drivers():
|
|
16
16
|
|
17
17
|
def get_users_usage(reset=True):
|
18
18
|
res = {}
|
19
|
-
|
19
|
+
from hiddifypanel.database import db
|
20
|
+
|
21
|
+
users = db.session.query(User).all()
|
22
|
+
# users = list(User.query.all())
|
20
23
|
res = defaultdict(lambda: {'usage': 0, 'devices': ''})
|
21
24
|
for driver in enabled_drivers():
|
22
25
|
try:
|
hiddifypanel/hutils/__init__.py
CHANGED
@@ -1,14 +1,46 @@
|
|
1
|
-
from
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
1
|
+
from typing import TYPE_CHECKING
|
2
|
+
import importlib
|
3
|
+
|
4
|
+
class LazyLoader:
|
5
|
+
def __init__(self, module_name: str,package=None):
|
6
|
+
self.module_name = module_name
|
7
|
+
self._module = None
|
8
|
+
self.package=package
|
9
|
+
|
10
|
+
|
11
|
+
def __getattr__(self, item):
|
12
|
+
if self._module is None:
|
13
|
+
self._module = importlib.import_module(self.module_name,self.package)
|
14
|
+
return getattr(self._module, item)
|
15
|
+
|
16
|
+
if TYPE_CHECKING:
|
17
|
+
from . import system
|
18
|
+
from . import importer
|
19
|
+
from . import github_issue
|
20
|
+
from . import flask
|
21
|
+
from . import convert
|
22
|
+
from . import random
|
23
|
+
from . import encode
|
24
|
+
from . import auth
|
25
|
+
from . import model
|
26
|
+
from . import crypto
|
27
|
+
from . import proxy
|
28
|
+
from . import node
|
29
|
+
from . import utils
|
30
|
+
from . import network
|
31
|
+
else:
|
32
|
+
# Define modules for lazy loading
|
33
|
+
network = LazyLoader(".network",__name__)
|
34
|
+
system = LazyLoader(".system",__name__)
|
35
|
+
importer = LazyLoader(".importer",__name__)
|
36
|
+
github_issue = LazyLoader(".github_issue",__name__)
|
37
|
+
flask = LazyLoader(".flask",__name__)
|
38
|
+
convert = LazyLoader(".convert",__name__)
|
39
|
+
random = LazyLoader(".random",__name__)
|
40
|
+
encode = LazyLoader(".encode",__name__)
|
41
|
+
auth = LazyLoader(".auth",__name__)
|
42
|
+
utils = LazyLoader(".utils",__name__)
|
43
|
+
model = LazyLoader(".model",__name__)
|
44
|
+
crypto = LazyLoader(".crypto",__name__)
|
45
|
+
proxy = LazyLoader(".proxy",__name__)
|
46
|
+
node = LazyLoader(".node",__name__)
|
hiddifypanel/hutils/crypto.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
import subprocess
|
3
|
+
import sys
|
3
4
|
from cryptography.hazmat.primitives import serialization
|
4
5
|
from cryptography.hazmat.primitives.asymmetric import x25519, ed25519
|
5
6
|
|
@@ -62,7 +63,7 @@ def generate_ssh_host_keys():
|
|
62
63
|
"ssh-keygen", "-t", key_type,
|
63
64
|
"-f", key_file,
|
64
65
|
"-N", ""
|
65
|
-
], check=True)
|
66
|
+
], check=True,stdout=sys.stderr)
|
66
67
|
|
67
68
|
keys_dict[key_type]={}
|
68
69
|
with open(key_file, "r") as f:
|
hiddifypanel/hutils/encode.py
CHANGED
hiddifypanel/hutils/flask.py
CHANGED
@@ -150,7 +150,7 @@ def is_admin_panel_call(deprecated_format: bool = False) -> bool:
|
|
150
150
|
if deprecated_format:
|
151
151
|
if f'{request.path}'.startswith(f'/{hconfig(ConfigEnum.proxy_path)}/') and "admin" in f'{request.path}':
|
152
152
|
return True
|
153
|
-
elif f'{request.path}'.startswith(f'/{hconfig(ConfigEnum.proxy_path_admin)}/
|
153
|
+
elif f'{request.path}'.startswith(f'/{hconfig(ConfigEnum.proxy_path_admin)}/'):
|
154
154
|
return True
|
155
155
|
return False
|
156
156
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
from flask_babel import gettext as _
|
2
2
|
from typing import List, Union
|
3
3
|
from flask import request
|
4
|
+
from loguru import logger
|
4
5
|
import maxminddb
|
5
6
|
import random
|
6
7
|
import os
|
@@ -37,13 +38,15 @@ apt.ircf.space APT
|
|
37
38
|
"""
|
38
39
|
|
39
40
|
try:
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
|
42
|
+
IPASN = maxminddb.open_database('GeoLite2-ASN.mmdb')
|
43
|
+
IPCOUNTRY = maxminddb.open_database('GeoLite2-Country.mmdb')
|
44
|
+
# __ipcity = maxminddb.open_database('GeoLite2-City.mmdb')
|
45
|
+
except BaseException as e:
|
46
|
+
logger.error("Error can not load maxminddb")
|
45
47
|
IPASN = {}
|
46
48
|
IPCOUNTRY = {}
|
49
|
+
# __ipcity = {}
|
47
50
|
|
48
51
|
__asn_map = {
|
49
52
|
'58224': 'MKH',
|
@@ -101,13 +104,13 @@ def get_country(user_ip: str = '') -> Union[dict, str]:
|
|
101
104
|
return 'unknown'
|
102
105
|
|
103
106
|
|
104
|
-
def get_city(user_ip: str = '') -> Union[dict, str]:
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
# def get_city(user_ip: str = '') -> Union[dict, str]:
|
108
|
+
# try:
|
109
|
+
# user_ip = user_ip or get_real_user_ip()
|
110
|
+
# res = __ipcity.get(user_ip)
|
111
|
+
# return {'city': res.get('city').get('name'), 'latitude': res.get('latitude'), 'longitude': res.get('longitude'), 'accuracy_radius': res.get('accuracy_radius')}
|
112
|
+
# except BaseException:
|
113
|
+
# return 'unknown'
|
111
114
|
|
112
115
|
|
113
116
|
def get_real_user_ip_debug(user_ip: str = '') -> str:
|
@@ -1,10 +1,15 @@
|
|
1
|
-
|
1
|
+
|
2
|
+
from typing import TYPE_CHECKING
|
2
3
|
from hiddifypanel.models import hconfig, ConfigEnum
|
4
|
+
if TYPE_CHECKING:
|
5
|
+
import cloudflare
|
3
6
|
|
4
|
-
__cf: cloudflare.Cloudflare # type: ignore
|
7
|
+
__cf: "cloudflare.Cloudflare" # type: ignore
|
5
8
|
|
6
9
|
|
7
10
|
def __prepare_cf_api_client() -> bool:
|
11
|
+
import cloudflare
|
12
|
+
|
8
13
|
'''Prepares cloudflare client if it's not already'''
|
9
14
|
global __cf
|
10
15
|
if __cf and isinstance(__cf, cloudflare.Cloudflare):
|
@@ -271,6 +271,7 @@ def add_stream_settings(base: dict, proxy: dict):
|
|
271
271
|
add_httpupgrade_stream(ss, proxy)
|
272
272
|
if proxy['transport'] == ProxyTransport.xhttp:
|
273
273
|
ss['network'] = proxy['transport']
|
274
|
+
ss['transport'] = "xhttp"
|
274
275
|
add_xhttp_stream(ss, proxy)
|
275
276
|
if proxy['transport'] == 'ws':
|
276
277
|
ss['network'] = proxy['transport']
|
hiddifypanel/hutils/system.py
CHANGED
@@ -19,7 +19,7 @@ def get_folder_size(folder_path: str) -> int:
|
|
19
19
|
|
20
20
|
def top_processes() -> dict:
|
21
21
|
# Get the process information
|
22
|
-
processes = [p for p in psutil.process_iter(['name', '
|
22
|
+
processes = [p for p in psutil.process_iter(['pid', 'name', 'username', 'cpu_percent', 'memory_info']) if p.info['name'] != '']
|
23
23
|
num_cores = psutil.cpu_count()
|
24
24
|
# Calculate memory usage, RAM usage, and CPU usage for each process
|
25
25
|
memory_usage = {}
|
@@ -27,20 +27,21 @@ def top_processes() -> dict:
|
|
27
27
|
cpu_usage = {}
|
28
28
|
for p in processes:
|
29
29
|
name = p.info['name']
|
30
|
-
if "
|
30
|
+
if p.info['username']=="hiddify-panel":
|
31
31
|
name = "Hiddify"
|
32
|
-
mem_info = p.info['memory_full_info']
|
33
|
-
if mem_info is None:
|
34
|
-
|
35
|
-
mem_usage = mem_info.uss
|
32
|
+
# mem_info = p.info['memory_full_info']
|
33
|
+
# if mem_info is None:
|
34
|
+
# continue
|
35
|
+
# mem_usage = mem_info.uss
|
36
|
+
mem_usage = p.info['memory_info'].rss
|
36
37
|
cpu_percent = p.info['cpu_percent'] / num_cores
|
37
38
|
if name in memory_usage:
|
38
39
|
memory_usage[name] += mem_usage / (1024 ** 3)
|
39
|
-
ram_usage[name] +=
|
40
|
+
ram_usage[name] += mem_usage / (1024 ** 3)
|
40
41
|
cpu_usage[name] += cpu_percent
|
41
42
|
else:
|
42
43
|
memory_usage[name] = mem_usage / (1024 ** 3)
|
43
|
-
ram_usage[name] =
|
44
|
+
ram_usage[name] = mem_usage / (1024 ** 3)
|
44
45
|
cpu_usage[name] = cpu_percent
|
45
46
|
|
46
47
|
while len(cpu_usage) < 5:
|
hiddifypanel/hutils/utils.py
CHANGED
hiddifypanel/models/admin.py
CHANGED
@@ -4,13 +4,13 @@ from flask import g
|
|
4
4
|
from hiddifypanel.models.usage import DailyUsage
|
5
5
|
from sqlalchemy import event, Column, Integer, Enum, Boolean, ForeignKey
|
6
6
|
from strenum import StrEnum
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
|
8
|
+
|
9
|
+
|
10
10
|
from hiddifypanel.database import db, db_execute
|
11
11
|
from hiddifypanel.models.role import Role
|
12
12
|
from hiddifypanel.models.base_account import BaseAccount
|
13
|
-
|
13
|
+
|
14
14
|
|
15
15
|
|
16
16
|
class AdminMode(StrEnum):
|
@@ -25,7 +25,7 @@ class AdminMode(StrEnum):
|
|
25
25
|
agent = auto()
|
26
26
|
|
27
27
|
|
28
|
-
class AdminUser(BaseAccount
|
28
|
+
class AdminUser(BaseAccount):
|
29
29
|
"""
|
30
30
|
This is a model class for a user in a database that includes columns for their ID, UUID, name, online status,
|
31
31
|
account expiration date, usage limit, package days, mode, start date, current usage, last reset time, and comment.
|
@@ -150,6 +150,8 @@ class AdminUser(BaseAccount, SerializerMixin):
|
|
150
150
|
def remove(self):
|
151
151
|
if self.id == 1 or self.id == g.account.id:
|
152
152
|
# raise ValidationError(_("Owner can not be deleted!"))
|
153
|
+
from flask_babel import gettext as __
|
154
|
+
from apiflask import abort
|
153
155
|
abort(422, __("Owner can not be deleted!"))
|
154
156
|
users = self.recursive_users_query().all()
|
155
157
|
for u in users:
|
@@ -6,10 +6,10 @@ from sqlalchemy import Column, String, BigInteger, Enum
|
|
6
6
|
from flask_login import UserMixin as FlaskLoginUserMixin
|
7
7
|
from hiddifypanel.models import Lang
|
8
8
|
from hiddifypanel.database import db
|
9
|
-
from sqlalchemy_serializer import SerializerMixin
|
10
9
|
|
11
10
|
|
12
|
-
|
11
|
+
|
12
|
+
class BaseAccount(db.Model, FlaskLoginUserMixin): # type: ignore
|
13
13
|
__abstract__ = True
|
14
14
|
uuid = Column(String(36), default=lambda: str(uuid.uuid4()), nullable=False, unique=True, index=True)
|
15
15
|
name = Column(String(512), nullable=False, default='')
|
@@ -48,7 +48,7 @@ class BaseAccount(db.Model, SerializerMixin, FlaskLoginUserMixin): # type: igno
|
|
48
48
|
@classmethod
|
49
49
|
def by_id(cls, id: int):
|
50
50
|
# return cls.query.filter(cls.id == id).first()
|
51
|
-
return
|
51
|
+
return db.session.query(cls).get(id)
|
52
52
|
|
53
53
|
@classmethod
|
54
54
|
def by_uuid(cls, uuid: str, create: bool = False):
|
hiddifypanel/models/child.py
CHANGED
@@ -8,7 +8,7 @@ from flask import g, has_app_context
|
|
8
8
|
|
9
9
|
|
10
10
|
from hiddifypanel.database import db, db_execute
|
11
|
-
|
11
|
+
|
12
12
|
|
13
13
|
|
14
14
|
class ChildMode(StrEnum):
|
@@ -19,7 +19,7 @@ class ChildMode(StrEnum):
|
|
19
19
|
# the child model is node
|
20
20
|
|
21
21
|
|
22
|
-
class Child(db.Model
|
22
|
+
class Child(db.Model): # type: ignore
|
23
23
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
24
24
|
name = Column(String(200), nullable=False, unique=False)
|
25
25
|
mode = Column(Enum(ChildMode), nullable=False, default=ChildMode.virtual)
|
@@ -61,11 +61,11 @@ class Child(db.Model, SerializerMixin): # type: ignore
|
|
61
61
|
|
62
62
|
@classmethod
|
63
63
|
def by_id(cls, id: int) -> 'Child':
|
64
|
-
return
|
64
|
+
return db.session.query(Child).filter(Child.id == id).first()
|
65
65
|
|
66
66
|
@classmethod
|
67
67
|
def by_unique_id(cls, unique_id: str) -> 'Child':
|
68
|
-
return
|
68
|
+
return db.session.query(Child).filter(Child.unique_id == unique_id).first()
|
69
69
|
|
70
70
|
@classmethod
|
71
71
|
def current(cls) -> "Child":
|
hiddifypanel/models/config.py
CHANGED
@@ -8,11 +8,11 @@ from hiddifypanel.cache import cache
|
|
8
8
|
from hiddifypanel.models.child import Child, ChildMode
|
9
9
|
from sqlalchemy import Column, String, Boolean, Enum, ForeignKey, Integer
|
10
10
|
from strenum import StrEnum
|
11
|
-
|
11
|
+
|
12
12
|
from loguru import logger
|
13
13
|
|
14
14
|
|
15
|
-
class BoolConfig(db.Model
|
15
|
+
class BoolConfig(db.Model):
|
16
16
|
child_id = Column(Integer, ForeignKey('child.id'), primary_key=True, default=0)
|
17
17
|
# category = db.Column(db.String(128), primary_key=True)
|
18
18
|
key = Column(Enum(ConfigEnum), primary_key=True)
|
@@ -35,7 +35,7 @@ class BoolConfig(db.Model, SerializerMixin):
|
|
35
35
|
return HConfigSchema().load(conf_dict)
|
36
36
|
|
37
37
|
|
38
|
-
class StrConfig(db.Model
|
38
|
+
class StrConfig(db.Model):
|
39
39
|
child_id = Column(Integer, ForeignKey('child.id'), primary_key=True, default=0)
|
40
40
|
# category = db.Column(db.String(128), primary_key=True)
|
41
41
|
key = Column(Enum(ConfigEnum), primary_key=True, default=ConfigEnum.admin_secret)
|
@@ -66,13 +66,13 @@ def hconfig(key: ConfigEnum, child_id: Optional[int] = None): # -> str | int |
|
|
66
66
|
value = None
|
67
67
|
try:
|
68
68
|
if key.type == bool:
|
69
|
-
bool_conf =
|
69
|
+
bool_conf = db.session.query(BoolConfig).filter(BoolConfig.key == key, BoolConfig.child_id == child_id).first()
|
70
70
|
if bool_conf:
|
71
71
|
value = bool_conf.value
|
72
72
|
else:
|
73
73
|
logger.warning(f'bool {key} not found ')
|
74
74
|
else:
|
75
|
-
str_conf =
|
75
|
+
str_conf = db.session.query(StrConfig).filter(StrConfig.key == key, StrConfig.child_id == child_id).first()
|
76
76
|
if str_conf:
|
77
77
|
value = str_conf.value
|
78
78
|
else:
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from enum import auto, Enum
|
2
|
+
import os
|
2
3
|
from typing import Union
|
3
4
|
|
4
5
|
from strenum import StrEnum
|
@@ -17,6 +18,7 @@ class Lang(HEnum):
|
|
17
18
|
ru = auto()
|
18
19
|
pt = auto()
|
19
20
|
zh = auto()
|
21
|
+
my = auto()
|
20
22
|
|
21
23
|
|
22
24
|
class PanelMode(HEnum):
|
@@ -193,7 +195,7 @@ class ConfigEnum(metaclass=FastEnum):
|
|
193
195
|
http_proxy_enable = _BoolConfigDscr(ConfigCategory.http)
|
194
196
|
block_iran_sites = _BoolConfigDscr(ConfigCategory.proxies, ApplyMode.apply_config, hide_in_virtual_child=True)
|
195
197
|
allow_invalid_sni = _BoolConfigDscr(ConfigCategory.tls, ApplyMode.apply_config, hide_in_virtual_child=True)
|
196
|
-
auto_update = _BoolConfigDscr(ConfigCategory.general, ApplyMode.apply_config, True, hide_in_virtual_child=True)
|
198
|
+
auto_update = _BoolConfigDscr(ConfigCategory.hidden if os.environ.get('HIDDIFY_DISABLE_UPDATE',"").lower() in {'1',"true"} else ConfigCategory.general, ApplyMode.apply_config, True, hide_in_virtual_child=True)
|
197
199
|
speed_test = _BoolConfigDscr(ConfigCategory.general, ApplyMode.reinstall, hide_in_virtual_child=True)
|
198
200
|
only_ipv4 = _BoolConfigDscr(ConfigCategory.general, ApplyMode.apply_config, hide_in_virtual_child=True)
|
199
201
|
|