Discord.py | Pillow ImageFilter
Задача кода: При использовании команды бот берет фотографию пользователя или того, кого пользователь отметил, и добавляет эффект размытия.
Проблема кода: Просмотрев довольно много источников, чтобы выполнить свою задачу, я не смог найти подробного ответа. На мой взгляд, мой код выглядит нормально, но он не работает, но, несмотря на то, ошибка не выводится.
Код:
from PIL import Image, ImageFilter
@Bot.command()
async def blur(ctx, user: discord.Member = None):
async with ctx.channel.typing():
await ctx.message.delete()
url = user.avatar_url
image = Image.open(url)
blurred_url = image.filter(ImageFilter.BLUR)
blurred_url.save("sas.png")
file = discord.File("sas.png", filename="sas.png")
await ctx.send(file=file)
Ответы (1 шт):
Возможно ошибка у вас не выводится потому что вы даже не запустили бота)
По крайней мере в конце вашего кода я не вижу строчки Bot.run('TOKEN') или чего-то такого.
Далее к проблемам кода
Первая проблема в том, что у вас по умолчанию, если не указан аргумент user, он принимает значение None. На этот случай нужно добавить условие проверки:
if user is None:
# значит нужно размыть аватарку автора
else:
# нужно размыть аватарку указанного пользователя
В противном случае бот будет пытаться размыть аватарку только объекта user, а объект None является пустым и не имеет атрибута avatar_url, соответственно, строка url = user.avatar_url работать не будет.
Об этом и сообщает discord-py:
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: AttributeError: 'NoneType' object has no attribute 'avatar_url'
Данная проблема решается одной строкой:
if user is None: user = ctx.author
Если user пустой, то он принимает значение автора сообщения
Следующая проблема заключается в том, что вы пытаетесь считать картинку по ссылке, в то время как библиотеке требуется локальная картинка на вашем компьютере. То есть, bytes-like object, объект, который можно считать по отдельным битам.
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: a bytes-like object is required, not 'coroutine'
Для решения этой проблемы достаточно просто скачать указанную картинку - прямая ссылка у вас уже есть:
from urllib.request import Request, urlopen
url = user.avatar_url # ссылка на аватарку пользователя
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'}) # эти параметры нужно передать дискорду, чтобы он думал, что заходит реальный человек - в противном случае не будет доступа
resource = urlopen(req) # открываем картинку
avatar = open("avatar", 'wb') # записываем картинку в файл
avatar.write(resource.read())
avatar.close() # закрываем файл
Затем все тоже самое, но открываем уже конкретный файл:
image = Image.open('avatar.png')
Готово! Результат:
Полный код:
import discord
from discord.ext import commands
from PIL import Image, ImageFilter
from urllib.request import Request, urlopen
Bot = commands.Bot(command_prefix='!', intents = discord.Intents.all())
@Bot.command()
async def blur(ctx, user: discord.Member = None):
if user is None: user = ctx.author
async with ctx.channel.typing():
await ctx.message.delete()
url = user.avatar_url
req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
resource = urlopen(req)
avatar = open("avatar.png", 'wb')
avatar.write(resource.read())
avatar.close()
image = Image.open('avatar.png')
blurred_url = image.filter(ImageFilter.BLUR)
blurred_url.save("sas.png")
file = discord.File("sas.png", filename="sas.png")
await ctx.send(file=file)
Bot.run('TOKEN')
Не забудьте указать токен!

