'How to return the keyboard to its original state after the completion of the script?

This script is part of a telegram bot. The task of this script is to provide the user with a multiple choice of options.

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
    Updater,
    CommandHandler,
    CallbackQueryHandler,
    ConversationHandler)

import logging

green_check = '\u2705'
grey_check = '\u2714'

FIRST, ANSWER = range(2)
TEXT_1 = 'Click'
CHECK = grey_check
CLICK = False

KEYS = {'1': (0, 0), '2': (0, 1), '3': (1, 0), '4': (1, 1)}

keyboard = [
[
    InlineKeyboardButton(f'1 {grey_check}', callback_data='1'),
    InlineKeyboardButton(f'2 {grey_check}', callback_data='2'),
],
[
    InlineKeyboardButton(f'3 {grey_check}', callback_data='3'),
    InlineKeyboardButton(f'4 {grey_check}', callback_data='4'),
],
[
    InlineKeyboardButton('Next \u27A1', callback_data='next'),
],
]


def start(update, context):
    CHECK = grey_check
    reply_markup = InlineKeyboardMarkup(keyboard)
    update.message.reply_text(TEXT_1, reply_markup=reply_markup)
    for i in range(1,5):
        context.user_data[f'BUTTON_{i}'] = False

    return FIRST


def clicked(click=None, data=None):
    global keyboard
    global CHECK
    if click == True:
        CHECK = green_check
    else:
        CHECK = grey_check

    keyboard[KEYS[data][0]][KEYS[data][1]] = InlineKeyboardButton(
        f'{data} {CHECK}', callback_data=f'{data}')

    reply_markup = InlineKeyboardMarkup(keyboard)

    return reply_markup


def press(update, context):
    data = update.callback_query.data
    global CLICK
    if context.user_data[f'BUTTON_{data}'] == False:
        context.user_data[f'BUTTON_{data}'] = True
    else:
        context.user_data[f'BUTTON_{data}'] = False

    reply_keyboard = clicked(context.user_data[f'BUTTON_{data}'], data)
    update.callback_query.edit_message_text(text=TEXT_1, reply_markup=reply_keyboard)
    return FIRST


def send(update, context):
    text = ''
    for i in range(1, 5):
        text += f'{i} - ' + str(context.user_data[f'BUTTON_{i}']) + '\n'
    context.user_data[ANSWER] = text
    update.callback_query.edit_message_text(text=context.user_data[ANSWER])
    return ConversationHandler.END


def main():
    updater = Updater(
        'TOKEN', use_context=True)
    dp = updater.dispatcher
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],
        states={
            FIRST: [
                    CallbackQueryHandler(press, pattern='^'+str(1)+'$'),
                    CallbackQueryHandler(press, pattern='^'+str(2)+'$'),
                    CallbackQueryHandler(press, pattern='^'+str(3)+'$'),
                    CallbackQueryHandler(press, pattern='^'+str(4)+'$'),
                    CallbackQueryHandler(send, pattern='^'+'next'+'$'),
                    ],
        },
        fallbacks=[CommandHandler('start', start)]
    )

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

if __name__ == "__main__":
    main()

After selecting the option, the color of the button changes to green, after sending the data and the next run of the /start script, the keyboard does not return to its original form. The buttons pressed by the user remain green, while the data change, when the buttons are pressed, occurs as expected.



Solution 1:[1]

After several attempts, I found this solution:

from telegram import InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
    Updater,
    CommandHandler,
    CallbackQueryHandler,
    ConversationHandler)

import logging

green_check = '\u2705'
grey_check = '\u2714'

FIRST, ANSWER = range(2)
TEXT_1 = 'Click'
CHECK = grey_check
CLICK = False
BUTTONS = []
KEYS = {'1': (0, 0), '2': (0, 1), '3': (1, 0), '4': (1, 1)}

keyboard = [
[
    InlineKeyboardButton(f'1 {CHECK}', callback_data='1'),
    InlineKeyboardButton(f'2 {CHECK}', callback_data='2'),
],
[
    InlineKeyboardButton(f'3 {CHECK}', callback_data='3'),
    InlineKeyboardButton(f'4 {CHECK}', callback_data='4'),
],
[
    InlineKeyboardButton('Next \u27A1', callback_data='next'),
],
]


def start(update, context):
    global CHECK
    global keyboard
    global BUTTONS
    CHECK = grey_check
    for data in BUTTONS:
        keyboard[KEYS[data][0]][KEYS[data][1]] = InlineKeyboardButton(
            f'{data} {CHECK}', callback_data=f'{data}')
    reply_markup = InlineKeyboardMarkup(keyboard)
    update.message.reply_text(TEXT_1, reply_markup=reply_markup)
    for i in range(1,5):
        context.user_data[f'BUTTON_{i}'] = False
    BUTTONS = []
    return FIRST


def clicked(click=None, data=None):
    global keyboard
    global CHECK
    global BUTTONS
    if click == True:
        CHECK = green_check
    else:
        CHECK = grey_check

    BUTTONS.append(data)
    keyboard[KEYS[data][0]][KEYS[data][1]] = InlineKeyboardButton(
        f'{data} {CHECK}', callback_data=f'{data}')

    reply_markup = InlineKeyboardMarkup(keyboard)

    return reply_markup


def press(update, context):
    data = update.callback_query.data
    global CLICK
    if context.user_data[f'BUTTON_{data}'] == False:
        context.user_data[f'BUTTON_{data}'] = True
    else:
        context.user_data[f'BUTTON_{data}'] = False

    reply_keyboard = clicked(context.user_data[f'BUTTON_{data}'], data)
    update.callback_query.edit_message_text(text=TEXT_1, reply_markup=reply_keyboard)
    return FIRST


def send(update, context):
    text = ''
    for i in range(1, 5):
        text += f'{i} - ' + str(context.user_data[f'BUTTON_{i}']) + '\n'
    context.user_data[ANSWER] = text
    update.callback_query.edit_message_text(text=context.user_data[ANSWER])

    return ConversationHandler.END


def main():
    updater = Updater(
        'TOKEN', use_context=True)
    dp = updater.dispatcher
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],
        states={
            FIRST: [
                    CallbackQueryHandler(press, pattern='^'+str(1)+'$'),
                    CallbackQueryHandler(press, pattern='^'+str(2)+'$'),
                    CallbackQueryHandler(press, pattern='^'+str(3)+'$'),
                    CallbackQueryHandler(press, pattern='^'+str(4)+'$'),
                    CallbackQueryHandler(send, pattern='^'+'next'+'$'),
                    ],
        },
        fallbacks=[CommandHandler('start', start)]
    )

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

if __name__ == "__main__":
    main()

Perhaps this is not the best solution. Do you have any ideas how to improve this code?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1