aiogram

How is it more correct to implement the blocking function in aiogram 3.0?


this is a tech support bot. The admin receives an appeal from the user and if it violates the rules, then through the inline button, the admin can ban this user. What is the best way to transfer data from one handler to another?

I did so, it seems to work. But I think there is a smarter solution (p.s почистил код от лишнего)

@probiv_router.message(Form.order_text)
async def form_order_text(message: Message, state: FSMContext):
    await state.update_data(order_text=message.text)

    order_data = await state.get_data()


    username = message.from_user.username
    userid = message.from_user.id
    
    await bot.send_message(chat_id=ADMIN_ID, text=
                                                  f'text: <b>text</b>',
                           parse_mode='HTML',
                           reply_markup=InlineKeyboardMarkup(inline_keyboard=[

                               [
                                   InlineKeyboardButton(text='write',
                                                        url=f'https://t.me/{userid}'),
                                   InlineKeyboardButton(text='ban', callback_data='ban_user')
                               ]
                           ]))

    await state.clear()

    @probiv_router.callback_query(F.data == 'ban_user')
    async def banuserfunc(callback: CallbackQuery):
        await callback.message.answer(f'user @{userid} banned')
                                     

Solution

  • Yes, there is a better solution.

    You can use the Callback Factory method: https://docs.aiogram.dev/en/latest/dispatcher/filters/callback_data.html#:~:text=Another%20abstract%20example%3A. The thing is that in callback_data you specify different data. For example, like in your case, it can be action and user_id.

    Also, I would use InlineKeyboardBuilder, instead of just keeping the InlineKeyboardButtons in arrays: https://docs.aiogram.dev/en/latest/utils/keyboard.html.

    Must be something like this:

    class BanUser(CallbackData, prefix="ban_user"):
        user_id: str
        # action: ... # in case you wanna add more manipulation actions, like get information about previous punishments etc. Don't forget to rename the class then.
    
    keyboard = InlineKeyboardBuilder()
    
    keyboard.add(
        InlineKeyboardButton(text="contact", url="...")
        InlineKeyboardButton(text="ban", callback_data=BanUser(user_id=user_id).pack()),
    )
    keyboard.adjust(1, 2)
    bot.send_message(..., reply_markup=keyboard.as_markup())
    
    @router.callback_query(BanUser.filter())
    async def ban_user(query: CallbackQuery, callback_data: BanUser, bot: Bot):
        ...