deeplinking.py

  1#!/usr/bin/env python
  2# pylint: disable=unused-argument
  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! Now let's get back to the private chat."
 61    )
 62    keyboard = InlineKeyboardMarkup.from_button(
 63        InlineKeyboardButton(text="Continue here!", url=url)
 64    )
 65    await update.message.reply_text(text, reply_markup=keyboard)
 66
 67
 68async def deep_linked_level_2(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 69    """Reached through the SO_COOL payload"""
 70    bot = context.bot
 71    url = helpers.create_deep_linked_url(bot.username, USING_ENTITIES)
 72    text = f'You can also mask the deep-linked URLs as links: <a href="{url}">▶️ CLICK HERE</a>.'
 73    await update.message.reply_text(text, parse_mode=ParseMode.HTML, disable_web_page_preview=True)
 74
 75
 76async def deep_linked_level_3(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 77    """Reached through the USING_ENTITIES payload"""
 78    await update.message.reply_text(
 79        "It is also possible to make deep-linking using InlineKeyboardButtons.",
 80        reply_markup=InlineKeyboardMarkup(
 81            [[InlineKeyboardButton(text="Like this!", callback_data=KEYBOARD_CALLBACKDATA)]]
 82        ),
 83    )
 84
 85
 86async def deep_link_level_3_callback(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 87    """Answers CallbackQuery with deeplinking url."""
 88    bot = context.bot
 89    url = helpers.create_deep_linked_url(bot.username, USING_KEYBOARD)
 90    await update.callback_query.answer(url=url)
 91
 92
 93async def deep_linked_level_4(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
 94    """Reached through the USING_KEYBOARD payload"""
 95    payload = context.args
 96    await update.message.reply_text(
 97        f"Congratulations! This is as deep as it gets 👏🏻\n\nThe payload was: {payload}"
 98    )
 99
100
101def main() -> None:
102    """Start the bot."""
103    # Create the Application and pass it your bot's token.
104    application = Application.builder().token("TOKEN").build()
105
106    # More info on what deep linking actually is (read this first if it's unclear to you):
107    # https://core.telegram.org/bots/features#deep-linking
108
109    # Register a deep-linking handler
110    application.add_handler(
111        CommandHandler("start", deep_linked_level_1, filters.Regex(CHECK_THIS_OUT))
112    )
113
114    # This one works with a textual link instead of an URL
115    application.add_handler(CommandHandler("start", deep_linked_level_2, filters.Regex(SO_COOL)))
116
117    # We can also pass on the deep-linking payload
118    application.add_handler(
119        CommandHandler("start", deep_linked_level_3, filters.Regex(USING_ENTITIES))
120    )
121
122    # Possible with inline keyboard buttons as well
123    application.add_handler(
124        CommandHandler("start", deep_linked_level_4, filters.Regex(USING_KEYBOARD))
125    )
126
127    # register callback handler for inline keyboard button
128    application.add_handler(
129        CallbackQueryHandler(deep_link_level_3_callback, pattern=KEYBOARD_CALLBACKDATA)
130    )
131
132    # Make sure the deep-linking handlers occur *before* the normal /start handler.
133    application.add_handler(CommandHandler("start", start))
134
135    # Run the bot until the user presses Ctrl-C
136    application.run_polling(allowed_updates=Update.ALL_TYPES)
137
138
139if __name__ == "__main__":
140    main()