1

From time to time my telegram bot seems to ignore messages. Unfortunately it never happens to me but to other users and only when they are asked to upload a photo or pdf. Sometimes the corresponding handler is not called. The problem persists even when the MessageHandler has no filters at all. I am using python-telegram-bot v13.7.

Please find below a minimal sample. It should print "receiving something" whenever the handler is called but sometimes it doesn't.

Is there anything I can do?

EDIT: modified the sample to be a MWE (you have to provide a valid telegram bot ID). Most of the time it works just fine but sometimes it will fail and not print "receiving something" although the user uploaded some document (mostly images).

from telegram import Update
from telegram.ext import (
    Updater,
    CommandHandler,
    MessageHandler,
    Filters,
    ConversationHandler,
    CallbackContext,
)

UPLOAD = 0

def welcome(update: Update, context: CallbackContext) -> int:
    update.message.reply_text('Available commands: /upload')
    return ConversationHandler.END

def upload(update: Update, context: CallbackContext) -> int:
    update.message.reply_text('Please upload document.')
    return UPLOAD

def receive(update: Update, context: CallbackContext) -> int:
    print('receiving something...')
    update.message.reply_text('Thank you.')
    return ConversationHandler.END

def cancel(*args) -> int:
    print('cancelled')
    return welcome(*args)

def handle(*args, **options):
    updater = Updater(" ...... ")
    dispatcher = updater.dispatcher

    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('upload', upload),
                      MessageHandler(Filters.text, welcome)
                      ],
        states={
            # UPLOAD: [CommandHandler('cancel', cancel), MessageHandler(Filters.photo | Filters.document.pdf, receive)],
            UPLOAD: [CommandHandler('cancel', cancel), MessageHandler(Filters.all, receive)],
        },
        fallbacks=[CommandHandler('cancel', cancel)],
        conversation_timeout=60
    )

    dispatcher.add_handler(conv_handler)
    updater.start_polling()
    updater.idle()

handle()
Christian K.
  • 2,785
  • 18
  • 40
  • 1
    > Is there anything I can do? - Yes, you can show proper [MWE](https://github.com/python-telegram-bot/python-telegram-bot/wiki/MWE) or at least explain how one should run your code snippet. ;) BTW, `None` is not a valid input for the first argument of `MessageHandler` - you'll probably want to try [`Filters.all`](https://python-telegram-bot.readthedocs.io/en/stable/telegram.ext.filters.html#telegram.ext.filters.Filters.all) instead – CallMeStag Mar 23 '22 at 17:00
  • Well, since it depends on having a real telegram bot ID I thought nobody would ever want to run it anyway. I will try what you suggest although using `None` it does seem to accept anything already. – Christian K. Mar 23 '22 at 17:48
  • Docs say, that only the first handler that returns `True` will be called. Any chance it's the `'cancel'`, stopping the other handler from running at all? – Mahrkeenerh Mar 31 '22 at 10:00
  • @Mahrkeenerh does not seem to be the case as most of the time it just works fine (95%) – Christian K. Mar 31 '22 at 22:22
  • do you get a message `"cancelled"` when it doesn't work? Do you get it when it does work? – Mahrkeenerh Mar 31 '22 at 23:03
  • @Mahrkeenerh when it fails there is no output at all. If I resend the same document immediatly after the failed reception it will fail again, however the bot will react to the /cancel command. – Christian K. Apr 01 '22 at 00:01

1 Answers1

1

One situation where such a behaviour can occure is a timeout. You have defined a timeout of 60 seconds and if the time is over, the bot silently does nothing and can not react to your uploaded file, because it's not anymore in the correct state for that. If this is you problem you can easily check this by defining a function triggering in the timeout-state.

I changed 2 things of your code:

  1. add a timeout function:
    def timeout(*args):
        print("timeout")
  1. add function to timeout state (ConversationHandler.TIMEOUT)
...
conv_handler = ConversationHandler(
    entry_points=[CommandHandler('upload', upload),
        MessageHandler(Filters.text, welcome)],
    states={
        UPLOAD: [CommandHandler('cancel', cancel), MessageHandler(Filters.all, receive)],
        ConversationHandler.TIMEOUT: [MessageHandler(Filters.all, timeout)]
    },
    fallbacks=[CommandHandler('cancel', cancel)],
    conversation_timeout=2,
)
...

(3. Reduce timeout for easier testing :))

From the documentation of conversation_timeout:

When this handler is inactive more than this timeout (in seconds), it will be automatically ended. If this value is 0 or None (default), there will be no timeout. The last received update and the corresponding context will be handled by ALL the handler’s who’s check_update method returns True that are in the state ConversationHandler.TIMEOUT.

A second situation where a bot CAN ignore messages is, when multiple users use the bot simultaneously. As far as i know CAN this lead to a situation where a user "hijacks" anothers state, so that the other users isn't anymore in the state of "uploading", so that this users can not upload a file until he "starts" the upload state. (I am not 100% shure about this, but you should give it a try)

D-E-N
  • 1,242
  • 7
  • 14