2025-12-09 15:05:38 +03:00
|
|
|
"""Handler для функции 'Слово дня'."""
|
|
|
|
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
from aiogram import Router, F
|
|
|
|
|
from aiogram.filters import Command
|
|
|
|
|
from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton
|
|
|
|
|
|
|
|
|
|
from database.db import async_session_maker
|
|
|
|
|
from database.models import WordOfDay, WordSource
|
|
|
|
|
from services.user_service import UserService
|
|
|
|
|
from services.vocabulary_service import VocabularyService
|
|
|
|
|
from services.wordofday_service import wordofday_service
|
|
|
|
|
from utils.i18n import t, get_user_lang, get_user_translation_lang
|
|
|
|
|
from utils.levels import get_user_level_for_language
|
|
|
|
|
|
|
|
|
|
router = Router()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def format_word_of_day(wod: WordOfDay, lang: str) -> str:
|
|
|
|
|
"""Форматировать слово дня для отображения."""
|
|
|
|
|
date_str = wod.date.strftime("%d.%m.%Y")
|
|
|
|
|
|
|
|
|
|
text = f"🌅 <b>{t(lang, 'wod.title')}</b> — {date_str}\n\n"
|
|
|
|
|
text += f"📝 <b>{wod.word}</b>\n"
|
|
|
|
|
|
|
|
|
|
if wod.transcription:
|
|
|
|
|
text += f"🔊 [{wod.transcription}]\n"
|
|
|
|
|
|
|
|
|
|
text += f"\n💬 {wod.translation}\n"
|
|
|
|
|
|
|
|
|
|
# Примеры
|
|
|
|
|
if wod.examples:
|
|
|
|
|
text += f"\n📖 <b>{t(lang, 'wod.examples')}:</b>\n"
|
|
|
|
|
for ex in wod.examples[:2]:
|
|
|
|
|
sentence = ex.get('sentence', '')
|
|
|
|
|
translation = ex.get('translation', '')
|
|
|
|
|
text += f"• <i>{sentence}</i>\n"
|
|
|
|
|
if translation:
|
|
|
|
|
text += f" ({translation})\n"
|
|
|
|
|
|
|
|
|
|
# Синонимы
|
|
|
|
|
if wod.synonyms:
|
|
|
|
|
text += f"\n🔗 <b>{t(lang, 'wod.synonyms')}:</b> {wod.synonyms}\n"
|
|
|
|
|
|
|
|
|
|
# Этимология/интересный факт
|
|
|
|
|
if wod.etymology:
|
|
|
|
|
text += f"\n💡 {wod.etymology}\n"
|
|
|
|
|
|
|
|
|
|
return text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.message(Command("wordofday"))
|
|
|
|
|
async def cmd_wordofday(message: Message):
|
|
|
|
|
"""Обработчик команды /wordofday."""
|
|
|
|
|
async with async_session_maker() as session:
|
|
|
|
|
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
|
|
|
|
|
|
|
|
|
|
if not user:
|
|
|
|
|
await message.answer(t('ru', 'common.start_first'))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
lang = get_user_lang(user)
|
|
|
|
|
learning_lang = user.learning_language or 'en'
|
|
|
|
|
level = get_user_level_for_language(user)
|
|
|
|
|
|
|
|
|
|
# Получаем слово дня из глобальной таблицы
|
|
|
|
|
wod = await wordofday_service.get_word_of_day(
|
|
|
|
|
learning_lang=learning_lang,
|
|
|
|
|
level=level
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if not wod:
|
|
|
|
|
# Слово ещё не сгенерировано - показываем сообщение
|
|
|
|
|
await message.answer(t(lang, 'wod.not_available'))
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Форматируем и отправляем
|
|
|
|
|
text = format_word_of_day(wod, lang)
|
|
|
|
|
|
|
|
|
|
# Кнопка добавления в словарь
|
|
|
|
|
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
|
|
|
|
[InlineKeyboardButton(
|
|
|
|
|
text=t(lang, 'wod.add_btn'),
|
|
|
|
|
callback_data=f"wod_add_{wod.id}"
|
|
|
|
|
)]
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
await message.answer(text, reply_markup=keyboard)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@router.callback_query(F.data.startswith("wod_add_"))
|
|
|
|
|
async def wod_add_callback(callback: CallbackQuery):
|
|
|
|
|
"""Добавить слово дня в словарь."""
|
|
|
|
|
await callback.answer()
|
|
|
|
|
|
|
|
|
|
wod_id = int(callback.data.replace("wod_add_", ""))
|
|
|
|
|
|
|
|
|
|
async with async_session_maker() as session:
|
|
|
|
|
user = await UserService.get_user_by_telegram_id(session, callback.from_user.id)
|
|
|
|
|
lang = get_user_lang(user)
|
|
|
|
|
|
|
|
|
|
# Получаем слово дня
|
|
|
|
|
wod = await session.get(WordOfDay, wod_id)
|
|
|
|
|
if not wod:
|
|
|
|
|
await callback.answer(t(lang, 'wod.not_found'), show_alert=True)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Проверяем, нет ли уже в словаре
|
|
|
|
|
existing = await VocabularyService.get_word_by_original(
|
|
|
|
|
session, user.id, wod.word, source_lang=wod.learning_lang
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if existing:
|
|
|
|
|
await callback.answer(t(lang, 'words.already_exists', word=wod.word), show_alert=True)
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
# Добавляем в словарь
|
|
|
|
|
translation_lang = get_user_translation_lang(user)
|
|
|
|
|
|
2025-12-10 19:42:10 +03:00
|
|
|
new_word = await VocabularyService.add_word(
|
2025-12-09 15:05:38 +03:00
|
|
|
session=session,
|
|
|
|
|
user_id=user.id,
|
|
|
|
|
word_original=wod.word,
|
|
|
|
|
word_translation=wod.translation,
|
|
|
|
|
source_lang=wod.learning_lang,
|
|
|
|
|
translation_lang=translation_lang,
|
|
|
|
|
transcription=wod.transcription,
|
|
|
|
|
difficulty_level=wod.level,
|
|
|
|
|
source=WordSource.SUGGESTED
|
|
|
|
|
)
|
|
|
|
|
|
2025-12-10 19:42:10 +03:00
|
|
|
# Добавляем переводы в word_translations (разбиваем по запятой)
|
|
|
|
|
# Берём первый пример из examples если есть
|
|
|
|
|
example = None
|
|
|
|
|
example_translation = None
|
|
|
|
|
if wod.examples and len(wod.examples) > 0:
|
|
|
|
|
example = wod.examples[0].get('sentence')
|
|
|
|
|
example_translation = wod.examples[0].get('translation')
|
|
|
|
|
|
|
|
|
|
await VocabularyService.add_translation_split(
|
|
|
|
|
session=session,
|
|
|
|
|
vocabulary_id=new_word.id,
|
|
|
|
|
translation=wod.translation,
|
|
|
|
|
context=example,
|
|
|
|
|
context_translation=example_translation,
|
|
|
|
|
is_primary=True
|
|
|
|
|
)
|
|
|
|
|
|
2025-12-09 15:05:38 +03:00
|
|
|
await session.commit()
|
|
|
|
|
|
|
|
|
|
# Обновляем сообщение
|
|
|
|
|
text = format_word_of_day(wod, lang)
|
|
|
|
|
text += f"\n✅ <i>{t(lang, 'wod.added')}</i>"
|
|
|
|
|
|
|
|
|
|
await callback.message.edit_text(text, reply_markup=None)
|