refactor(api): Pydantic request models for saved-views & feed state (R6 S1b)
- saved_views: CreateViewIn / UpdateViewIn / ReorderViewsIn. PATCH presence via model_fields_set; filters typed as dict (a non-object is now 422, an explicit null on update stays a 400 "filters must be an object"). - feed: VideoStateIn(status) / VideoProgressIn(position_seconds,duration_seconds) — the manual int()+400 in progress becomes a 422 on a non-number; the status membership 400 and the video 404 are unchanged. Gate: ruff clean.
This commit is contained in:
@@ -5,6 +5,7 @@ import re
|
||||
from datetime import date, datetime, timedelta, timezone
|
||||
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
from sqlalchemy import BigInteger, Select, and_, cast, false, func, or_, select
|
||||
from sqlalchemy.dialects.postgresql import insert as pg_insert
|
||||
from sqlalchemy.orm import Session, aliased
|
||||
@@ -571,14 +572,18 @@ def get_facets(
|
||||
return {"counts": counts}
|
||||
|
||||
|
||||
class VideoStateIn(BaseModel):
|
||||
status: str
|
||||
|
||||
|
||||
@router.post("/videos/{video_id}/state")
|
||||
def set_video_state(
|
||||
video_id: str,
|
||||
payload: dict,
|
||||
body: VideoStateIn,
|
||||
user: User = Depends(current_user),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
status = payload.get("status")
|
||||
status = body.status
|
||||
if status not in VALID_STATES:
|
||||
raise HTTPException(status_code=400, detail=f"status must be one of {VALID_STATES}")
|
||||
if db.get(Video, video_id) is None:
|
||||
@@ -653,10 +658,15 @@ def clear_video_state(
|
||||
return {"video_id": video_id, "status": "new", "position_seconds": 0}
|
||||
|
||||
|
||||
class VideoProgressIn(BaseModel):
|
||||
position_seconds: int = 0
|
||||
duration_seconds: int = 0
|
||||
|
||||
|
||||
@router.post("/videos/{video_id}/progress")
|
||||
def set_video_progress(
|
||||
video_id: str,
|
||||
payload: dict,
|
||||
body: VideoProgressIn,
|
||||
user: User = Depends(current_user),
|
||||
db: Session = Depends(get_db),
|
||||
) -> dict:
|
||||
@@ -664,11 +674,8 @@ def set_video_progress(
|
||||
Stores a per-user position on the video_states row without touching watch status, so a
|
||||
partially-watched video can render a progress bar and match the "in progress" filter.
|
||||
Trivially-early and near-finished positions clear the position rather than store it."""
|
||||
try:
|
||||
position = int(payload.get("position_seconds") or 0)
|
||||
duration = int(payload.get("duration_seconds") or 0)
|
||||
except (TypeError, ValueError):
|
||||
raise HTTPException(status_code=400, detail="position_seconds must be an integer")
|
||||
position = body.position_seconds
|
||||
duration = body.duration_seconds
|
||||
if position < 0:
|
||||
position = 0
|
||||
|
||||
|
||||
Reference in New Issue
Block a user