Files
tg_bot_language/services/vocabulary_service.py
mamonov.ep 72a63eeda5 Добавлены основные функции MVP: тематические подборки, импорт слов, диалоговая практика, напоминания и тест уровня
Новые команды:
- /words [тема] - AI-генерация тематических подборок слов (10 слов по теме с учётом уровня)
- /import - извлечение до 15 ключевых слов из текста (книги, статьи, песни)
- /practice - диалоговая практика с AI в 6 сценариях (ресторан, магазин, путешествие, работа, врач, общение)
- /reminder - настройка ежедневных напоминаний по расписанию
- /level_test - тест из 7 вопросов для определения уровня английского (A1-C2)

Основные изменения:
- AI сервис: добавлены методы generate_thematic_words, extract_words_from_text, start_conversation, continue_conversation, generate_level_test
- Диалоговая практика: исправление ошибок в реальном времени, подсказки, перевод реплик
- Напоминания: APScheduler для ежедневной отправки напоминаний в выбранное время
- Тест уровня: автоматическое определение уровня при регистрации, можно пропустить
- База данных: добавлены поля reminders_enabled, last_reminder_sent
- Vocabulary service: метод get_word_by_original для проверки дубликатов
- Зависимости: apscheduler==3.10.4

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-04 15:46:02 +03:00

144 lines
4.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from database.models import Vocabulary, WordSource, LanguageLevel
from typing import List, Optional
class VocabularyService:
"""Сервис для работы со словарным запасом"""
@staticmethod
async def add_word(
session: AsyncSession,
user_id: int,
word_original: str,
word_translation: str,
transcription: Optional[str] = None,
examples: Optional[dict] = None,
category: Optional[str] = None,
difficulty_level: Optional[str] = None,
source: WordSource = WordSource.MANUAL,
notes: Optional[str] = None
) -> Vocabulary:
"""
Добавить слово в словарь пользователя
Args:
session: Сессия базы данных
user_id: ID пользователя
word_original: Оригинальное слово
word_translation: Перевод
transcription: Транскрипция
examples: Примеры использования
category: Категория слова
difficulty_level: Уровень сложности
source: Источник добавления
notes: Заметки пользователя
Returns:
Созданный объект слова
"""
# Преобразование difficulty_level в enum
difficulty_enum = None
if difficulty_level:
try:
difficulty_enum = LanguageLevel[difficulty_level]
except KeyError:
difficulty_enum = None
new_word = Vocabulary(
user_id=user_id,
word_original=word_original,
word_translation=word_translation,
transcription=transcription,
examples=examples,
category=category,
difficulty_level=difficulty_enum,
source=source,
notes=notes
)
session.add(new_word)
await session.commit()
await session.refresh(new_word)
return new_word
@staticmethod
async def get_user_words(session: AsyncSession, user_id: int, limit: int = 50) -> List[Vocabulary]:
"""
Получить все слова пользователя
Args:
session: Сессия базы данных
user_id: ID пользователя
limit: Максимальное количество слов
Returns:
Список слов пользователя
"""
result = await session.execute(
select(Vocabulary)
.where(Vocabulary.user_id == user_id)
.order_by(Vocabulary.created_at.desc())
.limit(limit)
)
return list(result.scalars().all())
@staticmethod
async def get_words_count(session: AsyncSession, user_id: int) -> int:
"""
Получить количество слов в словаре пользователя
Args:
session: Сессия базы данных
user_id: ID пользователя
Returns:
Количество слов
"""
result = await session.execute(
select(Vocabulary).where(Vocabulary.user_id == user_id)
)
return len(list(result.scalars().all()))
@staticmethod
async def find_word(session: AsyncSession, user_id: int, word: str) -> Optional[Vocabulary]:
"""
Найти слово в словаре пользователя
Args:
session: Сессия базы данных
user_id: ID пользователя
word: Слово для поиска
Returns:
Объект слова или None
"""
result = await session.execute(
select(Vocabulary)
.where(Vocabulary.user_id == user_id)
.where(Vocabulary.word_original.ilike(f"%{word}%"))
)
return result.scalar_one_or_none()
@staticmethod
async def get_word_by_original(session: AsyncSession, user_id: int, word: str) -> Optional[Vocabulary]:
"""
Получить слово по точному совпадению
Args:
session: Сессия базы данных
user_id: ID пользователя
word: Слово для поиска (точное совпадение)
Returns:
Объект слова или None
"""
result = await session.execute(
select(Vocabulary)
.where(Vocabulary.user_id == user_id)
.where(Vocabulary.word_original == word.lower())
)
return result.scalar_one_or_none()