Не работает код на python aiogram3x, проблема с fsm

class Form(StatesGroup):
    text = State()

@dp.message()
async def forward_to_admin(message: types.Message):
    await bot.send_message(message.chat.id, "text")
    data = message.chat.id
    keyboard = types.InlineKeyboardMarkup(inline_keyboard=[[
        types.InlineKeyboardButton(text="text", callback_data='user_'+str(data))
    ]])
    for id in admin_id:
        await bot.send_message(id, f"Пользователь {message.from_user.first_name} написал:\n\n{message.text}\n\n", reply_markup=keyboard)

@dp.callback_query(lambda call: call.data.startswith('user_'))
async def forward_to_user(call: types.CallbackQuery, state: FSMContext):
    await state.set_state(Form.text)
    await bot.send_message(call.message.chat.id, f"Напишите ответ пользователю:")


@dp.callback_query(Form.text)
async def process_forward(call: types.CallbackQuery, state: FSMContext):
    await state.update_data(text=call.message.text)
    user_id = int(call.data.split('_')[1])
    text = call.message.text
    await bot.send_message(user_id, text)
    await state.clear()

в чем проблема? В первый раз работаю c Fsm, пока не понимаю.


Ответы (1 шт):

Автор решения: CausonQ

Не срабатывает, потому что ловящего ответ пользователю хендлера у вас нет. После того, как прилетело сообщение с кнопкой, стейт установился и бот ждет ответ. Когда вы отправляете ответ, боту приходит message со Form.text, а код у вас ждет callback_query. Вот и не срабатывает.

То есть, должно быть, примерно, так:

@dp.callback_query(lambda call: call.data.startswith('user_'))
async def forward_to_user(call: types.CallbackQuery, state: FSMContext, bot: Bot):
    await state.set_state(Form.text)
    user_id = int(call.data.split('_')[1])
    await state.update_data(chat=user_id)
    await bot.send_message(call.message.chat.id, f"Напишите ответ пользователю:")


@dp.message(Form.text)
async def process_forward(message: types.Message, state: FSMContext, bot: Bot):
    await state.update_data(text=message.text)
    data = await state.get_data()
    text = message.text
    await bot.send_message(data['chat'], text)
    await state.clear()

id чата вам нужно записать уже в коллбеке, что бы передать в хендлер, который отправляет ответ.

В общем виде схема следующая:

  1. Кто-то пишет сообщение, срабатывает хендлер forward_to_admin - отправляет сообщение с инлайн кнопкой.

  2. Жмем на кнопку, срабатывает forward_to_user: Устанавливается стейт, бот ждет сообщение; вот тут мы должны вытащить chat_id из callback_data, что бы передать дальше, вытаскиваем его и записываем в await state.update_data(chat=user_id)

  3. И вот тут, мы просто отправляем боту текстовое сообщение (ну или что угодно), для обработки нужен message, а не callback_query, что бы обработать наш ответ. Достаем, ранее записанный chat_id и по нему отправляем ответ

Надеюсь, понятно объяснил

→ Ссылка