feat: мини-истории, слово дня, меню практики
- Добавлены мини-истории для чтения с выбором жанра и вопросами - Кнопка показа/скрытия перевода истории - Количество вопросов берётся из настроек пользователя - Слово дня генерируется глобально в 00:00 UTC - Кнопка "Практика" открывает меню выбора режима - Убран автоматический create_all при запуске (только миграции) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -13,7 +13,7 @@ from aiogram.fsm.state import State, StatesGroup
|
||||
|
||||
from database.db import async_session_maker
|
||||
from services.user_service import UserService
|
||||
from utils.i18n import t, get_user_translation_lang
|
||||
from utils.i18n import t, get_user_translation_lang, get_user_lang
|
||||
from utils.levels import get_user_level_for_language
|
||||
|
||||
router = Router()
|
||||
@@ -57,16 +57,19 @@ def main_menu_keyboard(lang: str = 'ru') -> ReplyKeyboardMarkup:
|
||||
return ReplyKeyboardMarkup(
|
||||
resize_keyboard=True,
|
||||
keyboard=[
|
||||
[
|
||||
KeyboardButton(text=t(lang, "menu.add")),
|
||||
KeyboardButton(text=t(lang, "menu.vocab")),
|
||||
],
|
||||
[
|
||||
KeyboardButton(text=t(lang, "menu.task")),
|
||||
KeyboardButton(text=t(lang, "menu.practice")),
|
||||
],
|
||||
[
|
||||
KeyboardButton(text=t(lang, "menu.exercises")),
|
||||
KeyboardButton(text=t(lang, "menu.vocab")),
|
||||
],
|
||||
[
|
||||
KeyboardButton(text=t(lang, "menu.add")),
|
||||
KeyboardButton(text=t(lang, "menu.stats")),
|
||||
],
|
||||
[
|
||||
KeyboardButton(text=t(lang, "menu.settings")),
|
||||
],
|
||||
],
|
||||
@@ -326,8 +329,74 @@ async def btn_task_pressed(message: Message, state: FSMContext):
|
||||
|
||||
@router.message(_menu_match('menu.practice'))
|
||||
async def btn_practice_pressed(message: Message, state: FSMContext):
|
||||
from bot.handlers.practice import cmd_practice
|
||||
await cmd_practice(message, state)
|
||||
"""Показать меню практики"""
|
||||
await state.clear()
|
||||
|
||||
async with async_session_maker() as session:
|
||||
user = await UserService.get_user_by_telegram_id(session, message.from_user.id)
|
||||
lang = get_user_lang(user) if user else 'ru'
|
||||
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[InlineKeyboardButton(
|
||||
text=f"📖 {t(lang, 'practice_menu.stories')}",
|
||||
callback_data="practice_stories"
|
||||
)],
|
||||
[InlineKeyboardButton(
|
||||
text=f"💬 {t(lang, 'practice_menu.ai_chat')}",
|
||||
callback_data="practice_ai"
|
||||
)],
|
||||
])
|
||||
|
||||
await message.answer(
|
||||
f"💬 <b>{t(lang, 'practice_menu.title')}</b>\n\n{t(lang, 'practice_menu.choose')}",
|
||||
reply_markup=keyboard
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(F.data == "practice_stories")
|
||||
async def practice_stories_callback(callback: CallbackQuery, state: FSMContext):
|
||||
"""Переход к мини-историям"""
|
||||
await callback.answer()
|
||||
|
||||
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) if user else 'ru'
|
||||
|
||||
keyboard = InlineKeyboardMarkup(inline_keyboard=[
|
||||
[
|
||||
InlineKeyboardButton(text=f"🗣 {t(lang, 'story.genre.dialogue')}", callback_data="story_genre_dialogue"),
|
||||
InlineKeyboardButton(text=f"📰 {t(lang, 'story.genre.news')}", callback_data="story_genre_news"),
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(text=f"🎭 {t(lang, 'story.genre.story')}", callback_data="story_genre_story"),
|
||||
InlineKeyboardButton(text=f"📧 {t(lang, 'story.genre.letter')}", callback_data="story_genre_letter"),
|
||||
],
|
||||
[
|
||||
InlineKeyboardButton(text=f"🍳 {t(lang, 'story.genre.recipe')}", callback_data="story_genre_recipe"),
|
||||
],
|
||||
])
|
||||
|
||||
await callback.message.edit_text(
|
||||
f"📖 <b>{t(lang, 'story.title')}</b>\n\n{t(lang, 'story.choose_genre')}",
|
||||
reply_markup=keyboard
|
||||
)
|
||||
|
||||
|
||||
@router.callback_query(F.data == "practice_ai")
|
||||
async def practice_ai_callback(callback: CallbackQuery, state: FSMContext):
|
||||
"""Переход к AI практике"""
|
||||
await callback.answer()
|
||||
|
||||
async with async_session_maker() as session:
|
||||
user = await UserService.get_user_by_telegram_id(session, callback.from_user.id)
|
||||
if user:
|
||||
from bot.handlers.practice import PracticeStates
|
||||
from utils.levels import get_user_level_for_language
|
||||
await state.update_data(user_id=user.id, level=get_user_level_for_language(user))
|
||||
await state.set_state(PracticeStates.choosing_scenario)
|
||||
|
||||
from bot.handlers.practice import show_practice_menu
|
||||
await show_practice_menu(callback.message, callback.from_user.id, edit=True)
|
||||
|
||||
|
||||
@router.message(_menu_match('menu.import'))
|
||||
@@ -391,6 +460,14 @@ async def btn_settings_pressed(message: Message):
|
||||
await cmd_settings(message)
|
||||
|
||||
|
||||
|
||||
@router.message(_menu_match('menu.exercises'))
|
||||
async def btn_exercises_pressed(message: Message, state: FSMContext):
|
||||
"""Показать меню грамматических упражнений."""
|
||||
from bot.handlers.exercises import show_exercises_menu
|
||||
await show_exercises_menu(message, state, telegram_id=message.from_user.id)
|
||||
|
||||
|
||||
@router.message(_menu_match('menu.words'))
|
||||
async def btn_words_pressed(message: Message, state: FSMContext):
|
||||
"""Подсказать про тематические слова и показать быстрые темы."""
|
||||
|
||||
Reference in New Issue
Block a user