вызвать сообщение во время разговора с ботом telegram с python, до тайм-аута - PullRequest
1 голос
/ 12 апреля 2020

Я пытаюсь построить бот-телеграмму на основе прилагаемого примера. Я добавил в пример кода состояние для тайм-аута. Если в течение 60 секунд от клиента не будет получено никакой реакции - чат будет прерван, и пользователь будет уведомлен в сообщении, обработанном в функции «тайм-аут»

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())

, что я пытаюсь сделать, это отправить пользователя предупреждение перед прекращением чата. так, например, после 50 секунд бездействия отправьте сообщение типа «пожалуйста, введите что-нибудь». проблема в том, что весь шаблон диалога - это конечный автомат, основанный на реакции пользователя. у кого-нибудь есть идея, как вызвать событие до достижения тайм-аута

1 Ответ

0 голосов
/ 17 апреля 2020

я пытался добиться следующего:

  • прекратить чат через 60 секунд без реакции
  • сообщить пользователю, что чат будет прерван через 30 секунд.

для этого я использовал поток, а contex.user_data['mykey'] в качестве механизма сигнализации для потока для завершения.

Решение демонстрируется в прилагаемом коде :

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()
...