Reputation: 121
I am trying to build a telegram bot based on the attached example. I have added to the example code, a state for timeout. If no reaction from client will be received in 60 seconds - the chat will be terminated and the user will be notified in message handled in "timeout" function
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start)],
states={
CHOOSING: [MessageHandler(Filters.regex('^(Age|Favourite colour|Number of siblings)$'),
regular_choice),
MessageHandler(Filters.regex('^Something else...$'),
custom_choice)
],
TYPING_CHOICE: [MessageHandler(Filters.text,
regular_choice)
],
TYPING_REPLY: [MessageHandler(Filters.text,
received_information),
],
ConversationHandler.TIMEOUT: [MessageHandler(Filters.text | Filters.command, timeout)],
},
fallbacks=[MessageHandler(Filters.regex('^Done$'), done)],
conversation_timeout=60
def timeout(update, context):
update.message.reply_text('timeout reached, hope to see you next time',reply_markup=ReplyKeyboardRemove())
what I am trying to do is send the user a warning before the chat is terminated. so, for example, after 50 seconds of no activity send a message like "please enter something". the problem is the whole conversation pattern s a state machine based on user's reaction. anyone has a idea how to I trigger an event before timeout is reached
Upvotes: 1
Views: 2985
Reputation: 121
what I was trying to achieve is the following:
in order to do so I have used a thread, and contex.user_data['mykey']
as a signaling mechanism for the thread in order to terminate.
The solution is demonstrated it the attached code:
from telegram import ReplyKeyboardMarkup,ReplyKeyboardRemove,InlineKeyboardMarkup,InlineKeyboardButton
from telegram.ext import Updater, CommandHandler, MessageHandler, Filters, ConversationHandler
import threading
import time
TOKEN='your token'
STAGE1, STAGE2= range(2)
CHAT_TIMEOUT=60
def start(update, context):
"""Send a message when the command /start is issued."""
keyboard = [['lets start']]
update.message.reply_text('Welcome', reply_markup=ReplyKeyboardMarkup(keyboard=keyboard,
one_time_keyboard=True))
return STAGE1
def remider(update,context):
for i in range(int(CHAT_TIMEOUT / 2)):
thread_state=context.user_data['thread']
print(i)
if thread_state:
time.sleep(1)
else:
break
if thread_state:
update.message.reply_text('only 30 seconds left. Please Hurry!')
def stage1 (update,context):
context.user_data['thread'] = True
t=threading.Thread(target=remider, args=(update,context),daemon=True)
t.start()
# your code
keyboard=[['sample','sample','sample']]
update.message.reply_text('select your option',reply_markup=ReplyKeyboardMarkup(keyboard=keyboard,
one_time_keyboard=True))
return STAGE2
def stage2(update,context):
context.user_data['thread']=False
# your code
keyboard=[['sample2','sample2','sample2']]
update.message.reply_text('select your option', reply_markup=ReplyKeyboardMarkup(keyboard=keyboard,
one_time_keyboard=True))
return ConversationHandler.END
def cancel():
pass
def timeout(update, context):
update.message.reply_text('out time has ended. good bye')
def main():
"""Start the bot."""
# Create the Updater and pass it your bot's token.
# Make sure to set use_context=True to use the new context based callbacks
# Post version 12 this will no longer be necessary
updater = Updater(TOKEN, use_context=True)
# Get the dispatcher to register handlers
dp = updater.dispatcher
conv_handler = ConversationHandler(
entry_points=[CommandHandler('start', start)],
states={
STAGE1: [MessageHandler(Filters.text, stage1)],
STAGE2: [MessageHandler(Filters.text, stage2)],
ConversationHandler.TIMEOUT: [MessageHandler(Filters.text | Filters.command, timeout)],
},
fallbacks=[CommandHandler('cancel', cancel),],
conversation_timeout=CHAT_TIMEOUT
)
dp.add_handler(conv_handler)
# Start the Bot
updater.start_polling()
updater.idle()
if __name__=='__main__':
main()
Upvotes: 3