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