Files
mywhoosh2garmin/app/main.py
Bastian Wagner 2aba1265af mail notification
2026-08-15 20:47:02 +02:00

92 lines
3.1 KiB
Python

from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
from starlette.middleware.sessions import SessionMiddleware
from app.config import Settings, get_settings
from app.db.session import create_db_engine, create_session_factory, initialize_schema
from app.fit.rewriter import convert_fit_device
from app.garmin.uploader import GarminUploader
from app.mywhoosh.client import MyWhooshClient
from app.notifications.emailer import EmailNotifier
from app.security.credentials import CredentialCipher
from app.sync.manager import SyncManager
from app.sync.scheduler import SyncScheduler
from app.web.operations import router as operations_router
from app.web.routes import router as web_router
def create_app(settings: Settings | None = None) -> FastAPI:
resolved = settings or get_settings()
resolved.data_dir.mkdir(parents=True, exist_ok=True)
resolved.tokens_dir.mkdir(parents=True, exist_ok=True)
resolved.activities_dir.mkdir(parents=True, exist_ok=True)
@asynccontextmanager
async def lifespan(app: FastAPI):
cipher = CredentialCipher(resolved.credential_encryption_key)
def mywhoosh_factory(token_store):
return MyWhooshClient(token_store)
def garmin_factory(email, password, tokenstore):
return GarminUploader(email=email, password=password, tokenstore=tokenstore)
notifier = EmailNotifier(
host=resolved.smtp_host,
port=resolved.smtp_port,
username=resolved.smtp_username,
password=resolved.smtp_password,
from_address=resolved.smtp_from_address,
use_tls=resolved.smtp_use_tls,
)
sync_manager = SyncManager(
session_factory=app.state.session_factory,
credential_cipher=cipher,
settings=resolved,
mywhoosh_factory=mywhoosh_factory,
garmin_factory=garmin_factory,
fit_converter=convert_fit_device,
notifier=notifier,
)
app.state.sync_manager = sync_manager
scheduler = SyncScheduler(sync_manager, interval_seconds=resolved.sync_interval_minutes * 60)
app.state.scheduler = scheduler
await scheduler.start()
yield
await scheduler.stop()
app = FastAPI(title="MyWhoosh Garmin Sync", lifespan=lifespan)
app.state.settings = resolved
engine = create_db_engine(resolved.database_url)
initialize_schema(engine)
app.state.db_engine = engine
app.state.session_factory = create_session_factory(engine)
app.add_middleware(
SessionMiddleware,
secret_key=resolved.secret_key,
same_site="lax",
https_only=resolved.session_https_only,
)
app.include_router(web_router)
app.include_router(operations_router)
app.mount(
"/static",
StaticFiles(directory=str(Path(__file__).resolve().parent / "web" / "static")),
name="static",
)
@app.get("/healthz")
def healthz() -> dict[str, str]:
return {"status": "ok"}
return app