import logging from contextlib import asynccontextmanager from urllib.parse import urlparse from fastapi import Depends, FastAPI, Header, HTTPException, status from pydantic import BaseModel from rich.console import Console from rich.logging import RichHandler import providers from classes.application_result import ApplicationResult from language import _ from settings import INTERNAL_API_KEY, log_settings def setup_logging(): logging.basicConfig( level=logging.WARNING, format="%(message)s", datefmt="[%X]", handlers=[RichHandler(markup=True, console=Console(width=110))], ) logging.getLogger("flat-apply").setLevel(logging.DEBUG) logger = logging.getLogger("flat-apply") setup_logging() class ApplyRequest(BaseModel): url: str class ApplyResponse(BaseModel): success: bool message: str def require_api_key(x_internal_api_key: str | None = Header(default=None)) -> None: if not INTERNAL_API_KEY: raise HTTPException( status_code=status.HTTP_503_SERVICE_UNAVAILABLE, detail="apply service has no INTERNAL_API_KEY configured", ) if x_internal_api_key != INTERNAL_API_KEY: raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="invalid api key") @asynccontextmanager async def lifespan(_app: FastAPI): log_settings() logger.info(f"apply ready, providers: {sorted(providers.PROVIDERS)}") yield app = FastAPI(lifespan=lifespan, title="lazyflat-apply") @app.get("/health") def health(): return {"status": "ok"} @app.post("/apply", response_model=ApplyResponse, dependencies=[Depends(require_api_key)]) async def apply(req: ApplyRequest): url = req.url.strip() domain = urlparse(url).netloc.lower().removeprefix("www.") logger.info(f"apply request for domain={domain} url={url}") if domain not in providers.PROVIDERS: logger.warning(f"unsupported provider: {domain}") result = ApplicationResult(False, message=_("unsupported_association")) return ApplyResponse(success=result.success, message=str(result)) try: provider = providers.PROVIDERS[domain] result = await provider.apply_for_flat(url) logger.info(f"application result: {repr(result)}") except Exception as e: logger.exception("error while applying") result = ApplicationResult(False, f"Script Error:\n{e}") return ApplyResponse(success=result.success, message=str(result))