Reputation: 1177
I have written a simple telegram bot in python
with the python-telegram-bot
library that rolls a n-sided die and returns the result to the user.
My code for this:
# Let's make a dice bot
import random
import time
from telegram.ext import Updater,CommandHandler,MessageHandler, Filters
from telegram import Update
updater = Updater(token='MY-TOKEN', use_context=True)
dispatcher = updater.dispatcher
# relevant function here:
def dice_roll(sides):
roll = random.randint(1,sides)
return roll
def dice(update, context):
result = dice_roll(int(context.args[0]))
lucky_dice = "You rolled a "+str(result)
context.bot.send_message(chat_id=update.message.chat_id, text=lucky_dice)
dice_handler = CommandHandler('rollDice', dice)
dispatcher.add_handler(dice_handler)
# Polling function here:
updater.start_polling(clean=True)
What I'd like to improve
I do not really like the way users interact with the bot at the moment. To roll a die, the user has to define the number of sides of the die in the command argument, like this:
$user: /rollDice 6
$bot: You rolled a 5
This isn't really user-friendly, and it's also prone to errors if users add anything else to the argument or simply forget.
Instead, I'd like the bot to ask the user for the input explicitly, like this:
$user: /rollDice
$bot: Please enter the number of sides, the die should have
$user: 6
$bot: You rolled a 5
I looked into force_reply
, but my main issue is that I do not know how to access a new update/message within a handler function.
If I try something like this:
def dice(update, context):
context.bot.send_message(chat_id=update.message.chat_id, text="Please enter the number of sides, the die should have") # new line
result = dice_roll(int(context.args[0]))
lucky_dice = "You rolled a "+str(result)
context.bot.send_message(chat_id=update.message.chat_id, text=lucky_dice)
dice_handler = CommandHandler('rollDice', dice)
dispatcher.add_handler(dice_handler)
it does not really work, because a) the bot does not really give the user time to reply (adding a sleep
statement here seems very wrong) and b) it refers back to the original "command message" and not any new message sent in the meantime.
Any help is appreciated.
Upvotes: 2
Views: 3094
Reputation: 6802
You can use ConversationHandler
to achieve this, I am using similar code for my bot which asks user the bus number and replies with timetable. Most of the code is borrowed from: https://codeclimate.com/github/leandrotoledo/python-telegram-bot/examples/conversationbot.py/source
from telegram.ext import (Updater, CommandHandler, RegexHandler, ConversationHandler)
import random
# states
ROLLDICE = range(1)
def start(bot, update):
update.message.reply_text('Please enter the number of sides, the die should have')
return ROLLDICE
def cancel(bot, update):
update.message.reply_text('Bye! I hope we can talk again some day.')
return ConversationHandler.END
def rolldice(bot, update):
roll = random.randint(1, int(update.message.text))
update.message.reply_text('You rolled: ' + str(roll))
return ConversationHandler.END
def main():
updater = Updater(TOKEN)
dp = updater.dispatcher
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start)],
states={ROLLDICE: [RegexHandler('^[0-9]+$', rolldice)]},
fallbacks=[CommandHandler('cancel', cancel)]
)
dp.add_handler(conv_handler)
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
Output:
/start
Please enter the number of sides, the die should have
6
You rolled: 2
Upvotes: 2