import asyncio import os from contextlib import asynccontextmanager from typing import Optional from dotenv import load_dotenv from fastapi import FastAPI from fastapi.staticfiles import StaticFiles from starlette.middleware.sessions import SessionMiddleware from app.database import create_db, get_admin_user from app.routers import actions, auth, dashboard, layout, media, overlay, settings load_dotenv() _eventsub_task: Optional[asyncio.Task] = None def get_eventsub_task() -> Optional[asyncio.Task]: return _eventsub_task async def start_eventsub() -> None: global _eventsub_task from app.eventsub import run_eventsub admin = get_admin_user() if not admin: return if _eventsub_task and not _eventsub_task.done(): _eventsub_task.cancel() try: await _eventsub_task except asyncio.CancelledError: pass _eventsub_task = asyncio.create_task(run_eventsub(admin.broadcaster_id, admin.access_token)) @asynccontextmanager async def lifespan(app: FastAPI): create_db() await start_eventsub() yield if _eventsub_task and not _eventsub_task.done(): _eventsub_task.cancel() app = FastAPI(title="BashyOverlay", lifespan=lifespan) app.add_middleware(SessionMiddleware, secret_key=os.getenv("SECRET_KEY", "dev-secret-change-me")) app.mount("/static", StaticFiles(directory="static"), name="static") app.include_router(auth.router) app.include_router(dashboard.router) app.include_router(overlay.router) app.include_router(actions.router) app.include_router(media.router) app.include_router(layout.router) app.include_router(settings.router)