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),
+ )