main.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. from __future__ import annotations
  2. from contextlib import asynccontextmanager
  3. from typing import AsyncGenerator
  4. from fastapi import FastAPI
  5. from fastapi.middleware.cors import CORSMiddleware
  6. from app.config import settings
  7. from app.db import close_pool, init_pool, get_pool
  8. from app.middleware.logging import LoggingMiddleware
  9. from app.services.ws_hub import hub as ws_hub # noqa: F401
  10. from app.services.scheduler import start_scheduler, stop_scheduler
  11. @asynccontextmanager
  12. async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
  13. await init_pool()
  14. # 建 users 表并初始化 admin
  15. pool = get_pool()
  16. await pool.execute("""
  17. CREATE TABLE IF NOT EXISTS crawl.users (
  18. id BIGSERIAL PRIMARY KEY,
  19. username VARCHAR(100) NOT NULL UNIQUE,
  20. password_hash TEXT NOT NULL,
  21. created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
  22. )
  23. """)
  24. from app.routers.auth import ensure_admin_user
  25. await ensure_admin_user()
  26. await start_scheduler()
  27. yield
  28. await stop_scheduler()
  29. await close_pool()
  30. app = FastAPI(title="Sentinel Lens", lifespan=lifespan)
  31. app.add_middleware(
  32. CORSMiddleware,
  33. allow_origins=settings.allowed_origins,
  34. allow_credentials=True,
  35. allow_methods=["*"],
  36. allow_headers=["*"],
  37. )
  38. app.add_middleware(LoggingMiddleware)
  39. # Router registration
  40. from app.routers import stats # noqa: E402
  41. from app.routers import logs # noqa: E402
  42. from app.routers import scrape # noqa: E402
  43. from app.routers import public # noqa: E402
  44. from app.routers import ws # noqa: E402
  45. from app.routers import models # noqa: E402
  46. from app.routers import schedule # noqa: E402
  47. from app.routers import discounts # noqa: E402
  48. from app.routers import auth # noqa: E402
  49. from app.routers import scrape_stats # noqa: E402
  50. app.include_router(stats.router, prefix="/api")
  51. app.include_router(logs.router, prefix="/api")
  52. app.include_router(scrape.router, prefix="/api")
  53. app.include_router(public.router, prefix="/api/public")
  54. app.include_router(models.router, prefix="/api")
  55. app.include_router(schedule.router, prefix="/api")
  56. app.include_router(discounts.router, prefix="/api")
  57. app.include_router(auth.router, prefix="/api")
  58. app.include_router(scrape_stats.router, prefix="/api")
  59. app.include_router(ws.router)
  60. @app.get("/")
  61. async def health_check() -> dict:
  62. return {"status": "ok", "service": "sentinel-lens"}