V
V
vanguar2020-06-26 14:10:31
Python
vanguar, 2020-06-26 14:10:31

How to create a questionnaire in a telegram bot?

Good afternoon.
Problem:
When you click the inline "Start" button, a message appears: "Press /reg to start registration."
Pressing reg passes catches the CommandHandler and transfers control to the reg_handler function.
The message appears to the user: "Please enter your name" The
user enters a name and presses Enter.
A message should come from the Bot: "Select your gender to continue:", but nothing happens.
Only when you re-enter the command: "/reg" the message is displayed: "Select your gender to continue:" And so on.
As planned, the command: /reg should only start a dialog, but in fact the transition from function to function occurs not as a reaction / next step to user input, but by entering the command: "/reg". Where did I screw up, what did I do wrong?
Python version 3.8.3
python-telegram-bot==12.2.0
Below is the entire code.
Thank you.

NAME, GENDER, AGE = range(3)

# Идентификаторы кнопок
CALLBACK_BUTTON1_LEFT = "callback_button1_left"
CALLBACK_BUTTON2_RIGHT = "callback_button2_right"
CALLBACK_BUTTON3_MORE = "callback_button3_more"
REG = "reg"

TITLES = {
    CALLBACK_BUTTON1_LEFT: "Новое сообщение",
    CALLBACK_BUTTON2_RIGHT: "Отредактировать",
    CALLBACK_BUTTON3_MORE: "Регистрация пользователя",
    REG: "Начать",
}

def get_base_inline_keyboard():
    """Получить клавиатуру сообщений"""
    keyboard = [
        [
            InlineKeyboardButton(TITLES[CALLBACK_BUTTON1_LEFT], callback_data=CALLBACK_BUTTON1_LEFT),
            InlineKeyboardButton(TITLES[CALLBACK_BUTTON2_RIGHT], callback_data=CALLBACK_BUTTON2_RIGHT),
        ],
        [
            InlineKeyboardButton(TITLES[CALLBACK_BUTTON3_MORE], callback_data=CALLBACK_BUTTON3_MORE),
        ],

    ]
    return InlineKeyboardMarkup(keyboard)

def get_keyboard_2():
    """Получить клавиатуру сообщений_2"""
    keyboard = [

        [
            InlineKeyboardButton(TITLES[REG], callback_data=REG),
        ],

    ]
    return InlineKeyboardMarkup(keyboard)


def log_errors(f):  # Декоратор для отлова ошибок
    def inner(*args, **kwargs):
        try:
            return f(*args, **kwargs)
        except Exception as e:
            error_message = f'Произошла ошибка: {e}'
            print(error_message)
            raise e

    return inner
@log_errors
def do_start(update: Update, context: CallbackContext):
    chat_id = update.message.chat_id

    p, _ = Profile.objects.get_or_create(
        # _ - булевый флаг, кот означает профиль создан только что или нет! p - объект профиля, кот взят из базы
        external_id=chat_id,
        defaults={
            'name': update.message.from_user.username,
        }
    )
    update.message.reply_text(
        text=f'Отправь мне что-нибуть',
        reply_markup=get_base_inline_keyboard(),

    )

@log_errors
def do_help(update: Update, context: CallbackContext):
    chat_id = update.message.chat_id

    p, _ = Profile.objects.get_or_create(
        # _ - булевый флаг, кот означает профиль создан только что или нет! p - объект профиля, кот взят из базы
        external_id=chat_id,
        defaults={
            'name': update.message.from_user.username,
        }
    )
    update.message.reply_text(
        text=f'Этот Бот помогает найти попутчика в путешествие',
        reply_markup=get_base_inline_keyboard(),
    )


@log_errors
def do_about(update: Update, context: CallbackContext):
    chat_id = update.message.chat_id

    p, _ = Profile.objects.get_or_create(
        # _ - булевый флаг, кот означает профиль создан только что или нет! p - объект профиля, кот взят из базы
        external_id=chat_id,
        defaults={
            'name': update.message.from_user.username,
        }
    )
    update.message.reply_text(
        text=f'Мы группа энтузиастов и заядлых путешественников',
        reply_markup=get_base_inline_keyboard(),
    )


@log_errors
def keyboard_callback_handler(update: Update, context: CallbackContext):
    """Обработчик всех кнопок всех событий"""
    query = update.callback_query  # Идентификатор кнопки
    data = query.data

    chat_id = update.effective_message.chat_id
    p, _ = Profile.objects.get_or_create(
        # _ - булевый флаг, кот означает профиль создан только что или нет! p - объект профиля, кот взят из базы
        external_id=chat_id,
        defaults={
            'name': update.effective_message.from_user.username,
        }
    )

    if data == CALLBACK_BUTTON1_LEFT:

        update.effective_message.reply_text(

            text=f'Вы нажали на кнопку слева',
            reply_markup=get_base_inline_keyboard(),
        )
    elif data == CALLBACK_BUTTON2_RIGHT:

        update.effective_message.reply_text(

            text=f'Вы нажали на кнопку справа',
            reply_markup=get_base_inline_keyboard(),
        )
    elif data == CALLBACK_BUTTON3_MORE:
        update.effective_message.reply_text(

            text=f'Регистрация анкеты пользователя',
            reply_markup=get_keyboard_2(),
        )
    elif data == REG:
        update.effective_message.reply_text(
            text=f'Нажмите /reg для начала регистрации',
            reply_markup=get_base_reply_keyboard(),
            parse_mode='Markdown',
        )

@log_errors
def reg_handler(update: Update, context: CallbackContext):

    update.message.reply_text(f'''Укажите Ваше имя
    ''')
    return NAME


@log_errors
def name_handler(update: Update, context: CallbackContext):
    context.user_data[NAME] = update.effective_message.text

    update.effective_message.reply_text(f'''Выбирите свой пол, чтобы продолжить:
''')
    return GENDER

@log_errors
def age_handler(update: Update, context: CallbackContext):
    context.user_data[GENDER] = update.effective_message.text

    update.effective_message.reply_text(f'''введите свой возраст:
''')
    return AGE

@log_errors
def finish_handler(update: Update, context: CallbackContext):
    context.user_data[AGE] = update.effective_message.text

    update.effective_message.reply_text(f'''Все данные успешно сохранены''')
    return ConversationHandler.END

@log_errors
def cancel_handler(update: Update, context: CallbackContext):
    update.effective_message.reply_text(f'''Отмена''')
    return ConversationHandler.END


@log_errors
def do_count(update: Update, context: CallbackContext):
    chat_id = update.effective_message.chat_id

    p, _ = Profile.objects.get_or_create(
        # _ - булевый флаг, кот означает профиль создан только что или нет! p - объект профиля, кот взят из базы
        external_id=chat_id,
        defaults={
            'name': update.effective_message.from_user.username,
        }
    )
    count = Message.objects.filter(profile=p).count()

    update.effective_message.reply_text(
        text=f'У вас {count} сообщений',
    )

    reply_text = f"Ваш ID = {chat_id}\nMessage ID = {m.pk}\n{text}"
    update.effective_message.reply_text(
        text=reply_text,
    )


@log_errors
def do_echo(update: Update, context: CallbackContext):
    chat_id = update.effective_message.chat_id
    text = update.effective_message.text

    p, _ = Profile.objects.get_or_create(
        # _ - булевый флаг, кот означает профиль создан только что или нет! p - объект профиля, кот взят из базы
        external_id=chat_id,
        defaults={
            'name': update.effective_message.from_user.username,
        }
    )
    m = Message(
        profile=p,
        text=text,
    )
    m.save()

    if text == BUTTON1_HELP:
        return do_help(update=update, context=CallbackContext)
    elif text == BUTTON2_ABOUT:
        return do_about(update=update, context=CallbackContext)
 
class Command(BaseCommand):
    help = 'Телеграм-бот'

    def handle(self, *args, **options):
        request = Request(
            connect_timeout=0.5,
            read_timeout=1.0,
        )
        bot = Bot(
            request=request,
            token=settings.TOKEN,
        )
        print(bot.get_me())  # Расспечатаем инфу о боте

        # 2-обработчик
        updater = Updater(
            bot=bot,
            use_context=True,
        )

        conv_handler = ConversationHandler(
            entry_points=[
                CommandHandler('reg', reg_handler, pass_user_data=True),
            ],
            states={
                NAME: [
                    MessageHandler(Filters.all, name_handler, pass_user_data=True),
                ],
                GENDER: [
                    MessageHandler(Filters.all, age_handler, pass_user_data=True),
                ],
                AGE: [
                    MessageHandler(Filters.all, finish_handler, pass_user_data=True),
                ],
            },
            fallbacks=[
                CommandHandler('cancel', cancel_handler),
            ],
        )

        message_handler = MessageHandler(Filters.text, do_echo)
        updater.dispatcher.add_handler(message_handler)

        message_handler2 = CommandHandler('count', do_count)
        updater.dispatcher.add_handler(message_handler2)

        start_handler = CommandHandler('start', do_start)
        updater.dispatcher.add_handler(start_handler)

        buttons_handler = CallbackQueryHandler(callback=keyboard_callback_handler, )
        updater.dispatcher.add_handler(buttons_handler)

        help_handler = CommandHandler('help', do_help)
        updater.dispatcher.add_handler(help_handler)

        about_handler = CommandHandler('about', do_about)
        updater.dispatcher.add_handler(about_handler)

        updater.dispatcher.add_handler(conv_handler)
    
        updater.start_polling()
        updater.idle()

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question