diff --git a/app/__init__.py b/app/__init__.py index 34e6215..af4548b 100755 --- a/app/__init__.py +++ b/app/__init__.py @@ -2,12 +2,12 @@ import logging import uvicorn -import config +from app.config import env __version__ = "0.1.0" logger = logging.getLogger(__name__) -logger.setLevel(logging.DEBUG if config.DEBUG else logging.INFO) +logger.setLevel(logging.DEBUG if env.DEBUG else logging.INFO) handler = logging.StreamHandler() formatter = uvicorn.logging.ColourizedFormatter( "{levelprefix:<8} @{name}: {message}", style="{", use_colors=True diff --git a/app/config/__init__.py b/app/config/__init__.py new file mode 100644 index 0000000..b8d3d17 --- /dev/null +++ b/app/config/__init__.py @@ -0,0 +1,2 @@ +from .db import * +from .env import * diff --git a/app/config/db.py b/app/config/db.py new file mode 100644 index 0000000..126fac5 --- /dev/null +++ b/app/config/db.py @@ -0,0 +1,9 @@ +from functools import lru_cache + +from app.db import get_jwt_secret_key, GetDB + + +@lru_cache(maxsize=None) +def get_secret_key(): + with GetDB() as db: + return get_jwt_secret_key(db) diff --git a/config.py b/app/config/env.py similarity index 90% rename from config.py rename to app/config/env.py index 305fc1b..833fb6a 100755 --- a/config.py +++ b/app/config/env.py @@ -26,7 +26,9 @@ VITE_BASE_API = ( else config("VITE_BASE_API", default="/api/") ) -SUBSCRIPTION_URL_PREFIX = config("SUBSCRIPTION_URL_PREFIX", default="").strip("/") +SUBSCRIPTION_URL_PREFIX = config("SUBSCRIPTION_URL_PREFIX", default="").strip( + "/" +) TELEGRAM_API_TOKEN = config("TELEGRAM_API_TOKEN", default="") TELEGRAM_ADMIN_ID = config( @@ -37,7 +39,9 @@ TELEGRAM_ADMIN_ID = config( ], ) TELEGRAM_PROXY_URL = config("TELEGRAM_PROXY_URL", default="") -TELEGRAM_LOGGER_CHANNEL_ID = config("TELEGRAM_LOGGER_CHANNEL_ID", cast=int, default=0) +TELEGRAM_LOGGER_CHANNEL_ID = config( + "TELEGRAM_LOGGER_CHANNEL_ID", cast=int, default=0 +) JWT_ACCESS_TOKEN_EXPIRE_MINUTES = config( "JWT_ACCESS_TOKEN_EXPIRE_MINUTES", cast=int, default=1440 @@ -50,9 +54,13 @@ SUBSCRIPTION_PAGE_TEMPLATE = config( ) HOME_PAGE_TEMPLATE = config("HOME_PAGE_TEMPLATE", default="home/index.html") -SINGBOX_SUBSCRIPTION_TEMPLATE = config("SINGBOX_SUBSCRIPTION_TEMPLATE", default=None) +SINGBOX_SUBSCRIPTION_TEMPLATE = config( + "SINGBOX_SUBSCRIPTION_TEMPLATE", default=None +) XRAY_SUBSCRIPTION_TEMPLATE = config("XRAY_SUBSCRIPTION_TEMPLATE", default=None) -CLASH_SUBSCRIPTION_TEMPLATE = config("CLASH_SUBSCRIPTION_TEMPLATE", default=None) +CLASH_SUBSCRIPTION_TEMPLATE = config( + "CLASH_SUBSCRIPTION_TEMPLATE", default=None +) WEBHOOK_ADDRESS = config("WEBHOOK_ADDRESS", default=None) WEBHOOK_SECRET = config("WEBHOOK_SECRET", default=None) diff --git a/app/db/base.py b/app/db/base.py index fe6b922..ca9c952 100644 --- a/app/db/base.py +++ b/app/db/base.py @@ -1,8 +1,9 @@ -from config import SQLALCHEMY_DATABASE_URL from sqlalchemy import create_engine from sqlalchemy.orm import declarative_base from sqlalchemy.orm import sessionmaker +from app.config.env import SQLALCHEMY_DATABASE_URL + IS_SQLITE = SQLALCHEMY_DATABASE_URL.startswith("sqlite") if IS_SQLITE: diff --git a/app/db/crud.py b/app/db/crud.py index 52610c1..c55200a 100644 --- a/app/db/crud.py +++ b/app/db/crud.py @@ -7,6 +7,7 @@ from typing import List, Optional, Tuple, Union from sqlalchemy import and_, delete, update, select from sqlalchemy.orm import Session +from app.config.env import NOTIFY_DAYS_LEFT, NOTIFY_REACHED_USAGE_PERCENT from app.db.models import ( JWT, TLS, @@ -42,7 +43,6 @@ from app.utils.helpers import ( calculate_expiration_days, calculate_usage_percent, ) -from config import NOTIFY_DAYS_LEFT, NOTIFY_REACHED_USAGE_PERCENT def add_default_hosts(db: Session, inbounds: List[Inbound]): diff --git a/app/db/migrations/env.py b/app/db/migrations/env.py index 4ee6e67..16be362 100644 --- a/app/db/migrations/env.py +++ b/app/db/migrations/env.py @@ -1,12 +1,11 @@ from logging.config import fileConfig +from alembic import context from sqlalchemy import engine_from_config from sqlalchemy import pool -from alembic import context - +from app.config.env import SQLALCHEMY_DATABASE_URL from app.db.base import Base -from config import SQLALCHEMY_DATABASE_URL # this is the Alembic Config object, which provides # access to the values within the .ini file in use. diff --git a/app/marzneshin.py b/app/marzneshin.py index 9fc5937..667b949 100644 --- a/app/marzneshin.py +++ b/app/marzneshin.py @@ -13,9 +13,7 @@ from fastapi_pagination import add_pagination from starlette.staticfiles import StaticFiles from uvicorn import Config, Server -import config -from app.templates import render_template -from config import ( +from app.config.env import ( DEBUG, DOCS, HOME_PAGE_TEMPLATE, @@ -25,8 +23,9 @@ from config import ( UVICORN_SSL_KEYFILE, UVICORN_UDS, DASHBOARD_PATH, + WEBHOOK_ADDRESS, ) - +from app.templates import render_template from . import __version__, telegram from .routes import api_router from .tasks import ( @@ -80,7 +79,7 @@ scheduler.add_job( max_instances=1, ) -if config.WEBHOOK_ADDRESS: +if WEBHOOK_ADDRESS: scheduler.add_job( send_notifications, "interval", seconds=30, replace_existing=True ) diff --git a/app/models/user.py b/app/models/user.py index 9046035..6cf1ddd 100644 --- a/app/models/user.py +++ b/app/models/user.py @@ -13,7 +13,7 @@ from pydantic import ( model_validator, ) -from config import SUBSCRIPTION_URL_PREFIX +from app.config.env import SUBSCRIPTION_URL_PREFIX USERNAME_REGEXP = r"^\w{3,32}$" diff --git a/app/routes/subscription.py b/app/routes/subscription.py index bbf3365..fbcffc4 100644 --- a/app/routes/subscription.py +++ b/app/routes/subscription.py @@ -5,6 +5,9 @@ from fastapi import APIRouter from fastapi import Header, HTTPException, Path, Request, Response from fastapi.responses import HTMLResponse +from app.config.env import ( + SUBSCRIPTION_PAGE_TEMPLATE, +) from app.db import crud from app.db.models import Settings from app.dependencies import DBDep, SubUserDep, StartDateDep, EndDateDep @@ -12,9 +15,6 @@ from app.models.settings import SubscriptionSettings from app.models.user import UserResponse from app.templates import render_template from app.utils.share import encode_title, generate_subscription -from config import ( - SUBSCRIPTION_PAGE_TEMPLATE, -) router = APIRouter(prefix="/sub", tags=["Subscription"]) diff --git a/app/tasks/review_users.py b/app/tasks/review_users.py index 50549f8..643e0de 100644 --- a/app/tasks/review_users.py +++ b/app/tasks/review_users.py @@ -6,6 +6,11 @@ from typing import TYPE_CHECKING from sqlalchemy.orm import Session from app import marznode +from app.config.env import ( + NOTIFY_DAYS_LEFT, + NOTIFY_REACHED_USAGE_PERCENT, + WEBHOOK_ADDRESS, +) from app.db import ( GetDB, get_notification_reminder, @@ -19,11 +24,6 @@ from app.utils.helpers import ( calculate_expiration_days, calculate_usage_percent, ) -from config import ( - NOTIFY_DAYS_LEFT, - NOTIFY_REACHED_USAGE_PERCENT, - WEBHOOK_ADDRESS, -) if TYPE_CHECKING: from app.db.models import User diff --git a/app/tasks/send_notifications.py b/app/tasks/send_notifications.py index f9aaac7..9497f18 100644 --- a/app/tasks/send_notifications.py +++ b/app/tasks/send_notifications.py @@ -7,10 +7,10 @@ import aiohttp from fastapi.encoders import jsonable_encoder from requests import Session -import config +from app import config +from app.db import GetDB from app.db.models import NotificationReminder from app.utils.notification import queue -from app.db import GetDB logger = logging.getLogger(__name__) diff --git a/app/telegram/__init__.py b/app/telegram/__init__.py index 5746191..9609bdc 100644 --- a/app/telegram/__init__.py +++ b/app/telegram/__init__.py @@ -1,7 +1,7 @@ from telebot import asyncio_helper from telebot.async_telebot import AsyncTeleBot -from config import TELEGRAM_API_TOKEN, TELEGRAM_PROXY_URL +from app.config.env import TELEGRAM_API_TOKEN, TELEGRAM_PROXY_URL from app.telegram.report import ( report, report_new_user, diff --git a/app/telegram/report.py b/app/telegram/report.py index 70eaa61..f76e15f 100644 --- a/app/telegram/report.py +++ b/app/telegram/report.py @@ -5,8 +5,8 @@ from telebot.apihelper import ApiTelegramException from telebot.formatting import escape_html from app import telegram +from app.config.env import TELEGRAM_ADMIN_ID, TELEGRAM_LOGGER_CHANNEL_ID from app.utils.system import readable_size -from config import TELEGRAM_ADMIN_ID, TELEGRAM_LOGGER_CHANNEL_ID logger = logging.getLogger(__name__) diff --git a/app/templates/__init__.py b/app/templates/__init__.py index 6e897c6..499ce7c 100644 --- a/app/templates/__init__.py +++ b/app/templates/__init__.py @@ -3,7 +3,7 @@ from typing import Union import jinja2 -from config import CUSTOM_TEMPLATES_DIRECTORY +from app.config.env import CUSTOM_TEMPLATES_DIRECTORY from .filters import CUSTOM_FILTERS template_directories = ["app/templates"] diff --git a/app/utils/jwt.py b/app/utils/jwt.py index 508625a..4055b0f 100644 --- a/app/utils/jwt.py +++ b/app/utils/jwt.py @@ -1,17 +1,10 @@ from datetime import datetime, timedelta -from functools import lru_cache from typing import Union from jose import JWTError, jwt -from app.db import GetDB, get_jwt_secret_key -from config import JWT_ACCESS_TOKEN_EXPIRE_MINUTES - - -@lru_cache(maxsize=None) -def get_secret_key(): - with GetDB() as db: - return get_jwt_secret_key(db) +from app.config import get_secret_key +from app.config.env import JWT_ACCESS_TOKEN_EXPIRE_MINUTES def create_admin_token(username: str, is_sudo=False) -> str: diff --git a/app/utils/notification.py b/app/utils/notification.py index da20e6b..90a59e4 100644 --- a/app/utils/notification.py +++ b/app/utils/notification.py @@ -4,7 +4,7 @@ from enum import Enum from pydantic import BaseModel -import config +from app.config.env import WEBHOOK_ADDRESS from app.models.admin import Admin from app.models.user import UserResponse @@ -100,5 +100,5 @@ class UserSubscriptionRevoked(UserNotification): async def notify(message: Notification) -> None: - if config.WEBHOOK_ADDRESS: + if WEBHOOK_ADDRESS: queue.append(message) diff --git a/app/utils/share.py b/app/utils/share.py index 8522186..f504d65 100644 --- a/app/utils/share.py +++ b/app/utils/share.py @@ -18,6 +18,11 @@ from v2share import ( ) from v2share.links import LinksConfig +from app.config.env import ( + XRAY_SUBSCRIPTION_TEMPLATE, + SINGBOX_SUBSCRIPTION_TEMPLATE, + CLASH_SUBSCRIPTION_TEMPLATE, +) from app.db import GetDB, crud from app.models.proxy import ( InboundHostSecurity, @@ -26,11 +31,6 @@ from app.models.user import UserResponse from app.models.user import UserStatus from app.utils.keygen import gen_uuid, gen_password from app.utils.system import get_public_ip, readable_size -from config import ( - XRAY_SUBSCRIPTION_TEMPLATE, - SINGBOX_SUBSCRIPTION_TEMPLATE, - CLASH_SUBSCRIPTION_TEMPLATE, -) SERVER_IP = get_public_ip()