2025-12-04 11:09:54 +03:00
|
|
|
from datetime import datetime
|
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
|
|
from sqlalchemy import String, BigInteger, DateTime, Integer, Boolean, JSON, Enum as SQLEnum
|
|
|
|
|
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
|
|
|
|
|
import enum
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Base(DeclarativeBase):
|
|
|
|
|
"""Базовая модель"""
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class LanguageLevel(str, enum.Enum):
|
|
|
|
|
"""Уровни владения языком"""
|
|
|
|
|
A1 = "A1"
|
|
|
|
|
A2 = "A2"
|
|
|
|
|
B1 = "B1"
|
|
|
|
|
B2 = "B2"
|
|
|
|
|
C1 = "C1"
|
|
|
|
|
C2 = "C2"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class WordSource(str, enum.Enum):
|
|
|
|
|
"""Источник добавления слова"""
|
|
|
|
|
MANUAL = "manual" # Ручное добавление
|
|
|
|
|
SUGGESTED = "suggested" # Предложено ботом
|
|
|
|
|
CONTEXT = "context" # Из контекста диалога
|
|
|
|
|
IMPORT = "import" # Импорт из текста
|
|
|
|
|
ERROR = "error" # Из ошибок в заданиях
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class User(Base):
|
|
|
|
|
"""Модель пользователя"""
|
|
|
|
|
__tablename__ = "users"
|
|
|
|
|
|
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
|
|
|
telegram_id: Mapped[int] = mapped_column(BigInteger, unique=True, nullable=False)
|
|
|
|
|
username: Mapped[Optional[str]] = mapped_column(String(255))
|
|
|
|
|
language_interface: Mapped[str] = mapped_column(String(2), default="ru") # ru/en
|
|
|
|
|
learning_language: Mapped[str] = mapped_column(String(2), default="en") # en
|
|
|
|
|
level: Mapped[LanguageLevel] = mapped_column(SQLEnum(LanguageLevel), default=LanguageLevel.A1)
|
|
|
|
|
timezone: Mapped[str] = mapped_column(String(50), default="UTC")
|
|
|
|
|
daily_task_time: Mapped[Optional[str]] = mapped_column(String(5)) # HH:MM
|
Добавлены основные функции 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
|
|
|
reminders_enabled: Mapped[bool] = mapped_column(Boolean, default=False)
|
|
|
|
|
last_reminder_sent: Mapped[Optional[datetime]] = mapped_column(DateTime)
|
2025-12-04 11:09:54 +03:00
|
|
|
streak_days: Mapped[int] = mapped_column(Integer, default=0)
|
|
|
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
|
last_active: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Vocabulary(Base):
|
|
|
|
|
"""Модель словарного запаса"""
|
|
|
|
|
__tablename__ = "vocabulary"
|
|
|
|
|
|
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
|
|
|
user_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
|
|
|
|
|
word_original: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
|
|
|
word_translation: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
|
|
|
transcription: Mapped[Optional[str]] = mapped_column(String(255))
|
|
|
|
|
examples: Mapped[Optional[dict]] = mapped_column(JSON) # JSON массив примеров
|
|
|
|
|
category: Mapped[Optional[str]] = mapped_column(String(100))
|
|
|
|
|
difficulty_level: Mapped[Optional[LanguageLevel]] = mapped_column(SQLEnum(LanguageLevel))
|
|
|
|
|
source: Mapped[WordSource] = mapped_column(SQLEnum(WordSource), default=WordSource.MANUAL)
|
|
|
|
|
times_reviewed: Mapped[int] = mapped_column(Integer, default=0)
|
|
|
|
|
correct_answers: Mapped[int] = mapped_column(Integer, default=0)
|
|
|
|
|
last_reviewed: Mapped[Optional[datetime]] = mapped_column(DateTime)
|
|
|
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|
|
|
|
|
notes: Mapped[Optional[str]] = mapped_column(String(500)) # Заметки пользователя
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Task(Base):
|
|
|
|
|
"""Модель задания"""
|
|
|
|
|
__tablename__ = "tasks"
|
|
|
|
|
|
|
|
|
|
id: Mapped[int] = mapped_column(primary_key=True)
|
|
|
|
|
user_id: Mapped[int] = mapped_column(Integer, nullable=False, index=True)
|
|
|
|
|
task_type: Mapped[str] = mapped_column(String(50), nullable=False) # translate, sentence, fill, etc.
|
|
|
|
|
content: Mapped[dict] = mapped_column(JSON, nullable=False) # Содержание задания
|
|
|
|
|
correct_answer: Mapped[Optional[str]] = mapped_column(String(500))
|
|
|
|
|
user_answer: Mapped[Optional[str]] = mapped_column(String(500))
|
|
|
|
|
is_correct: Mapped[Optional[bool]] = mapped_column(Boolean)
|
|
|
|
|
ai_feedback: Mapped[Optional[str]] = mapped_column(String(1000))
|
|
|
|
|
completed_at: Mapped[Optional[datetime]] = mapped_column(DateTime)
|
|
|
|
|
created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
|