from aiogram import Router, F from aiogram.filters import Command from aiogram.types import Message, CallbackQuery, InlineKeyboardMarkup, InlineKeyboardButton from aiogram.fsm.context import FSMContext from aiogram.fsm.state import State, StatesGroup from database.db import async_session_maker from database.models import WordSource from services.user_service import UserService from services.vocabulary_service import VocabularyService from services.ai_service import ai_service router = Router() class AddWordStates(StatesGroup): """Состояния для добавления слова""" waiting_for_confirmation = State() waiting_for_word = State() @router.message(Command("add")) async def cmd_add(message: Message, state: FSMContext): """Обработчик команды /add [слово]""" # Получаем слово из команды parts = message.text.split(maxsplit=1) if len(parts) < 2: await message.answer( "Отправь слово, которое хочешь добавить:\n" "Например: /add elephant\n\n" "Или просто отправь слово без команды!" ) await state.set_state(AddWordStates.waiting_for_word) return word = parts[1].strip() await process_word_addition(message, state, word) @router.message(AddWordStates.waiting_for_word) async def process_word_input(message: Message, state: FSMContext): """Обработка ввода слова""" word = message.text.strip() await process_word_addition(message, state, word) async def process_word_addition(message: Message, state: FSMContext, word: str): """Обработка добавления слова""" # Получаем пользователя 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("Сначала запусти бота командой /start") return # Проверяем, есть ли уже такое слово existing_word = await VocabularyService.find_word(session, user.id, word) if existing_word: await message.answer( f"Слово '{word}' уже есть в твоём словаре!\n" f"Перевод: {existing_word.word_translation}" ) await state.clear() return # Показываем индикатор загрузки processing_msg = await message.answer("⏳ Ищу перевод и примеры...") # Получаем перевод через AI word_data = await ai_service.translate_word(word) # Удаляем сообщение о загрузке await processing_msg.delete() # Формируем примеры examples_text = "" if word_data.get("examples"): examples_text = "\n\nПримеры:\n" for idx, example in enumerate(word_data["examples"][:2], 1): examples_text += f"{idx}. {example['en']}\n {example['ru']}\n" # Отправляем карточку слова card_text = ( f"📝 {word_data['word']}\n" f"🔊 [{word_data.get('transcription', '')}]\n\n" f"🇷🇺 {word_data['translation']}\n" f"📂 Категория: {word_data.get('category', 'общая')}\n" f"📊 Уровень: {word_data.get('difficulty', 'A1')}" f"{examples_text}\n\n" f"Добавить это слово в словарь?" ) # Создаём inline-кнопки keyboard = InlineKeyboardMarkup(inline_keyboard=[ [ InlineKeyboardButton(text="✅ Добавить", callback_data=f"add_word_confirm"), InlineKeyboardButton(text="❌ Отмена", callback_data="add_word_cancel") ] ]) # Сохраняем данные слова в состоянии await state.update_data(word_data=word_data, user_id=user.id) await state.set_state(AddWordStates.waiting_for_confirmation) await message.answer(card_text, reply_markup=keyboard) @router.callback_query(F.data == "add_word_confirm", AddWordStates.waiting_for_confirmation) async def confirm_add_word(callback: CallbackQuery, state: FSMContext): """Подтверждение добавления слова""" data = await state.get_data() word_data = data.get("word_data") user_id = data.get("user_id") async with async_session_maker() as session: # Добавляем слово в базу await VocabularyService.add_word( session, user_id=user_id, word_original=word_data["word"], word_translation=word_data["translation"], transcription=word_data.get("transcription"), examples={"examples": word_data.get("examples", [])}, category=word_data.get("category"), difficulty_level=word_data.get("difficulty"), source=WordSource.MANUAL ) # Получаем общее количество слов words_count = await VocabularyService.get_words_count(session, user_id) await callback.message.edit_text( f"✅ Слово '{word_data['word']}' добавлено в твой словарь!\n\n" f"Всего слов в словаре: {words_count}\n\n" f"Продолжай добавлять новые слова или используй /task для практики!" ) await state.clear() await callback.answer() @router.callback_query(F.data == "add_word_cancel") async def cancel_add_word(callback: CallbackQuery, state: FSMContext): """Отмена добавления слова""" await callback.message.edit_text("Отменено. Можешь добавить другое слово командой /add") await state.clear() await callback.answer() @router.message(Command("vocabulary")) async def cmd_vocabulary(message: Message): """Обработчик команды /vocabulary""" 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("Сначала запусти бота командой /start") return # Получаем слова пользователя words = await VocabularyService.get_user_words(session, user.id, limit=10) total_count = await VocabularyService.get_words_count(session, user.id) if not words: await message.answer( "📚 Твой словарь пока пуст!\n\n" "Добавь первое слово командой /add или просто отправь мне слово." ) return # Формируем список слов words_list = "📚 Твой словарь:\n\n" for idx, word in enumerate(words, 1): progress = "" if word.times_reviewed > 0: accuracy = int((word.correct_answers / word.times_reviewed) * 100) progress = f" ({accuracy}% точность)" words_list += ( f"{idx}. {word.word_original} — {word.word_translation}\n" f" 🔊 [{word.transcription or ''}]{progress}\n\n" ) if total_count > 10: words_list += f"\nПоказаны последние 10 из {total_count} слов" else: words_list += f"\nВсего слов: {total_count}" await message.answer(words_list)