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