Introduction
Hey, this wiki page will walk you through the inline keyboard example found here. We will start with how python starts with the example, then follow through the code in the same way we expect updates from the user would go through it. Let's do it.
Disclaimer: We will conveniently ignore the imports.
Startup
if __name__ == '__main__':
main()
Lines 68 to 69 tell python that after starting the script, it's supposed to call the main function
main
application = Application.builder().token("TOKEN").build()
The first line in the main function builds an application instance from the Application class. The function calls lined up after another means that the calls happen on the return of the previous call. So .builder()
is called on Application
, .token("TOKEN")
on the return of .builder()
, .build()
on whatever .token("TOKEN")
returns. If you check the docs, you will find that builder returns an ApplicationBuilder instance. So looking there for token, we find that it also returns an (updated) ApplicationBuilder
instance, which is the same for almost every method on that page. This allows this chaining of function calls, since all the function are defined inside the ApplicationBuilder
and it is always returned. Finally, the .build()
builds and then returns the application instance we expect.
application.add_handler(CommandHandler("start", start))
application.add_handler(CallbackQueryHandler(button))
application.add_handler(CommandHandler("help", help_command))
Line 60 to 62 registers our three handlers. The first handler is a CommandHandler. Whenever a user sends a /start command to the bot, the function start
is called. Same situation with the third handler: Whenever a user sends the /help command, help_command
gets called.
The second handler is a CallbackQueryHandler. A Callbackquery is what Telegram sends to our bot when a user presses an InlineButton. Every press of a button gets sent to the button
handler.
application.run_polling()
Line 65 tells the PTB library to start the bot using polling, which means that the library will continuously make a request to the telegram servers and get new updates from there, if they exists.
Let's start our way through the handlers in the same way we would expect a user to go through it. This means we begin with the start handler:
start
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
In line 24 we define a function called start. It is an async function and it takes the two arguments update (instance of an Update) and context (instance of a CallbackContext). The context is the default context type, since we didn't change anything with it. If you want to see how that works, checkout the ContextType bot example. The -> None
indicates to a type checker that this function returns nothing.
keyboard = [
[
InlineKeyboardButton("Option 1", callback_data='1'),
InlineKeyboardButton("Option 2", callback_data='2'),
],
[InlineKeyboardButton("Option 3", callback_data='3')],
]
Line 26 to 32 a variable called keyboard is defined. It is a list of lists, representing a 2D-Matrix. Every "parent" list is a row in the actual inline keyboard (so [[1], [2]]
would be two rows), every entry inside an parent list is a column. So this keyboard will have two rows, Option 1 and Option 2 will be in the first; Option 3 in the second one.
reply_markup = InlineKeyboardMarkup(keyboard)
Line 34 turns our list into an actual Inline Keyboard that we can pass along with our message.
await update.message.reply_text('Please choose:', reply_markup=reply_markup)
In line 36 we reply to the update message with a text (hence reply_text) and pass the keyboard along in the reply_markup
argument. The await
tells the program to stop and wait for the function call to finish. async
and await
are both fundamentals of asyncio programming in python, explaining this further is outside of this example explainer. If you are curious, feel free to search for it, otherwise just accept these keywords as they are.
Now we expect people to press one of the provided buttons, so let's jump to the button callback
button
async def button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
Line 39 defines a function called button. It takes the two arguments update and context and returns nothing. Basically the same as start
.
query = update.callback_query
Line 41 defines query as a shortcut to access the provided CallbackQuery. This is the part of the update which has all the information in it, remember, it gets generated/send to the bot once a user presses a button.
await query.answer()
Line 45 here we answer the CallbackQuery
. We use a convenient shortcut PTB provides. It takes care of calling the actual function and passing all the required parameters to it. If you check out the function, you see that you can pass a text
argument to it, which will be displayed in a little pop-up on the client end, and if you pass show_alert
on top of it, the user has to dismiss the pop-up. Not useful for this example, so we just pass it without these optional arguments.
await query.edit_message_text(text=f"Selected option: {query.data}")
Line 47 edits the message where CallbackQuery
originates from with the text where we tell the user which option we picked. We insert query.data
into the string, which is the data we defined in the keyboard, so the number 1, 2 or 3. Since we don't pass the inline keyboard along again, it will disappear.
help
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
await update.message.reply_text("Use /start to test this bot.")
Line 50 to 52 is a simple callback. Here we reply to the /help command with the provided text: They should use /start to use this bot.
error
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
Line 18 to 21 are the only lines of the code we haven't covered yet. Here we set up the logging module to have the format we want, and we define logger in case we want to use it later. More docs regarding logging can be found here
This section of the wiki is currently in development, feedback is greatly appreciated. Ping one of the admins in our telegram group to anything you want to tell us.
Must read
Concepts & Important Elements
- Architecture Overview
- Builder Pattern for
Application
- Types of Handlers
- Working with Files and Media
- Exceptions, Warnings and Logging
- Concurrency in PTB
Notable Features
- Advanced Filters
- Storing data
- Making your bot persistent
- Adding Defaults
- Job Queue
- Arbitrary
callback_data
- Avoiding flood limits
- Webhooks
- Bot API Forward Compatiblity
Code Resources
- Frequently requested design patterns
- Code snippets
- Performance Optimizations
- Telegram Passport
- Bots built with PTB
- Automated Bot Tests
Examples explained
Networking
Other resources
- Where to host Telegram Bots
- How to host your bot
- Local API Server
- Type Checking with PTB
- Press
- Notes on GAE
- Related Projects
- Emoji
Transition Guides
Administration
- Wiki of
python-telegram-bot
© Copyright 2015-2024 – Licensed by Creative Commons