From 2f9cfcf15d3665495e23c787114510af024aa230 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Tue, 6 Dec 2022 16:14:00 +0000 Subject: [PATCH 1/6] Minor bugfixes --- jarvis/client/events/message.py | 3 ++- jarvis/cogs/dbrand.py | 2 +- jarvis/cogs/util.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/jarvis/client/events/message.py b/jarvis/client/events/message.py index e381a32..1ad16f3 100644 --- a/jarvis/client/events/message.py +++ b/jarvis/client/events/message.py @@ -83,7 +83,8 @@ class MessageEventMixin: "VtgZntXcnZ", "gPfYGbvTCE", ] - if (m := match.group(1)) not in allowed and setting.value: + is_mod = message.author.has_permission(Permissions.MANAGE_GUILD) or message.author.has_permission(Permissions.ADMINISTRATOR) + if (m := match.group(1)) not in allowed and setting.value and not is_mod: self.logger.debug(f"Removing non-allowed invite `{m}` from {message.guild.id}") try: await message.delete() diff --git a/jarvis/cogs/dbrand.py b/jarvis/cogs/dbrand.py index 858a5bb..95edcaf 100644 --- a/jarvis/cogs/dbrand.py +++ b/jarvis/cogs/dbrand.py @@ -145,7 +145,7 @@ class DbrandCog(Extension): title="Contact Support", description="", fields=fields, - url="https://dbrand.com/support", + url="https://dbrand.com/contact", color=color, ) diff --git a/jarvis/cogs/util.py b/jarvis/cogs/util.py index b00dce8..71ecc2b 100644 --- a/jarvis/cogs/util.py +++ b/jarvis/cogs/util.py @@ -223,7 +223,7 @@ class UtilCog(Extension): ) @cooldown(bucket=Buckets.USER, rate=1, interval=5) async def _avatar_slash(self, ctx: InteractionContext, user: User = None) -> None: - await self._userinfo(ctx, user) + await self._avatar(ctx, user) @context_menu(name="Avatar", context_type=CommandTypes.USER) async def _avatar_menu(self, ctx: InteractionContext) -> None: From e65c76b981cef7aeccd7759d24a005e9f9a9b727 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Tue, 6 Dec 2022 16:16:28 +0000 Subject: [PATCH 2/6] Add more allowed invites --- jarvis/client/events/message.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/jarvis/client/events/message.py b/jarvis/client/events/message.py index 1ad16f3..6b4a769 100644 --- a/jarvis/client/events/message.py +++ b/jarvis/client/events/message.py @@ -82,6 +82,8 @@ class MessageEventMixin: "dbrand", "VtgZntXcnZ", "gPfYGbvTCE", + "interactions", + "NTSHu97tHg" ] is_mod = message.author.has_permission(Permissions.MANAGE_GUILD) or message.author.has_permission(Permissions.ADMINISTRATOR) if (m := match.group(1)) not in allowed and setting.value and not is_mod: From 8471580517f2608b446ea11e4e2163e3b8c0af1f Mon Sep 17 00:00:00 2001 From: zevaryx Date: Wed, 14 Dec 2022 16:07:41 +0000 Subject: [PATCH 3/6] Allow autopurge of bot messages --- jarvis/client/events/message.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jarvis/client/events/message.py b/jarvis/client/events/message.py index 6b4a769..2d18e11 100644 --- a/jarvis/client/events/message.py +++ b/jarvis/client/events/message.py @@ -416,11 +416,11 @@ class MessageEventMixin: async def on_message(self, event: MessageCreate) -> None: """Handle on_message event. Calls other event handlers.""" message = event.message + await self.autopurge(message) if not isinstance(message.channel, DMChannel) and not message.author.bot: await self.autoreact(message) await self.massmention(message) await self.roleping(message) - await self.autopurge(message) await self.checks(message) await self.filters(message) if not (phish := await self.phishing(message)): From 622b0032469ad99a66bb7dfd57b177d53c96fa8e Mon Sep 17 00:00:00 2001 From: zevaryx Date: Wed, 14 Dec 2022 16:08:17 +0000 Subject: [PATCH 4/6] Fix bug in remindme if used in DMs --- jarvis/cogs/remindme.py | 50 ++++++++++++++--------------------------- 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/jarvis/cogs/remindme.py b/jarvis/cogs/remindme.py index 53a4874..2b47a79 100644 --- a/jarvis/cogs/remindme.py +++ b/jarvis/cogs/remindme.py @@ -55,6 +55,8 @@ class RemindmeCog(Extension): ) -> None: if private is None and ctx.guild: private = ctx.guild.member_count >= 5000 + elif private is None and not ctx.guild: + private = False modal = Modal( title="Set your reminder!", components=[ @@ -94,9 +96,7 @@ class RemindmeCog(Extension): await response.send("Hey, you should probably make this readable", ephemeral=True) return elif len(message) == 0: - await response.send( - "Hey, you should probably add content to your reminder", ephemeral=True - ) + await response.send("Hey, you should probably add content to your reminder", ephemeral=True) return base_settings = { @@ -105,9 +105,7 @@ class RemindmeCog(Extension): "RETURN_AS_TIMEZONE_AWARE": True, } rt_settings = base_settings.copy() - rt_settings["PARSERS"] = [ - x for x in default_parsers if x not in ["absolute-time", "timestamp"] - ] + rt_settings["PARSERS"] = [x for x in default_parsers if x not in ["absolute-time", "timestamp"]] rt_remind_at = parse(delay, settings=rt_settings) @@ -121,15 +119,11 @@ class RemindmeCog(Extension): remind_at = at_remind_at else: self.logger.debug(f"Failed to parse delay: {delay}") - await response.send( - f"`{delay}` is not a parsable date, please try again", ephemeral=True - ) + await response.send(f"`{delay}` is not a parsable date, please try again", ephemeral=True) return if remind_at < datetime.now(tz=timezone.utc): - await response.send( - f"`{delay}` is in the past. Past reminders aren't allowed", ephemeral=True - ) + await response.send(f"`{delay}` is in the past. Past reminders aren't allowed", ephemeral=True) return elif remind_at < datetime.now(tz=timezone.utc): @@ -165,18 +159,16 @@ class RemindmeCog(Extension): icon_url=ctx.author.display_avatar.url, ) embed.set_thumbnail(url=ctx.author.display_avatar.url) - - delete_button = Button( - style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) - copy_button = Button(style=ButtonStyles.GREEN, emoji="📋", custom_id=f"copy|rme|{r.id}") - components = [ActionRow(delete_button, copy_button)] + delete_button = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") + components = [delete_button] + if not r.guild == ctx.author.id: + copy_button = Button(style=ButtonStyles.GREEN, emoji="📋", custom_id=f"copy|rme|{r.id}") + components.append(copy_button) private = private if private is not None else False + components = [ActionRow(*components)] await response.send(embeds=embed, components=components, ephemeral=private) - async def get_reminders_embed( - self, ctx: InteractionContext, reminders: List[Reminder] - ) -> Embed: + async def get_reminders_embed(self, ctx: InteractionContext, reminders: List[Reminder]) -> Embed: """Build embed for paginator.""" fields = [] for reminder in reminders: @@ -219,9 +211,7 @@ class RemindmeCog(Extension): return embed = await self.get_reminders_embed(ctx, reminders) - components = Button( - style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @reminders.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a reminder") @@ -254,9 +244,7 @@ class RemindmeCog(Extension): ) embed.set_thumbnail(url=ctx.author.display_avatar.url) - components = Button( - style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") try: await reminder.delete() except Exception: @@ -288,18 +276,14 @@ class RemindmeCog(Extension): EmbedField(name="Created At", value=f" ()"), ] - embed = build_embed( - title="You have a reminder!", description=reminder.message, fields=fields - ) + embed = build_embed(title="You have a reminder!", description=reminder.message, fields=fields) embed.set_author( name=ctx.author.display_name + "#" + ctx.author.discriminator, icon_url=ctx.author.display_avatar.url, ) embed.set_thumbnail(url=ctx.author.display_avatar.url) - components = Button( - style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyles.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, ephemeral=reminder.private, components=components) if reminder.remind_at <= datetime.now(tz=timezone.utc) and not reminder.active: try: From f8cd9039b8da5f92f7b62b9596998fa86c891c6c Mon Sep 17 00:00:00 2001 From: zevaryx Date: Wed, 14 Dec 2022 16:08:34 +0000 Subject: [PATCH 5/6] Add delete_history to ban --- jarvis/cogs/admin/ban.py | 63 +++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 26 deletions(-) diff --git a/jarvis/cogs/admin/ban.py b/jarvis/cogs/admin/ban.py index 4ea06d5..455876b 100644 --- a/jarvis/cogs/admin/ban.py +++ b/jarvis/cogs/admin/ban.py @@ -1,5 +1,6 @@ """JARVIS BanCog.""" import re +from datetime import timedelta from jarvis_core.db import q from jarvis_core.db.models import Ban, Unban @@ -23,6 +24,8 @@ from jarvis.utils import build_embed from jarvis.utils.cogs import ModcaseCog from jarvis.utils.permissions import admin_or_permissions +time_pattern = re.compile(r"(\d+\.?\d+?[s|m|h|d|w]{1})\s?", re.I) + class BanCog(ModcaseCog): """JARVIS BanCog.""" @@ -35,9 +38,10 @@ class BanCog(ModcaseCog): duration: int, active: bool, mtype: str, + delete_history: int = 0, ) -> None: """Apply a Discord ban.""" - await ctx.guild.ban(user, reason=reason) + await ctx.guild.ban(user, reason=reason, delete_message_seconds=delete_history) b = Ban( user=user.id, username=user.username, @@ -81,9 +85,7 @@ class BanCog(ModcaseCog): @slash_command(name="ban", description="Ban a user") @slash_option(name="user", description="User to ban", opt_type=OptionTypes.USER, required=True) - @slash_option( - name="reason", description="Ban reason", opt_type=OptionTypes.STRING, required=True - ) + @slash_option(name="reason", description="Ban reason", opt_type=OptionTypes.STRING, required=True) @slash_option( name="btype", description="Ban type", @@ -101,6 +103,12 @@ class BanCog(ModcaseCog): opt_type=OptionTypes.INTEGER, required=False, ) + @slash_option( + name="delete_history", + description="Delete message history, format: 1w 3d 7h 5m 20s", + opt_type=OptionTypes.STRING, + required=False, + ) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) async def _ban( self, @@ -109,6 +117,7 @@ class BanCog(ModcaseCog): reason: str, btype: str = "perm", duration: int = 4, + delete_history: str = None, ) -> None: if user.id == ctx.author.id: await ctx.send("You cannot ban yourself.", ephemeral=True) @@ -122,10 +131,27 @@ class BanCog(ModcaseCog): elif btype == "temp" and duration > 744: await ctx.send("You cannot set a temp ban to > 1 month", ephemeral=True) return + if not time_pattern.match(delete_history): + await ctx.send("Invalid time string, please follow example: 1w 3d 7h 5m 20s", ephemeral=True) + return if len(reason) > 100: await ctx.send("Reason must be < 100 characters", ephemeral=True) return + if delete_history: + units = {"w": "weeks", "d": "days", "h": "hours", "m": "minutes", "s": "seconds"} + delta = {"weeks": 0, "days": 0, "hours": 0, "minutes": 0, "seconds": 0} + delete_history = delete_history.strip().lower() + if delete_history: + if times := time_pattern.findall(delete_history): + for t in times: + delta[units[t[-1]]] += float(t[:-1]) + delete_history = int(timedelta(**delta).total_seconds) + + if delete_history > 604800: + await ctx.send("Delete history cannot be greater than 7 days (604800 seconds)", ephemeral=True) + return + await ctx.defer() mtype = btype @@ -152,7 +178,7 @@ class BanCog(ModcaseCog): except Exception: self.logger.warn(f"Failed to send ban embed to {user.id}") try: - await ctx.guild.ban(user, reason=reason) + await self.discord_apply_ban(ctx, reason, user, duration, active, mtype, delete_history or 0) except Exception as e: await ctx.send(f"Failed to ban user:\n```\n{e}\n```", ephemeral=True) return @@ -166,15 +192,9 @@ class BanCog(ModcaseCog): if btype == "soft": active = False - await self.discord_apply_ban(ctx, reason, user, duration, active, mtype) - @slash_command(name="unban", description="Unban a user") - @slash_option( - name="user", description="User to unban", opt_type=OptionTypes.STRING, required=True - ) - @slash_option( - name="reason", description="Unban reason", opt_type=OptionTypes.STRING, required=True - ) + @slash_option(name="user", description="User to unban", opt_type=OptionTypes.STRING, required=True) + @slash_option(name="reason", description="Unban reason", opt_type=OptionTypes.STRING, required=True) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) async def _unban( self, @@ -212,14 +232,9 @@ class BanCog(ModcaseCog): if len(results) > 1: active_bans = [] for ban in bans: - active_bans.append( - "{0} ({1}): {2}".format(ban.user.username, ban.user.id, ban.reason) - ) + active_bans.append("{0} ({1}): {2}".format(ban.user.username, ban.user.id, ban.reason)) ab_message = "\n".join(active_bans) - message = ( - "More than one result. " - f"Please use one of the following IDs:\n```{ab_message}\n```" - ) + message = "More than one result. " f"Please use one of the following IDs:\n```{ab_message}\n```" await ctx.send(message) return else: @@ -230,9 +245,7 @@ class BanCog(ModcaseCog): # We take advantage of the previous checks to save CPU cycles if not discord_ban_info: if isinstance(user, User): - database_ban_info = await Ban.find_one( - q(guild=ctx.guild.id, user=user.id, active=True) - ) + database_ban_info = await Ban.find_one(q(guild=ctx.guild.id, user=user.id, active=True)) else: search = { "guild": ctx.guild.id, @@ -288,9 +301,7 @@ class BanCog(ModcaseCog): required=False, ) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) - async def _bans_list( - self, ctx: InteractionContext, btype: int = 0, active: bool = True - ) -> None: + async def _bans_list(self, ctx: InteractionContext, btype: int = 0, active: bool = True) -> None: types = [0, "perm", "temp", "soft"] search = {"guild": ctx.guild.id} if active: From 04dd11db43a146456a2774673f74daafb6c38737 Mon Sep 17 00:00:00 2001 From: zevaryx Date: Wed, 14 Dec 2022 16:08:40 +0000 Subject: [PATCH 6/6] Small changes --- jarvis/cogs/util.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/jarvis/cogs/util.py b/jarvis/cogs/util.py index 71ecc2b..4a18dd9 100644 --- a/jarvis/cogs/util.py +++ b/jarvis/cogs/util.py @@ -56,6 +56,10 @@ class UtilCog(Extension): async def _sex(self, ctx: InteractionContext) -> None: if ctx.author.id == 264072583987593217: await ctx.send("Oh fuck no, go fuck yourself") + elif ctx.author.id == 840031256201003008: + await ctx.send("https://tenor.com/view/fluffy-gabriel-iglesias-you-need-jesus-thats-what-you-need-pointing-up-gif-16385108") + elif ctx.author.id == 215564028615852033: + await ctx.send("As flattered as I am, I'm not into bestiality") else: await ctx.send("Not at this time, thank you for offering")