Hazkel
Hazkel

Reputation: 121

trigger message during conversation with telegram bot with python, before timout

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

Answers (1)

Hazkel
Hazkel

Reputation: 121

what I was trying to achieve is the following:

  • terminate the chat after 60 seconds of not reaction
  • let the user know the chat will be terminated after 30 seconds.

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

Related Questions