Skip to content

Commit

Permalink
refactor the code and add modules dynamicatonally for future extensions
Browse files Browse the repository at this point in the history
  • Loading branch information
hiddify-com committed Nov 15, 2024
1 parent 546c4e1 commit e369914
Show file tree
Hide file tree
Showing 13 changed files with 476 additions and 136 deletions.
162 changes: 42 additions & 120 deletions hiddifypanel/base.py
Original file line number Diff line number Diff line change
@@ -1,142 +1,62 @@
from flask import request, g
# from hiddifypanel.cache import cache
from hiddifypanel.models import *

import flask_bootstrap
import hiddifypanel
from flask_babel import Babel
from flask_session import Session


import datetime

from dotenv import dotenv_values
import os
import sys
from apiflask import APIFlask
from werkzeug.middleware.proxy_fix import ProxyFix
from loguru import logger
from hiddifypanel.panel.init_db import init_db
from hiddifypanel.hutils import hlogger
from sonora.wsgi import grpcWSGI


from dynaconf import FlaskDynaconf

def create_app(*args, cli=False, **config):

app = APIFlask(__name__, static_url_path="/<proxy_path>/static/", instance_relative_config=True, version='2.2.0', title="Hiddify API",
openapi_blueprint_url_prefix="/<proxy_path>/api", docs_ui='elements', json_errors=False, enable_openapi=not cli)
# app = Flask(__name__, static_url_path="/<proxy_path>/static/", instance_relative_config=True)
# app.asgi_app = WsgiToAsgi(app)

if not cli:

from hiddifypanel import auth
app.config["PREFERRED_URL_SCHEME"] = "https"
app.wsgi_app = ProxyFix(
app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1,
)


app.secret_key="asdsad"
app.servers = {
'name': 'current',
'url': '',
} # type: ignore
app.info = {
'description': 'Hiddify is a free and open source software. It is as it is.',
'termsOfService': 'https://hiddify.com',
'contact': {
'name': 'API Support',
'url': 'https://www.hiddify.com/support',
'email': '[email protected]'
},
'license': {
'name': 'Creative Commons Zero v1.0 Universal',
'url': 'https://github.com/hiddify/Hiddify-Manager/blob/main/LICENSE'
}
}
# setup flask server-side session
# app.config['APPLICATION_ROOT'] = './'
# app.config['SESSION_COOKIE_DOMAIN'] = '/'


app.jinja_env.line_statement_prefix = '%'
from hiddifypanel import hutils
app.jinja_env.filters['b64encode'] = hutils.encode.do_base_64
app.view_functions['admin.static'] = {} # fix bug in apiflask
flask_bootstrap.Bootstrap4(app)


for c, v in dotenv_values(os.environ.get("HIDDIFY_CFG_PATH", 'app.cfg')).items():
if v.isdecimal():
v = int(v)
else:
v = True if v.lower() == "true" else (False if v.lower() == "false" else v)

app.config[c] = v
hlogger.init_logger(app, cli)
hiddifypanel.database.init_app(app)
with app.app_context():
init_db()
hlogger.set_level(app,hconfig(ConfigEnum.log_level))

def get_locale():
# Put your logic here. Application can store locale in
# user profile, cookie, session, etc.
if "admin" in request.base_url:
g.locale = hconfig(ConfigEnum.admin_lang) or 'en'
else:
g.locale = auth.current_account.lang or hconfig(ConfigEnum.lang) or 'en'
return g.locale
app.jinja_env.globals['get_locale'] = get_locale
babel = Babel(app, locale_selector=get_locale)
if not cli:
app.config['SESSION_TYPE'] = 'redis'
from hiddifypanel.cache import redis_client
app.config['SESSION_REDIS'] = redis_client
app.config['SESSION_PERMANENT'] = True
app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=10)
app.security_schemes = { # equals to use config SECURITY_SCHEMES
'Hiddify-API-Key': {
'type': 'apiKey',
'in': 'header',
'name': 'Hiddify-API-Key',
}
}
Session(app)
app.wsgi_app = grpcWSGI(app.wsgi_app)
hiddifypanel.panel.common.init_app(app)
hiddifypanel.panel.common_bp.init_app(app)

from hiddifypanel.panel import user, commercial, admin
admin.init_app(app)
user.init_app(app)
commercial.init_app(app)
from .panel import node
node.init_app(app)

dyn=FlaskDynaconf(app,settings_files=[os.environ.get("HIDDIFY_CFG_PATH", 'app.cfg')])

if cli:
app.config['EXTENSIONS']=[
# "hiddifypanel.cache:init_app",
"hiddifypanel.database:init_app",
"hiddifypanel.panel.hlogger:init_cli",
"hiddifypanel.panel.cli:init_app",
"hiddifypanel.celery:init_app",
]
else:
app.config['EXTENSIONS']=[
# "hiddifypanel.cache:init_app",
"hiddifypanel.database:init_app",
"hiddifypanel.panel.hlogger:init_app",
"hiddifypanel.base_setup:init_app",
"hiddifypanel.panel.common:init_app",
"hiddifypanel.panel.common_bp:init_app",
"hiddifypanel.panel.admin:init_app",
"hiddifypanel.panel.user:init_app",
"hiddifypanel.panel.commercial:init_app",
"hiddifypanel.panel.node:init_app",
"hiddifypanel.celery:init_app",
]



app.config.update(config) # Override with passed config
# app.config['WTF_CSRF_CHECK_DEFAULT'] = False
# app.config['WTF_CSRF_ENABLED'] = False
# app.config['BABEL_TRANSLATION_DIRECTORIES'] = '/workspace/Hiddify-Server/hiddify-panel/src/translations.i18n'

# from flask_wtf.csrf import CSRFProtect

# csrf = CSRFProtect(app)

# @app.before_request
# def check_csrf():
# # if "/admin/user/" in request.base_url:
# # return
# # if "/admin/domain/" in request.base_url:
# # return
# # if "/admin/actions/" in request.base_url:
# # return
# # if "/api/" in request.base_url:
# # return
# csrf.protect()

hiddifypanel.panel.cli.init_app(app)

app.config.load_extensions("EXTENSIONS")
return app


Expand All @@ -145,16 +65,18 @@ def create_app_wsgi(*args, **kwargs):
# that doesn't allow **config
# to be passed to create_app
# https://github.com/pallets/flask/issues/4170
cli = ("hiddifypanel" in sys.argv[0]) or (sys.argv[1] in ["update-usage", "all-configs", "admin_links", "admin_path"])
cli = ("hiddifypanel" in sys.argv[0] ) or (sys.argv[1] in ["update-usage", "all-configs", "admin_links", "admin_path"])

app = create_app(cli=cli)
return app


# def create_cli_app(*args, **kwargs):
# # # workaround for Flask issue
# # # that doesn't allow **config
# # # to be passed to create_app
# # # https://github.com/pallets/flask/issues/4170
# # print(kwargs)
# app = create_app(*args, cli=True, **kwargs)
# return app

def create_celery_app():
# # workaround for Flask issue
# # that doesn't allow **config
# # to be passed to create_app
# # https://github.com/pallets/flask/issues/4170
# print(kwargs)
app = create_app(cli=True)
return app.extensions["celery"]
82 changes: 82 additions & 0 deletions hiddifypanel/base_setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from flask import request, g
import redis
# from hiddifypanel.cache import cache
from hiddifypanel.models import *

import flask_bootstrap
from flask_babel import Babel
from flask_session import Session

import datetime

from dotenv import dotenv_values
import os
import sys
from werkzeug.middleware.proxy_fix import ProxyFix
from loguru import logger
from sonora.wsgi import grpcWSGI



def init_app(app):
from hiddifypanel import auth
app.config["PREFERRED_URL_SCHEME"] = "https"
app.wsgi_app = ProxyFix(
app.wsgi_app, x_for=1, x_proto=1, x_host=1, x_prefix=1,
)


app.secret_key="asdsad"
app.servers = {
'name': 'current',
'url': '',
} # type: ignore
app.info = {
'description': 'Hiddify is a free and open source software. It is as it is.',
'termsOfService': 'https://hiddify.com',
'contact': {
'name': 'API Support',
'url': 'https://www.hiddify.com/support',
'email': '[email protected]'
},
'license': {
'name': 'Creative Commons Zero v1.0 Universal',
'url': 'https://github.com/hiddify/Hiddify-Manager/blob/main/LICENSE'
}
}
# setup flask server-side session
# app.config['APPLICATION_ROOT'] = './'
# app.config['SESSION_COOKIE_DOMAIN'] = '/'


app.jinja_env.line_statement_prefix = '%'
from hiddifypanel import hutils
app.jinja_env.filters['b64encode'] = hutils.encode.do_base_64
app.view_functions['admin.static'] = {} # fix bug in apiflask
flask_bootstrap.Bootstrap4(app)

def get_locale():
# Put your logic here. Application can store locale in
# user profile, cookie, session, etc.
if "admin" in request.base_url:
g.locale = hconfig(ConfigEnum.admin_lang) or 'en'
else:
g.locale = auth.current_account.lang or hconfig(ConfigEnum.lang) or 'en'
return g.locale
app.jinja_env.globals['get_locale'] = get_locale
babel = Babel(app, locale_selector=get_locale)

app.config['SESSION_TYPE'] = 'redis'

app.config['SESSION_REDIS'] = redis.from_url(os.environ['REDIS_URI_MAIN'])
app.config['SESSION_PERMANENT'] = True
app.config['PERMANENT_SESSION_LIFETIME'] = datetime.timedelta(days=10)
app.security_schemes = { # equals to use config SECURITY_SCHEMES
'Hiddify-API-Key': {
'type': 'apiKey',
'in': 'header',
'name': 'Hiddify-API-Key',
}
}
Session(app)
app.wsgi_app = grpcWSGI(app.wsgi_app)
2 changes: 1 addition & 1 deletion hiddifypanel/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from loguru import logger

redis_client = redis.from_url(os.environ["REDIS_URI_MAIN"])

# print(os.environ["REDIS_URI_MAIN"])

class CustomRedisCache(RedisCache):
def __init__(self, redis_client, prefix="rc", serializer=compact_dump, deserializer=loads, key_serializer=None, support_cluster=True, exception_handler=None):
Expand Down
45 changes: 45 additions & 0 deletions hiddifypanel/celery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from celery import Celery, Task
from celery.schedules import crontab

def init_app(app):
class FlaskTask(Task):
def __call__(self, *args: object, **kwargs: object) -> object:
with app.app_context():
return self.run(*args, **kwargs)

celery_app = Celery(app.name, task_cls=FlaskTask)

celery_app.config_from_object(dict(
broker_url=app.config['REDIS_URI_MAIN'],
result_backend=app.config['REDIS_URI_MAIN'],
# task_ignore_result=True,
))
app.extensions["celery"] = celery_app


# Calls test('hello') every 10 seconds.
from hiddifypanel.panel import usage
celery_app.add_periodic_task(60.0, usage.update_local_usage.s(), name='update usage')
# celery_app.conf.beat_schedule = {
# 'update_usage': {
# 'task': 'hiddifypanel.panel.usage.update_local_usage',
# 'schedule': 30.0,

# },
# }
from hiddifypanel.panel.cli import backup_task
celery_app.autodiscover_tasks()
# celery_app.add_periodic_task(30.0, backup_task.s(), name='backup task')
# celery_app.add_periodic_task(
# crontab(hour="*/6", minute=30),
# backup_task.delay(),
# )

celery_app.add_periodic_task(
crontab(hour="*/6", minute="0"),
backup_task.s(),
name="backup_task "
)

celery_app.set_default()
return celery_app
7 changes: 7 additions & 0 deletions hiddifypanel/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,20 @@
from sqlalchemy import Row, text, Sequence





db: SQLAlchemy = SQLAlchemy()
db.UUID = UUIDType # type: ignore


def init_app(app):
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db.init_app(app)
with app.app_context():
from hiddifypanel.panel.init_db import init_db
init_db()



def db_execute(query: str, return_val: bool = False, commit: bool = False, **params: dict):
Expand Down
16 changes: 8 additions & 8 deletions hiddifypanel/panel/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

from . import user
# from . import admin
from . import cli
# from .. import database
from . import common
# from . import commercial
# from .. import auth
from . import common_bp
# from . import user
# # from . import admin
# from . import cli
# # from .. import database
# from . import common
# # from . import commercial
# # from .. import auth
# from . import common_bp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import asyncio
import time
from flask import current_app as app, request
from flask import g
from flask.views import MethodView
Expand All @@ -16,7 +18,9 @@ class UpdateUserUsageApi(MethodView):

def get(self):
"""System: Update User Usage"""
return json.dumps(usage.update_local_usage(), indent=2)
# time.sleep(5)

return json.dumps(usage.update_local_usage_not_lock(), indent=2)


class AllConfigsApi(MethodView):
Expand Down
Loading

0 comments on commit e369914

Please sign in to comment.