| from __future__ import annotations |
|
|
| import asyncio |
| import logging |
|
|
| from fastapi import APIRouter, Depends |
|
|
| from app.api.auth import get_current_user_id |
| from app.api.schemas import WordCreate, WordResponse |
| from app.db.session import get_session_factory |
| from app.pipelines.define import define_word |
| from app.services.dictionary import delete_word, list_words, save_word |
| from app.services.user import get_or_create_user |
|
|
| router = APIRouter(prefix="/words", tags=["dictionary"]) |
|
|
| log = logging.getLogger(__name__) |
|
|
|
|
| async def _fill_meaning(user_id: int, word: str, level: str, lang: str = "ru") -> None: |
| """Generate and store a definition for a word saved without one (background).""" |
| meaning = await define_word(word, level, lang) |
| if not meaning: |
| return |
| factory = get_session_factory() |
| async with factory() as s: |
| await save_word(s, user_id, word, meaning) |
| log.info("auto-defined word %r for user %s", word, user_id) |
|
|
|
|
| @router.get("", response_model=list[WordResponse]) |
| async def get_words(user_id: int = Depends(get_current_user_id)) -> list[WordResponse]: |
| """List saved words.""" |
| factory = get_session_factory() |
| async with factory() as s: |
| words = await list_words(s, user_id) |
| return [WordResponse(word=w.word, meaning=w.meaning, created_at=w.created_at) for w in words] |
|
|
|
|
| @router.post("", response_model=dict[str, str]) |
| async def add_word( |
| body: WordCreate, |
| user_id: int = Depends(get_current_user_id), |
| ) -> dict[str, str]: |
| """Save a word. If no meaning is given, save instantly and fill a definition in the background.""" |
| word = body.word.lower().strip() |
| context = body.context.strip() if body.context else None |
| meaning = body.meaning.strip() if body.meaning else None |
| factory = get_session_factory() |
| async with factory() as s: |
| user = await get_or_create_user(s, user_id) |
| await save_word(s, user_id, word, meaning or "", context) |
| if not meaning: |
| asyncio.create_task(_fill_meaning(user_id, word, user.level, user.interface_language)) |
| return {"status": "saved"} |
|
|
|
|
| @router.delete("/{word}") |
| async def remove_word( |
| word: str, |
| user_id: int = Depends(get_current_user_id), |
| ) -> dict[str, bool]: |
| """Delete a word from dictionary.""" |
| factory = get_session_factory() |
| async with factory() as s: |
| deleted = await delete_word(s, user_id, word) |
| return {"deleted": deleted} |
|
|