deeplinking.py

  1#!/usr/bin/env python
  2# pylint: disable=unused-argument, import-error
  3# This program is dedicated to the public domain under the CC0 license.
  4
  5"""Bot that explains Telegram's "Deep Linking Parameters" functionality.
  6
  7This program is dedicated to the public domain under the CC0 license.
  8
  9This Bot uses the Application class to handle the bot.
 10
 11First, a few handler functions are defined. Then, those functions are passed to
 12the Application and registered at their respective places.
 13Then, the bot is started and runs until we press Ctrl-C on the command line.
 14
 15Usage:
 16Deep Linking example. Send /start to get the link.
 17Press Ctrl-C on the command line or send a signal to the process to stop the
 18bot.
 19"""
 20
 21import logging
 22
 23from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update, helpers
 24from telegram.constants import ParseMode
 25from telegram.ext import Application, CallbackQueryHandler, CommandHandler, ContextTypes, filters
 26
 27# Enable logging
 28logging.basicConfig(
 29    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
 30)
 31
 32# set higher logging level for httpx to avoid all GET and POST requests being logged
 33logging.getLogger("httpx").setLevel(logging.WARNING)
 34
 35logger = logging.getLogger(__name__)
 36
 37# Define constants that will allow us to reuse the deep-linking parameters.
 38CHECK_THIS_OUT = "check-this-out"
 39USING_ENTITIES = "using-entities-here"
 40USING_KEYBOARD = "using-keyboard-here"
 41SO_COOL = "so-cool"
 42
 43# Callback data to pass in 3rd level deep-linking
 44KEYBOARD_CALLBACKDATA = "keyboard-callback-data"
 45
 46
 47async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 48    """Send a deep-linked URL when the command /start is issued."""
 49    bot = context.bot
 50    url = helpers.create_deep_linked_url(bot.username, CHECK_THIS_OUT, group=True)
 51    text = "Feel free to tell your friends about it:\n\n" + url
 52    await update.message.reply_text(text)
 53
 54
 55async def deep_linked_level_1(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 56    """Reached through the CHECK_THIS_OUT payload"""
 57    bot = context.bot
 58    url = helpers.create_deep_linked_url(bot.username, SO_COOL)
 59    text = (
 60        "Awesome, you just accessed hidden functionality! "
 61        "Now let's get back to the private chat."
 62    )
 63    keyboard = InlineKeyboardMarkup.from_button(
 64        InlineKeyboardButton(text="Continue here!", url=url)
 65    )
 66    await update.message.reply_text(text, reply_markup=keyboard)
 67
 68
 69async def deep_linked_level_2(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 70    """Reached through the SO_COOL payload"""
 71    bot = context.bot
 72    url = helpers.create_deep_linked_url(bot.username, USING_ENTITIES)
 73    text = f'You can also mask the deep-linked URLs as links: <a href="{url}">▶️ CLICK HERE</a>.'
 74    await update.message.reply_text(text, parse_mode=ParseMode.HTML, disable_web_page_preview=True)
 75
 76
 77async def deep_linked_level_3(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 78    """Reached through the USING_ENTITIES payload"""
 79    await update.message.reply_text(
 80        "It is also possible to make deep-linking using InlineKeyboardButtons.",
 81        reply_markup=InlineKeyboardMarkup(
 82            [[InlineKeyboardButton(text="Like this!", callback_data=KEYBOARD_CALLBACKDATA)]]
 83        ),
 84    )
 85
 86
 87async def deep_link_level_3_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 88    """Answers CallbackQuery with deeplinking url."""
 89    bot = context.bot
 90    url = helpers.create_deep_linked_url(bot.username, USING_KEYBOARD)
 91    await update.callback_query.answer(url=url)
 92
 93
 94async def deep_linked_level_4(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 95    """Reached through the USING_KEYBOARD payload"""
 96    payload = context.args
 97    await update.message.reply_text(
 98        f"Congratulations! This is as deep as it gets 👏🏻\n\nThe payload was: {payload}"
 99    )
100
101
102def main() -> None:
103    """Start the bot."""
104    # Create the Application and pass it your bot's token.
105    application = Application.builder().token("TOKEN").build()
106
107    # More info on what deep linking actually is (read this first if it's unclear to you):
108    # https://core.telegram.org/bots/features#deep-linking
109
110    # Register a deep-linking handler
111    application.add_handler(
112        CommandHandler("start", deep_linked_level_1, filters.Regex(CHECK_THIS_OUT))
113    )
114
115    # This one works with a textual link instead of an URL
116    application.add_handler(CommandHandler("start", deep_linked_level_2, filters.Regex(SO_COOL)))
117
118    # We can also pass on the deep-linking payload
119    application.add_handler(
120        CommandHandler("start", deep_linked_level_3, filters.Regex(USING_ENTITIES))
121    )
122
123    # Possible with inline keyboard buttons as well
124    application.add_handler(
125        CommandHandler("start", deep_linked_level_4, filters.Regex(USING_KEYBOARD))
126    )
127
128    # register callback handler for inline keyboard button
129    application.add_handler(
130        CallbackQueryHandler(deep_link_level_3_callback, pattern=KEYBOARD_CALLBACKDATA)
131    )
132
133    # Make sure the deep-linking handlers occur *before* the normal /start handler.
134    application.add_handler(CommandHandler("start", start))
135
136    # Run the bot until the user presses Ctrl-C
137    application.run_polling(allowed_updates=Update.ALL_TYPES)
138
139
140if __name__ == "__main__":
141    main()