Introduce Builder Pattern for Updater and Dispatcher (#2646)

This commit is contained in:
Bibo-Joshi
2021-10-09 13:56:50 +02:00
committed by Hinrich Mahler
parent edb30cf342
commit 7afce46d9f
45 changed files with 2264 additions and 678 deletions
+18 -10
View File
@@ -11,27 +11,29 @@ from typing import List, Tuple, cast
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
Updater,
CommandHandler,
CallbackQueryHandler,
CallbackContext,
InvalidCallbackData,
PicklePersistence,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Sends a message with 5 inline buttons attached."""
number_list: List[int] = []
update.message.reply_text('Please choose:', reply_markup=build_keyboard(number_list))
def help_command(update: Update, context: CallbackContext) -> None:
def help_command(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Displays info on how to use the bot."""
update.message.reply_text(
"Use /start to test this bot. Use /clear to clear the stored data so that you can see "
@@ -39,10 +41,10 @@ def help_command(update: Update, context: CallbackContext) -> None:
)
def clear(update: Update, context: CallbackContext) -> None:
def clear(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Clears the callback data cache"""
context.bot.callback_data_cache.clear_callback_data() # type: ignore[attr-defined]
context.bot.callback_data_cache.clear_callback_queries() # type: ignore[attr-defined]
context.bot.callback_data_cache.clear_callback_data()
context.bot.callback_data_cache.clear_callback_queries()
update.effective_message.reply_text('All clear!')
@@ -53,7 +55,7 @@ def build_keyboard(current_list: List[int]) -> InlineKeyboardMarkup:
)
def list_button(update: Update, context: CallbackContext) -> None:
def list_button(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Parses the CallbackQuery and updates the message text."""
query = update.callback_query
query.answer()
@@ -73,7 +75,7 @@ def list_button(update: Update, context: CallbackContext) -> None:
context.drop_callback_data(query)
def handle_invalid_button(update: Update, context: CallbackContext) -> None:
def handle_invalid_button(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Informs the user that the button is no longer available."""
update.callback_query.answer()
update.effective_message.edit_text(
@@ -86,7 +88,13 @@ def main() -> None:
# We use persistence to demonstrate how buttons can still work after the bot was restarted
persistence = PicklePersistence(filepath='arbitrarycallbackdatabot')
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN", persistence=persistence, arbitrary_callback_data=True)
updater = (
Updater.builder()
.token("TOKEN")
.persistence(persistence)
.arbitrary_callback_data(True)
.build()
)
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CommandHandler('help', help_command))
+7 -6
View File
@@ -16,13 +16,14 @@ from typing import Tuple, Optional
from telegram import Update, Chat, ChatMember, ParseMode, ChatMemberUpdated
from telegram.ext import (
Updater,
CommandHandler,
CallbackContext,
ChatMemberHandler,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
@@ -66,7 +67,7 @@ def extract_status_change(
return was_member, is_member
def track_chats(update: Update, context: CallbackContext) -> None:
def track_chats(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Tracks the chats the bot is in."""
result = extract_status_change(update.my_chat_member)
if result is None:
@@ -101,7 +102,7 @@ def track_chats(update: Update, context: CallbackContext) -> None:
context.bot_data.setdefault("channel_ids", set()).discard(chat.id)
def show_chats(update: Update, context: CallbackContext) -> None:
def show_chats(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Shows which chats the bot is in"""
user_ids = ", ".join(str(uid) for uid in context.bot_data.setdefault("user_ids", set()))
group_ids = ", ".join(str(gid) for gid in context.bot_data.setdefault("group_ids", set()))
@@ -114,7 +115,7 @@ def show_chats(update: Update, context: CallbackContext) -> None:
update.effective_message.reply_text(text)
def greet_chat_members(update: Update, context: CallbackContext) -> None:
def greet_chat_members(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Greets new users in chats and announces when someone leaves"""
result = extract_status_change(update.chat_member)
if result is None:
@@ -139,7 +140,7 @@ def greet_chat_members(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Start the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+5 -4
View File
@@ -15,13 +15,14 @@ from typing import DefaultDict, Optional, Set
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup, ParseMode
from telegram.ext import (
Updater,
CommandHandler,
CallbackContext,
ContextTypes,
CallbackQueryHandler,
TypeHandler,
Dispatcher,
ExtBot,
Updater,
)
@@ -32,8 +33,8 @@ class ChatData:
self.clicks_per_message: DefaultDict[int, int] = defaultdict(int)
# The [dict, ChatData, dict] is for type checkers like mypy
class CustomContext(CallbackContext[dict, ChatData, dict]):
# The [ExtBot, dict, ChatData, dict] is for type checkers like mypy
class CustomContext(CallbackContext[ExtBot, dict, ChatData, dict]):
"""Custom class for context."""
def __init__(self, dispatcher: Dispatcher):
@@ -113,7 +114,7 @@ def track_users(update: Update, context: CustomContext) -> None:
def main() -> None:
"""Run the bot."""
context_types = ContextTypes(context=CustomContext, chat_data=ChatData)
updater = Updater("TOKEN", context_types=context_types)
updater = Updater.builder().token("TOKEN").context_types(context_types).build()
dispatcher = updater.dispatcher
# run track_users in its own group to not interfere with the user handlers
+11 -11
View File
@@ -18,25 +18,25 @@ import logging
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
ConversationHandler,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
GENDER, PHOTO, LOCATION, BIO = range(4)
def start(update: Update, context: CallbackContext) -> int:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Starts the conversation and asks the user about their gender."""
reply_keyboard = [['Boy', 'Girl', 'Other']]
@@ -52,7 +52,7 @@ def start(update: Update, context: CallbackContext) -> int:
return GENDER
def gender(update: Update, context: CallbackContext) -> int:
def gender(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Stores the selected gender and asks for a photo."""
user = update.message.from_user
logger.info("Gender of %s: %s", user.first_name, update.message.text)
@@ -65,7 +65,7 @@ def gender(update: Update, context: CallbackContext) -> int:
return PHOTO
def photo(update: Update, context: CallbackContext) -> int:
def photo(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Stores the photo and asks for a location."""
user = update.message.from_user
photo_file = update.message.photo[-1].get_file()
@@ -78,7 +78,7 @@ def photo(update: Update, context: CallbackContext) -> int:
return LOCATION
def skip_photo(update: Update, context: CallbackContext) -> int:
def skip_photo(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Skips the photo and asks for a location."""
user = update.message.from_user
logger.info("User %s did not send a photo.", user.first_name)
@@ -89,7 +89,7 @@ def skip_photo(update: Update, context: CallbackContext) -> int:
return LOCATION
def location(update: Update, context: CallbackContext) -> int:
def location(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Stores the location and asks for some info about the user."""
user = update.message.from_user
user_location = update.message.location
@@ -103,7 +103,7 @@ def location(update: Update, context: CallbackContext) -> int:
return BIO
def skip_location(update: Update, context: CallbackContext) -> int:
def skip_location(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Skips the location and asks for info about the user."""
user = update.message.from_user
logger.info("User %s did not send a location.", user.first_name)
@@ -114,7 +114,7 @@ def skip_location(update: Update, context: CallbackContext) -> int:
return BIO
def bio(update: Update, context: CallbackContext) -> int:
def bio(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Stores the info about the user and ends the conversation."""
user = update.message.from_user
logger.info("Bio of %s: %s", user.first_name, update.message.text)
@@ -123,7 +123,7 @@ def bio(update: Update, context: CallbackContext) -> int:
return ConversationHandler.END
def cancel(update: Update, context: CallbackContext) -> int:
def cancel(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Cancels and ends the conversation."""
user = update.message.from_user
logger.info("User %s canceled the conversation.", user.first_name)
@@ -137,7 +137,7 @@ def cancel(update: Update, context: CallbackContext) -> int:
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+8 -8
View File
@@ -19,19 +19,19 @@ from typing import Dict
from telegram import ReplyKeyboardMarkup, Update, ReplyKeyboardRemove
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
ConversationHandler,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3)
@@ -50,7 +50,7 @@ def facts_to_str(user_data: Dict[str, str]) -> str:
return "\n".join(facts).join(['\n', '\n'])
def start(update: Update, context: CallbackContext) -> int:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Start the conversation and ask user for input."""
update.message.reply_text(
"Hi! My name is Doctor Botter. I will hold a more complex conversation with you. "
@@ -61,7 +61,7 @@ def start(update: Update, context: CallbackContext) -> int:
return CHOOSING
def regular_choice(update: Update, context: CallbackContext) -> int:
def regular_choice(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Ask the user for info about the selected predefined choice."""
text = update.message.text
context.user_data['choice'] = text
@@ -70,7 +70,7 @@ def regular_choice(update: Update, context: CallbackContext) -> int:
return TYPING_REPLY
def custom_choice(update: Update, context: CallbackContext) -> int:
def custom_choice(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Ask the user for a description of a custom category."""
update.message.reply_text(
'Alright, please send me the category first, for example "Most impressive skill"'
@@ -79,7 +79,7 @@ def custom_choice(update: Update, context: CallbackContext) -> int:
return TYPING_CHOICE
def received_information(update: Update, context: CallbackContext) -> int:
def received_information(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Store info provided by user and ask for the next category."""
user_data = context.user_data
text = update.message.text
@@ -97,7 +97,7 @@ def received_information(update: Update, context: CallbackContext) -> int:
return CHOOSING
def done(update: Update, context: CallbackContext) -> int:
def done(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Display the gathered info and end the conversation."""
user_data = context.user_data
if 'choice' in user_data:
@@ -115,7 +115,7 @@ def done(update: Update, context: CallbackContext) -> int:
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+8 -8
View File
@@ -22,10 +22,10 @@ import logging
from telegram import ParseMode, InlineKeyboardMarkup, InlineKeyboardButton, Update, helpers
from telegram.ext import (
Updater,
CommandHandler,
CallbackQueryHandler,
Filters,
Updater,
CallbackContext,
)
@@ -46,7 +46,7 @@ SO_COOL = "so-cool"
KEYBOARD_CALLBACKDATA = "keyboard-callback-data"
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Send a deep-linked URL when the command /start is issued."""
bot = context.bot
url = helpers.create_deep_linked_url(bot.username, CHECK_THIS_OUT, group=True)
@@ -54,7 +54,7 @@ def start(update: Update, context: CallbackContext) -> None:
update.message.reply_text(text)
def deep_linked_level_1(update: Update, context: CallbackContext) -> None:
def deep_linked_level_1(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Reached through the CHECK_THIS_OUT payload"""
bot = context.bot
url = helpers.create_deep_linked_url(bot.username, SO_COOL)
@@ -68,7 +68,7 @@ def deep_linked_level_1(update: Update, context: CallbackContext) -> None:
update.message.reply_text(text, reply_markup=keyboard)
def deep_linked_level_2(update: Update, context: CallbackContext) -> None:
def deep_linked_level_2(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Reached through the SO_COOL payload"""
bot = context.bot
url = helpers.create_deep_linked_url(bot.username, USING_ENTITIES)
@@ -76,7 +76,7 @@ def deep_linked_level_2(update: Update, context: CallbackContext) -> None:
update.message.reply_text(text, parse_mode=ParseMode.MARKDOWN, disable_web_page_preview=True)
def deep_linked_level_3(update: Update, context: CallbackContext) -> None:
def deep_linked_level_3(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Reached through the USING_ENTITIES payload"""
update.message.reply_text(
"It is also possible to make deep-linking using InlineKeyboardButtons.",
@@ -86,14 +86,14 @@ def deep_linked_level_3(update: Update, context: CallbackContext) -> None:
)
def deep_link_level_3_callback(update: Update, context: CallbackContext) -> None:
def deep_link_level_3_callback(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Answers CallbackQuery with deeplinking url."""
bot = context.bot
url = helpers.create_deep_linked_url(bot.username, USING_KEYBOARD)
update.callback_query.answer(url=url)
def deep_linked_level_4(update: Update, context: CallbackContext) -> None:
def deep_linked_level_4(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Reached through the USING_KEYBOARD payload"""
payload = context.args
update.message.reply_text(
@@ -104,7 +104,7 @@ def deep_linked_level_4(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Start the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+12 -6
View File
@@ -18,19 +18,25 @@ bot.
import logging
from telegram import Update, ForceReply
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, CallbackContext
from telegram.ext import (
CommandHandler,
MessageHandler,
Filters,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
# Define a few command handlers. These usually take the two arguments update and
# context.
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Send a message when the command /start is issued."""
user = update.effective_user
update.message.reply_markdown_v2(
@@ -39,12 +45,12 @@ def start(update: Update, context: CallbackContext) -> None:
)
def help_command(update: Update, context: CallbackContext) -> None:
def help_command(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Send a message when the command /help is issued."""
update.message.reply_text('Help!')
def echo(update: Update, context: CallbackContext) -> None:
def echo(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Echo the user message."""
update.message.reply_text(update.message.text)
@@ -52,7 +58,7 @@ def echo(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Start the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+6 -6
View File
@@ -9,12 +9,12 @@ import logging
import traceback
from telegram import Update, ParseMode
from telegram.ext import Updater, CallbackContext, CommandHandler
from telegram.ext import CommandHandler, Updater, CallbackContext
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
# The token you got from @botfather when you created the bot
@@ -25,7 +25,7 @@ BOT_TOKEN = "TOKEN"
DEVELOPER_CHAT_ID = 123456789
def error_handler(update: object, context: CallbackContext) -> None:
def error_handler(update: object, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Log the error and send a telegram message to notify the developer."""
# Log the error before we do anything else, so we can see it even if something breaks.
logger.error(msg="Exception while handling an update:", exc_info=context.error)
@@ -51,12 +51,12 @@ def error_handler(update: object, context: CallbackContext) -> None:
context.bot.send_message(chat_id=DEVELOPER_CHAT_ID, text=message, parse_mode=ParseMode.HTML)
def bad_command(update: Update, context: CallbackContext) -> None:
def bad_command(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Raise an error to trigger the error handler."""
context.bot.wrong_method_name() # type: ignore[attr-defined]
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Displays info on how to trigger an error."""
update.effective_message.reply_html(
'Use /bad_command to cause an error.\n'
@@ -67,7 +67,7 @@ def start(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater(BOT_TOKEN)
updater = Updater.builder().token(BOT_TOKEN).build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+4 -5
View File
@@ -23,23 +23,22 @@ from telegram.ext import Updater, InlineQueryHandler, CommandHandler, CallbackCo
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
# Define a few command handlers. These usually take the two arguments update and
# context. Error handlers also receive the raised TelegramError object in error.
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Send a message when the command /start is issued."""
update.message.reply_text('Hi!')
def help_command(update: Update, context: CallbackContext) -> None:
def help_command(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Send a message when the command /help is issued."""
update.message.reply_text('Help!')
def inlinequery(update: Update, context: CallbackContext) -> None:
def inlinequery(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Handle the inline query."""
query = update.inline_query.query
@@ -74,7 +73,7 @@ def inlinequery(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+12 -5
View File
@@ -9,15 +9,22 @@ Basic example for a bot that uses inline keyboards. For an in-depth explanation,
import logging
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, CallbackContext
from telegram.ext import (
CommandHandler,
CallbackQueryHandler,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Sends a message with three inline buttons attached."""
keyboard = [
[
@@ -32,7 +39,7 @@ def start(update: Update, context: CallbackContext) -> None:
update.message.reply_text('Please choose:', reply_markup=reply_markup)
def button(update: Update, context: CallbackContext) -> None:
def button(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Parses the CallbackQuery and updates the message text."""
query = update.callback_query
@@ -43,7 +50,7 @@ def button(update: Update, context: CallbackContext) -> None:
query.edit_message_text(text=f"Selected option: {query.data}")
def help_command(update: Update, context: CallbackContext) -> None:
def help_command(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Displays info on how to use the bot."""
update.message.reply_text("Use /start to test this bot.")
@@ -51,7 +58,7 @@ def help_command(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CallbackQueryHandler(button))
+10 -10
View File
@@ -17,18 +17,18 @@ Press Ctrl-C on the command line to stop the bot.
import logging
from telegram import InlineKeyboardButton, InlineKeyboardMarkup, Update
from telegram.ext import (
Updater,
CommandHandler,
CallbackQueryHandler,
ConversationHandler,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
# Stages
@@ -37,7 +37,7 @@ FIRST, SECOND = range(2)
ONE, TWO, THREE, FOUR = range(4)
def start(update: Update, context: CallbackContext) -> int:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Send message on `/start`."""
# Get user that sent /start and log his name
user = update.message.from_user
@@ -59,7 +59,7 @@ def start(update: Update, context: CallbackContext) -> int:
return FIRST
def start_over(update: Update, context: CallbackContext) -> int:
def start_over(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Prompt same text & keyboard as `start` does but not as new message"""
# Get CallbackQuery from Update
query = update.callback_query
@@ -80,7 +80,7 @@ def start_over(update: Update, context: CallbackContext) -> int:
return FIRST
def one(update: Update, context: CallbackContext) -> int:
def one(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Show new choice of buttons"""
query = update.callback_query
query.answer()
@@ -97,7 +97,7 @@ def one(update: Update, context: CallbackContext) -> int:
return FIRST
def two(update: Update, context: CallbackContext) -> int:
def two(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Show new choice of buttons"""
query = update.callback_query
query.answer()
@@ -114,7 +114,7 @@ def two(update: Update, context: CallbackContext) -> int:
return FIRST
def three(update: Update, context: CallbackContext) -> int:
def three(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Show new choice of buttons"""
query = update.callback_query
query.answer()
@@ -132,7 +132,7 @@ def three(update: Update, context: CallbackContext) -> int:
return SECOND
def four(update: Update, context: CallbackContext) -> int:
def four(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Show new choice of buttons"""
query = update.callback_query
query.answer()
@@ -149,7 +149,7 @@ def four(update: Update, context: CallbackContext) -> int:
return FIRST
def end(update: Update, context: CallbackContext) -> int:
def end(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Returns `ConversationHandler.END`, which tells the
ConversationHandler that the conversation is over.
"""
@@ -162,7 +162,7 @@ def end(update: Update, context: CallbackContext) -> int:
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+16 -16
View File
@@ -19,20 +19,20 @@ from typing import Tuple, Dict, Any
from telegram import InlineKeyboardMarkup, InlineKeyboardButton, Update
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
ConversationHandler,
CallbackQueryHandler,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
# State definitions for top level conversation
@@ -71,7 +71,7 @@ def _name_switcher(level: str) -> Tuple[str, str]:
# Top level conversation callbacks
def start(update: Update, context: CallbackContext) -> str:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Select an action: Adding parent/child or show data."""
text = (
"You may choose to add a family member, yourself, show the gathered data, or end the "
@@ -104,7 +104,7 @@ def start(update: Update, context: CallbackContext) -> str:
return SELECTING_ACTION
def adding_self(update: Update, context: CallbackContext) -> str:
def adding_self(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Add information about yourself."""
context.user_data[CURRENT_LEVEL] = SELF
text = 'Okay, please tell me about yourself.'
@@ -117,7 +117,7 @@ def adding_self(update: Update, context: CallbackContext) -> str:
return DESCRIBING_SELF
def show_data(update: Update, context: CallbackContext) -> str:
def show_data(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Pretty print gathered data."""
def prettyprint(user_data: Dict[str, Any], level: str) -> str:
@@ -152,14 +152,14 @@ def show_data(update: Update, context: CallbackContext) -> str:
return SHOWING
def stop(update: Update, context: CallbackContext) -> int:
def stop(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""End Conversation by command."""
update.message.reply_text('Okay, bye.')
return END
def end(update: Update, context: CallbackContext) -> int:
def end(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""End conversation from InlineKeyboardButton."""
update.callback_query.answer()
@@ -170,7 +170,7 @@ def end(update: Update, context: CallbackContext) -> int:
# Second level conversation callbacks
def select_level(update: Update, context: CallbackContext) -> str:
def select_level(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Choose to add a parent or a child."""
text = 'You may add a parent or a child. Also you can show the gathered data or go back.'
buttons = [
@@ -191,7 +191,7 @@ def select_level(update: Update, context: CallbackContext) -> str:
return SELECTING_LEVEL
def select_gender(update: Update, context: CallbackContext) -> str:
def select_gender(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Choose to add mother or father."""
level = update.callback_query.data
context.user_data[CURRENT_LEVEL] = level
@@ -218,7 +218,7 @@ def select_gender(update: Update, context: CallbackContext) -> str:
return SELECTING_GENDER
def end_second_level(update: Update, context: CallbackContext) -> int:
def end_second_level(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Return to top level conversation."""
context.user_data[START_OVER] = True
start(update, context)
@@ -227,7 +227,7 @@ def end_second_level(update: Update, context: CallbackContext) -> int:
# Third level callbacks
def select_feature(update: Update, context: CallbackContext) -> str:
def select_feature(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Select a feature to update for the person."""
buttons = [
[
@@ -254,7 +254,7 @@ def select_feature(update: Update, context: CallbackContext) -> str:
return SELECTING_FEATURE
def ask_for_input(update: Update, context: CallbackContext) -> str:
def ask_for_input(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Prompt user to input data for selected feature."""
context.user_data[CURRENT_FEATURE] = update.callback_query.data
text = 'Okay, tell me.'
@@ -265,7 +265,7 @@ def ask_for_input(update: Update, context: CallbackContext) -> str:
return TYPING
def save_input(update: Update, context: CallbackContext) -> str:
def save_input(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Save input for feature and return to feature selection."""
user_data = context.user_data
user_data[FEATURES][user_data[CURRENT_FEATURE]] = update.message.text
@@ -275,7 +275,7 @@ def save_input(update: Update, context: CallbackContext) -> str:
return select_feature(update, context)
def end_describing(update: Update, context: CallbackContext) -> int:
def end_describing(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""End gathering of features and return to parent conversation."""
user_data = context.user_data
level = user_data[CURRENT_LEVEL]
@@ -293,7 +293,7 @@ def end_describing(update: Update, context: CallbackContext) -> int:
return END
def stop_nested(update: Update, context: CallbackContext) -> str:
def stop_nested(update: Update, context: CallbackContext.DEFAULT_TYPE) -> str:
"""Completely end conversation from within nested conversation."""
update.message.reply_text('Okay, bye.')
@@ -303,7 +303,7 @@ def stop_nested(update: Update, context: CallbackContext) -> str:
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+5 -3
View File
@@ -14,9 +14,10 @@ import logging
from pathlib import Path
from telegram import Update
from telegram.ext import Updater, MessageHandler, Filters, CallbackContext
from telegram.ext import MessageHandler, Filters, Updater, CallbackContext
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.DEBUG
)
@@ -24,7 +25,7 @@ logging.basicConfig(
logger = logging.getLogger(__name__)
def msg(update: Update, context: CallbackContext) -> None:
def msg(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Downloads and prints the received passport data."""
# Retrieve passport data
passport_data = update.message.passport_data
@@ -102,7 +103,8 @@ def msg(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Start the bot."""
# Create the Updater and pass it your token and private key
updater = Updater("TOKEN", private_key=Path('private.key').read_bytes())
private_key = Path('private.key')
updater = Updater.builder().token("TOKEN").private_key(private_key.read_bytes()).build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+9 -9
View File
@@ -8,24 +8,24 @@ import logging
from telegram import LabeledPrice, ShippingOption, Update
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
PreCheckoutQueryHandler,
ShippingQueryHandler,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
def start_callback(update: Update, context: CallbackContext) -> None:
def start_callback(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Displays info on how to use the bot."""
msg = (
"Use /shipping to get an invoice for shipping-payment, or /noshipping for an "
@@ -35,7 +35,7 @@ def start_callback(update: Update, context: CallbackContext) -> None:
update.message.reply_text(msg)
def start_with_shipping_callback(update: Update, context: CallbackContext) -> None:
def start_with_shipping_callback(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Sends an invoice with shipping-payment."""
chat_id = update.message.chat_id
title = "Payment Example"
@@ -69,7 +69,7 @@ def start_with_shipping_callback(update: Update, context: CallbackContext) -> No
)
def start_without_shipping_callback(update: Update, context: CallbackContext) -> None:
def start_without_shipping_callback(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Sends an invoice without shipping-payment."""
chat_id = update.message.chat_id
title = "Payment Example"
@@ -91,7 +91,7 @@ def start_without_shipping_callback(update: Update, context: CallbackContext) ->
)
def shipping_callback(update: Update, context: CallbackContext) -> None:
def shipping_callback(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Answers the ShippingQuery with ShippingOptions"""
query = update.shipping_query
# check the payload, is this from your bot?
@@ -109,7 +109,7 @@ def shipping_callback(update: Update, context: CallbackContext) -> None:
# after (optional) shipping, it's the pre-checkout
def precheckout_callback(update: Update, context: CallbackContext) -> None:
def precheckout_callback(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Answers the PreQecheckoutQuery"""
query = update.pre_checkout_query
# check the payload, is this from your bot?
@@ -121,7 +121,7 @@ def precheckout_callback(update: Update, context: CallbackContext) -> None:
# finally, after contacting the payment provider...
def successful_payment_callback(update: Update, context: CallbackContext) -> None:
def successful_payment_callback(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Confirms the successful payment."""
# do something after successfully receiving payment?
update.message.reply_text("Thank you for your payment!")
@@ -130,7 +130,7 @@ def successful_payment_callback(update: Update, context: CallbackContext) -> Non
def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+9 -9
View File
@@ -19,20 +19,20 @@ from typing import Dict
from telegram import ReplyKeyboardMarkup, Update, ReplyKeyboardRemove
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
ConversationHandler,
PicklePersistence,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
CHOOSING, TYPING_REPLY, TYPING_CHOICE = range(3)
@@ -51,7 +51,7 @@ def facts_to_str(user_data: Dict[str, str]) -> str:
return "\n".join(facts).join(['\n', '\n'])
def start(update: Update, context: CallbackContext) -> int:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Start the conversation, display any stored data and ask user for input."""
reply_text = "Hi! My name is Doctor Botter."
if context.user_data:
@@ -69,7 +69,7 @@ def start(update: Update, context: CallbackContext) -> int:
return CHOOSING
def regular_choice(update: Update, context: CallbackContext) -> int:
def regular_choice(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Ask the user for info about the selected predefined choice."""
text = update.message.text.lower()
context.user_data['choice'] = text
@@ -84,7 +84,7 @@ def regular_choice(update: Update, context: CallbackContext) -> int:
return TYPING_REPLY
def custom_choice(update: Update, context: CallbackContext) -> int:
def custom_choice(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Ask the user for a description of a custom category."""
update.message.reply_text(
'Alright, please send me the category first, for example "Most impressive skill"'
@@ -93,7 +93,7 @@ def custom_choice(update: Update, context: CallbackContext) -> int:
return TYPING_CHOICE
def received_information(update: Update, context: CallbackContext) -> int:
def received_information(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Store info provided by user and ask for the next category."""
text = update.message.text
category = context.user_data['choice']
@@ -110,14 +110,14 @@ def received_information(update: Update, context: CallbackContext) -> int:
return CHOOSING
def show_data(update: Update, context: CallbackContext) -> None:
def show_data(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Display the gathered info."""
update.message.reply_text(
f"This is what you already told me: {facts_to_str(context.user_data)}"
)
def done(update: Update, context: CallbackContext) -> int:
def done(update: Update, context: CallbackContext.DEFAULT_TYPE) -> int:
"""Display the gathered info and end the conversation."""
if 'choice' in context.user_data:
del context.user_data['choice']
@@ -133,7 +133,7 @@ def main() -> None:
"""Run the bot."""
# Create the Updater and pass it your bot's token.
persistence = PicklePersistence(filepath='conversationbot')
updater = Updater("TOKEN", persistence=persistence)
updater = Updater.builder().token("TOKEN").persistence(persistence).build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher
+12 -10
View File
@@ -19,22 +19,24 @@ from telegram import (
Update,
)
from telegram.ext import (
Updater,
CommandHandler,
PollAnswerHandler,
PollHandler,
MessageHandler,
Filters,
Updater,
CallbackContext,
)
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Inform user about what this bot can do"""
update.message.reply_text(
'Please select /poll to get a Poll, /quiz to get a Quiz or /preview'
@@ -42,7 +44,7 @@ def start(update: Update, context: CallbackContext) -> None:
)
def poll(update: Update, context: CallbackContext) -> None:
def poll(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Sends a predefined poll"""
questions = ["Good", "Really good", "Fantastic", "Great"]
message = context.bot.send_poll(
@@ -64,7 +66,7 @@ def poll(update: Update, context: CallbackContext) -> None:
context.bot_data.update(payload)
def receive_poll_answer(update: Update, context: CallbackContext) -> None:
def receive_poll_answer(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Summarize a users poll vote"""
answer = update.poll_answer
poll_id = answer.poll_id
@@ -93,7 +95,7 @@ def receive_poll_answer(update: Update, context: CallbackContext) -> None:
)
def quiz(update: Update, context: CallbackContext) -> None:
def quiz(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Send a predefined poll"""
questions = ["1", "2", "4", "20"]
message = update.effective_message.reply_poll(
@@ -106,7 +108,7 @@ def quiz(update: Update, context: CallbackContext) -> None:
context.bot_data.update(payload)
def receive_quiz_answer(update: Update, context: CallbackContext) -> None:
def receive_quiz_answer(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Close quiz after three participants took it"""
# the bot can receive closed poll updates we don't care about
if update.poll.is_closed:
@@ -120,7 +122,7 @@ def receive_quiz_answer(update: Update, context: CallbackContext) -> None:
context.bot.stop_poll(quiz_data["chat_id"], quiz_data["message_id"])
def preview(update: Update, context: CallbackContext) -> None:
def preview(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Ask user to create a poll and display a preview of it"""
# using this without a type lets the user chooses what he wants (quiz or poll)
button = [[KeyboardButton("Press me!", request_poll=KeyboardButtonPollType())]]
@@ -131,7 +133,7 @@ def preview(update: Update, context: CallbackContext) -> None:
)
def receive_poll(update: Update, context: CallbackContext) -> None:
def receive_poll(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""On receiving polls, reply to it by a closed poll copying the received poll"""
actual_poll = update.effective_message.poll
# Only need to set the question and options, since all other parameters don't matter for
@@ -145,7 +147,7 @@ def receive_poll(update: Update, context: CallbackContext) -> None:
)
def help_handler(update: Update, context: CallbackContext) -> None:
def help_handler(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Display a help message"""
update.message.reply_text("Use /quiz, /poll or /preview to test this bot.")
@@ -153,7 +155,7 @@ def help_handler(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Run bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
dispatcher = updater.dispatcher
dispatcher.add_handler(CommandHandler('start', start))
dispatcher.add_handler(CommandHandler('poll', poll))
+7 -8
View File
@@ -21,13 +21,12 @@ bot.
import logging
from telegram import Update
from telegram.ext import Updater, CommandHandler, CallbackContext
from telegram.ext import CommandHandler, Updater, CallbackContext
# Enable logging
logging.basicConfig(
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)
@@ -37,18 +36,18 @@ logger = logging.getLogger(__name__)
# since context is an unused local variable.
# This being an example and not having context present confusing beginners,
# we decided to have it present as context.
def start(update: Update, context: CallbackContext) -> None:
def start(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Sends explanation on how to use the bot."""
update.message.reply_text('Hi! Use /set <seconds> to set a timer')
def alarm(context: CallbackContext) -> None:
def alarm(context: CallbackContext.DEFAULT_TYPE) -> None:
"""Send the alarm message."""
job = context.job
context.bot.send_message(job.context, text='Beep!')
def remove_job_if_exists(name: str, context: CallbackContext) -> bool:
def remove_job_if_exists(name: str, context: CallbackContext.DEFAULT_TYPE) -> bool:
"""Remove job with given name. Returns whether job was removed."""
current_jobs = context.job_queue.get_jobs_by_name(name)
if not current_jobs:
@@ -58,7 +57,7 @@ def remove_job_if_exists(name: str, context: CallbackContext) -> bool:
return True
def set_timer(update: Update, context: CallbackContext) -> None:
def set_timer(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Add a job to the queue."""
chat_id = update.message.chat_id
try:
@@ -80,7 +79,7 @@ def set_timer(update: Update, context: CallbackContext) -> None:
update.message.reply_text('Usage: /set <seconds>')
def unset(update: Update, context: CallbackContext) -> None:
def unset(update: Update, context: CallbackContext.DEFAULT_TYPE) -> None:
"""Remove the job if the user changed their mind."""
chat_id = update.message.chat_id
job_removed = remove_job_if_exists(str(chat_id), context)
@@ -91,7 +90,7 @@ def unset(update: Update, context: CallbackContext) -> None:
def main() -> None:
"""Run bot."""
# Create the Updater and pass it your bot's token.
updater = Updater("TOKEN")
updater = Updater.builder().token("TOKEN").build()
# Get the dispatcher to register handlers
dispatcher = updater.dispatcher