@gaifutar

Как считать информацию о состоянии с клика пользователем по инлайн клавиатуре?

Делаю бота, часть задачи - сделать меню, где бот задает вопросы, а пользователь отвечает. Всего условно 4 этапа:
Этап 1 - бот спрашивает, какую активность пользователь выбирает.
Этап 2 - бот спрашивает ФИО пользователя.
Этап 3 - бот спрашивает телефон пользователя.
Этап 4 - бот выводит всю информацию с этапов 1-3 на экран.

Когда я делаю все без кнопок, использую FSM (Finite State Machine), то все работает. Но я хочу, чтобы этап 1 был в виде инлайн клавиатуры - пользователь кликает на вариант, информация об этом варианте фиксируется (вместо того, чтобы пользователь писал вручную). Когда пытаюсь реализовать, кнопки добавить получилось, но вот информация с клика так и не передается, остается "разрыв", пользователю все равно вручную приходится вводить текст и только после этого идет переход на следующий этап.

Подскажите, пожалуйста, что мне нужно изменить в коде? Где ошибка? Код прилагаю:

from aiogram import Bot, Dispatcher, types, executor
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.dispatcher.filters import Command
from aiogram.dispatcher.filters.state import StatesGroup, State
from aiogram.dispatcher import FSMContext
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from API_KEY_1196494 import API_KEY

# making a class for a state to move from one state to another later and tie commands to a current state
class reg_state (StatesGroup):
    activity = State()
    full_name = State()
    phone = State()

# button names content
button1_text = 'Activity 1'
button2_text = 'Activity 2'

# buttons
button1 = InlineKeyboardButton (text = button1_text, callback_data='activity1')
button2 = InlineKeyboardButton (text = button2_text, callback_data='activity2')

#keyboard
keyboard_inline = InlineKeyboardMarkup().add(button1).add(button2)

# answers
enter_your_name_details = 'Enter your full name'
enter_your_phone = "Enter your phone number"

bot = Bot(API_KEY)
storage = MemoryStorage()
dp = Dispatcher(bot, storage = storage)


# job initiated, asking to choose activity
@dp.message_handler(commands=['start'])
async def activity_reg (message: types.Message):
    user_name_greeting = message.from_user.first_name
    await message.answer (text = f"{user_name_greeting}, Which activity do you want to choose?", reply_markup=keyboard_inline)
        

# reading button info
async def inline_buttons_handler(call: types.CallbackQuery):
    match call.data:
        case 'activity1':
            await call.message.answer (f"You chose {button1_text}")
            await bot.answer_callback_query(callback_query_id=call.id)
            await reg_state.activity.set()
        case 'activity2':
            await call.message.answer (f"You chose {button2_text}")
            await bot.answer_callback_query(callback_query_id=call.id)
            await reg_state.activity.set()
    await call.answer()

@dp.callback_query_handler(inline_buttons_handler)

# grabbing the info about activity provided by the user and asking for name
@dp.message_handler(state=reg_state.activity)
async def grab_activity (message: types.Message, state: FSMContext):
    await state.update_data(activity = message.text)
    await message.answer (enter_your_name_details)
    await reg_state.full_name.set()

# grabbing the info about the user's name and asking for phone
@dp.message_handler(state=reg_state.full_name)
async def grab_full_name (message: types.Message, state: FSMContext):
    await state.update_data(full_name = message.text)
    await message.answer (enter_your_phone)
    await reg_state.phone.set()

# grabbing user's phone info and wrapping it up
@dp.message_handler (state = reg_state.phone)
async def grab_phone (message: types.Message, state: FSMContext):
    await state.update_data (phone = message.text)
    data_full = await state.get_data()
    await message.answer(f"Activity: {data_full['activity']}'\n"
                         f"Full name: {data_full['full_name']}\n"
                         f"Phone: {data_full['phone']}")
    await state.finish()

if __name__ == '__main__':
    executor.start_polling(dp)
  • Вопрос задан
  • 228 просмотров
Пригласить эксперта
Ответы на вопрос 1
@gaifutar Автор вопроса
Сделал решение, вопрос закрыт. Сам спросил - сам ответил.

from aiogram import Bot, Dispatcher, types, executor
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton
from aiogram.dispatcher.filters import Command
from aiogram.dispatcher.filters.state import StatesGroup, State
from aiogram.dispatcher import FSMContext
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from API_KEY_1196494 import API_KEY

# making a class for a state to move from one state to another later and tie commands to a current state
class reg_state (StatesGroup):
    activity = State()
    full_name = State()
    phone = State()

# button names content
button1_text = 'Activity 1' 
button2_text = 'Activity 2'

# buttons
button1 = InlineKeyboardButton (text = button1_text, callback_data='activity1')
button2 = InlineKeyboardButton (text = button2_text, callback_data='activity2')

#keyboard
keyboard_inline = InlineKeyboardMarkup().add(button1).add(button2)

# answers
enter_your_name_details = 'Enter your full name'
enter_your_phone = "Enter your phone number"

bot = Bot(API_KEY)
storage = MemoryStorage()
dp = Dispatcher(bot, storage = storage)


# job initiated, asking to choose activity
@dp.message_handler(commands=['start'])
async def activity_reg (message: types.Message):
    user_name_greeting = message.from_user.first_name
    await message.answer (text = f"{user_name_greeting}, Which activity do you want to choose?", reply_markup=keyboard_inline)

@dp.callback_query_handler(lambda call: call.data in ['activity1', 'activity2'])
async def inline_buttons_handler(call: types.CallbackQuery, state: FSMContext):
    await bot.answer_callback_query(callback_query_id=call.id)
    await state.update_data(activity=call.data)
    await reg_state.full_name.set()
    await call.message.answer (enter_your_name_details)


# grabbing the info about the user's name and asking for phone
@dp.message_handler(state=reg_state.full_name)
async def grab_full_name (message: types.Message, state: FSMContext):
    await state.update_data(full_name = message.text)
    await message.answer (enter_your_phone)
    await reg_state.phone.set()

# grabbing user's phone info and wrapping it up
@dp.message_handler (state = reg_state.phone)
async def grab_phone (message: types.Message, state: FSMContext):
    await state.update_data (phone = message.text)
    data_full = await state.get_data()
    await message.answer(f"Activity: {data_full['activity']}'\n"
                         f"Full name: {data_full['full_name']}\n"
                         f"Phone: {data_full['phone']}")
    await state.finish()



if __name__ == '__main__':
    executor.start_polling(dp)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы