diff --git a/backend/routers/pipeline.py b/backend/routers/pipeline.py index bd478ec..d685631 100644 --- a/backend/routers/pipeline.py +++ b/backend/routers/pipeline.py @@ -1306,6 +1306,48 @@ async def reindex_all( } +# ── Admin: Avatar fetching ─────────────────────────────────────────────────── + +@router.post("/admin/pipeline/creators/{creator_id}/fetch-avatar") +async def fetch_creator_avatar( + creator_id: str, + db: AsyncSession = Depends(get_session), +): + """Trigger avatar lookup from TheAudioDB for a single creator.""" + from pipeline.stages import fetch_creator_avatar as _task + + creator = (await db.execute( + select(Creator).where(Creator.id == creator_id) + )).scalar_one_or_none() + if not creator: + raise HTTPException(status_code=404, detail="Creator not found") + + _task.delay(creator_id) + return {"status": "dispatched", "creator": creator.name, "creator_id": creator_id} + + +@router.post("/admin/pipeline/creators/fetch-all-avatars") +async def fetch_all_avatars( + db: AsyncSession = Depends(get_session), +): + """Trigger avatar lookup for all creators missing avatars.""" + from pipeline.stages import fetch_creator_avatar as _task + + result = await db.execute( + select(Creator.id, Creator.name).where( + (Creator.avatar_url.is_(None)) | (Creator.avatar_source == "generated") + ) + ) + creators = result.all() + + dispatched = 0 + for cid, name in creators: + _task.delay(str(cid)) + dispatched += 1 + + return {"status": "dispatched", "count": dispatched} + + # ── Admin: Worker status ───────────────────────────────────────────────────── WORKER_STATUS_CACHE_KEY = "chrysopedia:worker_status" diff --git a/backend/schemas.py b/backend/schemas.py index 54bf520..9f4d11d 100644 --- a/backend/schemas.py +++ b/backend/schemas.py @@ -37,6 +37,7 @@ class CreatorRead(CreatorBase): model_config = ConfigDict(from_attributes=True) id: uuid.UUID + avatar_url: str | None = None view_count: int = 0 created_at: datetime updated_at: datetime @@ -288,6 +289,7 @@ class CreatorInfo(BaseModel): name: str slug: str genres: list[str] | None = None + avatar_url: str | None = None class SourceVideoSummary(BaseModel):