Creating a Telegram Chatbot Quiz with Python | by Beppe Catanese | Towards Data Science

One of the features that make Telegram a great Chatbot platform is the ability to create Polls. This was introduced in 2019, later improved by adding the Quiz mode and, most importantly, by making it available to the Telegram Chatbot API.
It is possible to create a Poll directly in the Telegram application (without coding) but here we will explore how to develop from scratch a Telegram Chatbot quiz using the Python Telegram Bot library.
First some warming up: play with a live example and test your knowledge of the world’s capitals 😎. Kick off the conversation with the /start command (*).
t.me
(*) Please be patient, it runs on-demand and might take few seconds to wake up and start chatting 😊
The setup involves 3 steps:
talk the BotFather to create a new chatbot and obtain the authorization Token
configure the Updater object and the method handlers
start the chatbot (in Polling mode in this example, but a Webhook could be used instead)
def main():  updater = Updater('secret token', use_context=True)  dp = updater.dispatcher  # command handlers  dp.add_handler(CommandHandler("help", help_command_handler))  # message handler  dp.add_handler(MessageHandler(Filters.text, main_handler))  # quiz handler  dp.add_handler(PollHandler(poll_handler, pass_chat_data=True, pass_user_data=True))  # start  updater.start_polling()  updater.idle()
It is important to understand that the handlers defined above are responsible for processing the ‘help’ Command, simple text messages and Poll answers.
We are going first to create a helper method to grab the Chat id: this is going to be very useful in this tutorial, but also if you develop other Telegram Chatbots.
# extract chat_id based on the incoming objectdef get_chat_id(update, context):  chat_id = -1  if update.message is not None:    chat_id = update.message.chat.id  elif update.callback_query is not None:    chat_id = update.callback_query.message.chat.id  elif update.poll is not None:    chat_id = context.bot_data[update.poll.id]  return chat_id
Creating a Quiz answer can be done using the send_poll method
c_id = get_chat_id(update, context)q = 'What is the capital of Italy?'answers = ['Rome', 'London', 'Amsterdam']message = context.bot.send_poll(chat_id=c_id, question=q, options=answers, type=Poll.QUIZ, correct_option_id=0)
The type must be Poll.QUIZ to trigger the Quiz effects (confetti upon choosing the right answer) and thecorrect_option_id must match (positionally) the correct option in the provided list of answers.
Let’s not stop at the basics but make the Quiz a little bit fancier.
It is possible to add a countdown to make it more exciting:
message = context.bot.send_poll(chat_id=c_id, question=q, options=answers, type=Poll.QUIZ, correct_option_id=0, open_period=5)
An additional explanation can be included to provide extra information after the user has answered: notice the lamp icon available to the user.
message = context.bot.send_poll(chat_id=c_id, question=q, options=answers, type=Poll.QUIZ, correct_option_id=0, explanation= 'Well, honestly that depends on what you eat', explanation_parse_mode = telegram.ParseMode.MARKDOWN_V2)
It is important to understand how to process the user answers.
The Telegram BOT API provides the methods and objects to render a nice interface as well as celebrating the correct answer (or marking a wrong response). However, the developer needs to track the successful answers and build the necessary logic, like for example calculating a score, increasing the complexity of the following question, etc...
All quiz answers are sent to the PollHandler where the update object will carry the payload with all necessary information
# handling Poll answersdef poll_handler(update, context):  # Quiz question  question = update.poll.question  # position of correct answer  correct_answer = update.poll.correct_option_id  # first option (text and voted yes|no)  option_1_text = update.poll.options[0].text  option_1_vote = update.poll.options[0].voter_count
Each option in the payload indicates if it has been voted or not (voter_count equal to 1).
# find the answer chosen by the userdef get_answer(update):  answers = update.poll.options  ret = ""  for answer in answers:    if answer.voter_count == 1:      # found it      ret = answer.text      break  return ret
Using the correct_option_id it is possible to establish whether the answer given by the user is correct or not.
# determine if user answer is correctdef is_answer_correct(update):  answers = update.poll.options  ret = False  counter = 0  for answer in answers:    if answer.voter_count == 1 and \                update.poll.correct_option_id == counter:      ret = True      break        counter = counter + 1  return ret
It is possible to create a Regular Poll instead of a Quiz: the logic and code are the same, however, there are some differences that make the standard Poll more suitable for surveys and questionnaires:
no confetti celebration
allowing multiple answers
make results visible to the users
message = context.bot.send_poll(chat_id=cid, question=q, options=answers, type=Poll.REGULAR, allows_multiple_answers=True,is_anonymous=False)
We have introduced all key concepts of developing a Quiz on Telegram, check out the Github repo to start from a base Quiz implementation with the code snippets presented in the article.
If you are developing Telegram chatbots you might find this useful:
towardsdatascience.com
Find me on Twitter for questions and suggestions and, if you create a Telegram Quiz chatbot, share it with me!