83 lines
2.9 KiB
Python
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
|