Search code examples
pythontelegrampython-telegram-bot

CallbackQueryHandler is not being called in python-telegram-bot


I am using InlineKeyboard while making a telegram bot using python-telegram-bot. The problem is that the query handler function, button(), is not being called on clicking any button in the inline keyboard.

Here is the code

from telegram import *
from telegram.ext import *

print('bot executed')
token = <BOT_TOKEN>


async def send_message_in_channel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    global new_data
    await context.bot.send_message(chat_id=<CHANNEL_USERNAME>, text="new_data")


async def message(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    await context.bot.delete_message(update.effective_chat.id, message_id=update.message.id)


async def button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    query = update.callback_query
    await query.answer()
    print('button reached')
    if query.data == 'True':
        print("choose yes")
        await send_message_in_channel(update, context)
    elif query.data == 'False':
        print("choose no")

async def option(new_data) -> None:
    bot = Bot(token=token)
    options = [
        [
            InlineKeyboardButton('Yes, Post It', callback_data="True"),
            InlineKeyboardButton('No, Don\'t Post', callback_data="False")
        ],
    ]

    reply_markup = InlineKeyboardMarkup(options)
    await bot.send_message(chat_id=<MY_OWN_CHAT_ID>, text=new_data, reply_markup=reply_markup, disable_web_page_preview=True)


if __name__ == '__main__':
    new_data = ''
    
    application = ApplicationBuilder().token(token).build()
    application.add_handler(CallbackQueryHandler(button))
    application.add_handler(MessageHandler(
        filters.TEXT & (~filters.COMMAND), message))
    application.run_polling()

The option() function is being called from a external function with text as parameter 'new_data'.

I didn't face this issue while calling option from bot itself like using CommandHandler('start', option) and replacing new_data with 'update, context'. But that is not what I want. Since on calling option() from outside, I don't have any context or update object.

I also tried changing context of button() from ContextTypes.DEFAULT_TYPE to CallbackContext with no luck.


Solution

  • When I run the option function before calling application.run_polling, your example works fine for me, i.e. the CallbackqueryHandler(button) is called as expected. I tested on the following setup (output of python -m telegram):

    python-telegram-bot 20.2 (v20.2-17-g3f444dad)
    Bot API 6.6
    Python 3.11.3 (tags/v3.11.3:f3909b8, Apr  4 2023, 23:49:59) [MSC v.1934 64 bit (AMD64)]
    

    I have a few additional comments:

    • global new_data: global is in general discuraged. Note that python-telegram-bot comes with a built-in mechanism that helps you avoid those.
    • there is not really a need to initialize a new Bot instance within option. If you define your application object on a global level, you can directly use the application.bot.
    • changing ContextTypes.DEFAULT_TYPE to CallbackContext can not be expected to have any runtime effect. Those are type hints. You can read up on that topic e.g. here and here.

    Disclaimer: I'm currently the maintainer of python-telegram-bot.