Reputation: 2399
I have a bot where I have a menu with buttons. When a button is clicked I send some data accordingly. If the selected menu has sub menu I update the buttons.
At some options (buttons) I need user's location so I need to start a conversation.
In all examples I came upon, a conversation starts when a commend is executed (for example /start
).
How can I start a conversation when a button is clicked? I added an example code gathered from python-telegram-bot
's examples to be close to my original code since I created class
es to encapsulate the operations and generate buttons from a json file.
example:
import logging
from telegram import ReplyKeyboardMarkup, ReplyKeyboardRemove, Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import (
Updater,
CommandHandler,
MessageHandler,
Filters,
ConversationHandler,
CallbackContext, CallbackQueryHandler,
)
# 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:
keyboard = [
[
InlineKeyboardButton("Hello", callback_data='1'),
InlineKeyboardButton("Good bye", callback_data='2'),
],
[InlineKeyboardButton("Where are you", callback_data='3')],
]
reply_markup = InlineKeyboardMarkup(keyboard)
update.message.reply_text('Please choose:', reply_markup=reply_markup)
def button(update: Update, context: CallbackContext) -> None:
query = update.callback_query
# CallbackQueries need to be answered, even if no notification to the user is needed
# Some clients may have trouble otherwise. See https://core.telegram.org/bots/api#callbackquery
query.answer()
if query.data == "1":
query.edit_message_text(text=f"Hello bro how are you?")
elif query.data == "2":
query.edit_message_text(text=f"Can't you stay? I feel lonely.")
elif query.data == "3":
query.edit_message_text(text=f"Start Conersation here")
else:
query.edit_message_text(text=f"WTF")
def ask(update: Update, context: CallbackContext) -> int:
reply_keyboard = [['Boy', 'Girl', 'Other']]
update.message.reply_text(
'Hi! My name is Professor Bot. I will hold a conversation with you. '
'Send /cancel to stop talking to me.\n\n'
'Are you a boy or a girl?',
reply_markup=ReplyKeyboardMarkup(
reply_keyboard, one_time_keyboard=True, input_field_placeholder='Boy or Girl?'
),
)
return GENDER
def gender(update: Update, context: CallbackContext) -> int:
user = update.message.from_user
logger.info("Gender of %s: %s", user.first_name, update.message.text)
update.message.reply_text(
'I see! Please send me a photo of yourself, '
'so I know what you look like, or send /skip if you don\'t want to.',
reply_markup=ReplyKeyboardRemove(),
)
return PHOTO
def photo(update: Update, context: CallbackContext) -> int:
user = update.message.from_user
photo_file = update.message.photo[-1].get_file()
photo_file.download('user_photo.jpg')
logger.info("Photo of %s: %s", user.first_name, 'user_photo.jpg')
update.message.reply_text(
'Gorgeous! Now, send me your location please, or send /skip if you don\'t want to.'
)
return LOCATION
def skip_photo(update: Update, context: CallbackContext) -> int:
user = update.message.from_user
logger.info("User %s did not send a photo.", user.first_name)
update.message.reply_text(
'I bet you look great! Now, send me your location please, or send /skip.'
)
return LOCATION
def location(update: Update, context: CallbackContext) -> int:
user = update.message.from_user
user_location = update.message.location
logger.info(
"Location of %s: %f / %f", user.first_name, user_location.latitude, user_location.longitude
)
update.message.reply_text(
'Maybe I can visit you sometime! At last, tell me something about yourself.'
)
return BIO
def skip_location(update: Update, context: CallbackContext) -> int:
user = update.message.from_user
logger.info("User %s did not send a location.", user.first_name)
update.message.reply_text(
'You seem a bit paranoid! At last, tell me something about yourself.'
)
return BIO
def bio(update: Update, context: CallbackContext) -> int:
user = update.message.from_user
logger.info("Bio of %s: %s", user.first_name, update.message.text)
update.message.reply_text('Thank you! I hope we can talk again some day.')
return ConversationHandler.END
def cancel(update: Update, context: CallbackContext) -> int:
user = update.message.from_user
logger.info("User %s canceled the conversation.", user.first_name)
update.message.reply_text(
'Bye! I hope we can talk again some day.', reply_markup=ReplyKeyboardRemove()
)
return ConversationHandler.END
def main() -> None:
updater = Updater("token")
updater.dispatcher.add_handler(CommandHandler('start', start))
updater.dispatcher.add_handler(CallbackQueryHandler(button))
conv_handler = ConversationHandler(
entry_points=[CommandHandler('ask', ask)],
states={
GENDER: [MessageHandler(Filters.regex('^(Boy|Girl|Other)$'), gender)],
PHOTO: [MessageHandler(Filters.photo, photo), CommandHandler('skip', skip_photo)],
LOCATION: [
MessageHandler(Filters.location, location),
CommandHandler('skip', skip_location),
],
BIO: [MessageHandler(Filters.text & ~Filters.command, bio)],
},
fallbacks=[CommandHandler('cancel', cancel)],
)
updater.dispatcher.add_handler(conv_handler)
updater.start_polling()
updater.idle()
if __name__ == '__main__':
main()
With this code user can initiate conversation by /ask
and display button menu by /start
.
How can I start the conversation when button defined as InlineKeyboardButton("Where are you", callback_data='3')
is clicked?
Upvotes: 1
Views: 3282
Reputation: 7050
You can just use a CallbackQueryHandler
is entry point for the conversation.
Disclaimer: I'm currently the maintainer of python-telegram-bot
Upvotes: 1