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