Почему не работает FSM(state) при channel_post_handler?

Рейтинг: 0Ответов: 1Опубликовано: 12.02.2023

При нажатии на кнопку бот отправляет сообщение с просьбой указать название (название отправляю в ответ), записывая message_data (для примера), дальше через через state должен вызываться обработчик постов в канале, но этого не происходит(в коде не отправляет последний print "test handler"). Если использовать без state все работает, так же если использовать это в самом боте через message_handler тоже все работает. Почему не работает и как можно использовать FSM для сообщений в канале, ибо нужно сохранять несколько подряд сообщений от туда при нажатии кнопки.

  @dp.callback_query_handler(text='test_video')
async def test_video(call: types.CallbackQuery, state: FSMContext):
    message_data = await bot.send_message(chat_id=call.message.chat.id, text='Хорошо теперь отправь мне название', reply_markup= ikb_back)

    async with state.proxy() as data:
        data['message_data'] = message_data

    print("test set")  # отправляет
    await astate.Admin_State.test_video.name.set()


@dp.channel_post_handler(state=astate.Admin_State.test_video.name)
async def print_test_video(message: types.Message, state: FSMContext):
    print("test handler")  # не отправляет

Ответы

▲ 0

FSMContext устроен так, что для каждого диалога хранит свой контекст — вы упустили это. После нажатия на кнопку в одном диалоге активировался нужный вам state, который вы потом пытаетесь поймать уже в другом диалоге — канале, для которого этот state не задан. Перенести контекст одного диалога в контекст другого — так сделать не получится.
Тогда, сообщение, в котором находится кнопка test_video, тоже должно быть отправлено в канал. Либо же, наоборот, как вы сделали, считывать сообщения не из канала, а из того же диалога при помощи message_handler.

Чтобы решить проблему, с которой вы столкнулись, вам необходим пустой хэндлер сообщений из канала и внешняя переменная, в которой вы будете хранить необходимое вам состояние:

get_video_name = False


@dp.callback_query_handler(text='test_video')
async def test_video(call: types.CallbackQuery):
    message_data = await bot.send_message(chat_id=call.message.chat.id, text='Хорошо теперь отправь мне название', reply_markup= ikb_back)

    async with state.proxy() as data:
        data['message_data'] = message_data

    print("test set")  # отправляет
    get_video_name = True


@dp.channel_post_handler()
async def print_test_video(message: types.Message):
    if get_video_name:
        print("test handler")  # не отправляет
        get_video_name = False

Конечно, не очень уместно делать так, как это сделал я. Хранить какие бы то ни было данные в виде глобальных переменных — не совсем хорошая практика, и гораздо лучше, если у вас есть какая-то БД или в крайнем случае JSON-файл, где вы могли бы это хранить.