1

I'm making a discord bot that sends a message whenever someones changes their avatar. It downloads their previous avatar and the new avatar, and joins them together, but I'm getting this error:

Ignoring exception in on_user_update
Traceback (most recent call last):
File "/app/.heroku/python/lib/python3.6/site-packages/discord/client.py", line 343, in _run_event
await coro(*args, **kwargs)
File "bot.py", line 40, in on_user_update
images = [Image.open(x) for x in ['originalAvatar.png', 'updatedAvatar.png']]
File "bot.py", line 40, in <listcomp>
images = [Image.open(x) for x in ['originalAvatar.png', 'updatedAvatar.png']]
File "/app/.heroku/python/lib/python3.6/site-packages/PIL/Image.py", line 2959, in open
"cannot identify image file %r" % (filename if filename else fp)
PIL.UnidentifiedImageError: cannot identify image file 'originalAvatar.png'

This is my code:

@bot.event
async def on_user_update(before, after):
if before.avatar != after.avatar:
    mencao = after.mention
    channel = bot.get_channel(zzzzzzzzzzzzz)
    authorId = after.id
    tempo = datetime.date.today().strftime("%d/%m/%Y")

    originalFile = before.avatar_url_as(format='png', static_format='webp', size=128)
    updatedFile = after.avatar_url_as(format='png', static_format='webp', size=128)

    r = requests.get(originalFile, allow_redirects=True)
    open('originalAvatar.png', 'wb').write(r.content)
    s = requests.get(updatedFile, allow_redirects=True)
    open('updatedAvatar.png', 'wb').write(s.content)

    images = [Image.open(x) for x in ['originalAvatar.png', 'updatedAvatar.png']]
    widths, heights = zip(*(i.size for i in images))

    total_width = sum(widths)
    max_height = max(heights)

    new_im = Image.new('RGB', (total_width, max_height))

    x_offset = 0
    for im in images:
        new_im.paste(im, (x_offset, 0))
        x_offset += im.size[0]

    new_im.save('test.png')

    file = discord.File("test.png", filename="image.png")
    embed = discord.Embed(name="title", description=f"\U0001F5BC {mencao} **alterou o avatar**", color=0xe12674)
    embed.set_image(url="attachment://image.png")
    embed.set_footer(text=f"ID do usuário: {authorId} • {tempo}")

    await channel.send(file=file, embed=embed)

    if os.path.exists(f"originalAvatar.png"):
        os.remove(f"originalAvatar.png")
    if os.path.exists(f"updatedAvatar.png"):
        os.remove(f"updatedAvatar.png")
    if os.path.exists("test.png"):
        os.remove("test.png")

I'm running the python file on heroku btw, how do I fix this?

UPDATE: I've replaced open('originalAvatar.png', 'wb').write(r.content) with

 with open('originalAvatar.png', 'wb').write(r.content) as f:
            r.raw.decode_content = True
            shutil.copyfileobj(r.raw, f)

but now it gives me this error:

Ignoring exception in on_user_update
Traceback (most recent call last):
File "/home/lucas/.local/lib/python3.8/site-packages/discord/client.py", line 
343, in _run_event
await coro(*args, **kwargs)
File "/home/lucas/bot/bot.py", line 36, in on_user_update
with open('originalAvatar.png', 'wb').write(r.content) as f:
AttributeError: __enter__

and here is the on_message part of the code:

 @bot.event
 async def on_message(message):
 mensagem = message.content
 if mensagem.startswith("$avatar") and hasNumbers(mensagem) == False:
     nome = message.author.name
     avatar = message.author.avatar_url_as(size=2048)
     r = requests.get(avatar, allow_redirects=True)
     with open('Avatar.gif', 'wb').write(r.content) as f:
         r.raw.decode_content = True
         shutil.copyfileobj(r.raw, f)
  • I suspect that if you view the contents of `originalAvatar.png` in a hex editor, it doesn't actually contain valid PNG data. Also you're not closing either of the open files so that could be an issue. You should use `with open`: https://docs.python.org/3/tutorial/inputoutput.html#reading-and-writing-files – Random Davis Feb 16 '21 at 19:51
  • Also you're not necessarily downloading images correctly; this looks different than your implementation. You're not using `r.raw` or `r.raw.decode_content`: https://stackoverflow.com/questions/13137817/how-to-download-image-using-requests – Random Davis Feb 16 '21 at 19:52
  • I have replaced ```open('originalAvatar.png', 'wb').write(r.content)``` with ```with open(originalAvatar.png', 'wb').write(r.content) as f: r.raw.decode_content = True shutil.copyfileobj(r.raw, f)``` and it works, *but* now it says ```File "/home/lucas/bot/bot.py", line 83, in on_message with open('Avatar.gif', 'wb').write(r.content) as f: AttributeError: __enter__``` –  Feb 16 '21 at 20:06
  • Sorry if my markdown is wonky, I'm new to this –  Feb 16 '21 at 20:08
  • Just put the updated info into your post so it's formatted properly, comments aren't meant for large blocks of code. – Random Davis Feb 16 '21 at 20:09
  • Also that error is from `on_message` which you didn't include the code of here. Seems like a separate issue entirely but I can't be sure unless you post the relevant code and the entire error. – Random Davis Feb 16 '21 at 20:11
  • My bad, I copied the wrong thing, but that error is also occuring on ```on_member_update``` –  Feb 16 '21 at 20:20
  • The line `with open('originalAvatar.png', 'wb').write(r.content) as f:` is wrong. You just want `with open('originalAvatar.png', 'wb') as f:`, and then put `f.write(r.content)` inside that block. – Random Davis Feb 16 '21 at 20:34
  • That worked! Thanks –  Feb 16 '21 at 21:37
  • Okay, I'll post my suggestions as an answer so you can upvote/accept it if you want. – Random Davis Feb 16 '21 at 21:52

1 Answers1

0

The following lines have a couple of issues:

r = requests.get(originalFile, allow_redirects=True)
open('originalAvatar.png', 'wb').write(r.content)

For one, it does not close the file originalAvatar.png. The with open statement should be used to avoid this issue. Secondly, it's not writing the actual raw binary data of the image to the file correctly. There are multiple ways to do this (see here), so I'll show just one possible method, based on this question:

r = requests.get(originalFile, allow_redirects=True)
r.raw.decode_content = True
with f = open('originalAvatar.png', 'wb'):
    shutil.copyfileobj(r.raw, f)
Random Davis
  • 6,662
  • 4
  • 14
  • 24