### Example of post_init callback Source: https://docs.python-telegram-bot.org/en/stable/telegram.ext.applicationbuilder.html This example demonstrates how to use the post_init method to set bot commands after initialization but before starting the polling or webhook. ```python async def post_init(application: Application) -> None: await application.bot.set_my_commands([('start', 'Starts the bot')]) application = Application.builder().token("TOKEN").post_init(post_init).build() ``` -------------------------------- ### Main Bot Setup Source: https://docs.python-telegram-bot.org/en/stable/examples.paymentbot.html This snippet demonstrates how to set up the Telegram bot application, add various handlers for commands, shipping queries, pre-checkout queries, and successful payments, and then start polling for updates. ```python def main() -> None: """Starts the bot and sets up handlers.""" # Create the Application and pass it your bot's token. application = Application.builder().token("TOKEN").build() # Start command to display usage instructions application.add_handler(CommandHandler("start", start_callback)) # Command handlers for starting the payment process application.add_handler(CommandHandler("shipping", start_with_shipping_callback)) application.add_handler(CommandHandler("noshipping", start_without_shipping_callback)) # Handler for shipping query (if product requires shipping) application.add_handler(ShippingQueryHandler(shipping_callback)) # Pre-checkout handler for verifying payment details. application.add_handler(PreCheckoutQueryHandler(precheckout_callback)) # Handler for successful payment. Notify the user that the payment was successful. application.add_handler( MessageHandler(filters.SUCCESSFUL_PAYMENT, successful_payment_callback) ) # Start polling for updates until interrupted (CTRL+C) application.run_polling(allowed_updates=Update.ALL_TYPES) if __name__ == "__main__": main() ``` -------------------------------- ### Optional Dependencies Installation Source: https://docs.python-telegram-bot.org/en/stable Examples of installing python-telegram-bot with various optional dependencies. ```bash pip install "python-telegram-bot[passport]" pip install "python-telegram-bot[socks]" pip install "python-telegram-bot[http2]" pip install "python-telegram-bot[rate-limiter]" pip install "python-telegram-bot[webhooks]" pip install "python-telegram-bot[callback-data]" pip install "python-telegram-bot[job-queue]" ``` ```bash pip install "python-telegram-bot[socks,webhooks]" ``` ```bash pip install "python-telegram-bot[all]" ``` ```bash pip install "python-telegram-bot[ext]" ``` -------------------------------- ### ConversationBot2 Example Source: https://docs.python-telegram-bot.org/en/stable/examples.conversationbot2.html This is the main example code for the ConversationBot2, demonstrating how to set up and run a conversation bot. ```python import logging from telegram import Update from telegram.ext import ( Application, CommandHandler, ConversationHandler, MessageHandler, filters, CallbackContext, ) # Enable logging logging.basicConfig( format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO ) logger = logging.getLogger(__name__) # Define states for the conversation ASK_NAME, ASK_AGE, ASK_HOBBY = range(3) async def start(update: Update, context: CallbackContext) -> int: """Starts the conversation and asks for the user's name.""" await update.message.reply_text( "Hi! My name is Professor Bot. " "I will keep track of your conversations with me.\n" "What's your name? " "Send /cancel to stop the conversation at any time." ) return ASK_NAME async def ask_name(update: Update, context: CallbackContext) -> int: """Stores the user's name and asks for their age.""" user = update.message.from_user logger.info("Name of %s: %s", user.first_name, update.message.text) context.user_data["name"] = update.message.text await update.message.reply_text( f"Nice to meet you, {context.user_data['name']}! " "How old are you?" ) return ASK_AGE def received_age(update: Update, context: CallbackContext) -> int: """Stores the user's age and asks for their hobby.""" user = update.message.from_user logger.info("Age of %s: %s", user.first_name, update.message.text) context.user_data["age"] = update.message.text await update.message.reply_text( "Awesome! Your age is {}. " "Finally, what's your hobby?" ) return ASK_HOBBY async def ask_hobby(update: Update, context: CallbackContext) -> int: """Stores the user's hobby and ends the conversation.""" user = update.message.from_user logger.info("Hobby of %s: %s", user.first_name, update.message.text) context.user_data["hobby"] = update.message.text await update.message.reply_text( f"Cool! So your name is {context.user_data['name']}, " f"you are {context.user_data['age']} years old, " f"and your hobby is {context.user_data['hobby']}. " "I'll remember this!" ) return ConversationHandler.END async def cancel(update: Update, context: CallbackContext) -> int: """Cancels and ends the conversation.""" user = update.message.from_user logger.info("User %s canceled the conversation.", user.first_name) await update.message.reply_text( "Bye! I hope we can talk again some day." ) return ConversationHandler.END def main() -> None: """Run the bot.""" # Create the Application and pass it your bot's token. application = Application.builder().token("YOUR_BOT_TOKEN").build() # Create a ConversationHandler conv_handler = ConversationHandler( entry_points=[CommandHandler("start", start)], states={ ASK_NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_name)], ASK_AGE: [MessageHandler(filters.TEXT & ~filters.COMMAND, received_age)], ASK_HOBBY: [MessageHandler(filters.TEXT & ~filters.COMMAND, ask_hobby)], }, fallbacks=[CommandHandler("cancel", cancel)], ) # Add the conversation handler to the application application.add_handler(conv_handler) # Run the bot until the user presses Ctrl-C application.run_polling(allowed_updates=Update.ALL_TYPES) if __name__ == "__main__": main() ``` -------------------------------- ### Example Usage Source: https://docs.python-telegram-bot.org/en/stable/telegram.inputstorycontentvideo.html This example shows how to create an InputStoryContentVideo object and send it as a story. ```python from telegram import InputStoryContentVideo # Assuming you have a bot instance and a chat_id # bot.send_story(chat_id=chat_id, video=InputStoryContentVideo(video="/path/to/your/video.mp4")) ``` -------------------------------- ### Basic Conversation Handler Example Source: https://docs.python-telegram-bot.org/en/stable/examples.conversationbot.html A simple example of a ConversationHandler that guides the user through a series of questions to collect information. ```Python from telegram import Update from telegram.ext import (Application, CommandHandler, ContextTypes, ConversationHandler, MessageHandler, filters) # Define states for the conversation NAME, AGE, GENDER = range(3) async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Starts the conversation and asks for the user's name.""" await update.message.reply_text( "Hi! My name is Bot. I will guide you through a series of questions. \n" "Send /cancel at any time to exit.\n\n" "What's your name?" ) return NAME async def name(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Stores the user's name and asks for their age.""" user_data = context.user_data user_data['name'] = update.message.text await update.message.reply_text(f"Nice to meet you, {user_data['name']}! What's your age?" ) return AGE async def age(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Stores the user's age and asks for their gender.""" user_data = context.user_data try: user_data['age'] = int(update.message.text) await update.message.reply_text( "Great! What's your gender? (Male/Female/Other)" ) return GENDER except ValueError: await update.message.reply_text( "This doesn't look like a valid age. Please enter a number." ) return AGE async def gender(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Stores the user's gender and ends the conversation.""" user_data = context.user_data user_data['gender'] = update.message.text await update.message.reply_text( f"Okay, I've got your name: {user_data['name']}, " f"age: {user_data['age']}, " f"and gender: {user_data['gender']}. " "Thanks for providing the information!" ) # Clear user data for the next conversation context.user_data.clear() return ConversationHandler.END async def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Cancels and ends the conversation.""" user = update.message.from_user await update.message.reply_text( "Okay, I will stop the conversation. " "Hope to talk to you later!" ) context.user_data.clear() return ConversationHandler.END def main() -> None: """Run the bot.""" # Create the Application and pass it your bot's token. application = Application.builder().token("YOUR_BOT_TOKEN").build() # Setup the ConversationHandler conv_handler = ConversationHandler( entry_points=[CommandHandler("start", start)], states={ NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, name)], AGE: [MessageHandler(filters.TEXT & ~filters.COMMAND, age)], GENDER: [MessageHandler(filters.TEXT & ~filters.COMMAND, gender)], }, fallbacks=[CommandHandler("cancel", cancel)], ) application.add_handler(conv_handler) # Run the bot until the user presses Ctrl-C application.run_polling(allowed_updates=Update.ALL_TYPES) if __name__ == "__main__": main() ``` -------------------------------- ### Sending a video as a story Source: https://docs.python-telegram-bot.org/en/stable/telegram.inputstorycontentvideo.html This example shows how to send a video as a story using the `InputStoryContentVideo` class. ```Python from telegram import InputStoryContentVideo # Assuming 'bot' is an instance of Bot and 'chat_id' is the target chat ID await bot.send_story( chat_id=chat_id, video=InputStoryContentVideo(video="/path/to/your/video.mp4"), caption="My awesome story!" ) ``` -------------------------------- ### Custom Webhook Bot Implementation Source: https://docs.python-telegram-bot.org/en/stable/examples.customwebhookbot.html This Python script implements a Telegram bot using a custom webhook setup with Flask and Uvicorn. It defines custom context types, handlers for start and webhook updates, and sets up a Flask web application to receive updates from Telegram and custom sources. ```python import html import logging import asyncio from http import HTTPStatus from flask import Flask, request, Response, abort, make_response from telegram import Update from telegram.constants import ParseMode from telegram.ext import ( Application, CallbackContext, CallbackQuery, CommandHandler, ContextTypes, TypeHandler, ) from telegram.warnings import PTBWarning from telegram.webhook import WebhookUpdate import uvicorn from uvicorn.workers import WsgiToAsgi # Enable logging logging.basicConfig(format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO) logger = logging.getLogger(__name__) # Define your bot token, URL, and port here TOKEN = "" URL = "" PORT = 8443 # Port to listen on ADMIN_CHAT_ID = "" class CustomContext(CallbackContext[Application, dict, dict, dict]): """ Custom CallbackContext class that makes `user_data` available for updates of type `WebhookUpdate`. """ @classmethod def from_update(cls, update: object, application: "Application") -> "CustomContext": if isinstance(update, WebhookUpdate): return cls(application=application, user_id=update.user_id) return super().from_update(update, application) async def start(update: Update, context: CustomContext) -> None: """Display a message with instructions on how to use this bot.""" payload_url = html.escape(f"{URL}/submitpayload?user_id=&payload=") text = ( f"To check if the bot is still running, call {URL}/healthcheck.\n\n" f"To post a custom update, call {payload_url}." ) await update.message.reply_html(text=text) async def webhook_update(update: WebhookUpdate, context: CustomContext) -> None: """Handle custom updates.""" chat_member = await context.bot.get_chat_member(chat_id=update.user_id, user_id=update.user_id) payloads = context.user_data.setdefault("payloads", []) payloads.append(update.payload) combined_payloads = "\n• ".join(payloads) text = ( f"The user {chat_member.user.mention_html()} has sent a new payload. " f"So far they have sent the following payloads: \n\n• {combined_payloads}" ) await context.bot.send_message(chat_id=ADMIN_CHAT_ID, text=text, parse_mode=ParseMode.HTML) async def main() -> None: """Set up PTB application and a web application for handling the incoming requests.""" context_types = ContextTypes(context=CustomContext) # Here we set updater to None because we want our custom webhook server to handle the updates # and hence we don't need an Updater instance application = ( Application.builder().token(TOKEN).updater(None).context_types(context_types).build() ) # register handlers application.add_handler(CommandHandler("start", start)) application.add_handler(TypeHandler(type=WebhookUpdate, callback=webhook_update)) # Pass webhook settings to telegram await application.bot.set_webhook(url=f"{URL}/telegram", allowed_updates=Update.ALL_TYPES) # Set up webserver flask_app = Flask(__name__) @flask_app.post("/telegram") # type: ignore[untyped-decorator] async def telegram() -> Response: """Handle incoming Telegram updates by putting them into the `update_queue`""" await application.update_queue.put(Update.de_json(data=request.json, bot=application.bot)) return Response(status=HTTPStatus.OK) @flask_app.route("/submitpayload", methods=["GET", "POST"]) # type: ignore[untyped-decorator] async def custom_updates() -> Response: """ Handle incoming webhook updates by also putting them into the `update_queue` if the required parameters were passed correctly. """ try: user_id = int(request.args["user_id"]) payload = request.args["payload"] except KeyError: abort( HTTPStatus.BAD_REQUEST, "Please pass both `user_id` and `payload` as query parameters.", ) except ValueError: abort(HTTPStatus.BAD_REQUEST, "The `user_id` must be a string!") await application.update_queue.put(WebhookUpdate(user_id=user_id, payload=payload)) return Response(status=HTTPStatus.OK) @flask_app.get("/healthcheck") # type: ignore[untyped-decorator] async def health() -> Response: """For the health endpoint, reply with a simple plain text message.""" response = make_response("The bot is still running fine :)", HTTPStatus.OK) response.mimetype = "text/plain" return response webserver = uvicorn.Server( config=uvicorn.Config( app=WsgiToAsgi(flask_app), port=PORT, use_colors=False, host="127.0.0.1", ) ) # Run application and webserver together async with application: await application.start() await webserver.serve() await application.stop() if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### MenuButtonWebApp Example Source: https://docs.python-telegram-bot.org/en/stable/telegram.menubuttonwebapp.html This example shows how to create a MenuButtonWebApp object. ```python from telegram import MenuButtonWebApp menu_button = MenuButtonWebApp( text="Open Web App", web_app=WebAppInfo(url="https://example.com") ) ``` -------------------------------- ### Install httpx with http2 support Source: https://docs.python-telegram-bot.org/en/stable/telegram.ext.applicationbuilder.html Instructions on how to install the necessary dependency for HTTP/2 support. ```bash pip install httpx[http2] ``` -------------------------------- ### Deep Linking with Custom Command Source: https://docs.python-telegram-bot.org/en/stable/examples.deeplinking.html This example demonstrates how to use a custom command for deep linking. Instead of the default `/start`, a `/mycommand` is used to handle the deep link. ```python from telegram import Update from telegram.ext import Application, CommandHandler, ContextTypes from telegram.ext.deeplinking import extract_args async def handle_deep_link(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Handles a custom deep link command and extracts the payload.""" payload = extract_args(context.args) await update.message.reply_text(f"Custom deep link received with payload: {payload}") def main() -> None: """Run the bot.""" application = Application.builder().token("YOUR_BOT_TOKEN").build() application.add_handler(CommandHandler("mycommand", handle_deep_link)) application.run_polling(allowed_updates=Update.ALL_TYPES) if __name__ == "__main__": main() ``` -------------------------------- ### JobQueue with Updater Source: https://docs.python-telegram-bot.org/en/stable/telegram.ext.jobqueue.html This example shows how to integrate JobQueue with the Updater for a complete bot setup. ```python from telegram.ext import Updater, JobQueue def callback_alarm(context): """Callback for this example with some data.""" context.bot.send_message(chat_id=context.job.context, text="Beep!") def remove_job(update, context): """Remove the scheduled job.""" current_jobs = context.job_queue.get_jobs_by_name('alarm') if current_jobs: for job in current_jobs: job.schedule_removal() update.message.reply_text('All alarms removed!') else: update.message.reply_text('No alarms to remove.') def set_alarm(update, context): """Add a job to the queue.""" chat_id = update.message.chat_id due = 5 # seconds # The job_queue is available in context.job_queue context.job_queue.run_once(callback_alarm, due, context=chat_id, name='alarm') update.message.reply_text('Alarm set!') def main(): # Create the Updater and pass it your bot's token. updater = Updater("YOUR_BOT_TOKEN", use_context=True) # Get the dispatcher to register handlers dp = updater.dispatcher # on different commands - answer in Telegram dp.add_handler(CommandHandler('set', set_alarm)) dp.add_handler(CommandHandler('remove', remove_job)) # Start the Bot updater.start_polling() # Run the bot until you press Ctrl-C or the process receives SIGINT, # SIGTERM or SIGABRT. This should be used most of the time, since # start_polling() is non-blocking and will stop the bot gracefully. updater.idle() if __name__ == '__main__': main() ``` -------------------------------- ### MenuButtonWebApp Source: https://docs.python-telegram-bot.org/en/stable/telegram.menubuttonwebapp.html This is an example of how to use MenuButtonWebApp. ```python from telegram import MenuButtonWebApp menu_button = MenuButtonWebApp(text="Open Web App", url="https://www.example.com") ``` -------------------------------- ### Conversation Bot Example Source: https://docs.python-telegram-bot.org/en/stable/examples.conversationbot2.html This Python script demonstrates a complex conversation flow using `ConversationHandler` in the `python-telegram-bot` library. It guides the user through providing information about themselves, storing it, and displaying it at the end. ```Python #!/usr/bin/env python # pylint: disable=unused-argument # This program is dedicated to the public domain under the CC0 license. """ First, a few callback functions are defined. Then, those functions are passed to the Application and registered at their respective places. Then, the bot is started and runs until we press Ctrl-C on the command line. Usage: Example of a bot-user conversation using ConversationHandler. Send /start to initiate the conversation. Press Ctrl-C on the command line or send a signal to the process to stop the bot. """ import logging from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update from telegram.ext import ( Application, CommandHandler, ContextTypes, ConversationHandler, MessageHandler, filters, ) # Enable logging logging.basicConfig( format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO ) # set higher logging level for httpx to avoid all GET and POST requests being logged logging.getLogger("httpx").setLevel(logging.WARNING) logger = logging.getLogger(__name__) CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3) reply_keyboard = [ ["Age", "Favourite colour"], ["Number of siblings", "Something else..."], ["Done"], ] markup = ReplyKeyboardMarkup(reply_keyboard, one_time_keyboard=True) def facts_to_str(user_data: dict[str, str]) -> str: """Helper function for formatting the gathered user info.""" facts = [f"{key} - {value}" for key, value in user_data.items()] return "\n".join(facts).join(["\n", "\n"]) async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Start the conversation and ask user for input.""" await update.message.reply_text( "Hi! My name is Doctor Botter. I will hold a more complex conversation with you. " "Why don't you tell me something about yourself?", reply_markup=markup, ) return CHOOSING def regular_choice(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Ask the user for info about the selected predefined choice.""" text = update.message.text context.user_data["choice"] = text await update.message.reply_text(f"Your {text.lower()}? Yes, I would love to hear about that!") return TYPING_REPLY def custom_choice(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Ask the user for a description of a custom category.""" await update.message.reply_text( 'Alright, please send me the category first, for example "Most impressive skill"' ) return TYPING_CHOICE async def received_information(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Store info provided by user and ask for the next category.""" user_data = context.user_data text = update.message.text category = user_data["choice"] user_data[category] = text del user_data["choice"] await update.message.reply_text( "Neat! Just so you know, this is what you already told me:" f"{facts_to_str(user_data)}\nYou can tell me more, or change your opinion" " on something.", reply_markup=markup, ) return CHOOSING async def done(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: """Display the gathered info and end the conversation.""" user_data = context.user_data if "choice" in user_data: del user_data["choice"] await update.message.reply_text( f"I learned these facts about you: {facts_to_str(user_data)}Until next time!", reply_markup=ReplyKeyboardRemove(), ) user_data.clear() return ConversationHandler.END def main() -> None: """Run the bot.""" # Create the Application and pass it your bot's token. application = Application.builder().token("TOKEN").build() # Add conversation handler with the states CHOOSING, TYPING_CHOICE and TYPING_REPLY conv_handler = ConversationHandler( entry_points=[CommandHandler("start", start)], states={ CHOOSING: [ MessageHandler( filters.Regex("^(Age|Favourite colour|Number of siblings)$$"), regular_choice ), MessageHandler(filters.Regex("^Something else...$"), custom_choice), ], TYPING_CHOICE: [ MessageHandler( filters.TEXT & ~(filters.COMMAND | filters.Regex("^Done$")), regular_choice, ) ], TYPING_REPLY: [ MessageHandler( ``` -------------------------------- ### Example: Using filters.COMMAND Source: https://docs.python-telegram-bot.org/en/stable/telegram.ext.filters.html To allow messages starting with a command use MessageHandler(filters.COMMAND, command_at_start_callback). ```python MessageHandler(filters.COMMAND, command_at_start_callback) ``` -------------------------------- ### Basic ConversationHandler Example Source: https://docs.python-telegram-bot.org/en/stable/telegram.ext.conversationhandler.html A simple example demonstrating how to set up a `ConversationHandler` with entry points, states, and fallbacks. ```python def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: update.message.reply_text( "Hi! My\n" "I'll send you a series of messages, and you reply to me with the appropriate answer\n" "Send /cancel at any time to exit.", reply_markup=ForceReply(selective=True), ) return NAME def name(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: user = update.message.from_user update.message.reply_text( f'I received your name: {update.message.text}.\n'\n f'I will send you a series of messages, and you reply to me with the appropriate answer\n' f'Send /cancel at any time to exit.', reply_markup=ForceReply(selective=True), ) context.user_data['name'] = update.message.text return AGE def age(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: user = update.message.from_user update.message.reply_text( f'I received your age: {update.message.text}.\n'\n f'I will send you a series of messages, and you reply to me with the appropriate answer\n' f'Send /cancel at any time to exit.', reply_markup=ForceReply(selective=True), ) context.user_data['age'] = update.message.text return LOCATION def location(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: user = update.message.from_user update.message.reply_text( f'I received your location: {update.message.text}.\n'\n f'I will send you a series of messages, and you reply to me with the appropriate answer\n' f'Send /cancel at any time to exit.', reply_markup=ForceReply(selective=True), ) context.user_data['location'] = update.message.text return END def end(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: user = update.message.from_user update.message.reply_text( f'Nice to meet you, {context.user_data["name"]}. Your age is {context.user_data["age"]}. Your location is {context.user_data["location"]}.\n' f'I will send you a series of messages, and you reply to me with the appropriate answer\n' f'Send /cancel at any time to exit.', ) return ConversationHandler.END def cancel(update: Update, context: ContextTypes.DEFAULT_TYPE) -> int: user = update.message.from_user logger.info("User %s canceled the conversation.", user.first_name) update.message.reply_text( 'Bye! I’ll see you later.', reply_markup=ReplyKeyboardRemove()) return ConversationHandler.END def main() -> None: """Run the bot.""" # Create the Application and pass it your bot's token. application = Application.builder().token(TOKEN).build() # on different commands - answer in Telegram conv_handler = ConversationHandler( entry_points=[CommandHandler('start', start)], states={ NAME: [MessageHandler(filters.TEXT & ~filters.COMMAND, name)], AGE: [MessageHandler(filters.TEXT & ~filters.COMMAND, age)], LOCATION: [MessageHandler(filters.TEXT & ~filters.COMMAND, location)], }, fallbacks=[CommandHandler('cancel', cancel)], ) application.add_handler(conv_handler) # Run the bot until the user presses Ctrl-C application.run_polling() if __name__ == '__main__': main() ``` -------------------------------- ### initialize Source: https://docs.python-telegram-bot.org/en/stable/telegram.ext.simpleupdateprocessor.html Does nothing. ```python async initialize() ``` -------------------------------- ### arbitrarycallbackdatabot.py Source: https://docs.python-telegram-bot.org/en/stable/examples.arbitrarycallbackdatabot.html This example showcases how PTBs "arbitrary callback data" feature can be used. For detailed info on arbitrary callback data, see the wiki page at https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data. Note: To use arbitrary callback data, you must install PTB via `pip install "python-telegram-bot[callback-data]"` ```python #!/usr/bin/env python # pylint: disable=unused-argument # This program is dedicated to the public domain under the CC0 license. """This example showcases how PTBs \"arbitrary callback data\" feature can be used. For detailed info on arbitrary callback data, see the wiki page at https://github.com/python-telegram-bot/python-telegram-bot/wiki/Arbitrary-callback_data Note: To use arbitrary callback data, you must install PTB via `pip install \"python-telegram-bot[callback-data]\"` """ import logging from typing import cast from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update from telegram.ext import ( Application, CallbackQueryHandler, CommandHandler, ContextTypes, InvalidCallbackData, PicklePersistence, ) # Enable logging logging.basicConfig( format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO ) # set higher logging level for httpx to avoid all GET and POST requests being logged logging.getLogger("httpx").setLevel(logging.WARNING) logger = logging.getLogger(__name__) async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Sends a message with 5 inline buttons attached.""" number_list: list[int] = [] await update.message.reply_text("Please choose:", reply_markup=build_keyboard(number_list)) async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Displays info on how to use the bot.""" await update.message.reply_text( "Use /start to test this bot. Use /clear to clear the stored data so that you can see " "what happens, if the button data is not available. " ) async def clear(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Clears the callback data cache""" context.bot.callback_data_cache.clear_callback_data() context.bot.callback_data_cache.clear_callback_queries() await update.effective_message.reply_text("All clear!") def build_keyboard(current_list: list[int]) -> InlineKeyboardMarkup: """Helper function to build the next inline keyboard.""" return InlineKeyboardMarkup.from_column( [InlineKeyboardButton(str(i), callback_data=(i, current_list)) for i in range(1, 6)] ) async def list_button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Parses the CallbackQuery and updates the message text.""" query = update.callback_query await query.answer() # Get the data from the callback_data. # If you're using a type checker like MyPy, you'll have to use typing.cast # to make the checker get the expected type of the callback_data number, number_list = cast("tuple[int, list[int]]", query.data) # append the number to the list number_list.append(number) await query.edit_message_text( text=f"So far you've selected {number_list}. Choose the next item:", reply_markup=build_keyboard(number_list), ) # we can delete the data stored for the query, because we've replaced the buttons context.drop_callback_data(query) async def handle_invalid_button(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Informs the user that the button is no longer available.""" await update.callback_query.answer() await update.effective_message.edit_text( "Sorry, I could not process this button click 😕 Please send /start to get a new keyboard." ) def main() -> None: """Run the bot.""" # We use persistence to demonstrate how buttons can still work after the bot was restarted persistence = PicklePersistence(filepath="arbitrarycallbackdatabot") # Create the Application and pass it your bot's token. application = ( Application.builder() .token("TOKEN") .persistence(persistence) .arbitrary_callback_data(True) .build() ) application.add_handler(CommandHandler("start", start)) application.add_handler(CommandHandler("help", help_command)) application.add_handler(CommandHandler("clear", clear)) application.add_handler( CallbackQueryHandler(handle_invalid_button, pattern=InvalidCallbackData) ) application.add_handler(CallbackQueryHandler(list_button)) # Run the bot until the user presses Ctrl-C application.run_polling(allowed_updates=Update.ALL_TYPES) if __name__ == "__main__": main() ``` -------------------------------- ### Install webhooks Source: https://docs.python-telegram-bot.org/en/stable/telegram.ext.application.html To use the run_webhook method, you must install PTB with the optional requirement 'webhooks'. ```bash pip install "python-telegram-bot[webhooks]" ``` -------------------------------- ### webappbot.py Source: https://docs.python-telegram-bot.org/en/stable/examples.webappbot.html This is the main file for the webappbot example. It sets up the bot, defines handlers, and starts the bot. ```python import logging from telegram import Update from telegram.ext import Application, CommandHandler, ContextTypes # Enable logging logging.basicConfig( format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO ) # set higher logging level for httpx to avoid all GET and POST requests being logged logging.getLogger("httpx").setLevel(logging.WARNING) logger = logging.getLogger(__name__) async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Send a message when the command /start is issued.""" await update.message.reply_text("Hi! I'm an example bot that uses the WebApp feature. Send /web to see the WebApp.") async def web_command(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None: """Send a message with a button that opens a WebApp.""" await update.message.reply_text( "Use the button below to open the WebApp.", reply_markup=InlineKeyboardMarkup( [ [InlineKeyboardButton(text="Open WebApp", url="https://telegram.web.app")], ] ), ) def main() -> None: """Start the bot.""" # Create the Application and pass it your bot's token. application = Application.builder().token("YOUR_BOT_TOKEN").build() # on different commands - answer in Telegram application.add_handler(CommandHandler("start", start)) application.add_handler(CommandHandler("web", web_command)) # Run the bot until the user presses Ctrl-C application.run_polling(allowed_updates=Update.ALL_TYPES) if __name__ == "__main__": main() ```