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