feat(notify-bridge): phase 6 - database models and server API
New database schema with ServiceProvider abstraction: - ServiceProvider (replaces ImmichServer): type + JSON config - Tracker (replaces AlbumTracker): owns tracking_config_id - TrackingConfig: provider_type scoped, owned by Tracker - TemplateConfig: provider_type scoped, owned by Target - NotificationTarget: owns template_config_id (not tracking_config_id) - TrackerState, EventLog, User, TelegramBot, TelegramChat Full FastAPI server: - /api/providers: CRUD + test connection + list collections - /api/trackers: CRUD - /api/tracking-configs: CRUD with provider_type filter - /api/template-configs: CRUD with provider_type filter, system defaults - /api/targets: CRUD - /api/template-vars: variable docs filtered by provider type - /api/auth: setup, login, refresh, me, password change - /api/health: health check - Default template seeding on first startup (EN/RU for Immich) - pydantic-settings with NOTIFY_BRIDGE_ env prefix Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,38 @@
|
||||
"""Notify Bridge Server — FastAPI application entry point."""
|
||||
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI(title="Notify Bridge", version="0.1.0")
|
||||
from .database.engine import init_db
|
||||
from .database.models import * # noqa: F401,F403 — ensure all models registered
|
||||
|
||||
from .auth.routes import router as auth_router
|
||||
from .api.providers import router as providers_router
|
||||
from .api.trackers import router as trackers_router
|
||||
from .api.tracking_configs import router as tracking_configs_router
|
||||
from .api.template_configs import router as template_configs_router
|
||||
from .api.targets import router as targets_router
|
||||
from .api.template_vars import router as template_vars_router
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
await init_db()
|
||||
await _seed_default_templates()
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(title="Notify Bridge", version="0.1.0", lifespan=lifespan)
|
||||
|
||||
# Register routes — static paths before parameterized
|
||||
app.include_router(auth_router)
|
||||
app.include_router(template_vars_router)
|
||||
app.include_router(providers_router)
|
||||
app.include_router(trackers_router)
|
||||
app.include_router(tracking_configs_router)
|
||||
app.include_router(template_configs_router)
|
||||
app.include_router(targets_router)
|
||||
|
||||
|
||||
@app.get("/api/health")
|
||||
@@ -10,6 +40,38 @@ async def health():
|
||||
return {"status": "ok"}
|
||||
|
||||
|
||||
async def _seed_default_templates():
|
||||
"""Seed default templates on first startup if no templates exist."""
|
||||
from sqlmodel import func, select
|
||||
from sqlmodel.ext.asyncio.session import AsyncSession
|
||||
from .database.engine import get_engine
|
||||
from .database.models import TemplateConfig
|
||||
from notify_bridge_core.templates.defaults import load_default_templates
|
||||
|
||||
engine = get_engine()
|
||||
async with AsyncSession(engine) as session:
|
||||
result = await session.exec(select(func.count()).select_from(TemplateConfig))
|
||||
count = result.one()
|
||||
if count > 0:
|
||||
return
|
||||
|
||||
for locale in ("en", "ru"):
|
||||
slots = load_default_templates(locale)
|
||||
if not slots:
|
||||
continue
|
||||
name = f"Default ({locale.upper()})"
|
||||
config = TemplateConfig(
|
||||
user_id=0,
|
||||
provider_type="immich",
|
||||
name=name,
|
||||
description=f"Default Immich templates ({locale.upper()})",
|
||||
**slots,
|
||||
)
|
||||
session.add(config)
|
||||
|
||||
await session.commit()
|
||||
|
||||
|
||||
def run():
|
||||
import uvicorn
|
||||
uvicorn.run(app, host="0.0.0.0", port=8420)
|
||||
|
||||
Reference in New Issue
Block a user