added jpeg compress to imagmagic, fixed some issues with rolemanagement age

This commit is contained in:
Brandon 2023-02-01 16:42:00 -05:00
parent b56b54578a
commit df579194c2
5 changed files with 109 additions and 21 deletions

View file

@ -4,6 +4,7 @@ from wand.image import Image
from io import BytesIO
from typing import Optional, Tuple, Literal
import asyncio, functools, urllib
from PIL import Image as PILImage
MAX_SIZE = 8 * 1024 * 1024
@ -18,7 +19,9 @@ class ImageMagic(commands.Cog):
def __init__(self, bot):
super().__init__()
self.config = Config.get_conf(self, identifier=4928034571, force_registration=True)
self.config = Config.get_conf(
self, identifier=4928034571, force_registration=True
)
self.bot = bot
async def _get_image(self, ctx, link: str = None) -> Image:
@ -33,7 +36,9 @@ class ImageMagic(commands.Cog):
if ctx.message.reference:
msg = ctx.message.reference.resolved
if msg is None:
msg = await ctx.channel.fetch_message(ctx.message.reference.message_id)
msg = await ctx.channel.fetch_message(
ctx.message.reference.message_id
)
if msg and msg.attachments:
for a in msg.attachments:
path = urllib.parse.urlparse(a.url).path
@ -61,7 +66,9 @@ class ImageMagic(commands.Cog):
except:
raise ImageFindError("Invalid filetype")
except (OSError, aiohttp.ClientError):
raise ImageFindError("An image could not be found. Make sure you provide a direct link.")
raise ImageFindError(
"An image could not be found. Make sure you provide a direct link."
)
else: # attached image
path = urllib.parse.urlparse(ctx.message.attachments[0].url).path
if ctx.message.attachments[0].size > max_filesize:
@ -85,6 +92,27 @@ class ImageMagic(commands.Cog):
intensity /= 10
return intensity
def _jpeg_compress(self, img: Image, quality: int) -> Image:
# save image to temp variable to load it as a PIL image
temp_file = BytesIO()
img.save(file=temp_file)
temp_file.seek(0)
# load as PIL image
pil_img = PILImage.open(temp_file)
img = PILImage.new("RGB", pil_img.size)
img.paste(pil_img)
# compress
temp_file = BytesIO()
img.save(temp_file, "JPEG", quality=quality)
temp_file.seek(0)
# return as wand image
img = Image(file=temp_file)
return img, "jpeg.jpeg"
def _distortion(self, img: Image, func: str, args: Tuple) -> Tuple[Image, str]:
# distort
img.iterator_reset()
@ -110,7 +138,9 @@ class ImageMagic(commands.Cog):
return
try:
await ctx.reply(file=discord.File(BytesIO(img.make_blob()), name), mention_author=False)
await ctx.reply(
file=discord.File(BytesIO(img.make_blob()), name), mention_author=False
)
except discord.errors.HTTPException:
await ctx.reply("That image is too large.", mention_author=False)
return
@ -126,8 +156,21 @@ class ImageMagic(commands.Cog):
pass
@distort.command()
async def barrel(self, ctx, intensity: Optional[float] = 10, *, link: str = None):
async def jpeg(self, ctx, quality: Optional[float] = 10, *, link: str = None):
"""
Applies JPEG compression to image
"""
quality = int(self._intensity(quality) * 100)
async with ctx.typing():
try:
img = await self._get_image(ctx, link)
except ImageFindError as e:
return await ctx.reply(e, mention_author=False)
await self._command_body(ctx, args=(self._jpeg_compress, img, quality))
@distort.command()
async def barrel(self, ctx, intensity: Optional[float] = 10, *, link: str = None):
"""
Bulges the center of the image outward
"""
@ -145,7 +188,10 @@ class ImageMagic(commands.Cog):
self._distortion,
img,
"distort",
("barrel", (amount * intensity, amount * intensity, amount * intensity, 0)),
(
"barrel",
(amount * intensity, amount * intensity, amount * intensity, 0),
),
),
)
@ -162,7 +208,9 @@ class ImageMagic(commands.Cog):
except ImageFindError as e:
return await ctx.reply(e, mention_author=False)
await self._command_body(ctx, args=(self._distortion, img, "implode", (amount * intensity,)))
await self._command_body(
ctx, args=(self._distortion, img, "implode", (amount * intensity,))
)
@distort.command()
async def swirl(self, ctx, intensity: Optional[float] = 10, *, link: str = None):
@ -170,7 +218,19 @@ class ImageMagic(commands.Cog):
Swirls the center of the image
"""
switch = {0: 0, 1: 18, 2: 36, 3: 54, 4: 72, 5: 90, 6: 108, 7: 126, 8: 144, 9: 162, 10: 180}
switch = {
0: 0,
1: 18,
2: 36,
3: 54,
4: 72,
5: 90,
6: 108,
7: 126,
8: 144,
9: 162,
10: 180,
}
intensity = float(switch.get(round(intensity), 180))
async with ctx.typing():
@ -179,7 +239,9 @@ class ImageMagic(commands.Cog):
except ImageFindError as e:
return await ctx.reply(e, mention_author=False)
await self._command_body(ctx, args=(self._distortion, img, "swirl", (intensity,)))
await self._command_body(
ctx, args=(self._distortion, img, "swirl", (intensity,))
)
@distort.command()
async def charcoal(self, ctx, intensity: Optional[float], *, link: str = None):
@ -193,7 +255,9 @@ class ImageMagic(commands.Cog):
except ImageFindError as e:
return await ctx.reply(e, mention_author=False)
await self._command_body(ctx, args=(self._distortion, img, "charcoal", (1.5, 0.5)))
await self._command_body(
ctx, args=(self._distortion, img, "charcoal", (1.5, 0.5))
)
@distort.command()
async def sketch(self, ctx, intensity: Optional[float], *, link: str = None):
@ -207,7 +271,9 @@ class ImageMagic(commands.Cog):
except ImageFindError as e:
return await ctx.reply(e, mention_author=False)
await self._command_body(ctx, args=(self._distortion, img, "sketch", (0.5, 0.0, 98.0)))
await self._command_body(
ctx, args=(self._distortion, img, "sketch", (0.5, 0.0, 98.0))
)
@distort.command()
async def zoom(self, ctx, intensity: Optional[float], *, link: str = None):
@ -225,7 +291,15 @@ class ImageMagic(commands.Cog):
w = img.width
img = self._distortion(img, "transform", (f"{w}x{h}", "150%"))[0]
await self._command_body(ctx, args=(self._distortion, img, "transform", (f"{w/1.5}x{h/1.5}+{w/2}+{h/2}",)))
await self._command_body(
ctx,
args=(
self._distortion,
img,
"transform",
(f"{w/1.5}x{h/1.5}+{w/2}+{h/2}",),
),
)
async def red_delete_data_for_user(

View file

@ -7,5 +7,8 @@
"description": "Manipulates images.",
"hidden": false,
"end_user_data_statement": "This cog does not store user data.",
"requirements": ["wand"]
}
"requirements": [
"wand",
"Pillow"
]
}

View file

@ -1,6 +1,6 @@
from .core import RoleManagement
__red_end_user_data_statement__ = "This will only store sticky and subscribed roles for users."
__red_end_user_data_statement__ = "This will only store birthdays, sticky, and subscribed roles for users."
def setup(bot):

View file

@ -101,6 +101,7 @@ class RoleManagement(
age_verification=None,
) # subscribed_users maps str(user.id)-> end time in unix timestamp
self.config.register_member(roles=[], forbidden=[], birthday=None)
self.config.register_user(birthday=None)
self.config.init_custom("REACTROLE", 2)
self.config.register_custom(
"REACTROLE", roleid=None, channelid=None, guildid=None
@ -176,6 +177,16 @@ class RoleManagement(
except RuntimeError:
pass
# fix moving birthdays to user config from member config
for guild in self.bot.guilds:
for member in guild.members:
m_age = await self.config.member(member).birthday()
u_age = await self.config.user(member).birthday()
if m_age and u_age is None:
await self.config.user(member).birthday.set(m_age)
await self.config.member(member).birthday.set(None)
self._ready.set()
async def wait_for_ready(self):
@ -295,7 +306,7 @@ class RoleManagement(
)
return
await self.config.member(member).birthday.set(dob.strftime("%m/%d/%Y"))
await self.config.user(member).birthday.set(dob.strftime("%m/%d/%Y"))
await ctx.tick()
@commands.guild_only()
@ -1279,7 +1290,7 @@ class RoleManagement(
member = ctx.author
guild = member.guild
dob = await self.config.member(member).birthday()
dob = await self.config.user(member).birthday()
min_age = await self.config.role(role).age_verification()
age_log = await self.config.guild(guild).age_log()
today = datetime.utcnow().date()
@ -1351,7 +1362,7 @@ class RoleManagement(
await member.send(
f"Thank you! Please check back in `{guild}` to confirm you obtained the role. If not, you may not meet the age requirement for the role."
)
await self.config.member(member).birthday.set(dob_str)
await self.config.user(member).birthday.set(dob_str)
if age_log:
try:
await modlog.create_case(
@ -1424,4 +1435,4 @@ class RoleManagement(
requester: Literal["discord_deleted_user", "owner", "user", "user_strict"],
user_id: int,
):
pass
await self.config.user_from_id(user_id).clear()

View file

@ -18,5 +18,5 @@
],
"hidden": false,
"min_bot_version": "3.4.0",
"end_user_data_statement": "This will only store sticky and subscribed roles for users."
}
"end_user_data_statement": "This will only store birthdays, sticky, and subscribed roles for users."
}