| 1 |
f7af2b3 |
Dawsh |
2y ago |
import logging |
| 2 |
d377c4c |
Dawsh |
2y ago |
from contextlib import asynccontextmanager |
| 3 |
f4fecee |
Dawsh |
2y ago |
from typing import AsyncGenerator |
| 4 |
f4fecee |
Dawsh |
2y ago |
|
| 5 |
f7af2b3 |
Dawsh |
2y ago |
from apscheduler.schedulers.asyncio import AsyncIOScheduler |
| 6 |
f7af2b3 |
Dawsh |
2y ago |
from fastapi import FastAPI, Request, status |
| 7 |
f7af2b3 |
Dawsh |
2y ago |
from fastapi.encoders import jsonable_encoder |
| 8 |
f7af2b3 |
Dawsh |
2y ago |
from fastapi.exceptions import RequestValidationError |
| 9 |
f7af2b3 |
Dawsh |
2y ago |
from fastapi.middleware.cors import CORSMiddleware |
| 10 |
eafb4a4 |
Mrdn |
2y ago |
from fastapi.responses import HTMLResponse, JSONResponse |
| 11 |
d4ec019 |
Dawsh |
2y ago |
from fastapi_pagination import add_pagination |
| 12 |
f7af2b3 |
Dawsh |
2y ago |
from starlette.staticfiles import StaticFiles |
| 13 |
eafb4a4 |
Mrdn |
2y ago |
from uvicorn import Config, Server |
| 14 |
f7af2b3 |
Dawsh |
2y ago |
|
| 15 |
8111eb7 |
Dawsh |
2y ago |
from app.config.env import ( |
| 16 |
01cdf2e |
Dawsh |
2y ago |
DEBUG, |
| 17 |
01cdf2e |
Dawsh |
2y ago |
DOCS, |
| 18 |
01cdf2e |
Dawsh |
2y ago |
HOME_PAGE_TEMPLATE, |
| 19 |
01cdf2e |
Dawsh |
2y ago |
UVICORN_HOST, |
| 20 |
01cdf2e |
Dawsh |
2y ago |
UVICORN_PORT, |
| 21 |
01cdf2e |
Dawsh |
2y ago |
UVICORN_SSL_CERTFILE, |
| 22 |
01cdf2e |
Dawsh |
2y ago |
UVICORN_SSL_KEYFILE, |
| 23 |
01cdf2e |
Dawsh |
2y ago |
UVICORN_UDS, |
| 24 |
a0e778c |
Mrdn |
2y ago |
DASHBOARD_PATH, |
| 25 |
01cdf2e |
Dawsh |
2y ago |
) |
| 26 |
8111eb7 |
Dawsh |
2y ago |
from app.templates import render_template |
| 27 |
8440155 |
mahdim10 |
1y ago |
from . import __version__ |
| 28 |
2de9d72 |
Dawsh |
2y ago |
from .routes import api_router |
| 29 |
01cdf2e |
Dawsh |
2y ago |
from .tasks import ( |
| 30 |
01cdf2e |
Dawsh |
2y ago |
nodes_startup, |
| 31 |
01cdf2e |
Dawsh |
2y ago |
record_user_usages, |
| 32 |
01cdf2e |
Dawsh |
2y ago |
reset_user_data_usage, |
| 33 |
01cdf2e |
Dawsh |
2y ago |
review_users, |
| 34 |
8440155 |
mahdim10 |
1y ago |
expire_days_reached, |
| 35 |
01cdf2e |
Dawsh |
2y ago |
) |
| 36 |
8440155 |
mahdim10 |
1y ago |
from .webhooks import webhooks_router |
| 37 |
f7af2b3 |
Dawsh |
2y ago |
|
| 38 |
f7af2b3 |
Dawsh |
2y ago |
logger = logging.getLogger(__name__) |
| 39 |
f7af2b3 |
Dawsh |
2y ago |
|
| 40 |
f4fecee |
Dawsh |
2y ago |
|
| 41 |
f4fecee |
Dawsh |
2y ago |
@asynccontextmanager |
| 42 |
f4fecee |
Dawsh |
2y ago |
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]: |
| 43 |
f4fecee |
Dawsh |
2y ago |
await nodes_startup() |
| 44 |
f4fecee |
Dawsh |
2y ago |
yield |
| 45 |
f4fecee |
Dawsh |
2y ago |
scheduler.shutdown() |
| 46 |
f4fecee |
Dawsh |
2y ago |
|
| 47 |
f4fecee |
Dawsh |
2y ago |
|
| 48 |
f7af2b3 |
Dawsh |
2y ago |
app = FastAPI( |
| 49 |
f7af2b3 |
Dawsh |
2y ago |
title="MarzneshinAPI", |
| 50 |
f7af2b3 |
Dawsh |
2y ago |
description="Unified GUI Censorship Resistant Solution Powered by Xray", |
| 51 |
f7af2b3 |
Dawsh |
2y ago |
version=__version__, |
| 52 |
f4fecee |
Dawsh |
2y ago |
lifespan=lifespan, |
| 53 |
f7af2b3 |
Dawsh |
2y ago |
docs_url="/docs" if DOCS else None, |
| 54 |
f7af2b3 |
Dawsh |
2y ago |
redoc_url="/redoc" if DOCS else None, |
| 55 |
f7af2b3 |
Dawsh |
2y ago |
) |
| 56 |
f7af2b3 |
Dawsh |
2y ago |
|
| 57 |
8440155 |
mahdim10 |
1y ago |
app.webhooks.include_router(webhooks_router) |
| 58 |
8440155 |
mahdim10 |
1y ago |
|
| 59 |
2de9d72 |
Dawsh |
2y ago |
app.include_router(api_router) |
| 60 |
d4ec019 |
Dawsh |
2y ago |
add_pagination(app) |
| 61 |
f7af2b3 |
Dawsh |
2y ago |
|
| 62 |
f7af2b3 |
Dawsh |
2y ago |
|
| 63 |
f7af2b3 |
Dawsh |
2y ago |
@app.get("/", response_class=HTMLResponse) |
| 64 |
2de9d72 |
Dawsh |
2y ago |
def home_page(): |
| 65 |
f7af2b3 |
Dawsh |
2y ago |
return render_template(HOME_PAGE_TEMPLATE) |
| 66 |
f7af2b3 |
Dawsh |
2y ago |
|
| 67 |
f7af2b3 |
Dawsh |
2y ago |
|
| 68 |
f7af2b3 |
Dawsh |
2y ago |
app.add_middleware( |
| 69 |
f7af2b3 |
Dawsh |
2y ago |
CORSMiddleware, |
| 70 |
f7af2b3 |
Dawsh |
2y ago |
allow_origins=["*"], |
| 71 |
f7af2b3 |
Dawsh |
2y ago |
allow_credentials=True, |
| 72 |
f7af2b3 |
Dawsh |
2y ago |
allow_methods=["*"], |
| 73 |
f7af2b3 |
Dawsh |
2y ago |
allow_headers=["*"], |
| 74 |
f7af2b3 |
Dawsh |
2y ago |
) |
| 75 |
f7af2b3 |
Dawsh |
2y ago |
|
| 76 |
f7af2b3 |
Dawsh |
2y ago |
scheduler = AsyncIOScheduler(timezone="UTC") |
| 77 |
eafb4a4 |
Mrdn |
2y ago |
scheduler.add_job(record_user_usages, "interval", coalesce=True, seconds=30) |
| 78 |
f1ab16c |
Dawsh |
2y ago |
scheduler.add_job( |
| 79 |
d377c4c |
Dawsh |
2y ago |
review_users, "interval", seconds=30, coalesce=True, max_instances=1 |
| 80 |
f1ab16c |
Dawsh |
2y ago |
) |
| 81 |
8440155 |
mahdim10 |
1y ago |
scheduler.add_job( |
| 82 |
8440155 |
mahdim10 |
1y ago |
expire_days_reached, "interval", seconds=30, coalesce=True, max_instances=1 |
| 83 |
8440155 |
mahdim10 |
1y ago |
) |
| 84 |
eafb4a4 |
Mrdn |
2y ago |
scheduler.add_job(reset_user_data_usage, "interval", coalesce=True, hours=1) |
| 85 |
f7af2b3 |
Dawsh |
2y ago |
|
| 86 |
f7af2b3 |
Dawsh |
2y ago |
|
| 87 |
f7af2b3 |
Dawsh |
2y ago |
@app.exception_handler(RequestValidationError) |
| 88 |
f1ab16c |
Dawsh |
2y ago |
def validation_exception_handler( |
| 89 |
f1ab16c |
Dawsh |
2y ago |
request: Request, exc: RequestValidationError |
| 90 |
f1ab16c |
Dawsh |
2y ago |
): |
| 91 |
f7af2b3 |
Dawsh |
2y ago |
details = {} |
| 92 |
f7af2b3 |
Dawsh |
2y ago |
for error in exc.errors(): |
| 93 |
f7af2b3 |
Dawsh |
2y ago |
details[error["loc"][-1]] = error.get("msg") |
| 94 |
f7af2b3 |
Dawsh |
2y ago |
return JSONResponse( |
| 95 |
f7af2b3 |
Dawsh |
2y ago |
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, |
| 96 |
f7af2b3 |
Dawsh |
2y ago |
content=jsonable_encoder({"detail": details}), |
| 97 |
f7af2b3 |
Dawsh |
2y ago |
) |
| 98 |
f7af2b3 |
Dawsh |
2y ago |
|
| 99 |
f7af2b3 |
Dawsh |
2y ago |
|
| 100 |
f7af2b3 |
Dawsh |
2y ago |
async def main(): |
| 101 |
eafb4a4 |
Mrdn |
2y ago |
if not DEBUG: |
| 102 |
f7af2b3 |
Dawsh |
2y ago |
app.mount( |
| 103 |
a0e778c |
Mrdn |
2y ago |
DASHBOARD_PATH, |
| 104 |
4466347 |
Mrdn |
2y ago |
StaticFiles(directory="dashboard/dist", html=True), |
| 105 |
4466347 |
Mrdn |
2y ago |
name="dashboard", |
| 106 |
f7af2b3 |
Dawsh |
2y ago |
) |
| 107 |
a0e778c |
Mrdn |
2y ago |
app.mount( |
| 108 |
a0e778c |
Mrdn |
2y ago |
"/static/", |
| 109 |
a0e778c |
Mrdn |
2y ago |
StaticFiles(directory="dashboard/dist/static"), |
| 110 |
a0e778c |
Mrdn |
2y ago |
name="static", |
| 111 |
a0e778c |
Mrdn |
2y ago |
) |
| 112 |
a0e778c |
Mrdn |
2y ago |
app.mount( |
| 113 |
a0e778c |
Mrdn |
2y ago |
"/locales/", |
| 114 |
a0e778c |
Mrdn |
2y ago |
StaticFiles(directory="dashboard/dist/locales"), |
| 115 |
a0e778c |
Mrdn |
2y ago |
name="locales", |
| 116 |
a0e778c |
Mrdn |
2y ago |
) |
| 117 |
f7af2b3 |
Dawsh |
2y ago |
scheduler.start() |
| 118 |
f7af2b3 |
Dawsh |
2y ago |
cfg = Config( |
| 119 |
f7af2b3 |
Dawsh |
2y ago |
app=app, |
| 120 |
f7af2b3 |
Dawsh |
2y ago |
host=UVICORN_HOST, |
| 121 |
f7af2b3 |
Dawsh |
2y ago |
port=UVICORN_PORT, |
| 122 |
f7af2b3 |
Dawsh |
2y ago |
uds=(None if DEBUG else UVICORN_UDS), |
| 123 |
f7af2b3 |
Dawsh |
2y ago |
ssl_certfile=UVICORN_SSL_CERTFILE, |
| 124 |
f7af2b3 |
Dawsh |
2y ago |
ssl_keyfile=UVICORN_SSL_KEYFILE, |
| 125 |
f7af2b3 |
Dawsh |
2y ago |
workers=1, |
| 126 |
f7af2b3 |
Dawsh |
2y ago |
reload=DEBUG, |
| 127 |
f7af2b3 |
Dawsh |
2y ago |
log_level=logging.DEBUG if DEBUG else logging.INFO, |
| 128 |
f7af2b3 |
Dawsh |
2y ago |
) |
| 129 |
f7af2b3 |
Dawsh |
2y ago |
server = Server(cfg) |
| 130 |
f7af2b3 |
Dawsh |
2y ago |
await server.serve() |