I'm trying to make a telegram bot that gets lyrics from the genius API. When the bot asks for the artist, it sends the question for the song title right after, but I'm trying to make the bot work like the input() command in python.
I know I could make the user split the string with a comma between the artist and the song title, but that would be a last resort option.
Here's the code I'm talking about.
def lyrics(update: Update, context: CallbackContext) -> None:
update.message.reply_text("Enter artist")
artist_name = update.message.text
artist = genius.search_artist(artist_name, max_songs=0)
update.message.reply_text("Enter song title")
song_name = update.message.text
song = artist.song(song_name)
update.message.reply_text(song.lyrics)
And an example without the lyrics thing
update.message.reply_text("Reply something")
reply = update.message.text
update.message.reply_text("2nd answer")
reply2 = update.message.text
You might be looking for ConversationHandler
, which can handle conversations.
To start, we need to import the following modules and define Dispatcher
, which takes all the handlers for your bot.
from telegram import Update
from telegram.ext import (
Updater,
Filters,
CommandHandler,
MessageHandler,
ConversationHandler,
CallbackContext
)
updater = Updater('your token here', use_context=True)
dispatcher = updater.dispatcher
Then, we attach the conversation handler to the dispatcher with dispatcher.add_handler
.
You can specify states like the following and define a conversation handler.
Note that states must be int
, for readability, we define constants ARTIST
and TITLE
for different states.
For more information about Filters, check out the documentation here. We only need Filters.text
here as we only take texts as input for MessageHandler
.
ARTIST, TITLE = 0, 1
dispatcher.add_handler(ConversationHandler(
entry_points=[CommandHandler('start', intro)],
states={
ARTIST: [MessageHandler(Filters.text, callback=artist)],
TITLE: [MessageHandler(Filters.text, callback=title)]
},
fallbacks=[CommandHandler('quit', quit)]
))
The conversation is started with entry_points
and proceeded with different states. Each of these requires a handler. For example, we define a CommandHandler
called intro
for entry_points
, which is called when the user inputs the command /start
.
def intro(update: Update, context: CallbackContext) -> int:
update.message.reply_text('Enter artist')
# Specify the succeeding state to enter
return ARTIST
The other handlers like artist
and title
are straightforward as well. For example:
def artist(update: Update, context: CallbackContext) -> int:
artist_name = update.message.text
# This variable needs to be stored globally to be retrieved in the next state
artist = genius.search_artist(artist_name, max_songs=0)
update.message.reply_text('Enter song title')
# Let the conversation proceed to the next state
return TITLE
def title(update: Update, context: CallbackContext) -> int:
song_name = update.message.text
song = artist.song(song_name)
update.message.reply_text(song.lyrics)
# return ConversationHandler.END to end the conversation
return ConversationHandler.END
Also, the conversation needs a fallback handler. In the code example, we define a simple quit function to end the conversation when the user types in the command /quit
.
def quit(update: Update, context: CallbackContext):
return ConversationHandler.END
An advantage of using ConversationHandler
is that you can add any new states at any time to ask more questions. ConversationHandler
also makes filtering messages easier.
You can also take a look at an example of a conversation bot here which utilizes ConversationHandler
.