Files
quickbot/bot/handlers/user_handlers/__init__.py

103 lines
3.1 KiB
Python

from typing import TYPE_CHECKING
from aiogram import Router, F
from aiogram.types import Message, CallbackQuery, InlineKeyboardButton
from aiogram.fsm.context import FSMContext
from ..context import ContextData, CallbackCommand
from ....model.settings import Settings
from ....utils.main import get_send_message, clear_state
from ....model.descriptors import CommandCallbackContext
from ..navigation import (
save_navigation_context,
get_navigation_context,
pop_navigation_context,
)
if TYPE_CHECKING:
from ....main import QBotApp
router = Router()
@router.message(F.text.startswith("/"))
async def command_text(message: Message, **kwargs):
str_command = message.text.lstrip("/")
callback_data = ContextData(
command=CallbackCommand.USER_COMMAND, user_command=str_command
)
await command_handler(message=message, callback_data=callback_data, **kwargs)
@router.callback_query(ContextData.filter(F.command == CallbackCommand.USER_COMMAND))
async def command_callback(message: CallbackQuery, **kwargs):
await command_handler(message=message, **kwargs)
async def command_handler(message: Message | CallbackQuery, **kwargs):
callback_data: ContextData = kwargs.pop("callback_data")
str_command = callback_data.user_command
app: "QBotApp" = kwargs.pop("app")
command = app.bot_commands.get(str_command)
if not command:
return
state: FSMContext = kwargs.pop("state")
state_data = await state.get_data()
if command.register_navigation:
clear_state(state_data=state_data)
if command.clear_navigation:
state_data.pop("navigation_stack", None)
state_data.pop("navigation_context", None)
if command.register_navigation:
stack = save_navigation_context(
callback_data=callback_data, state_data=state_data
)
callback_context = CommandCallbackContext[app.user_class](
message=message,
callback_data=callback_data,
db_session=kwargs.pop("db_session"),
user=kwargs.pop("user"),
app=app,
state_data=state_data,
state=state,
i18n=kwargs.pop("i18n"),
kwargs=kwargs,
)
await command.handler(callback_context)
await state.set_data(state_data)
if command.register_navigation:
stack, navigation_context = get_navigation_context(state_data=state_data)
back_callback_data = pop_navigation_context(stack=stack)
if back_callback_data:
callback_context.keyboard_builder.row(
InlineKeyboardButton(
text=(await Settings.get(Settings.APP_STRINGS_BACK_BTN)),
callback_data=back_callback_data.pack(),
)
)
send_message = get_send_message(message)
if isinstance(message, CallbackCommand):
message = message.message
if callback_context.message_text:
await send_message(
text=callback_context.message_text,
reply_markup=callback_context.keyboard_builder.as_markup(),
)
else:
await message.edit_reply_markup(
reply_markup=callback_context.keyboard_builder.as_markup()
)