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 database.db import async_session_maker from database.models import LanguageLevel from bot.handlers.start import main_menu_keyboard from services.user_service import UserService router = Router() def _is_en(user) -> bool: try: return (getattr(user, 'language_interface', 'ru') or 'ru') == 'en' except Exception: return False def _is_ja(user) -> bool: try: return (getattr(user, 'language_interface', 'ru') or 'ru') == 'ja' except Exception: return False def get_settings_keyboard(user) -> InlineKeyboardMarkup: """Создать клавиатуру настроек""" is_en = _is_en(user) is_ja = _is_ja(user) keyboard = InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton( text=( "📊 Level: " if is_en else ("📊 レベル: " if is_ja else "📊 Уровень: ") ) + f"{user.level.value}", callback_data="settings_level" )], [InlineKeyboardButton( text=( "🎯 Learning language: " if is_en else ("🎯 学習言語: " if is_ja else "🎯 Язык изучения: ") ) + (user.learning_language.upper()), callback_data="settings_learning" )], [InlineKeyboardButton( text=( "🌐 Interface language: " if is_en else ("🌐 インターフェース言語: " if is_ja else "🌐 Язык интерфейса: ") ) + ("🇬🇧 English" if getattr(user, 'language_interface', 'ru') == 'en' else ("🇯🇵 日本語" if getattr(user, 'language_interface', 'ru') == 'ja' else "🇷🇺 Русский")), callback_data="settings_language" )], [InlineKeyboardButton( text=("❌ Close" if is_en else ("❌ 閉じる" if is_ja else "❌ Закрыть")), callback_data="settings_close" )] ]) return keyboard def get_level_keyboard(user=None) -> InlineKeyboardMarkup: """Клавиатура выбора уровня""" lang = getattr(user, 'language_interface', 'ru') if user is not None else 'ru' if lang == 'en': levels = [ ("A1 - Beginner", "set_level_A1"), ("A2 - Elementary", "set_level_A2"), ("B1 - Intermediate", "set_level_B1"), ("B2 - Upper-intermediate", "set_level_B2"), ("C1 - Advanced", "set_level_C1"), ("C2 - Proficient", "set_level_C2"), ] elif lang == 'ja': levels = [ ("A1 - 初級", "set_level_A1"), ("A2 - 初級(上)", "set_level_A2"), ("B1 - 中級", "set_level_B1"), ("B2 - 中級(上)", "set_level_B2"), ("C1 - 上級", "set_level_C1"), ("C2 - ネイティブ", "set_level_C2"), ] else: levels = [ ("A1 - Начальный", "set_level_A1"), ("A2 - Элементарный", "set_level_A2"), ("B1 - Средний", "set_level_B1"), ("B2 - Выше среднего", "set_level_B2"), ("C1 - Продвинутый", "set_level_C1"), ("C2 - Профессиональный", "set_level_C2"), ] keyboard = [] for level_name, callback_data in levels: keyboard.append([InlineKeyboardButton(text=level_name, callback_data=callback_data)]) back_label = "⬅️ Back" if lang == 'en' else ("⬅️ 戻る" if lang == 'ja' else "⬅️ Назад") keyboard.append([InlineKeyboardButton(text=back_label, callback_data="settings_back")]) return InlineKeyboardMarkup(inline_keyboard=keyboard) def get_language_keyboard(user=None) -> InlineKeyboardMarkup: """Клавиатура выбора языка интерфейса""" lang = getattr(user, 'language_interface', 'ru') if user is not None else 'ru' back = "⬅️ Back" if lang == 'en' else ("⬅️ 戻る" if lang == 'ja' else "⬅️ Назад") keyboard = InlineKeyboardMarkup(inline_keyboard=[ [InlineKeyboardButton(text="🇷🇺 Русский", callback_data="set_lang_ru")], [InlineKeyboardButton(text="🇬🇧 English", callback_data="set_lang_en")], [InlineKeyboardButton(text="🇯🇵 日本語", callback_data="set_lang_ja")], [InlineKeyboardButton(text=back, callback_data="settings_back")] ]) return keyboard def get_learning_language_keyboard(user=None) -> InlineKeyboardMarkup: """Клавиатура выбора языка изучения""" lang = getattr(user, 'language_interface', 'ru') if user is not None else 'ru' back = "⬅️ Back" if lang == 'en' else ("⬅️ 戻る" if lang == 'ja' else "⬅️ Назад") # Пары (код -> подпись) options = [ ("en", "🇬🇧 English" if lang != 'ja' else "🇬🇧 英語"), ("es", "🇪🇸 Spanish" if lang == 'en' else ("🇪🇸 スペイン語" if lang == 'ja' else "🇪🇸 Испанский")), ("de", "🇩🇪 German" if lang == 'en' else ("🇩🇪 ドイツ語" if lang == 'ja' else "🇩🇪 Немецкий")), ("fr", "🇫🇷 French" if lang == 'en' else ("🇫🇷 フランス語" if lang == 'ja' else "🇫🇷 Французский")), ("ja", "🇯🇵 Japanese" if lang == 'en' else ("🇯🇵 日本語" if lang == 'ja' else "🇯🇵 Японский")), ] keyboard = [[InlineKeyboardButton(text=label, callback_data=f"set_learning_{code}")] for code, label in options] keyboard.append([InlineKeyboardButton(text=back, callback_data="settings_back")]) return InlineKeyboardMarkup(inline_keyboard=keyboard) @router.message(Command("settings")) async def cmd_settings(message: Message): """Обработчик команды /settings""" 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 lang = getattr(user, 'language_interface', 'ru') title = "⚙️ Settings\n\n" if lang == 'en' else ("⚙️ 設定\n\n" if lang == 'ja' else "⚙️ Настройки\n\n") level_label = "📊 English level: " if lang == 'en' else ("📊 英語レベル: " if lang == 'ja' else "📊 Уровень английского: ") lang_label = "🌐 Interface language: " if lang == 'en' else ("🌐 インターフェース言語: " if lang == 'ja' else "🌐 Язык интерфейса: ") lang_value = 'English' if lang == 'en' else ('日本語' if lang == 'ja' else ('Русский' if user.language_interface == 'ru' else 'English')) footer = "Choose what to change:" if lang == 'en' else ("変更したい項目を選択:" if lang == 'ja' else "Выбери, что хочешь изменить:") settings_text = f"{title}{level_label}{user.level.value}\n{lang_label}{lang_value}\n\n{footer}" await message.answer(settings_text, reply_markup=get_settings_keyboard(user)) @router.callback_query(F.data == "settings_level") async def settings_level(callback: CallbackQuery): """Показать выбор уровня""" async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) lang = getattr(user, 'language_interface', 'ru') if user else 'ru' title = "📊 Choose your English level:\n\n" if lang == 'en' else ("📊 英語レベルを選択:\n\n" if lang == 'ja' else "📊 Выбери свой уровень английского:\n\n") body = ( "A1-A2 - Beginner\nB1-B2 - Intermediate\nC1-C2 - Advanced\n\n" if lang == 'en' else ( "A1-A2 - 初級\nB1-B2 - 中級\nC1-C2 - 上級\n\n" if lang == 'ja' else "A1-A2 - Начинающий\nB1-B2 - Средний\nC1-C2 - Продвинутый\n\n" )) tail = "This affects difficulty of suggested words and tasks." if lang == 'en' else ("これは提案される単語や課題の難易度に影響します。" if lang == 'ja' else "Это влияет на сложность предлагаемых слов и заданий.") await callback.message.edit_text(title + body + tail, reply_markup=get_level_keyboard(user)) await callback.answer() @router.callback_query(F.data == "settings_learning") async def settings_learning(callback: CallbackQuery): """Показать выбор языка изучения""" async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) lang = getattr(user, 'language_interface', 'ru') if user else 'ru' title = "🎯 Select learning language:\n\n" if lang == 'en' else ("🎯 学習言語を選択:\n\n" if lang == 'ja' else "🎯 Выбери язык изучения:\n\n") await callback.message.edit_text(title, reply_markup=get_learning_language_keyboard(user)) await callback.answer() @router.callback_query(F.data.startswith("set_learning_")) async def set_learning_language(callback: CallbackQuery): """Установить язык изучения""" code = callback.data.split("_")[-1] async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if user: await UserService.update_user_learning_language(session, user.id, code) lang = getattr(user, 'language_interface', 'ru') if lang == 'en': text = f"✅ Learning language: {code.upper()}" back = "⬅️ Back to settings" elif lang == 'ja': text = f"✅ 学習言語: {code.upper()}" back = "⬅️ 設定に戻る" else: text = f"✅ Язык изучения: {code.upper()}" back = "⬅️ К настройкам" await callback.message.edit_text( text, reply_markup=InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text=back, callback_data="settings_back")]]) ) await callback.answer() @router.callback_query(F.data.startswith("set_level_")) async def set_level(callback: CallbackQuery): """Установить уровень""" level_str = callback.data.split("_")[-1] # A1, A2, B1, B2, C1, C2 async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if user: # Обновляем уровень await UserService.update_user_level(session, user.id, LanguageLevel[level_str]) lang = getattr(user, 'language_interface', 'ru') changed = "✅ Level changed to " if lang == 'en' else ("✅ レベルが変更されました: " if lang == 'ja' else "✅ Уровень изменен на ") msg = changed + f"{level_str}\n\n" + ("You will now receive words and tasks matching your level!" if lang == 'en' else ("これからレベルに合った単語と課題が出題されます!" if lang == 'ja' else "Теперь ты будешь получать слова и задания, соответствующие твоему уровню!")) back = "⬅️ Back to settings" if lang == 'en' else ("⬅️ 設定に戻る" if lang == 'ja' else "⬅️ К настройкам") await callback.message.edit_text( msg, reply_markup=InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text=back, callback_data="settings_back")]]) ) await callback.answer() @router.callback_query(F.data == "settings_language") async def settings_language(callback: CallbackQuery): """Показать выбор языка""" async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) lang = getattr(user, 'language_interface', 'ru') if user else 'ru' title = "🌐 Select interface language:\n\n" if lang == 'en' else ("🌐 インターフェース言語を選択:\n\n" if lang == 'ja' else "🌐 Выбери язык интерфейса:\n\n") desc = "This will change the language of bot messages." if lang == 'en' else ("ボットの表示言語が変更されます。" if lang == 'ja' else "Это изменит язык всех сообщений бота.") await callback.message.edit_text( title + desc, reply_markup=get_language_keyboard(user) ) await callback.answer() @router.callback_query(F.data.startswith("set_lang_")) async def set_language(callback: CallbackQuery): """Установить язык""" lang = callback.data.split("_")[-1] # ru | en | ja async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if user: await UserService.update_user_language(session, user.id, lang) if lang == 'en': text = "✅ Interface language: English" back = "⬅️ Back" elif lang == 'ja': text = "✅ インターフェース言語: 日本語" back = "⬅️ 戻る" else: text = "✅ Язык интерфейса: Русский" back = "⬅️ К настройкам" await callback.message.edit_text( text, reply_markup=InlineKeyboardMarkup(inline_keyboard=[[InlineKeyboardButton(text=back, callback_data="settings_back")]]) ) # Обновляем клавиатуру чата на выбранный язык menu_updated = "Main menu updated ⤵️" if lang == 'en' else ("メインメニューを更新しました ⤵️" if lang == 'ja' else "Клавиатура обновлена ⤵️") await callback.message.answer(menu_updated, reply_markup=main_menu_keyboard(lang)) await callback.answer() @router.callback_query(F.data == "settings_back") async def settings_back(callback: CallbackQuery): """Вернуться к настройкам""" async with async_session_maker() as session: user = await UserService.get_user_by_telegram_id(session, callback.from_user.id) if user: lang = getattr(user, 'language_interface', 'ru') title = "⚙️ Settings\n\n" if lang == 'en' else ("⚙️ 設定\n\n" if lang == 'ja' else "⚙️ Настройки\n\n") level_label = "📊 English level: " if lang == 'en' else ("📊 英語レベル: " if lang == 'ja' else "📊 Уровень английского: ") lang_label = "🌐 Interface language: " if lang == 'en' else ("🌐 インターフェース言語: " if lang == 'ja' else "🌐 Язык интерфейса: ") lang_value = 'English' if user.language_interface == 'en' else ('日本語' if user.language_interface == 'ja' else 'Русский') footer = "Choose what to change:" if lang == 'en' else ("変更したい項目を選択:" if lang == 'ja' else "Выбери, что хочешь изменить:") settings_text = f"{title}{level_label}{user.level.value}\n{lang_label}{lang_value}\n\n{footer}" await callback.message.edit_text(settings_text, reply_markup=get_settings_keyboard(user)) await callback.answer() @router.callback_query(F.data == "settings_close") async def settings_close(callback: CallbackQuery): """Закрыть настройки""" await callback.message.delete() await callback.answer()