71 lines
2.0 KiB
Python
71 lines
2.0 KiB
Python
# routers/search.py
|
|
from fastapi import APIRouter, Query
|
|
from fastapi.concurrency import run_in_threadpool
|
|
from pydantic import BaseModel
|
|
|
|
from search.search_client import videos_index
|
|
|
|
router = APIRouter(prefix="/search", tags=["search"])
|
|
|
|
|
|
class VideoHit(BaseModel):
|
|
id: int
|
|
title: str
|
|
filename: str
|
|
date: str | None
|
|
channel_id: int
|
|
channel_name: str
|
|
playlist_id: int | None
|
|
playlist_name: str | None
|
|
preview_path: str
|
|
_formatted: dict | None = None
|
|
|
|
|
|
class SearchResponse(BaseModel):
|
|
query: str
|
|
total: int
|
|
took_ms: int
|
|
items: list[VideoHit]
|
|
|
|
|
|
@router.get("/videos", response_model=SearchResponse)
|
|
async def search_videos(
|
|
q: str = Query("", max_length=200, description="Поисковый запрос; пусто = показать всё"),
|
|
channel_id: int | None = None,
|
|
playlist_id: int | None = None,
|
|
date_from: str | None = Query(None, pattern=r"^\d{4}-\d{2}-\d{2}$"),
|
|
date_to: str | None = Query(None, pattern=r"^\d{4}-\d{2}-\d{2}$"),
|
|
sort: str | None = Query(None, description="date:desc | date:asc | id:desc"),
|
|
limit: int = Query(20, le=100),
|
|
offset: int = Query(0, ge=0),
|
|
):
|
|
filters = []
|
|
if channel_id is not None:
|
|
filters.append(f"channel_id = {channel_id}")
|
|
if playlist_id is not None:
|
|
filters.append(f"playlist_id = {playlist_id}")
|
|
if date_from:
|
|
filters.append(f'date >= "{date_from}"')
|
|
if date_to:
|
|
filters.append(f'date <= "{date_to}"')
|
|
|
|
params = {
|
|
"limit": limit,
|
|
"offset": offset,
|
|
"attributesToHighlight": ["title", "filename"],
|
|
"highlightPreTag": "<mark>",
|
|
"highlightPostTag": "</mark>",
|
|
}
|
|
if filters:
|
|
params["filter"] = " AND ".join(filters)
|
|
if sort:
|
|
params["sort"] = [sort]
|
|
|
|
result = await run_in_threadpool(videos_index().search, q, params)
|
|
|
|
return {
|
|
"query": q,
|
|
"total": result["estimatedTotalHits"],
|
|
"took_ms": result["processingTimeMs"],
|
|
"items": result["hits"],
|
|
} |