1

I'm programming a telegram bot in python that, on command, starts sending a photo of a window on my computer to the chat every few seconds. Of course I don't want the chat to get spammed with photos so instead I want to go back and edit the first message that I send using edit_media.

Currently my callback function to the command looks like this:

def callback(update: Update, context: CallbackContext):
    first = True
    while True:
        image = screenshot('Snake')     # Gets a screenshot of the window
        bytesio = io.BytesIO()
        image.save(bytesio, format='PNG')
        bytes_image = bytes(bytesio.getvalue())     # Convert to bytes object
        if first:       # First time send a full message 
            context.bot.send_photo(update.message.chat_id, bytes_image)
            first = False
        else:       
            update.message.edit_media(media=InputMediaPhoto(media=bytes_image)) # Edit the message with the next photo
        time.sleep(2)

When this function runs, the first message is sent successfully, but trying to edit the message raises an error: telegram.error.BadRequest: Message can't be edited

How do I solve this so that the image is successfully edited?

The full traceback of the error is:

Traceback (most recent call last):
  File "C:\Users\...\telegram\ext\dispatcher.py", line 555, in process_update
    handler.handle_update(update, self, check, context)
  File "C:\Users\...\telegram\ext\handler.py", line 198, in handle_update
    return self.callback(update, context)
  File "C:\Users\...\TelegramGameHub\main.py", line 56, in snake
    update.message.edit_media(media=InputMediaPhoto(media=bytes_image))
  File "C:\Users\...\telegram\message.py", line 2016, in edit_media
    return self.bot.edit_message_media(
  File "C:\Users\...\telegram\bot.py", line 130, in decorator
    result = func(*args, **kwargs)
  File "C:\Users\...\telegram\bot.py", line 2723, in edit_message_media
    return self._message(
  File "C:\Users\...\telegram\ext\extbot.py", line 199, in _message
    result = super()._message(
  File "C:\Users\...\telegram\bot.py", line 332, in _message
    result = self._post(endpoint, data, timeout=timeout, api_kwargs=api_kwargs)
  File "C:\Users\...\telegram\bot.py", line 295, in _post
    return self.request.post(
  File "C:\Users\...\telegram\utils\request.py", line 354, in post
    result = self._request_wrapper('POST', url, fields=data, **urlopen_kwargs)
  File "C:\Users\...\telegram\utils\request.py", line 279, in _request_wrapper
    raise BadRequest(message)
Manusman
  • 57
  • 6

1 Answers1

1

The problem is that your line

update.message.edit_media(media=InputMediaPhoto(media=bytes_image))

doesn't edit the photo message that you sent. It instead tries to edit the message that initially triggered the callback.

To get a hold of the message that you send, you'll need to do something like

message = context.bot.send_photo(update.message.chat_id, bytes_image)

Note that PTB provides shortcuts for these kind of things. So you could abbreviate this to

message = update.message.reply_photo(bytes_image)

which is (almost) equivalent.

Now you can call message.edit_media(...) to update the photo.

Another thing to note is that your loop

while True:
   ...
   time.sleep(2)

is blocking. That means that after entering the function callback, your bot won't process any other updates. (Side note in case you know what run_async does: Even if you run this callback asynchronously, it will block one of the worker threads and as soon as enough updates have triggered this callback, all the worker threads are blocked and your bot won't process any more updates)

I highly recommend to use the built in JobQueue for such things. See also the wiki page and the example.


Disclaimer: I'm currently the maintainer of python-telegram-bot.

CallMeStag
  • 5,467
  • 1
  • 7
  • 22
  • Thanks for the answer, you are correct I was mistakenly trying to edit the wrong message. After fixing the problem I ran into the other thing you mentioned where the loop is blocking, I created another thread using `threading` to fix this, is that ok or should I use a `JobQueue` instead? – Manusman Jul 18 '21 at 19:09
  • Also, if you have the time and patience I'd love if you could go over the rest of the programs code and tell me what I could improve. Of course, no obligations. I posted what I've done so far [here](https://pastebin.com/wd68cRn1) – Manusman Jul 18 '21 at 19:17
  • Starting a thread sounds reasonable as well, sure – CallMeStag Jul 19 '21 at 06:09