"""世谱 API。""" from fastapi import APIRouter, Depends, Header, Query, Request from app.api.v1.deps import get_current_user from app.schemas.auth import CurrentUser from app.schemas.lorebook import ( LorebookCreateRequest, LorebookEntryCreateRequest, LorebookEntryResponse, LorebookEntryUpdateRequest, LorebookResponse, LorebookUpdateRequest, ) from app.services.idempotency import run_idempotent from app.services.lorebook import ( create_entry, create_lorebook, delete_entry, delete_lorebook, get_lorebook, list_lorebooks, update_entry, update_lorebook, ) router = APIRouter(prefix="/lorebooks", tags=["lorebooks"]) @router.post("", response_model=LorebookResponse) async def create_lorebook_api( payload: LorebookCreateRequest, request: Request, idempotency_key: str | None = Header(default=None, alias="Idempotency-Key"), current_user: CurrentUser = Depends(get_current_user), ) -> LorebookResponse: return await run_idempotent( key=idempotency_key, method="POST", path=str(request.url.path), payload=payload, response_type=LorebookResponse, resource_type="lorebook", handler=lambda session: create_lorebook( session, payload, owner_scope=current_user.owner_scope ), ) @router.get("", response_model=list[LorebookResponse]) async def list_lorebooks_api( character_id: str | None = Query(default=None), scope: str | None = Query(default=None), current_user: CurrentUser = Depends(get_current_user), ) -> list[LorebookResponse]: return await list_lorebooks( character_id=character_id, owner_scope=current_user.owner_scope, scope=scope, ) @router.get("/{lorebook_id}", response_model=LorebookResponse) async def get_lorebook_api( lorebook_id: str, current_user: CurrentUser = Depends(get_current_user), ) -> LorebookResponse: return await get_lorebook(lorebook_id, owner_scope=current_user.owner_scope) @router.patch("/{lorebook_id}", response_model=LorebookResponse) async def update_lorebook_api( lorebook_id: str, payload: LorebookUpdateRequest, current_user: CurrentUser = Depends(get_current_user), ) -> LorebookResponse: return await update_lorebook(lorebook_id, payload, owner_scope=current_user.owner_scope) @router.delete("/{lorebook_id}", response_model=LorebookResponse) async def delete_lorebook_api( lorebook_id: str, current_user: CurrentUser = Depends(get_current_user), ) -> LorebookResponse: return await delete_lorebook(lorebook_id, owner_scope=current_user.owner_scope) @router.post("/{lorebook_id}/entries", response_model=LorebookEntryResponse) async def create_entry_api( lorebook_id: str, payload: LorebookEntryCreateRequest, request: Request, idempotency_key: str | None = Header(default=None, alias="Idempotency-Key"), current_user: CurrentUser = Depends(get_current_user), ) -> LorebookEntryResponse: return await run_idempotent( key=idempotency_key, method="POST", path=str(request.url.path), payload=payload, response_type=LorebookEntryResponse, resource_type="lorebook_entry", handler=lambda session: create_entry( session, lorebook_id, payload, owner_scope=current_user.owner_scope ), ) @router.patch("/{lorebook_id}/entries/{entry_id}", response_model=LorebookEntryResponse) async def update_entry_api( lorebook_id: str, entry_id: str, payload: LorebookEntryUpdateRequest, current_user: CurrentUser = Depends(get_current_user), ) -> LorebookEntryResponse: return await update_entry( lorebook_id, entry_id, payload, owner_scope=current_user.owner_scope ) @router.delete("/{lorebook_id}/entries/{entry_id}", status_code=204) async def delete_entry_api( lorebook_id: str, entry_id: str, current_user: CurrentUser = Depends(get_current_user), ) -> None: await delete_entry(lorebook_id, entry_id, owner_scope=current_user.owner_scope)