Files
spotify_vibe/app/api/routes.py
2026-02-26 19:33:05 +00:00

83 lines
2.9 KiB
Python

from __future__ import annotations
from fastapi import APIRouter, Depends, Header, HTTPException, Query, Request
from fastapi.responses import HTMLResponse
from app.services.app_services import AppServices
def get_router() -> APIRouter:
router = APIRouter()
def runtime(request: Request):
return request.app.state.runtime
def services(request: Request) -> AppServices:
return request.app.state.services
@router.get("/health")
async def health():
return {"ok": True}
@router.get("/auth/spotify/start")
async def spotify_start(
chat_id: str = Query(...),
username: str | None = Query(default=None),
svc: AppServices = Depends(services),
):
url = await svc.auth.create_connect_url(chat_id=chat_id, username=username)
return {"url": url}
@router.get("/auth/spotify/callback", response_class=HTMLResponse)
async def spotify_callback(
request: Request,
code: str | None = None,
state: str | None = None,
error: str | None = None,
svc: AppServices = Depends(services),
):
try:
if error:
raise ValueError(f"Spotify returned error: {error}")
if not code or not state:
raise ValueError("Missing code/state in callback")
chat_id, display_name = await svc.auth.handle_callback(code=code, state=state)
runner = request.app.state.runtime.telegram_runner
if runner is not None:
await runner.send_message(chat_id, f"Spotify подключен: {display_name}\nТеперь можно /generate")
return """
<html><body style="font-family:sans-serif;padding:24px">
<h2>Spotify connected</h2>
<p>Return to Telegram and use <code>/generate</code>.</p>
</body></html>
"""
except Exception as exc:
return HTMLResponse(
content=(
"<html><body style='font-family:sans-serif;padding:24px'>"
f"<h2>Auth failed</h2><p>{exc}</p></body></html>"
),
status_code=400,
)
@router.post("/internal/jobs/nightly")
async def run_nightly(
request: Request,
authorization: str | None = Header(default=None),
svc: AppServices = Depends(services),
):
rt = runtime(request)
expected = f"Bearer {rt.settings.internal_job_token}"
if authorization != expected:
raise HTTPException(status_code=401, detail="Unauthorized")
outcomes = await svc.jobs.generate_for_all_connected_users()
return {
"ok": True,
"count": len(outcomes),
"results": [
{"user_id": o.user_id, "ok": o.ok, "message": o.message, "playlist_url": o.playlist_url} for o in outcomes
],
}
return router