Вызов функция по порядку не происходит, потому что параметр context_type = ['text']. Aiogram Python

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

Всем привет! Картина выглядит примерно так : Я делаю телеграм-бота , у которого есть функционал для пользователя (некого рабочего), который в конце смены делает отчет о проделанной им работе. Чтобы записать данные о проделанной работе , в телеграм боте есть "Меню" , из которого он выбирает по некому "дереву" данные для заполнения лога . Дерево выглядит примерно так [Изделие -> детали->тех. процесс с деталью -> количество сделанных деталей], все кнопки генерируются динамически, в зависимости от выбора предыдущего пункта юзера, а данные для генерации берутся из БД. Я столкнулся с проблемой , что функция не переходит на следующий этап , потому что в context_type в 3х декораторах стоит параметр ['text'] , однако я не могу захардкодить эту часть кода. Потому что предполагается , что не известно , какой выбор сделает юзер.

Вопрос : Как сделать так , чтобы после завершения изменения состояния одного параметра , вызывалась следующая функция.

@dp.message_handler(text=["Отчёт о работе"])
async def add_item(message: types.Message):
    await WorkReport.product.set()
    await message.answer(text="Выбери изделие", reply_markup=kb.product_name_panel)


@dp.callback_query_handler(state=WorkReport.product)
async def add_item_product(call: types.CallbackQuery, state: FSMContext):
    async with state.proxy() as data:
        data['product'] = call.data
    await call.message.answer(text="Выбери деталь", reply_markup=kb.DetailsOfProductButton(product_name=call.data))
    await WorkReport.next()


@dp.message_handler(content_types=['text'], state=WorkReport)
async def add_item_detail(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['detail'] = message.text
    await message.answer(text="Выбери операцию", reply_markup=kb.PartOperationButton(data['product'], data['detail']))
    await WorkReport.next()


@dp.message_handler(content_types=['text'], state=WorkReport)
async def add_item_operation(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['operation'] = message.text
    await WorkReport.next()


@dp.message_handler(content_types=['text'], state=WorkReport)
async def add_item_amount(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['amount'] = message.text
    await state.finish()

Ответы

▲ 0Принят

Дело не в content_types=['text'], его можно даже не указывать. Проблема в том, что в хэндлере вы указываете не состояние, а саму машину состояний. Ваша FSM должна выглядеть так:

class WorkReport(StatesGroup):
    product = State()
    detail = State()
    operation = State()
    amount = State()

а дальше вы уже должны указывать нужный state для хэндлера. Ваш код должен выглядеть как-то так:

@dp.message_handler(text=["Отчёт о работе"])
async def add_item(message: types.Message):
    await WorkReport.product.set()
    await message.answer(text="Выбери изделие", reply_markup=kb.product_name_panel)


@dp.callback_query_handler(state=WorkReport.product)
async def add_item_product1(call: types.CallbackQuery, state: FSMContext):
    async with state.proxy() as data:
        data['product'] = call.data
    await call.message.edit_text(text="Выбери деталь", reply_markup=kb.DetailsOfProductButton(product_name=call.data))
    await WorkReport.next()


@dp.callback_query_handler(state=WorkReport.detail)
async def add_item_detail(call: types.CallbackQuery, state: FSMContext):
    async with state.proxy() as data:
        data['detail'] = call.data
    await call.message.edit_text(text="Выбери операцию", reply_markup=kb.PartOperationButton(data['product'], data['detail']))
    await WorkReport.next()


@dp.callback_query_handler(state=WorkReport.operation)
async def add_item_operation(call: types.CallbackQuery, state: FSMContext):
    async with state.proxy() as data:
        data['operation'] = call.data
    await call.message.answer(text="Укажите количество")
    await WorkReport.next()


@dp.message_handler(state=WorkReport.amount)
async def add_item_amount(message: types.Message, state: FSMContext):
    async with state.proxy() as data:
        data['amount'] = message.text
    await message.answer(f"Вы выбрали:\n{data['product']}\n{data['detail']}\n{data['operation']}\n{data['amount']}")
    await state.finish()

Из вашего кода не понятно как именно вы генерируете клавиатуру, но указанная выше FSM подразумевает, что для product, detail и operation клавиатура будет генерироваться, а amount пользователь вводит вручную