From cfc4467b5631b8b63f30dc8c84f02f9eaaf9b447 Mon Sep 17 00:00:00 2001 From: kolo Date: Thu, 1 Jan 2026 23:14:56 +0300 Subject: [PATCH] commit --- src/trudex/application/__main__.py | 8 +++++ .../bot/admin_dialogs/main_menu.py | 6 ++-- .../bot/creator_dialogs/main_menu.py | 6 ++-- src/trudex/application/bot/handlers.py | 18 ++++++++--- .../application/bot/user_dialogs/__init__.py | 1 - .../application/bot/user_dialogs/main_menu.py | 26 +++++++++++++++ .../application/bot/user_dialogs/states.py | 5 +++ .../infrastructure/utils/bot_commands.py | 32 +++++++++++++++++++ 8 files changed, 90 insertions(+), 12 deletions(-) create mode 100644 src/trudex/application/bot/user_dialogs/main_menu.py create mode 100644 src/trudex/application/bot/user_dialogs/states.py create mode 100644 src/trudex/infrastructure/utils/bot_commands.py diff --git a/src/trudex/application/__main__.py b/src/trudex/application/__main__.py index 87487e7..a728242 100644 --- a/src/trudex/application/__main__.py +++ b/src/trudex/application/__main__.py @@ -13,7 +13,9 @@ from trudex.application.bot.creator_dialogs.main_menu import creator_menu_dialog from trudex.application.bot.handlers import router from trudex.application.bot.middlewares.reject_not_admin import RejectNotAdminMiddleware from trudex.application.bot.middlewares.reject_not_creator import RejectNotCreatorMiddleware +from trudex.application.bot.user_dialogs.main_menu import user_menu_dialog from trudex.infrastructure.di import DatabaseProvider +from trudex.infrastructure.utils.bot_commands import setup_bot_commands from trudex.infrastructure.utils.config import Config @@ -35,6 +37,7 @@ async def main() -> None: dp.message.middleware(RejectNotCreatorMiddleware()) dp.include_router(router) + dp.include_router(user_menu_dialog) dp.include_router(admin_menu_dialog) dp.include_router(creator_menu_dialog) @@ -42,6 +45,11 @@ async def main() -> None: setup_dishka(container, dp, auto_inject=True) setup_dialogs(dp) + async with container() as request_container: + from trudex.infrastructure.database.repo.user import UserRepository + user_repo = await request_container.get(UserRepository) + await setup_bot_commands(bot, config, user_repo) + logging.info("Бот запущен") try: diff --git a/src/trudex/application/bot/admin_dialogs/main_menu.py b/src/trudex/application/bot/admin_dialogs/main_menu.py index bf8b240..7120cc3 100644 --- a/src/trudex/application/bot/admin_dialogs/main_menu.py +++ b/src/trudex/application/bot/admin_dialogs/main_menu.py @@ -1,7 +1,7 @@ from aiogram.types import CallbackQuery, Message from aiogram_dialog import Dialog, DialogManager, Window from aiogram_dialog.widgets.input import MessageInput -from aiogram_dialog.widgets.kbd import Back, Button, Column, ScrollingGroup, Select +from aiogram_dialog.widgets.kbd import Back, Button, Column, ScrollingGroup, Select, SwitchTo from aiogram_dialog.widgets.text import Const, Format from dishka import FromDishka from dishka.integrations.aiogram_dialog import inject @@ -129,12 +129,12 @@ admin_menu_dialog = Dialog( Window( Const("Введите ID или @username пользователя:"), MessageInput(on_user_input), - Back(Const("◀️ Назад")), + SwitchTo(Const("◀️ Назад"), id="back_to_list", state=AdminMenuSG.users_list), state=AdminMenuSG.users_input, ), Window( Format("{user_info}"), - Back(Const("◀️ Назад")), + SwitchTo(Const("◀️ Назад"), id="back_to_list", state=AdminMenuSG.users_list), state=AdminMenuSG.user_detail, getter=get_user_detail_data, ), diff --git a/src/trudex/application/bot/creator_dialogs/main_menu.py b/src/trudex/application/bot/creator_dialogs/main_menu.py index e651161..0972908 100644 --- a/src/trudex/application/bot/creator_dialogs/main_menu.py +++ b/src/trudex/application/bot/creator_dialogs/main_menu.py @@ -1,7 +1,7 @@ from aiogram.types import CallbackQuery, Message from aiogram_dialog import Dialog, DialogManager, Window from aiogram_dialog.widgets.input import MessageInput -from aiogram_dialog.widgets.kbd import Back, Button, Cancel, Column, Row, ScrollingGroup, Select +from aiogram_dialog.widgets.kbd import Back, Button, Cancel, Column, Row, ScrollingGroup, Select, SwitchTo from aiogram_dialog.widgets.text import Const, Format from dishka import FromDishka from dishka.integrations.aiogram_dialog import inject @@ -173,14 +173,14 @@ creator_menu_dialog = Dialog( Window( Const("Введите ID или @username пользователя:"), MessageInput(on_user_input), - Back(Const("◀️ Назад")), + SwitchTo(Const("◀️ Назад"), id="back_to_list", state=CreatorMenuSG.users_list), state=CreatorMenuSG.users_input, ), Window( Format("{user_info}"), Column( Button(Const("👑 Сделать администратором"), id="make_admin", on_click=on_make_admin_clicked, when="show_make_admin"), - Back(Const("◀️ Назад")), + SwitchTo(Const("◀️ Назад"), id="back_to_list", state=CreatorMenuSG.users_list), ), state=CreatorMenuSG.user_detail, getter=get_user_detail_data, diff --git a/src/trudex/application/bot/handlers.py b/src/trudex/application/bot/handlers.py index 81aad48..6df0610 100644 --- a/src/trudex/application/bot/handlers.py +++ b/src/trudex/application/bot/handlers.py @@ -1,11 +1,13 @@ from aiogram import Router from aiogram.filters import Command, CommandStart -from aiogram.types import Message +from aiogram.types import ErrorEvent, Message from aiogram_dialog import DialogManager, StartMode +from aiogram_dialog.api.exceptions import OutdatedIntent, UnknownIntent from dishka.integrations.aiogram import FromDishka from trudex.application.bot.admin_dialogs.states import AdminMenuSG from trudex.application.bot.creator_dialogs.states import CreatorMenuSG +from trudex.application.bot.user_dialogs.states import UserMenuSG from trudex.infrastructure.database.dao.user import UserDAO @@ -13,7 +15,7 @@ router = Router() @router.message(CommandStart()) -async def start_handler(message: Message, user_dao: FromDishka[UserDAO]) -> None: +async def start_handler(message: Message, user_dao: FromDishka[UserDAO], dialog_manager: DialogManager) -> None: assert message.from_user is not None await user_dao.upsert( @@ -23,14 +25,20 @@ async def start_handler(message: Message, user_dao: FromDishka[UserDAO]) -> None last_name=message.from_user.last_name, ) - await message.answer("Привет! Я бот для тестирования по охране труда.") + await dialog_manager.start(UserMenuSG.main, mode=StartMode.RESET_STACK) @router.message(Command("admin")) -async def admin_command(message: Message, dialog_manager: DialogManager) -> None: +async def admin_command(_message: Message, dialog_manager: DialogManager) -> None: await dialog_manager.start(AdminMenuSG.main, mode=StartMode.RESET_STACK) @router.message(Command("creator")) -async def creator_command(message: Message, dialog_manager: DialogManager) -> None: +async def creator_command(_message: Message, dialog_manager: DialogManager) -> None: await dialog_manager.start(CreatorMenuSG.main, mode=StartMode.RESET_STACK) + + +@router.error() +async def dialog_error_handler(event: ErrorEvent, dialog_manager: DialogManager) -> None: + if isinstance(event.exception, (UnknownIntent, OutdatedIntent)): + await dialog_manager.start(UserMenuSG.main, mode=StartMode.RESET_STACK) diff --git a/src/trudex/application/bot/user_dialogs/__init__.py b/src/trudex/application/bot/user_dialogs/__init__.py index 8b13789..e69de29 100644 --- a/src/trudex/application/bot/user_dialogs/__init__.py +++ b/src/trudex/application/bot/user_dialogs/__init__.py @@ -1 +0,0 @@ - diff --git a/src/trudex/application/bot/user_dialogs/main_menu.py b/src/trudex/application/bot/user_dialogs/main_menu.py new file mode 100644 index 0000000..9779efa --- /dev/null +++ b/src/trudex/application/bot/user_dialogs/main_menu.py @@ -0,0 +1,26 @@ +from aiogram.types import CallbackQuery +from aiogram_dialog import Dialog, DialogManager, Window +from aiogram_dialog.widgets.kbd import Button, Column +from aiogram_dialog.widgets.text import Const + +from trudex.application.bot.user_dialogs.states import UserMenuSG + + +async def on_tests_clicked(_callback: CallbackQuery, _button: Button, _manager: DialogManager) -> None: + await _callback.answer("Доступные тесты") + + +async def on_results_clicked(_callback: CallbackQuery, _button: Button, _manager: DialogManager) -> None: + await _callback.answer("Мои результаты") + + +user_menu_dialog = Dialog( + Window( + Const("📚 Главное меню\n\nВыберите раздел:"), + Column( + Button(Const("📝 Доступные тесты"), id="tests", on_click=on_tests_clicked), + Button(Const("📊 Мои результаты"), id="results", on_click=on_results_clicked), + ), + state=UserMenuSG.main, + ), +) diff --git a/src/trudex/application/bot/user_dialogs/states.py b/src/trudex/application/bot/user_dialogs/states.py new file mode 100644 index 0000000..7435483 --- /dev/null +++ b/src/trudex/application/bot/user_dialogs/states.py @@ -0,0 +1,5 @@ +from aiogram.fsm.state import State, StatesGroup + + +class UserMenuSG(StatesGroup): + main = State() diff --git a/src/trudex/infrastructure/utils/bot_commands.py b/src/trudex/infrastructure/utils/bot_commands.py new file mode 100644 index 0000000..d017f64 --- /dev/null +++ b/src/trudex/infrastructure/utils/bot_commands.py @@ -0,0 +1,32 @@ +from aiogram import Bot +from aiogram.types import BotCommand, BotCommandScopeAllPrivateChats, BotCommandScopeChat + +from trudex.infrastructure.database.repo.user import UserRepository +from trudex.infrastructure.utils.config import Config + + +async def setup_bot_commands(bot: Bot, config: Config, user_repo: UserRepository) -> None: + await bot.set_my_commands( + commands=[ + BotCommand(command="start", description="Главное меню"), + ], + scope=BotCommandScopeAllPrivateChats(), + ) + + admins = await user_repo.get_admins() + for admin in admins: + await bot.set_my_commands( + commands=[ + BotCommand(command="start", description="Главное меню"), + BotCommand(command="admin", description="Админ-панель"), + ], + scope=BotCommandScopeChat(chat_id=admin.id), + ) + + await bot.set_my_commands( + commands=[ + BotCommand(command="start", description="Главное меню"), + BotCommand(command="creator", description="Панель создателя"), + ], + scope=BotCommandScopeChat(chat_id=config.bot.creator_id), + )