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