"""Feed router — personalized feed, trending, new.""" from fastapi import APIRouter, Depends, Query from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.database import get_db from app.models import User, Shader from app.schemas import ShaderFeedItem, DwellReport from app.middleware.auth import get_optional_user, get_current_user router = APIRouter() @router.get("", response_model=list[ShaderFeedItem]) async def get_feed( limit: int = Query(20, ge=1, le=50), cursor: str | None = Query(None), db: AsyncSession = Depends(get_db), user: User | None = Depends(get_optional_user), ): """ Personalized feed for authenticated users (pgvector taste match). Trending/new for anonymous users. """ # TODO: Implement full recommendation engine (Track F) # For now: return newest public shaders query = ( select(Shader) .where(Shader.is_public == True, Shader.render_status == "ready") .order_by(Shader.created_at.desc()) .limit(limit) ) result = await db.execute(query) return result.scalars().all() @router.get("/trending", response_model=list[ShaderFeedItem]) async def get_trending( limit: int = Query(20, ge=1, le=50), db: AsyncSession = Depends(get_db), ): query = ( select(Shader) .where(Shader.is_public == True, Shader.render_status == "ready") .order_by(Shader.score.desc()) .limit(limit) ) result = await db.execute(query) return result.scalars().all() @router.get("/new", response_model=list[ShaderFeedItem]) async def get_new( limit: int = Query(20, ge=1, le=50), db: AsyncSession = Depends(get_db), ): query = ( select(Shader) .where(Shader.is_public == True, Shader.render_status == "ready") .order_by(Shader.created_at.desc()) .limit(limit) ) result = await db.execute(query) return result.scalars().all() @router.post("/dwell", status_code=204) async def report_dwell( body: DwellReport, db: AsyncSession = Depends(get_db), user: User | None = Depends(get_optional_user), ): """Report dwell time signal for recommendation engine.""" from app.models import EngagementEvent event = EngagementEvent( user_id=user.id if user else None, session_id=body.session_id, shader_id=body.shader_id, event_type="dwell", dwell_secs=body.dwell_secs, metadata={"replayed": body.replayed}, ) db.add(event) # TODO: Update user taste vector (Track F)