[Blurplefy] Update colors and clean up

This commit is contained in:
aikaterna
2022-05-07 11:33:46 -07:00
committed by GitHub
parent d1efba9abd
commit 31b9835cae

View File

@@ -1,29 +1,38 @@
# Ported for Red v3 from: https://github.com/Rocked03/Blurplefied # Ported for Red v3 from: https://github.com/Rocked03/Blurplefied
# pip install python-resize-image
# pip install pillow
import discord
from PIL import Image, ImageEnhance, ImageSequence
from io import BytesIO
import aiohttp import aiohttp
import asyncio import asyncio
import datetime import datetime
import io from io import BytesIO
import logging
import math import math
from PIL import Image, ImageEnhance, ImageSequence, UnidentifiedImageError
import random
import sys
from resizeimage import resizeimage from resizeimage import resizeimage
from redbot.core import Config, commands, checks from types import SimpleNamespace
blurple = (114, 137, 218) import discord
blurplehex = 0x7289DA
darkblurple = (78, 93, 148) from redbot.core import Config, commands, checks
white = (255, 255, 255) from redbot.core.utils.predicates import MessagePredicate
log = logging.getLogger("red.aikaterna.blurplefy")
# LEGACY_BLURPLE = (114, 137, 218)
# LEGACY_DARK_BLURPLE = (78, 93, 148)
BLURPLE = (88, 101, 242)
DARK_BLURPLE = (69, 79, 191)
WHITE = (255, 255, 255)
class Blurplefy(commands.Cog): class Blurplefy(commands.Cog):
"""Blurplefy images and check blurple content of images.""" """Blurplefy images and check blurple content of images."""
async def red_delete_data_for_user(self, **kwargs): async def red_delete_data_for_user(self, **kwargs):
""" Nothing to delete """ """Nothing to delete"""
return return
def __init__(self, bot): def __init__(self, bot):
@@ -40,16 +49,18 @@ class Blurplefy(commands.Cog):
@commands.command() @commands.command()
@checks.admin_or_permissions(manage_roles=True) @checks.admin_or_permissions(manage_roles=True)
async def blurplerole(self, ctx): async def blurplerole(self, ctx):
"""Toggle a role award for having a blurple profile picture.""" """Toggle a role award for having a blurple profile picture.
A user's profile picture will be checked when they use [p]blurple.
"""
blurple_role_id = await self.config.guild(ctx.guild).blurple_role() blurple_role_id = await self.config.guild(ctx.guild).blurple_role()
if blurple_role_id is None: if blurple_role_id is None:
await ctx.send("Enter the role name to award: it needs to be a valid, already existing role.") msg = "Enter the role name to award: it needs to be a valid, already existing role, "
msg += "and the name must match exactly (don't use a role mention)."
def check(m): await ctx.send(msg)
return m.author == ctx.author pred = MessagePredicate.same_context(ctx)
try: try:
blurple_role = await ctx.bot.wait_for("message", timeout=15.0, check=check) blurple_role = await ctx.bot.wait_for("message", timeout=15.0, check=pred)
blurple_role_obj = discord.utils.get(ctx.guild.roles, name=blurple_role.content) blurple_role_obj = discord.utils.get(ctx.guild.roles, name=blurple_role.content)
if blurple_role_obj is None: if blurple_role_obj is None:
return await ctx.send("No role with that name.") return await ctx.send("No role with that name.")
@@ -59,12 +70,7 @@ class Blurplefy(commands.Cog):
role_enabled = await self.config.guild(ctx.guild).role_enabled() role_enabled = await self.config.guild(ctx.guild).role_enabled()
await self.config.guild(ctx.guild).role_enabled.set(not role_enabled) await self.config.guild(ctx.guild).role_enabled.set(not role_enabled)
await ctx.send(f"Blurple role awarding {'enabled' if not role_enabled else 'disabled'}.")
if not role_enabled:
word = "enabled"
else:
word = "disabled"
await ctx.send("Blurple role awarding {}.".format(word))
@commands.guild_only() @commands.guild_only()
@commands.command() @commands.command()
@@ -74,7 +80,7 @@ class Blurplefy(commands.Cog):
await self.config.guild(ctx.guild).blurple_role.set(role_name.id) await self.config.guild(ctx.guild).blurple_role.set(role_name.id)
blurple_role_id = await self.config.guild(ctx.guild).blurple_role() blurple_role_id = await self.config.guild(ctx.guild).blurple_role()
blurple_role_obj = discord.utils.get(ctx.guild.roles, id=blurple_role_id) blurple_role_obj = discord.utils.get(ctx.guild.roles, id=blurple_role_id)
await ctx.send("Blurple award role set to: {}.".format(blurple_role_obj.name)) await ctx.send(f"Blurple award role set to: {blurple_role_obj.name}.")
blurple_role_enabled = await self.config.guild(ctx.guild).role_enabled() blurple_role_enabled = await self.config.guild(ctx.guild).role_enabled()
if not blurple_role_enabled: if not blurple_role_enabled:
await ctx.invoke(self.blurplerole) await ctx.invoke(self.blurplerole)
@@ -82,7 +88,6 @@ class Blurplefy(commands.Cog):
async def blurplefy(self, ctx, user: discord.Member = None): async def blurplefy(self, ctx, user: discord.Member = None):
"""Blurplefy a user or image.""" """Blurplefy a user or image."""
picture = None picture = None
await ctx.send("{}, starting blurple image analysis.".format(ctx.message.author.mention))
link = ctx.message.attachments link = ctx.message.attachments
if user is None and not link: if user is None and not link:
picture = ctx.author.avatar_url picture = ctx.author.avatar_url
@@ -94,19 +99,19 @@ class Blurplefy(commands.Cog):
else: else:
picture = user.avatar_url picture = user.avatar_url
try: try:
async with self.session.request("GET", str(picture)) as r: async with self.session.get(str(picture)) as r:
response = await r.read() response = await r.read()
except ValueError: except ValueError:
await ctx.send("{}, please link a valid image URL.".format(ctx.author.display_name)) await ctx.send(f"{ctx.author.display_name}, please link a valid image URL.")
return return
@commands.guild_only() @commands.guild_only()
@commands.command() @commands.command()
@commands.cooldown(rate=1, per=30, type=commands.BucketType.user) @commands.cooldown(rate=1, per=30, type=commands.BucketType.user)
async def blurple(self, ctx, user: discord.Member = None): async def blurple(self, ctx, user: discord.Member = None):
"""Check a user or uploaded image for blurple content.""" """Check a user or an attached uploaded image for blurple content."""
await ctx.trigger_typing()
picture = None picture = None
await ctx.send("{}, starting blurple image analysis.".format(ctx.message.author.mention))
link = ctx.message.attachments link = ctx.message.attachments
if user is None and not link: if user is None and not link:
picture = ctx.author.avatar_url picture = ctx.author.avatar_url
@@ -121,15 +126,19 @@ class Blurplefy(commands.Cog):
role_check = False role_check = False
try: try:
async with self.session.request("GET", str(picture)) as r: async with self.session.get(str(picture)) as r:
response = await r.read() response = await r.read()
except ValueError: except ValueError:
await ctx.send("{}, please link a valid image URL.".format(ctx.author.display_name)) await ctx.send(f"{ctx.author.display_name}, please link a valid image URL.")
return return
try: try:
im = Image.open(BytesIO(response)) im = Image.open(BytesIO(response))
except Exception: except UnidentifiedImageError:
await ctx.send("{}, please link a valid image URL.".format(ctx.author.display_name)) await ctx.send(f"{ctx.author.display_name}, this doesn't look like an image.")
return
except Exception as exc:
log.exception("Blurplefy encountered an error:\n ", exc_info=exc)
await ctx.send(f"{ctx.author.display_name}, please link a valid image URL.")
return return
im = im.convert("RGBA") im = im.convert("RGBA")
@@ -143,32 +152,30 @@ class Blurplefy(commands.Cog):
im = resizeimage.resize_width(im, (imsize[0] * downsizefraction)) im = resizeimage.resize_width(im, (imsize[0] * downsizefraction))
imsize = list(im.size) imsize = list(im.size)
impixels = imsize[0] * imsize[1] impixels = imsize[0] * imsize[1]
await ctx.send("{}, image resized smaller for easier processing.".format(ctx.message.author.display_name))
image = self.blurple_imager(im, imsize) msg = f"{ctx.author.display_name}, image resized smaller for easier processing."
image = discord.File(fp=image, filename="image.png") await ctx.send(msg)
blurplenesspercentage = round(((nooftotalpixels / noofpixels) * 100), 2) image_object = await self.blurple_imager(im, imsize)
percentblurple = round(((noofblurplepixels / noofpixels) * 100), 2) image = discord.File(fp=image_object.file, filename=f"{random.randint(1,10000)}_image.png")
percentdblurple = round(((noofdarkblurplepixels / noofpixels) * 100), 2)
percentwhite = round(((noofwhitepixels / noofpixels) * 100), 2) blurpleness_percentage = round(((image_object.nooftotalpixels / image_object.noofpixels) * 100), 2)
percent_blurple = round(((image_object.noofblurplepixels / image_object.noofpixels) * 100), 2)
percent_dblurple = round(((image_object.noofdarkblurplepixels / image_object.noofpixels) * 100), 2)
percent_white = round(((image_object.noofwhitepixels / image_object.noofpixels) * 100), 2)
embed = discord.Embed(title="", colour=0x7289DA) embed = discord.Embed(title="", colour=0x7289DA)
embed.add_field(name="Total amount of Blurple", value="{}%".format(blurplenesspercentage), inline=False) embed.add_field(name=f"Total amount of Blurple", value=f"{blurpleness_percentage}%", inline=False)
embed.add_field(name="Blurple (rgb(114, 137, 218))", value="{}%".format(percentblurple), inline=True) embed.add_field(name=f"Blurple (rgb(88, 101, 242))", value=f"{percent_blurple}%", inline=True)
embed.add_field(name="White (rgb(255, 255, 255))", value="{}\\%".format(percentwhite), inline=True) embed.add_field(name=f"White (rgb(255, 255, 255))", value=f"{percent_white}%", inline=True)
embed.add_field( embed.add_field(name=f"Dark Blurple (rgb(69, 79, 191))", value=f"{percent_dblurple}%", inline=True)
name="Dark Blurple (rgb(78, 93, 148))", value="{}\\%".format(percentdblurple), inline=True,
)
embed.add_field( embed.add_field(
name="Guide", name="Guide",
value="Blurple, White, Dark Blurple = \nBlurple, White, and Dark Blurple (respectively) \nBlack = Not Blurple, White, or Dark Blurple", value="Blurple, White, Dark Blurple = \nBlurple, White, and Dark Blurple (respectively) \nBlack = Not Blurple, White, or Dark Blurple",
inline=False, inline=False,
) )
embed.set_footer( embed.set_footer(
text="Please note: Discord slightly reduces quality of the images, therefore the percentages may be slightly inaccurate. | Content requested by {}".format( text=f"Please note: Discord slightly reduces quality of the images, therefore the percentages may be slightly inaccurate.\nContent requested by {str(ctx.author)}"
ctx.author
)
) )
embed.set_image(url="attachment://image.png") embed.set_image(url="attachment://image.png")
embed.set_thumbnail(url=picture) embed.set_thumbnail(url=picture)
@@ -178,32 +185,34 @@ class Blurplefy(commands.Cog):
if role_check and blurple_role_enabled: if role_check and blurple_role_enabled:
blurple_role_id = await self.config.guild(ctx.guild).blurple_role() blurple_role_id = await self.config.guild(ctx.guild).blurple_role()
blurple_role_obj = discord.utils.get(ctx.guild.roles, id=blurple_role_id) blurple_role_obj = discord.utils.get(ctx.guild.roles, id=blurple_role_id)
if not blurple_role_obj:
msg = "The role that is set for the blurple role doesn't exist, so I can't award the role to any qualifying users."
return await ctx.send(msg)
if not ctx.channel.permissions_for(ctx.me).manage_roles:
msg = "I need the Manage Roles permission here to be able to add the set blurple role to users that have a qualifying profile picture set."
return await ctx.send(msg)
if ( if (
blurplenesspercentage > 75 blurpleness_percentage > 75
and picture == ctx.author.avatar_url and picture == ctx.author.avatar_url
and blurple_role_obj not in ctx.author.roles and blurple_role_obj not in ctx.author.roles
and percentblurple > 5 and percent_blurple > 5
): ):
await ctx.send( msg = f"{ctx.author.display_name}, as your profile pic has enough blurple (over 75% in total and over 5% blurple), "
"{}, as your profile pic has enough blurple (over 75% in total and over 5% blurple), you have recieved the role **{}**!".format( msg += f"you have recieved the role **{blurple_role_obj.name}**!"
ctx.message.author.display_name, blurple_role_obj.name await ctx.send(msg)
)
)
await ctx.author.add_roles(blurple_role_obj) await ctx.author.add_roles(blurple_role_obj)
elif picture == ctx.author.avatar_url and blurple_role_obj not in ctx.author.roles: elif picture == ctx.author.avatar_url and blurple_role_obj not in ctx.author.roles:
await ctx.send( msg = f"{ctx.author.display_name}, your profile pic does not have enough blurple (over 75% in total and over 5% blurple), "
"{}, your profile pic does not have enough blurple (over 75% in total and over 5% blurple), therefore you are not eligible for the role {}.".format( msg += f"therefore you are not eligible for the role {blurple_role_obj.name}."
ctx.message.author.display_name, blurple_role_obj.name await ctx.send(msg)
)
)
@commands.guild_only() @commands.guild_only()
@commands.command() @commands.command()
@commands.cooldown(rate=1, per=30, type=commands.BucketType.user) @commands.cooldown(rate=1, per=30, type=commands.BucketType.user)
async def blurplefy(self, ctx, user: discord.Member = None): async def blurplefy(self, ctx, user: discord.Member = None):
"""Blurplefy a user or uploaded image.""" """Blurplefy a user or an uploaded image attached to the command."""
await ctx.trigger_typing()
picture = None picture = None
await ctx.send("{}, starting blurple image analysis.".format(ctx.message.author.mention))
link = ctx.message.attachments link = ctx.message.attachments
if user is None and not link: if user is None and not link:
picture = ctx.author.avatar_url picture = ctx.author.avatar_url
@@ -215,15 +224,19 @@ class Blurplefy(commands.Cog):
else: else:
picture = user.avatar_url picture = user.avatar_url
try: try:
async with self.session.request("GET", str(picture)) as r: async with self.session.get(str(picture)) as r:
response = await r.read() response = await r.read()
except ValueError: except ValueError:
await ctx.send("{}, please link a valid image URL.".format(ctx.author.display_name)) await ctx.send(f"{ctx.author.display_name}, please link a valid image URL.")
return return
try: try:
im = Image.open(BytesIO(response)) im = Image.open(BytesIO(response))
except Exception: except UnidentifiedImageError:
await ctx.send("{}, please link a valid image URL.".format(ctx.author.display_name)) await ctx.send(f"{ctx.author.display_name}, this doesn't look like an image.")
return
except Exception as exc:
log.exception("Blurplefy encountered an error:\n ", exc_info=exc)
await ctx.send(f"{ctx.author.display_name}, please link a valid image URL.")
return return
imsize = list(im.size) imsize = list(im.size)
@@ -235,67 +248,58 @@ class Blurplefy(commands.Cog):
i = im.info["version"] i = im.info["version"]
isgif = True isgif = True
gifloop = int(im.info["loop"]) gifloop = int(im.info["loop"])
except Exception: except KeyError:
# no version key
isgif = False isgif = False
except Exception as exc:
await ctx.send("{}, image fetched, analyzing image...".format(ctx.message.author.display_name)) log.exception("Blurplefy encountered an error:\n ", exc_info=exc)
if impixels > maxpixelcount: if impixels > maxpixelcount:
downsizefraction = math.sqrt(maxpixelcount / impixels) downsizefraction = math.sqrt(maxpixelcount / impixels)
im = resizeimage.resize_width(im, (imsize[0] * downsizefraction)) im = resizeimage.resize_width(im, (imsize[0] * downsizefraction))
imsize = list(im.size) imsize = list(im.size)
impixels = imsize[0] * imsize[1] impixels = imsize[0] * imsize[1]
await ctx.send("{}, image resized smaller for easier processing".format(ctx.message.author.display_name)) await ctx.send(f"{ctx.author.display_name}, image resized smaller for easier processing.")
if isgif is False: if isgif is False:
image = self.imager(im, imsize) image = await self.imager(im, imsize)
else: else:
image = self.gifimager(im, gifloop, imsize) image = await self.gifimager(im, gifloop, imsize)
await ctx.send("{}, image data extracted.".format(ctx.author.display_name))
max_size = 8 * 1024 * 1024
size = sys.getsizeof(image)
if size > max_size:
await ctx.send(
f"{ctx.author.display_name}, whoops! It looks like this image is too big to upload. Try a smaller image (less than 8mb)."
)
return
if isgif is False: if isgif is False:
image = discord.File(fp=image, filename="image.png") image = discord.File(fp=image, filename="image.png")
else: else:
image = discord.File(fp=image, filename="image.gif") image = discord.File(fp=image, filename="image.gif")
try: embed = discord.Embed(title="", colour=0x7289DA)
embed = discord.Embed(title="", colour=0x7289DA) embed.set_author(name="Blurplefier - makes your image blurple!")
embed.set_author(name="Blurplefier - makes your image blurple!") if isgif is False:
if isgif is False: embed.set_image(url="attachment://image.png")
embed.set_image(url="attachment://image.png") else:
else: embed.set_image(url="attachment://image.gif")
embed.set_image(url="attachment://image.gif") embed.set_footer(
embed.set_footer( text=f"Please note - This blurplefier is automated and therefore may not always give you the best result.\nContent requested by {str(ctx.author)}"
text="Please note - This blurplefier is automated and therefore may not always give you the best result. | Content requested by {}".format( )
ctx.author embed.set_thumbnail(url=picture)
) await ctx.send(embed=embed, file=image)
)
embed.set_thumbnail(url=picture)
await ctx.send(embed=embed, file=image)
except Exception:
await ctx.send(
"{}, whoops! It looks like this gif is too big to upload. Try a smaller image (less than 8mb).".format(
ctx.author.name
)
)
@staticmethod @staticmethod
def blurple_imager(im, imsize): async def blurple_imager(im, imsize):
colourbuffer = 20 colourbuffer = 20
global noofblurplepixels
noofblurplepixels = 0 noofblurplepixels = 0
global noofwhitepixels
noofwhitepixels = 0 noofwhitepixels = 0
global noofdarkblurplepixels
noofdarkblurplepixels = 0 noofdarkblurplepixels = 0
global nooftotalpixels
nooftotalpixels = 0 nooftotalpixels = 0
global noofpixels
noofpixels = 0 noofpixels = 0
blurple = (114, 137, 218)
darkblurple = (78, 93, 148)
white = (255, 255, 255)
img = im.load() img = im.load()
for x in range(imsize[0]): for x in range(imsize[0]):
i = 1 i = 1
@@ -306,11 +310,11 @@ class Blurplefy(commands.Cog):
checkwhite = 1 checkwhite = 1
checkdarkblurple = 1 checkdarkblurple = 1
for i in range(3): for i in range(3):
if not (blurple[i] + colourbuffer > pixel[i] > blurple[i] - colourbuffer): if not (BLURPLE[i] + colourbuffer > pixel[i] > BLURPLE[i] - colourbuffer):
checkblurple = 0 checkblurple = 0
if not (darkblurple[i] + colourbuffer > pixel[i] > darkblurple[i] - colourbuffer): if not (DARK_BLURPLE[i] + colourbuffer > pixel[i] > DARK_BLURPLE[i] - colourbuffer):
checkdarkblurple = 0 checkdarkblurple = 0
if not (white[i] + colourbuffer > pixel[i] > white[i] - colourbuffer): if not (WHITE[i] + colourbuffer > pixel[i] > WHITE[i] - colourbuffer):
checkwhite = 0 checkwhite = 0
if checkblurple == 0 and checkdarkblurple == 0 and checkwhite == 0: if checkblurple == 0 and checkdarkblurple == 0 and checkwhite == 0:
check = 0 check = 0
@@ -326,13 +330,20 @@ class Blurplefy(commands.Cog):
noofwhitepixels += 1 noofwhitepixels += 1
noofpixels += 1 noofpixels += 1
image_file_object = io.BytesIO() image_file_object = BytesIO()
im.save(image_file_object, format="png") im.save(image_file_object, format="png")
image_file_object.seek(0) image_file_object.seek(0)
return image_file_object return SimpleNamespace(
file=image_file_object,
noofblurplepixels=noofblurplepixels,
noofwhitepixels=noofwhitepixels,
noofdarkblurplepixels=noofdarkblurplepixels,
nooftotalpixels=nooftotalpixels,
noofpixels=noofpixels,
)
@staticmethod @staticmethod
def imager(im, imsize): async def imager(im, imsize):
im = im.convert(mode="L") im = im.convert(mode="L")
im = ImageEnhance.Contrast(im).enhance(1000) im = ImageEnhance.Contrast(im).enhance(1000)
im = im.convert(mode="RGB") im = im.convert(mode="RGB")
@@ -345,15 +356,15 @@ class Blurplefy(commands.Cog):
pixel = img[x, y] pixel = img[x, y]
if pixel != (255, 255, 255): if pixel != (255, 255, 255):
img[x, y] = (114, 137, 218) img[x, y] = BLURPLE
image_file_object = io.BytesIO() image_file_object = BytesIO()
im.save(image_file_object, format="png") im.save(image_file_object, format="png")
image_file_object.seek(0) image_file_object.seek(0)
return image_file_object return image_file_object
@staticmethod @staticmethod
def gifimager(im, gifloop, imsize): async def gifimager(im, gifloop, imsize):
frames = [frame.copy() for frame in ImageSequence.Iterator(im)] frames = [frame.copy() for frame in ImageSequence.Iterator(im)]
newgif = [] newgif = []
@@ -368,10 +379,10 @@ class Blurplefy(commands.Cog):
for y in range(imsize[1]): for y in range(imsize[1]):
pixel = img[x, y] pixel = img[x, y]
if pixel != (255, 255, 255): if pixel != (255, 255, 255):
img[x, y] = (114, 137, 218) img[x, y] = BLURPLE
newgif.append(frame) newgif.append(frame)
image_file_object = io.BytesIO() image_file_object = BytesIO()
gif = newgif[0] gif = newgif[0]
gif.save(image_file_object, format="gif", save_all=True, append_images=newgif[1:], loop=0) gif.save(image_file_object, format="gif", save_all=True, append_images=newgif[1:], loop=0)
image_file_object.seek(0) image_file_object.seek(0)
@@ -379,17 +390,22 @@ class Blurplefy(commands.Cog):
@commands.command() @commands.command()
async def countdown(self, ctx): async def countdown(self, ctx):
"""Countdown to Discord's 7th Anniversary.""" """Countdown to Discord's next anniversary."""
embed = discord.Embed(name="", colour=0x7289DA) embed = discord.Embed(name="\N{ZERO WIDTH SPACE}", colour=0x7289DA)
timeleft = datetime.datetime(2021, 5, 13) + datetime.timedelta(hours=7) - datetime.datetime.utcnow() now = datetime.datetime.utcnow()
embed.set_author(name="Time left until Discord's 6th Anniversary")
if int(timeleft.total_seconds()) < 0: timeleft = datetime.datetime(now.year, 5, 13) + datetime.timedelta(hours=7) - datetime.datetime.utcnow()
timeleft = datetime.datetime(2022, 5, 13) + datetime.timedelta(hours=7) - datetime.datetime.utcnow() discord_years = now.year - 2015
embed.set_author(name="Time left until Discord's 6th Anniversary") if timeleft.total_seconds() < 0:
embed.add_field( timeleft = (
name="Countdown to midnight, May 13, California time (UTC-7):", datetime.datetime((now.year + 1), 5, 13) + datetime.timedelta(hours=7) - datetime.datetime.utcnow()
value=("{}".format(self._dynamic_time(int(timeleft.total_seconds())))), )
) discord_years = (now.year + 1) - 2015
discord_years_suffix = self._get_suffix(discord_years)
embed.set_author(name=f"Time left until Discord's {discord_years}{discord_years_suffix} Anniversary")
time = self._dynamic_time(int(timeleft.total_seconds()))
embed.add_field(name="Countdown to midnight, May 13, California time (UTC-7):", value=f"{time}")
await ctx.send(embed=embed) await ctx.send(embed=embed)
@staticmethod @staticmethod
@@ -410,5 +426,14 @@ class Blurplefy(commands.Cog):
msg = "" msg = ""
return msg.format(d, h, m, s) return msg.format(d, h, m, s)
@staticmethod
def _get_suffix(num):
suffixes = {1: "st", 2: "nd", 3: "rd"}
if 10 <= num % 100 <= 20:
suffix = "th"
else:
suffix = suffixes.get(num % 10, "th")
return suffix
def cog_unload(self): def cog_unload(self):
self.bot.loop.create_task(self.session.close()) self.bot.loop.create_task(self.session.close())