From cd6aa668a03c0277a7e5366e06607549187122d9 Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Sun, 17 Mar 2024 00:00:42 -0600 Subject: [PATCH] [fix] Pre-commit formatting --- README.md | 2 +- jarvis/__init__.py | 16 +--- jarvis/branding.py | 11 ++- jarvis/client/__init__.py | 5 +- jarvis/client/errors.py | 32 ++----- jarvis/client/events/__init__.py | 70 +++++--------- jarvis/client/events/components.py | 23 ++--- jarvis/client/events/member.py | 41 +++----- jarvis/client/events/message.py | 140 ++++++++-------------------- jarvis/client/tasks.py | 8 +- jarvis/cogs/core/admin/__init__.py | 1 + jarvis/cogs/core/admin/autoreact.py | 53 ++++------- jarvis/cogs/core/admin/ban.py | 49 +++------- jarvis/cogs/core/admin/filters.py | 25 ++--- jarvis/cogs/core/admin/kick.py | 1 + jarvis/cogs/core/admin/lock.py | 3 +- jarvis/cogs/core/admin/lockdown.py | 6 +- jarvis/cogs/core/admin/modcase.py | 75 +++++---------- jarvis/cogs/core/admin/mute.py | 54 +++-------- jarvis/cogs/core/admin/purge.py | 3 +- jarvis/cogs/core/admin/roleping.py | 1 + jarvis/cogs/core/admin/settings.py | 1 + jarvis/cogs/core/admin/temprole.py | 3 +- jarvis/cogs/core/admin/verify.py | 3 +- jarvis/cogs/core/admin/warning.py | 31 ++---- jarvis/cogs/core/botutil.py | 13 +-- jarvis/cogs/core/data.py | 12 +-- jarvis/cogs/core/remindme.py | 66 ++++--------- jarvis/cogs/core/util.py | 91 +++++------------- jarvis/cogs/extra/__init__.py | 1 + jarvis/cogs/extra/calc.py | 87 +++++------------ jarvis/cogs/extra/dev.py | 44 +++------ jarvis/cogs/extra/image.py | 3 +- jarvis/cogs/extra/pinboard.py | 35 +++---- jarvis/cogs/extra/rolegiver.py | 129 +++++++------------------ jarvis/cogs/extra/tags.py | 71 +++++--------- jarvis/cogs/unique/__init__.py | 1 + jarvis/cogs/unique/ctc2.py | 23 ++--- jarvis/cogs/unique/dbrand.py | 67 ++++--------- jarvis/cogs/unique/gl.py | 1 + jarvis/config.py | 8 +- jarvis/const.py | 2 - jarvis/data/dbrand.py | 1 + jarvis/data/pigpen.py | 1 + jarvis/data/robotcamo.py | 1 + jarvis/data/unicode.py | 1 + jarvis/data/units.py | 36 +++---- jarvis/embeds/admin.py | 7 ++ jarvis/utils/__init__.py | 11 +-- jarvis/utils/cogs.py | 48 +++------- jarvis/utils/permissions.py | 3 +- jarvis/utils/updates.py | 2 +- pyproject.toml | 3 +- run.py | 7 +- 54 files changed, 448 insertions(+), 984 deletions(-) diff --git a/README.md b/README.md index 4781a7c..46846ce 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
- JARVIS + JARVIS # Just Another Rather Very Intelligent System diff --git a/jarvis/__init__.py b/jarvis/__init__.py index bf8ef8c..82aff29 100644 --- a/jarvis/__init__.py +++ b/jarvis/__init__.py @@ -1,4 +1,5 @@ """Main JARVIS package.""" + import logging from functools import partial from typing import Any @@ -26,6 +27,7 @@ def jlogger(logger: logging.Logger, event: Any) -> None: Args: logger: Logger to use event: Event to parse + """ jlog = partial(logger.log, 11) if isinstance(event, jurigged.live.WatchOperation): @@ -61,21 +63,13 @@ async def run() -> None: config = load_config() logger = get_logger("jarvis", show_locals=False) # jconfig.log_level == "DEBUG") logger.setLevel(config.log_level) - file_handler = logging.FileHandler( - filename="jarvis.log", encoding="UTF-8", mode="w" - ) - file_handler.setFormatter( - logging.Formatter("[%(asctime)s] [%(name)s] [%(levelname)8s] %(message)s") - ) + file_handler = logging.FileHandler(filename="jarvis.log", encoding="UTF-8", mode="w") + file_handler.setFormatter(logging.Formatter("[%(asctime)s] [%(name)s] [%(levelname)8s] %(message)s")) logger.addHandler(file_handler) # Configure client intents = ( - Intents.DEFAULT - | Intents.MESSAGES - | Intents.GUILD_MEMBERS - | Intents.GUILD_MESSAGES - | Intents.MESSAGE_CONTENT + Intents.DEFAULT | Intents.MESSAGES | Intents.GUILD_MEMBERS | Intents.GUILD_MESSAGES | Intents.MESSAGE_CONTENT ) redis_config = config.redis.model_dump() redis_host = redis_config.pop("host") diff --git a/jarvis/branding.py b/jarvis/branding.py index e7d2a02..825d0af 100644 --- a/jarvis/branding.py +++ b/jarvis/branding.py @@ -1,4 +1,5 @@ """JARVIS brandings.""" + PRIMARY_COLOR = "#3498db" HARD_ACTION = "#ff0000" MODERATE_ACTION = "#ff9900" @@ -29,14 +30,14 @@ def get_command_color(command: str) -> str: Returns: Hex color string + """ if command in COMMAND_TYPES["HARD"]: return HARD_ACTION - elif command in COMMAND_TYPES["MODERATE"]: + if command in COMMAND_TYPES["MODERATE"]: return MODERATE_ACTION - elif command in COMMAND_TYPES["SOFT"]: + if command in COMMAND_TYPES["SOFT"]: return SOFT_ACTION - elif command in COMMAND_TYPES["GOOD"]: + if command in COMMAND_TYPES["GOOD"]: return GOOD_ACTION - else: - return CUSTOM_COMMANDS.get(command, PRIMARY_COLOR) + return CUSTOM_COMMANDS.get(command, PRIMARY_COLOR) diff --git a/jarvis/client/__init__.py b/jarvis/client/__init__.py index 777c371..8247ec7 100644 --- a/jarvis/client/__init__.py +++ b/jarvis/client/__init__.py @@ -1,4 +1,5 @@ """Custom JARVIS client.""" + import logging from typing import TYPE_CHECKING @@ -21,9 +22,7 @@ CMD_FMT = fmt(Fore.GREEN, Format.BOLD) class Jarvis(StatipyClient, ErrorMixin, EventMixin, TaskMixin): - def __init__( - self, redis: "aioredis.Redis", erapi: str, *args, **kwargs - ): # noqa: ANN002 ANN003 + def __init__(self, redis: "aioredis.Redis", erapi: str, *args, **kwargs): super().__init__(*args, **kwargs) self.redis = redis self.logger = logging.getLogger(__name__) diff --git a/jarvis/client/errors.py b/jarvis/client/errors.py index cf0f9f1..6267f51 100644 --- a/jarvis/client/errors.py +++ b/jarvis/client/errors.py @@ -1,4 +1,5 @@ """JARVIS error handling mixin.""" + import traceback from datetime import datetime, timezone @@ -40,26 +41,21 @@ class ErrorMixin: error = event.error if isinstance(error, HTTPException): errors = error.search_for_message(error.errors) - out = ( - f"HTTPException: {error.status}|{error.response.reason}: " - + "\n".join(errors) - ) + out = f"HTTPException: {error.status}|{error.response.reason}: " + "\n".join(errors) self.logger.error(out, exc_info=error) else: self.logger.error(f"Ignoring exception in {source}", exc_info=error) - async def on_command_error( - self, ctx: BaseContext, error: Exception, *args: list, **kwargs: dict - ) -> None: + async def on_command_error(self, ctx: BaseContext, error: Exception, *args: list, **kwargs: dict) -> None: """NAFF on_command_error override.""" name = ctx.invoke_target self.logger.debug(f"Handling error in {name}: {error}") if isinstance(error, CommandOnCooldown): await ctx.send(str(error), ephemeral=True) - return - elif isinstance(error, CommandCheckFailure): + return None + if isinstance(error, CommandCheckFailure): await ctx.send("I'm afraid I can't let you do that", ephemeral=True) - return + return None guild = await self.fetch_guild(DEFAULT_GUILD) channel = await guild.fetch_channel(DEFAULT_ERROR_CHANNEL) error_time = datetime.now(tz=timezone.utc).strftime("%d-%m-%Y %H:%M-%S.%f UTC") @@ -80,11 +76,7 @@ class ErrorMixin: v = v[97] + "..." arg_str += f" - {v}" callback_args = "\n".join(f" - {i}" for i in args) if args else " None" - callback_kwargs = ( - "\n".join(f" {k}: {v}" for k, v in kwargs.items()) - if kwargs - else " None" - ) + callback_kwargs = "\n".join(f" {k}: {v}" for k, v in kwargs.items()) if kwargs else " None" full_message = ERROR_MSG.format( guild_name=ctx.guild.name, error_time=error_time, @@ -96,11 +88,7 @@ class ErrorMixin: tb = traceback.format_exception(error) if isinstance(error, HTTPException): errors = error.search_for_message(error.errors) - tb[ - -1 - ] = f"HTTPException: {error.status}|{error.response.reason}: " + "\n".join( - errors - ) + tb[-1] = f"HTTPException: {error.status}|{error.response.reason}: " + "\n".join(errors) error_message = "".join(traceback.format_exception(error)) if len(full_message + error_message) >= 1800: error_message = "\n ".join(error_message.split("\n")) @@ -119,9 +107,7 @@ class ErrorMixin: f"\n```yaml\n{full_message}\n```" f"\nException:\n```py\n{error_message}\n```" ) - await ctx.send( - "Whoops! Encountered an error. The error has been logged.", ephemeral=True - ) + await ctx.send("Whoops! Encountered an error. The error has been logged.", ephemeral=True) try: await ctx.defer(ephemeral=True) return await super().on_command_error(ctx, error, *args, **kwargs) diff --git a/jarvis/client/events/__init__.py b/jarvis/client/events/__init__.py index 4f60075..97b9da2 100644 --- a/jarvis/client/events/__init__.py +++ b/jarvis/client/events/__init__.py @@ -1,9 +1,10 @@ """JARVIS event mixin.""" + import asyncio from aiohttp import ClientSession from beanie.operators import Set -from interactions import listen, Intents +from interactions import listen from interactions.ext.prefixed_commands.context import PrefixedContext from interactions.models.discord.channel import DMChannel from interactions.models.discord.embed import EmbedField @@ -31,22 +32,16 @@ class EventMixin(MemberEventMixin, MessageEventMixin, ComponentEventMixin): async def _sync_domains(self) -> None: self.logger.debug("Loading phishing domains") - async with ClientSession( - headers={"X-Identity": "Discord: zevaryx#5779"} - ) as session: + async with ClientSession(headers={"X-Identity": "Discord: zevaryx#5779"}) as session: response = await session.get("https://phish.sinking.yachts/v2/all") response.raise_for_status() self.phishing_domains = await response.json() - self.logger.info( - f"Protected from {len(self.phishing_domains)} phishing domains" - ) + self.logger.info(f"Protected from {len(self.phishing_domains)} phishing domains") @listen() async def on_startup(self) -> None: """NAFF on_startup override. Prometheus info generated here.""" - await StaticStat.find_one( - StaticStat.name == "jarvis_version", StaticStat.client_id == self.user.id - ).upsert( + await StaticStat.find_one(StaticStat.name == "jarvis_version", StaticStat.client_id == self.user.id).upsert( Set( { StaticStat.client_name: self.client_name, @@ -64,16 +59,14 @@ class EventMixin(MemberEventMixin, MessageEventMixin, ComponentEventMixin): if not self.synced: await self._sync_domains() self._update_domains.start() - asyncio.create_task(self._chunk_all()) + chunk_task = asyncio.create_task(self._chunk_all()) self.synced = True except Exception as e: self.logger.error("Failed to load anti-phishing", exc_info=e) - self.logger.info("Logged in as {}".format(self.user)) # noqa: T001 - self.logger.info( - "Connected to {} guild(s)".format(len(self.guilds)) - ) # noqa: T001 + self.logger.info("Logged in as {}".format(self.user)) + self.logger.info("Connected to {} guild(s)".format(len(self.guilds))) self.logger.info("Current version: {}".format(const.__version__)) - self.logger.info( # noqa: T001 + self.logger.info( "https://discord.com/api/oauth2/authorize?client_id=" "{}&permissions=8&scope=bot%20applications.commands".format(self.user.id) ) @@ -91,9 +84,7 @@ class EventMixin(MemberEventMixin, MessageEventMixin, ComponentEventMixin): if not isinstance(self.interaction_tree[cid][_], ContextMenu) ) global_context_menus = sum( - 1 - for _ in self.interaction_tree[cid] - if isinstance(self.interaction_tree[cid][_], ContextMenu) + 1 for _ in self.interaction_tree[cid] if isinstance(self.interaction_tree[cid][_], ContextMenu) ) else: guild_base_commands += sum( @@ -102,22 +93,12 @@ class EventMixin(MemberEventMixin, MessageEventMixin, ComponentEventMixin): if not isinstance(self.interaction_tree[cid][_], ContextMenu) ) guild_context_menus += sum( - 1 - for _ in self.interaction_tree[cid] - if isinstance(self.interaction_tree[cid][_], ContextMenu) + 1 for _ in self.interaction_tree[cid] if isinstance(self.interaction_tree[cid][_], ContextMenu) ) - self.logger.info( - "Loaded {:>3} global base slash commands".format(global_base_commands) - ) - self.logger.info( - "Loaded {:>3} global context menus".format(global_context_menus) - ) - self.logger.info( - "Loaded {:>3} guild base slash commands".format(guild_base_commands) - ) - self.logger.info( - "Loaded {:>3} guild context menus".format(guild_context_menus) - ) + self.logger.info("Loaded {:>3} global base slash commands".format(global_base_commands)) + self.logger.info("Loaded {:>3} global context menus".format(global_context_menus)) + self.logger.info("Loaded {:>3} guild base slash commands".format(guild_base_commands)) + self.logger.info("Loaded {:>3} guild context menus".format(guild_context_menus)) except Exception: self.logger.error("interaction_tree not found, try updating NAFF") @@ -126,18 +107,15 @@ class EventMixin(MemberEventMixin, MessageEventMixin, ComponentEventMixin): _ = await Reminder.find().to_list(None) self.logger.debug("Updating ERAPI") await self.erapi.update_async() + await asyncio.wait([chunk_task]) # Modlog async def on_command(self, ctx: BaseContext) -> None: """NAFF on_command override.""" name = ctx.invoke_target if not isinstance(ctx.channel, DMChannel) and name not in ["pw"]: - modlog = await Setting.find_one( - Setting.guild == ctx.guild.id, Setting.setting == "activitylog" - ) - ignore = await Setting.find_one( - Setting.guild == ctx.guild.id, Setting.setting == "log_ignore" - ) + modlog = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "activitylog") + ignore = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "log_ignore") if modlog and (ignore and ctx.channel.id not in ignore.value): channel = await ctx.guild.fetch_channel(modlog.value) args = [] @@ -169,16 +147,10 @@ class EventMixin(MemberEventMixin, MessageEventMixin, ComponentEventMixin): fields=fields, color="#fc9e3f", ) - embed.set_author( - name=ctx.author.username, icon_url=ctx.author.display_avatar.url - ) - embed.set_footer( - text=f"{ctx.author.user.username}#{ctx.author.discriminator} | {ctx.author.id}" - ) + embed.set_author(name=ctx.author.username, icon_url=ctx.author.display_avatar.url) + embed.set_footer(text=f"{ctx.author.user.username}#{ctx.author.discriminator} | {ctx.author.id}") if channel: await channel.send(embeds=embed) else: - self.logger.warning( - f"Activitylog channel no longer exists in {ctx.guild.name}, removing" - ) + self.logger.warning(f"Activitylog channel no longer exists in {ctx.guild.name}, removing") await modlog.delete() diff --git a/jarvis/client/events/components.py b/jarvis/client/events/components.py index 3678c28..c4b9a45 100644 --- a/jarvis/client/events/components.py +++ b/jarvis/client/events/components.py @@ -1,4 +1,5 @@ """JARVIS component event mixin.""" + from beanie import PydanticObjectId from interactions import listen from interactions.api.events.internal import ButtonPressed @@ -84,11 +85,7 @@ class ComponentEventMixin: for component in row.components: component.disabled = True await context.message.edit(components=context.message.components) - msg = ( - "Cancelled" - if context.custom_id == "modcase|no" - else "Moderation case opened" - ) + msg = "Cancelled" if context.custom_id == "modcase|no" else "Moderation case opened" await context.send(msg) await self.redis.delete(user_key) await self.redis.delete(action_key) @@ -114,9 +111,7 @@ class ComponentEventMixin: await context.send("I'm afraid I can't let you do that", ephemeral=True) return True # User does not have perms to delete - if pin := await Pin.find_one( - Pin.pin == context.message.id, Pin.guild == context.guild.id - ): + if pin := await Pin.find_one(Pin.pin == context.message.id, Pin.guild == context.guild.id): await pin.delete() await context.message.delete() @@ -139,12 +134,8 @@ class ComponentEventMixin: if await Reminder.find_one( Reminder.parent == str(reminder.id), Reminder.user == context.author.id, - ) or await Reminder.find_one( - Reminder.id == reminder.id, Reminder.user == context.author.id - ): - await context.send( - "You've already copied this reminder!", ephemeral=True - ) + ) or await Reminder.find_one(Reminder.id == reminder.id, Reminder.user == context.author.id): + await context.send("You've already copied this reminder!", ephemeral=True) else: new_reminder = Reminder( user=context.author.id, @@ -160,9 +151,7 @@ class ComponentEventMixin: await context.send("Reminder copied!", ephemeral=True) else: - await context.send( - "That reminder doesn't exist anymore", ephemeral=True - ) + await context.send("That reminder doesn't exist anymore", ephemeral=True) return True diff --git a/jarvis/client/events/member.py b/jarvis/client/events/member.py index 372fb56..1454468 100644 --- a/jarvis/client/events/member.py +++ b/jarvis/client/events/member.py @@ -1,4 +1,5 @@ """JARVIS member event mixin.""" + import asyncio from interactions import listen @@ -20,19 +21,13 @@ class MemberEventMixin: """Handle on_member_add event.""" user = event.member guild = event.guild - unverified = await Setting.find_one( - Setting.guild == guild.id, Setting.setting == "unverified" - ) - temproles = await Temprole.find( - Temprole.guild == guild.id, Temprole.user == user.id - ).to_list() + unverified = await Setting.find_one(Setting.guild == guild.id, Setting.setting == "unverified") + temproles = await Temprole.find(Temprole.guild == guild.id, Temprole.user == user.id).to_list() if unverified: self.logger.debug(f"Applying unverified role to {user.id} in {guild.id}") role = await guild.fetch_role(unverified.value) if not role: - self.logger.warn( - f"Unverified role no longer exists for guild {guild.id}" - ) + self.logger.warn(f"Unverified role no longer exists for guild {guild.id}") await unverified.delete() elif role not in user.roles: await user.add_role(role, reason="User just joined and is unverified") @@ -43,18 +38,14 @@ class MemberEventMixin: if not role: await temprole.delete() elif role not in user.roles: - await user.add_role( - role, reason="User joined and has existing temprole" - ) + await user.add_role(role, reason="User joined and has existing temprole") @listen() async def on_member_remove(self, event: MemberRemove) -> None: """Handle on_member_remove event.""" user = event.member guild = event.guild - log = await Setting.find_one( - Setting.guild == guild.id, Setting.setting == "activitylog" - ) + log = await Setting.find_one(Setting.guild == guild.id, Setting.setting == "activitylog") if log: self.logger.debug(f"User {user.id} left {guild.id}") channel = await guild.fetch_channel(log.value) @@ -95,7 +86,7 @@ class MemberEventMixin: async def process_rolechange(self, before: Member, after: Member) -> Embed: """Process role changes.""" if before.roles == after.roles: - return + return None new_roles = [] removed_roles = [] @@ -126,7 +117,7 @@ class MemberEventMixin: async def process_rename(self, before: Member, after: Member) -> None: """Process name change.""" if before.nickname == after.nickname and before.username == after.username: - return + return None fields = ( EmbedField( @@ -151,29 +142,21 @@ class MemberEventMixin: before = event.before after = event.after - if ( - before.display_name == after.display_name and before.roles == after.roles - ) or (not after or not before): + if (before.display_name == after.display_name and before.roles == after.roles) or (not after or not before): return - log = await Setting.find_one( - Setting.guild == before.guild.id, Setting.setting == "activitylog" - ) + log = await Setting.find_one(Setting.guild == before.guild.id, Setting.setting == "activitylog") if log: channel = await before.guild.fetch_channel(log.value) await asyncio.sleep(0.5) # Wait for audit log embed = None if before._role_ids != after._role_ids: - verified = await Setting.find_one( - Setting.guild == before.guild.id, Setting.setting == "verified" - ) + verified = await Setting.find_one(Setting.guild == before.guild.id, Setting.setting == "verified") v_role = None if verified: v_role = await before.guild.fetch_role(verified.value) if not v_role: - self.logger.debug( - f"Guild {before.guild.id} verified role no longer exists" - ) + self.logger.debug(f"Guild {before.guild.id} verified role no longer exists") await verified.delete() else: if not before.has_role(v_role) and after.has_role(v_role): diff --git a/jarvis/client/events/message.py b/jarvis/client/events/message.py index 1232081..46d1a08 100644 --- a/jarvis/client/events/message.py +++ b/jarvis/client/events/message.py @@ -1,4 +1,5 @@ """JARVIS message event mixin""" + import re from datetime import datetime, timedelta, timezone @@ -40,9 +41,7 @@ class MessageEventMixin: ) if autopurge: if not message.author.has_permission(Permissions.ADMINISTRATOR): - self.logger.debug( - f"Autopurging message {message.guild.id}/{message.channel.id}/{message.id}" - ) + self.logger.debug(f"Autopurging message {message.guild.id}/{message.channel.id}/{message.id}") await message.delete(delay=autopurge.delay) async def autoreact(self, message: Message) -> None: @@ -52,9 +51,7 @@ class MessageEventMixin: Autoreact.channel == message.channel.id, ) if autoreact: - self.logger.debug( - f"Autoreacting to message {message.guild.id}/{message.channel.id}/{message.id}" - ) + self.logger.debug(f"Autoreacting to message {message.guild.id}/{message.channel.id}/{message.id}") for reaction in autoreact.reactions: await message.add_reaction(reaction) if autoreact.thread: @@ -75,13 +72,11 @@ class MessageEventMixin: # channel = find(lambda x: x.id == 599068193339736096, message._mention_ids) # if channel and message.author.id == 293795462752894976: # await channel.send( - # content="https://cdn.discordapp.com/attachments/664621130044407838/805218508866453554/tech.gif" # noqa: E501 + # content="https://cdn.discordapp.com/attachments/664621130044407838/805218508866453554/tech.gif" # ) content = re.sub(r"\s+", "", message.content) match = invites.search(content) - setting = await Setting.find_one( - Setting.guild == message.guild.id, Setting.setting == "noinvite" - ) + setting = await Setting.find_one(Setting.guild == message.guild.id, Setting.setting == "noinvite") if not setting: setting = Setting(guild=message.guild.id, setting="noinvite", value=True) await setting.save() @@ -89,20 +84,19 @@ class MessageEventMixin: guild_invites = [x.code for x in await message.guild.fetch_invites()] if message.guild.vanity_url_code: guild_invites.append(message.guild.vanity_url_code) - allowed = guild_invites + [ + allowed = [ + *guild_invites, "dbrand", "VtgZntXcnZ", "gPfYGbvTCE", "interactions", "NTSHu97tHg", ] - is_mod = message.author.has_permission( - Permissions.MANAGE_GUILD - ) or message.author.has_permission(Permissions.ADMINISTRATOR) + 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}" - ) + self.logger.debug(f"Removing non-allowed invite `{m}` from {message.guild.id}") try: await message.delete() except Exception: @@ -159,9 +153,7 @@ class MessageEventMixin: value=1, ) await Stat(meta=md, name="warning").insert() - embed = warning_embed( - message.author, "Sent a message with a filtered word", self.user - ) + embed = warning_embed(message.author, "Sent a message with a filtered word", self.user) try: await message.reply(embeds=embed) except Exception: @@ -180,21 +172,19 @@ class MessageEventMixin: Setting.setting == "massmention", ) - is_mod = message.author.has_permission( - Permissions.MANAGE_GUILD - ) or message.author.has_permission(Permissions.ADMINISTRATOR) + is_mod = message.author.has_permission(Permissions.MANAGE_GUILD) or message.author.has_permission( + Permissions.ADMINISTRATOR + ) if ( massmention - and int(massmention.value) > 0 # noqa: W503 - and len(message._mention_ids + message._mention_roles) # noqa: W503 - - (1 if message.author.id in message._mention_ids else 0) # noqa: W503 - > massmention.value # noqa: W503 - and not is_mod # noqa: W503 + and int(massmention.value) > 0 + and len(message._mention_ids + message._mention_roles) + - (1 if message.author.id in message._mention_ids else 0) + > massmention.value + and not is_mod ): - self.logger.debug( - f"Massmention threshold on {message.guild.id}/{message.channel.id}/{message.id}" - ) + self.logger.debug(f"Massmention threshold on {message.guild.id}/{message.channel.id}/{message.id}") expires_at = datetime.now(tz=timezone.utc) + timedelta(hours=24) await Warning( active=True, @@ -226,20 +216,11 @@ class MessageEventMixin: if message.author.has_permission(Permissions.MANAGE_GUILD): return except Exception as e: - self.logger.error( - "Failed to get permissions, pretending check failed", exc_info=e - ) + self.logger.error("Failed to get permissions, pretending check failed", exc_info=e) - if ( - await Roleping.find( - Roleping.guild == message.guild.id, Roleping.active == True - ).count() - == 0 - ): + if await Roleping.find(Roleping.guild == message.guild.id, Roleping.active == True).count() == 0: return - rolepings = await Roleping.find( - Roleping.guild == message.guild.id, Roleping.active == True - ).to_list() + rolepings = await Roleping.find(Roleping.guild == message.guild.id, Roleping.active == True).to_list() # Get all role IDs involved with message roles = [x.id async for x in message.mention_roles] @@ -263,9 +244,7 @@ class MessageEventMixin: # Check if user in a bypass list def check_has_role(roleping: Roleping) -> bool: - return any( - role.id in roleping.bypass.roles for role in message.author.roles - ) + return any(role.id in roleping.bypass.roles for role in message.author.roles) user_has_bypass = False for roleping in rolepings: @@ -276,15 +255,8 @@ class MessageEventMixin: user_has_bypass = True break - if ( - role_in_rolepings - and user_missing_role - and not user_is_admin - and not user_has_bypass - ): - self.logger.debug( - f"Rolepinged role in {message.guild.id}/{message.channel.id}/{message.id}" - ) + if role_in_rolepings and user_missing_role and not user_is_admin and not user_has_bypass: + self.logger.debug(f"Rolepinged role in {message.guild.id}/{message.channel.id}/{message.id}") expires_at = datetime.now(tz=timezone.utc) + timedelta(hours=24) await Warning( active=True, @@ -426,9 +398,7 @@ class MessageEventMixin: value=1, ) await Stat(meta=md, name="warning").insert() - reasons = ", ".join( - f"{m['source']}: {m['type']}" for m in data["matches"] - ) + reasons = ", ".join(f"{m['source']}: {m['type']}" for m in data["matches"]) embed = warning_embed(message.author, reasons, self.user) try: await message.channel.send(embeds=embed) @@ -474,9 +444,7 @@ class MessageEventMixin: """Timeout a user.""" expires_at = datetime.now(tz=timezone.utc) + timedelta(minutes=30) try: - await user.timeout( - communication_disabled_until=expires_at, reason="Phishing link" - ) + await user.timeout(communication_disabled_until=expires_at, reason="Phishing link") await Mute( user=user.id, reason="Auto mute for harmful link", @@ -525,20 +493,10 @@ class MessageEventMixin: before = event.before after = event.after if not after.author.bot: - modlog = await Setting.find_one( - Setting.guild == after.guild.id, Setting.setting == "activitylog" - ) - ignore = await Setting.find_one( - Setting.guild == after.guild.id, Setting.setting == "log_ignore" - ) - if modlog and ( - not ignore or (ignore and after.channel.id not in ignore.value) - ): - if ( - not before - or before.content == after.content - or before.content is None - ): + modlog = await Setting.find_one(Setting.guild == after.guild.id, Setting.setting == "activitylog") + ignore = await Setting.find_one(Setting.guild == after.guild.id, Setting.setting == "log_ignore") + if modlog and (not ignore or (ignore and after.channel.id not in ignore.value)): + if not before or before.content == after.content or before.content is None: return try: channel = before.guild.get_channel(modlog.value) @@ -567,9 +525,7 @@ class MessageEventMixin: icon_url=after.author.display_avatar.url, url=after.jump_url, ) - embed.set_footer( - text=f"{after.author.username} | {after.author.id}" - ) + embed.set_footer(text=f"{after.author.username} | {after.author.id}") await channel.send(embeds=embed) except Exception as e: self.logger.warning( @@ -590,15 +546,9 @@ class MessageEventMixin: async def on_message_delete(self, event: MessageDelete) -> None: """Process on_message_delete events.""" message = event.message - modlog = await Setting.find_one( - Setting.guild == message.guild.id, Setting.setting == "activitylog" - ) - ignore = await Setting.find_one( - Setting.guild == message.guild.id, Setting.setting == "log_ignore" - ) - if modlog and ( - not ignore or (ignore and message.channel.id not in ignore.value) - ): + modlog = await Setting.find_one(Setting.guild == message.guild.id, Setting.setting == "activitylog") + ignore = await Setting.find_one(Setting.guild == message.guild.id, Setting.setting == "log_ignore") + if modlog and (not ignore or (ignore and message.channel.id not in ignore.value)): try: content = message.content or message.system_content or "N/A" except AttributeError: @@ -607,9 +557,7 @@ class MessageEventMixin: try: if message.attachments: - value = "\n".join( - [f"[{x.filename}]({x.url})" for x in message.attachments] - ) + value = "\n".join([f"[{x.filename}]({x.url})" for x in message.attachments]) fields.append( EmbedField( name="Attachments", @@ -619,9 +567,7 @@ class MessageEventMixin: ) if message.sticker_items: - value = "\n".join( - [f"Sticker: {x.name}" for x in message.sticker_items] - ) + value = "\n".join([f"Sticker: {x.name}" for x in message.sticker_items]) fields.append( EmbedField( name="Stickers", @@ -653,11 +599,7 @@ class MessageEventMixin: icon_url=message.author.display_avatar.url, url=message.jump_url, ) - embed.set_footer( - text=(f"{message.author.username} | " f"{message.author.id}") - ) + embed.set_footer(text=(f"{message.author.username} | " f"{message.author.id}")) await channel.send(embeds=embed) except Exception as e: - self.logger.warning( - f"Failed to process edit {message.guild.id}/{message.channel.id}/{message.id}: {e}" - ) + self.logger.warning(f"Failed to process edit {message.guild.id}/{message.channel.id}/{message.id}: {e}") diff --git a/jarvis/client/tasks.py b/jarvis/client/tasks.py index 5fb63d2..ad7d0c5 100644 --- a/jarvis/client/tasks.py +++ b/jarvis/client/tasks.py @@ -4,7 +4,6 @@ from datetime import datetime import pytz from aiohttp import ClientSession -from beanie.operators import Set from croniter import croniter from interactions.models.internal.tasks.task import Task from interactions.models.internal.tasks.triggers import BaseTrigger, IntervalTrigger @@ -19,6 +18,7 @@ class CronTrigger(BaseTrigger): Attributes: schedule str: The cron schedule, use https://crontab.guru for help + """ def __init__(self, schedule: str) -> None: @@ -31,9 +31,7 @@ class CronTrigger(BaseTrigger): class TaskMixin: @Task.create(IntervalTrigger(minutes=1)) async def _update_domains(self) -> None: - async with ClientSession( - headers={"X-Identity": "Discord: zevaryx#5779"} - ) as session: + async with ClientSession(headers={"X-Identity": "Discord: zevaryx#5779"}) as session: response = await session.get("https://phish.sinking.yachts/v2/recent/60") response.raise_for_status() data = await response.json() @@ -63,7 +61,7 @@ class TaskMixin: await self.erapi.update_async() @Task.create(CronTrigger("0 0 1 * *")) - async def _cleanup(self) -> None: + async def _cleanup(self) -> None: # noqa: C901 self.logger.debug("Getting all unique guild, channel, and user IDs") guild_ids = [] channel_ids = [] diff --git a/jarvis/cogs/core/admin/__init__.py b/jarvis/cogs/core/admin/__init__.py index b945b28..c7e8093 100644 --- a/jarvis/cogs/core/admin/__init__.py +++ b/jarvis/cogs/core/admin/__init__.py @@ -1,4 +1,5 @@ """JARVIS Admin Cogs.""" + import logging from interactions import Client diff --git a/jarvis/cogs/core/admin/autoreact.py b/jarvis/cogs/core/admin/autoreact.py index 2fe4e59..f7fc492 100644 --- a/jarvis/cogs/core/admin/autoreact.py +++ b/jarvis/cogs/core/admin/autoreact.py @@ -1,4 +1,5 @@ """JARVIS Autoreact Cog.""" + import logging import re from typing import Optional, Tuple @@ -39,10 +40,9 @@ class AutoReactCog(Extension): Returns: Tuple of success? and error message + """ - exists = await Autoreact.find_one( - Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id - ) + exists = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id) if exists: return False, f"Autoreact already exists for {channel.mention}." @@ -56,9 +56,7 @@ class AutoReactCog(Extension): return True, None - async def delete_autoreact( - self, ctx: InteractionContext, channel: GuildText - ) -> bool: + async def delete_autoreact(self, ctx: InteractionContext, channel: GuildText) -> bool: """ Remove an autoreact monitor on a channel. @@ -68,10 +66,9 @@ class AutoReactCog(Extension): Returns: Success? + """ - ar = await Autoreact.find_one( - Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id - ) + ar = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id) if ar: await ar.delete() return True @@ -107,7 +104,7 @@ class AutoReactCog(Extension): ctx: InteractionContext, channel: GuildText, thread: bool = True, - emote: str = None, + emote: str = None, # noqa: RUF013 ) -> None: await ctx.defer() if emote: @@ -125,18 +122,12 @@ class AutoReactCog(Extension): lambda x: x.id == emoji_id, await ctx.guild.fetch_all_custom_emojis(), ): - await ctx.send( - "Please use a custom emote from this server.", ephemeral=True - ) + await ctx.send("Please use a custom emote from this server.", ephemeral=True) return - autoreact = await Autoreact.find_one( - Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id - ) + autoreact = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id) if not autoreact: await self.create_autoreact(ctx, channel, thread) - autoreact = await Autoreact.find_one( - Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id - ) + autoreact = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id) if emote and emote in autoreact.reactions: await ctx.send( f"Emote already added to {channel.mention} autoreactions.", @@ -176,12 +167,8 @@ class AutoReactCog(Extension): required=True, ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) - async def _autoreact_remove( - self, ctx: InteractionContext, channel: GuildText, emote: str - ) -> None: - autoreact = await Autoreact.find_one( - Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id - ) + async def _autoreact_remove(self, ctx: InteractionContext, channel: GuildText, emote: str) -> None: + autoreact = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id) if not autoreact: await ctx.send( f"Please create autoreact first with /autoreact add {channel.mention} {emote}", @@ -215,9 +202,7 @@ class AutoReactCog(Extension): required=True, ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) - async def _autoreact_delete( - self, ctx: InteractionContext, channel: GuildText - ) -> None: + async def _autoreact_delete(self, ctx: InteractionContext, channel: GuildText) -> None: result = await self.delete_autoreact(ctx, channel) if not result: await ctx.send(f"No autoreact found in {channel.mention}", ephemeral=True) @@ -234,12 +219,8 @@ class AutoReactCog(Extension): opt_type=OptionType.CHANNEL, required=True, ) - async def _autoreact_list( - self, ctx: InteractionContext, channel: GuildText - ) -> None: - exists = await Autoreact.find_one( - Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id - ) + async def _autoreact_list(self, ctx: InteractionContext, channel: GuildText) -> None: + exists = await Autoreact.find_one(Autoreact.guild == ctx.guild.id, Autoreact.channel == channel.id) if not exists: await ctx.send( f"Please create autoreact first with /autoreact add {channel.mention} ", @@ -248,9 +229,7 @@ class AutoReactCog(Extension): return message = "" if len(exists.reactions) > 0: - message = f"Current active autoreacts on {channel.mention}:\n" + "\n".join( - exists.reactions - ) + message = f"Current active autoreacts on {channel.mention}:\n" + "\n".join(exists.reactions) else: message = f"No reactions set on {channel.mention}" await ctx.send(message) diff --git a/jarvis/cogs/core/admin/ban.py b/jarvis/cogs/core/admin/ban.py index d17b8af..92e8412 100644 --- a/jarvis/cogs/core/admin/ban.py +++ b/jarvis/cogs/core/admin/ban.py @@ -1,4 +1,5 @@ """JARVIS BanCog.""" + import re from datetime import timedelta @@ -68,9 +69,7 @@ class BanCog(ModcaseCog): await ctx.send(embeds=embed) - async def discord_apply_unban( - self, ctx: InteractionContext, user: User, reason: str - ) -> None: + async def discord_apply_unban(self, ctx: InteractionContext, user: User, reason: str) -> None: """Apply a Discord unban.""" await ctx.guild.unban(user, reason=reason) discrim = user.discriminator @@ -91,9 +90,7 @@ class BanCog(ModcaseCog): await ctx.send(embeds=embed) @slash_command(name="ban", description="Ban a user") - @slash_option( - name="user", description="User to ban", opt_type=OptionType.USER, required=True - ) + @slash_option(name="user", description="User to ban", opt_type=OptionType.USER, required=True) @slash_option( name="reason", description="Ban reason", @@ -124,14 +121,14 @@ class BanCog(ModcaseCog): required=False, ) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) - async def _ban( + async def _ban( # noqa: C901 self, ctx: InteractionContext, user: User, reason: str, btype: str = "perm", duration: int = 4, - delete_history: str = None, + delete_history: str = None, # noqa: RUF013 ) -> None: if user.id == ctx.author.id: await ctx.send("You cannot ban yourself.", ephemeral=True) @@ -185,9 +182,7 @@ class BanCog(ModcaseCog): mtype = "perma" guild_name = ctx.guild.name - user_message = ( - f"You have been {mtype}banned from {guild_name}." + f" Reason:\n{reason}" - ) + user_message = f"You have been {mtype}banned from {guild_name}." + f" Reason:\n{reason}" if mtype == "temp": user_message += f"\nDuration: {duration} hours" @@ -216,9 +211,7 @@ class BanCog(ModcaseCog): except Exception: self.logger.warn(f"Failed to send ban embed to {user.id}") try: - await self.discord_apply_ban( - ctx, reason, user, duration, active, mtype, delete_history or 0 - ) + 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 @@ -240,7 +233,7 @@ class BanCog(ModcaseCog): required=True, ) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) - async def _unban( + async def _unban( # noqa: C901 self, ctx: InteractionContext, user: str, @@ -267,8 +260,7 @@ class BanCog(ModcaseCog): user, discrim = user.split("#") if discrim: discord_ban_info = find( - lambda x: x.user.username == user - and x.user.discriminator == discrim, + lambda x: x.user.username == user and x.user.discriminator == discrim, bans, ) else: @@ -277,16 +269,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 discord_ban_info = results[0] @@ -331,9 +316,7 @@ class BanCog(ModcaseCog): admin=ctx.author.id, reason=reason, ).save() - await ctx.send( - "Unable to find user in Discord, but removed entry from database." - ) + await ctx.send("Unable to find user in Discord, but removed entry from database.") bans = SlashCommand(name="bans", description="User bans") @@ -357,9 +340,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: @@ -421,9 +402,7 @@ class BanCog(ModcaseCog): pages.append(embed) else: for i in range(0, len(bans), 5): - embed = build_embed( - title=title, description="", fields=fields[i : i + 5] - ) + embed = build_embed(title=title, description="", fields=fields[i : i + 5]) embed.set_thumbnail(url=ctx.guild.icon.url) pages.append(embed) diff --git a/jarvis/cogs/core/admin/filters.py b/jarvis/cogs/core/admin/filters.py index 1c239fb..ddde460 100644 --- a/jarvis/cogs/core/admin/filters.py +++ b/jarvis/cogs/core/admin/filters.py @@ -1,4 +1,5 @@ """Filters cog.""" + import asyncio import difflib import re @@ -31,16 +32,12 @@ class FilterCog(Extension): self.bot = bot self.cache: Dict[int, List[str]] = {} - async def _edit_filter( - self, ctx: InteractionContext, name: str, search: bool = False - ) -> None: + async def _edit_filter(self, ctx: InteractionContext, name: str, search: bool = False) -> None: try: content = "" f: Filter = None if search: - if f := await Filter.find_one( - Filter.name == name, Filter.guild == ctx.guild.id - ): + if f := await Filter.find_one(Filter.name == name, Filter.guild == ctx.guild.id): content = "\n".join(f.filters) kw = "Updating" if search else "Creating" @@ -60,9 +57,7 @@ class FilterCog(Extension): ) await ctx.send_modal(modal) try: - data = await self.bot.wait_for_modal( - modal, author=ctx.author.id, timeout=60 * 5 - ) + data = await self.bot.wait_for_modal(modal, author=ctx.author.id, timeout=60 * 5) filters = data.responses.get("filters").split("\n") except asyncio.TimeoutError: return @@ -82,9 +77,7 @@ class FilterCog(Extension): content = content.splitlines() diff = "\n".join(difflib.ndiff(content, filters)).replace("`", "\u200b`") - await data.send( - f"Filter `{new_name}` has been updated:\n\n```diff\n{diff}\n```" - ) + await data.send(f"Filter `{new_name}` has been updated:\n\n```diff\n{diff}\n```") if ctx.guild.id not in self.cache: self.cache[ctx.guild.id] = [] @@ -97,9 +90,7 @@ class FilterCog(Extension): filter_ = SlashCommand(name="filter", description="Manage keyword filters") - @filter_.subcommand( - sub_cmd_name="create", sub_cmd_description="Create a new filter" - ) + @filter_.subcommand(sub_cmd_name="create", sub_cmd_description="Create a new filter") @slash_option( name="name", description="Name of new filter", @@ -170,9 +161,7 @@ class FilterCog(Extension): if not self.cache.get(ctx.guild.id): filters = await Filter.find(Filter.guild == ctx.guild.id).to_list() self.cache[ctx.guild.id] = [f.name for f in filters] - results = process.extract( - ctx.input_text, self.cache.get(ctx.guild.id), limit=25 - ) + results = process.extract(ctx.input_text, self.cache.get(ctx.guild.id), limit=25) choices = [{"name": r[0], "value": r[0]} for r in results] await ctx.send(choices=choices) diff --git a/jarvis/cogs/core/admin/kick.py b/jarvis/cogs/core/admin/kick.py index 93185a8..4950c2c 100644 --- a/jarvis/cogs/core/admin/kick.py +++ b/jarvis/cogs/core/admin/kick.py @@ -1,4 +1,5 @@ """JARVIS KickCog.""" + from interactions import InteractionContext, Permissions from interactions.models.discord.user import User from interactions.models.internal.application_commands import ( diff --git a/jarvis/cogs/core/admin/lock.py b/jarvis/cogs/core/admin/lock.py index a6f4ebb..2f71ea1 100644 --- a/jarvis/cogs/core/admin/lock.py +++ b/jarvis/cogs/core/admin/lock.py @@ -1,4 +1,5 @@ """JARVIS LockCog.""" + import logging from typing import Union @@ -56,7 +57,7 @@ class LockCog(Extension): await ctx.send("Duration must be > 0", ephemeral=True) return - elif duration > 60 * 24 * 7: + if duration > 60 * 24 * 7: await ctx.send("Duration must be <= 7 days", ephemeral=True) return diff --git a/jarvis/cogs/core/admin/lockdown.py b/jarvis/cogs/core/admin/lockdown.py index c001d75..5d230a5 100644 --- a/jarvis/cogs/core/admin/lockdown.py +++ b/jarvis/cogs/core/admin/lockdown.py @@ -1,4 +1,5 @@ """JARVIS LockdownCog.""" + import logging from interactions import Client, Extension, InteractionContext @@ -26,6 +27,7 @@ async def lock(bot: Client, target: GuildChannel, admin: Member, reason: str, du bot: Bot instance target: Target channel admin: Admin who initiated lockdown + """ to_deny = Permissions.SEND_MESSAGES | Permissions.CONNECT | Permissions.SPEAK current = get(target.permission_overwrites, id=target.guild.id) @@ -51,6 +53,7 @@ async def lock_all(bot: Client, guild: Guild, admin: Member, reason: str, durati bot: Bot instance guild: Target guild admin: Admin who initiated lockdown + """ role = await guild.fetch_role(guild.id) categories = find_all(lambda x: isinstance(x, GuildCategory), guild.channels) @@ -71,6 +74,7 @@ async def unlock_all(bot: Client, guild: Guild, admin: Member) -> None: bot: Bot instance target: Target channel admin: Admin who ended lockdown + """ locks = Lock.find(Lock.guild == guild.id, Lock.active == True) async for lock in locks: @@ -125,7 +129,7 @@ class LockdownCog(Extension): if duration <= 0: await ctx.send("Duration must be > 0", ephemeral=True) return - elif duration > 60 * 24 * 7: + if duration > 60 * 24 * 7: await ctx.send("Duration must be <= 7 days", ephemeral=True) return diff --git a/jarvis/cogs/core/admin/modcase.py b/jarvis/cogs/core/admin/modcase.py index 6bbde0e..a9cfde5 100644 --- a/jarvis/cogs/core/admin/modcase.py +++ b/jarvis/cogs/core/admin/modcase.py @@ -1,4 +1,5 @@ """JARVIS Moderation Case management.""" + from typing import TYPE_CHECKING, List, Optional from interactions import Extension, InteractionContext, Permissions @@ -40,20 +41,15 @@ class CaseCog(Extension): Args: mod_case: Moderation case guild: Originating guild + """ action_table = Table() - action_table.add_column( - header="Type", justify="left", style="orange4", no_wrap=True - ) - action_table.add_column( - header="Admin", justify="left", style="cyan", no_wrap=True - ) + action_table.add_column(header="Type", justify="left", style="orange4", no_wrap=True) + action_table.add_column(header="Admin", justify="left", style="cyan", no_wrap=True) action_table.add_column(header="Reason", justify="left", style="white") note_table = Table() - note_table.add_column( - header="Admin", justify="left", style="cyan", no_wrap=True - ) + note_table.add_column(header="Admin", justify="left", style="cyan", no_wrap=True) note_table.add_column(header="Content", justify="left", style="white") console = Console() @@ -71,17 +67,13 @@ class CaseCog(Extension): admin_text = "[N/A]" if admin: admin_text = f"{admin.username}" - action_table.add_row( - action.action_type.title(), admin_text, parent_action.reason - ) + action_table.add_row(action.action_type.title(), admin_text, parent_action.reason) with console.capture() as cap: console.print(action_table) tmp_output = cap.get() if len(tmp_output) >= 800: - action_output_extra = ( - f"... and {len(mod_case.actions[idx:])} more actions" - ) + action_output_extra = f"... and {len(mod_case.actions[idx:])} more actions" break action_output = tmp_output @@ -128,9 +120,7 @@ class CaseCog(Extension): name="Actions", value=action_output if mod_case.actions else "No Actions Found", ), - EmbedField( - name="Notes", value=note_output if mod_case.notes else "No Notes Found" - ), + EmbedField(name="Notes", value=note_output if mod_case.notes else "No Notes Found"), ) embed = build_embed( @@ -156,6 +146,7 @@ class CaseCog(Extension): Args: mod_case: Moderation case guild: Originating guild + """ embeds = [] user = await self.bot.fetch_user(mod_case.user) @@ -181,9 +172,7 @@ class CaseCog(Extension): if admin: admin_text = admin.mention - fields = ( - EmbedField(name=action.action_type.title(), value=parent_action.reason), - ) + fields = (EmbedField(name=action.action_type.title(), value=parent_action.reason),) embed = build_embed( title="Moderation Case Action", description=f"{admin_text} initiated an action against {user_mention}", @@ -236,12 +225,8 @@ class CaseCog(Extension): case = SlashCommand(name="case", description="Manage a moderation case") show = case.group(name="show", description="Show information about a specific case") - @show.subcommand( - sub_cmd_name="summary", sub_cmd_description="Summarize a specific case" - ) - @slash_option( - name="cid", description="Case ID", opt_type=OptionType.STRING, required=True - ) + @show.subcommand(sub_cmd_name="summary", sub_cmd_description="Summarize a specific case") + @slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) async def _case_show_summary(self, ctx: InteractionContext, cid: str) -> None: case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid) @@ -253,9 +238,7 @@ class CaseCog(Extension): await ctx.send(embeds=embed) @show.subcommand(sub_cmd_name="actions", sub_cmd_description="Get case actions") - @slash_option( - name="cid", description="Case ID", opt_type=OptionType.STRING, required=True - ) + @slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) async def _case_show_actions(self, ctx: InteractionContext, cid: str) -> None: case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid) @@ -268,9 +251,7 @@ class CaseCog(Extension): await paginator.send(ctx) @case.subcommand(sub_cmd_name="close", sub_cmd_description="Show a specific case") - @slash_option( - name="cid", description="Case ID", opt_type=OptionType.STRING, required=True - ) + @slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) async def _case_close(self, ctx: InteractionContext, cid: str) -> None: case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid) @@ -284,12 +265,8 @@ class CaseCog(Extension): embed = await self.get_summary_embed(case, ctx.guild) await ctx.send(embeds=embed) - @case.subcommand( - sub_cmd_name="repoen", sub_cmd_description="Reopen a specific case" - ) - @slash_option( - name="cid", description="Case ID", opt_type=OptionType.STRING, required=True - ) + @case.subcommand(sub_cmd_name="repoen", sub_cmd_description="Reopen a specific case") + @slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) async def _case_reopen(self, ctx: InteractionContext, cid: str) -> None: case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.nanoid == cid) @@ -303,12 +280,8 @@ class CaseCog(Extension): embed = await self.get_summary_embed(case, ctx.guild) await ctx.send(embeds=embed) - @case.subcommand( - sub_cmd_name="note", sub_cmd_description="Add a note to a specific case" - ) - @slash_option( - name="cid", description="Case ID", opt_type=OptionType.STRING, required=True - ) + @case.subcommand(sub_cmd_name="note", sub_cmd_description="Add a note to a specific case") + @slash_option(name="cid", description="Case ID", opt_type=OptionType.STRING, required=True) @slash_option( name="note", description="Note to add", @@ -323,9 +296,7 @@ class CaseCog(Extension): return if not case.open: - await ctx.send( - "Case is closed, please re-open to add a new comment", ephemeral=True - ) + await ctx.send("Case is closed, please re-open to add a new comment", ephemeral=True) return if len(note) > 50: @@ -341,9 +312,7 @@ class CaseCog(Extension): await ctx.send(embeds=embed) @case.subcommand(sub_cmd_name="new", sub_cmd_description="Open a new case") - @slash_option( - name="user", description="Target user", opt_type=OptionType.USER, required=True - ) + @slash_option(name="user", description="Target user", opt_type=OptionType.USER, required=True) @slash_option( name="note", description="Note to add", @@ -352,9 +321,7 @@ class CaseCog(Extension): ) @check(admin_or_permissions(Permissions.BAN_MEMBERS)) async def _case_new(self, ctx: InteractionContext, user: Member, note: str) -> None: - case = await Modlog.find_one( - Modlog.guild == ctx.guild.id, Modlog.user == user.id, Modlog.open == True - ) + case = await Modlog.find_one(Modlog.guild == ctx.guild.id, Modlog.user == user.id, Modlog.open == True) if case: await ctx.send(f"Case already open with ID `{case.nanoid}`", ephemeral=True) return diff --git a/jarvis/cogs/core/admin/mute.py b/jarvis/cogs/core/admin/mute.py index 413dcac..09b58f7 100644 --- a/jarvis/cogs/core/admin/mute.py +++ b/jarvis/cogs/core/admin/mute.py @@ -1,4 +1,5 @@ """JARVIS MuteCog.""" + import asyncio from datetime import datetime, timedelta, timezone @@ -27,9 +28,7 @@ from jarvis.utils.permissions import admin_or_permissions class MuteCog(ModcaseCog): """JARVIS MuteCog.""" - async def _apply_timeout( - self, ctx: InteractionContext, user: Member, reason: str, until: datetime - ) -> None: + async def _apply_timeout(self, ctx: InteractionContext, user: Member, reason: str, until: datetime) -> None: await user.timeout(communication_disabled_until=until, reason=reason) duration = int((until - datetime.now(tz=timezone.utc)).seconds / 60) await Mute( @@ -44,11 +43,7 @@ class MuteCog(ModcaseCog): return mute_embed(user=user, admin=ctx.author, reason=reason, guild=ctx.guild) @context_menu(name="Mute User", context_type=CommandType.USER) - @check( - admin_or_permissions( - Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS - ) - ) + @check(admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS)) async def _timeout_cm(self, ctx: InteractionContext) -> None: modal = Modal( *[ @@ -71,9 +66,7 @@ class MuteCog(ModcaseCog): ) await ctx.send_modal(modal) try: - response = await self.bot.wait_for_modal( - modal, author=ctx.author.id, timeout=60 * 5 - ) + response = await self.bot.wait_for_modal(modal, author=ctx.author.id, timeout=60 * 5) reason = response.responses.get("reason") until = response.responses.get("until") except asyncio.TimeoutError: @@ -84,9 +77,7 @@ class MuteCog(ModcaseCog): "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_until = parse(until, settings=rt_settings) @@ -101,14 +92,10 @@ class MuteCog(ModcaseCog): until = at_until else: self.logger.debug(f"Failed to parse delay: {until}") - await response.send( - f"`{until}` is not a parsable date, please try again", ephemeral=True - ) + await response.send(f"`{until}` is not a parsable date, please try again", ephemeral=True) return if until < datetime.now(tz=timezone.utc): - await response.send( - f"`{old_until}` is in the past, which isn't allowed", ephemeral=True - ) + await response.send(f"`{old_until}` is in the past, which isn't allowed", ephemeral=True) return try: embed = await self._apply_timeout(ctx, ctx.target, reason, until) @@ -117,9 +104,7 @@ class MuteCog(ModcaseCog): await response.send("Unable to mute this user", ephemeral=True) @slash_command(name="mute", description="Mute a user") - @slash_option( - name="user", description="User to mute", opt_type=OptionType.USER, required=True - ) + @slash_option(name="user", description="User to mute", opt_type=OptionType.USER, required=True) @slash_option( name="reason", description="Reason for mute", @@ -144,11 +129,7 @@ class MuteCog(ModcaseCog): SlashCommandChoice(name="Week(s)", value=10080), ], ) - @check( - admin_or_permissions( - Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS - ) - ) + @check(admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS)) async def _timeout( self, ctx: InteractionContext, @@ -173,9 +154,7 @@ class MuteCog(ModcaseCog): # Max 4 weeks (2419200 seconds) per API duration = time * scale if duration > 40320: - await ctx.send( - "Mute must be less than 4 weeks (40,320 minutes)", ephemeral=True - ) + await ctx.send("Mute must be less than 4 weeks (40,320 minutes)", ephemeral=True) return until = datetime.now(tz=timezone.utc) + timedelta(minutes=duration) @@ -198,16 +177,11 @@ class MuteCog(ModcaseCog): opt_type=OptionType.STRING, required=True, ) - @check( - admin_or_permissions( - Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS - ) - ) + @check(admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS)) async def _unmute(self, ctx: InteractionContext, user: Member, reason: str) -> None: if ( not user.communication_disabled_until - or user.communication_disabled_until.timestamp() - < datetime.now(tz=timezone.utc).timestamp() # noqa: W503 + or user.communication_disabled_until.timestamp() < datetime.now(tz=timezone.utc).timestamp() ): await ctx.send("User is not muted", ephemeral=True) return @@ -218,8 +192,6 @@ class MuteCog(ModcaseCog): await user.timeout(communication_disabled_until=datetime.now(tz=timezone.utc)) - embed = unmute_embed( - user=user, admin=ctx.author, reason=reason, guild=ctx.guild - ) + embed = unmute_embed(user=user, admin=ctx.author, reason=reason, guild=ctx.guild) await ctx.send(embeds=embed) diff --git a/jarvis/cogs/core/admin/purge.py b/jarvis/cogs/core/admin/purge.py index 2c2930d..a7c0154 100644 --- a/jarvis/cogs/core/admin/purge.py +++ b/jarvis/cogs/core/admin/purge.py @@ -1,4 +1,5 @@ """JARVIS PurgeCog.""" + import logging from interactions import Client, Extension, InteractionContext, Permissions @@ -67,7 +68,7 @@ class PurgeCog(Extension): if delay <= 0: await ctx.send("Delay must be > 0", ephemeral=True) return - elif delay > 300: + if delay > 300: await ctx.send("Delay must be < 5 minutes", ephemeral=True) return diff --git a/jarvis/cogs/core/admin/roleping.py b/jarvis/cogs/core/admin/roleping.py index f407e7a..72e5e6d 100644 --- a/jarvis/cogs/core/admin/roleping.py +++ b/jarvis/cogs/core/admin/roleping.py @@ -1,4 +1,5 @@ """JARVIS RolepingCog.""" + import logging from interactions import Client, Extension, InteractionContext, Permissions diff --git a/jarvis/cogs/core/admin/settings.py b/jarvis/cogs/core/admin/settings.py index bea5e78..70cbaaf 100644 --- a/jarvis/cogs/core/admin/settings.py +++ b/jarvis/cogs/core/admin/settings.py @@ -1,4 +1,5 @@ """JARVIS Settings Management Cog.""" + import asyncio import logging from typing import Any diff --git a/jarvis/cogs/core/admin/temprole.py b/jarvis/cogs/core/admin/temprole.py index 60b27af..60459bc 100644 --- a/jarvis/cogs/core/admin/temprole.py +++ b/jarvis/cogs/core/admin/temprole.py @@ -1,4 +1,5 @@ """JARVIS temporary role handler.""" + import logging from datetime import datetime, timezone @@ -46,7 +47,7 @@ class TemproleCog(Extension): ) @check(admin_or_permissions(Permissions.MANAGE_ROLES)) async def _temprole( - self, ctx: InteractionContext, user: Member, role: Role, duration: str, reason: str = None + self, ctx: InteractionContext, user: Member, role: Role, duration: str, reason: str = None # noqa: RUF013 ) -> None: await ctx.defer() if not isinstance(user, Member): diff --git a/jarvis/cogs/core/admin/verify.py b/jarvis/cogs/core/admin/verify.py index 7c6afcc..822ff91 100644 --- a/jarvis/cogs/core/admin/verify.py +++ b/jarvis/cogs/core/admin/verify.py @@ -1,4 +1,5 @@ """JARVIS Verify Cog.""" + import asyncio import logging from random import randint @@ -14,7 +15,7 @@ from jarvis_core.db.models import Setting def create_layout() -> list: """Create verify component layout.""" buttons = [] - yes = randint(0, 2) # noqa: S311 + yes = randint(0, 2) for i in range(3): label = "YES" if i == yes else "NO" id = f"no_{i}" if not i == yes else "yes" diff --git a/jarvis/cogs/core/admin/warning.py b/jarvis/cogs/core/admin/warning.py index 16d613e..6c9e451 100644 --- a/jarvis/cogs/core/admin/warning.py +++ b/jarvis/cogs/core/admin/warning.py @@ -1,4 +1,5 @@ """JARVIS WarningCog.""" + from datetime import datetime, timedelta, timezone from interactions import InteractionContext, Permissions @@ -24,9 +25,7 @@ class WarningCog(ModcaseCog): """JARVIS WarningCog.""" @slash_command(name="warn", description="Warn a user") - @slash_option( - name="user", description="User to warn", opt_type=OptionType.USER, required=True - ) + @slash_option(name="user", description="User to warn", opt_type=OptionType.USER, required=True) @slash_option( name="reason", description="Reason for warning", @@ -40,16 +39,14 @@ class WarningCog(ModcaseCog): required=False, ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) - async def _warn( - self, ctx: InteractionContext, user: Member, reason: str, duration: int = 24 - ) -> None: + async def _warn(self, ctx: InteractionContext, user: Member, reason: str, duration: int = 24) -> None: if len(reason) > 100: await ctx.send("Reason must be < 100 characters", ephemeral=True) return if duration <= 0: await ctx.send("Duration must be > 0", ephemeral=True) return - elif duration >= 120: + if duration >= 120: await ctx.send("Duration must be < 5 days", ephemeral=True) return if not await ctx.guild.fetch_member(user.id): @@ -70,9 +67,7 @@ class WarningCog(ModcaseCog): await ctx.send(embeds=embed) @slash_command(name="warnings", description="Get count of user warnings") - @slash_option( - name="user", description="User to view", opt_type=OptionType.USER, required=True - ) + @slash_option(name="user", description="User to view", opt_type=OptionType.USER, required=True) @slash_option( name="active", description="View active only", @@ -80,9 +75,7 @@ class WarningCog(ModcaseCog): required=False, ) # @check(admin_or_permissions(Permissions.MANAGE_GUILD)) - async def _warnings( - self, ctx: InteractionContext, user: Member, active: bool = True - ) -> None: + async def _warnings(self, ctx: InteractionContext, user: Member, active: bool = True) -> None: warnings = ( await Warning.find( Warning.user == user.id, @@ -126,9 +119,7 @@ class WarningCog(ModcaseCog): for i in range(0, len(fields), 5): embed = build_embed( title="Warnings", - description=( - f"{len(warnings)} total | {len(active_warns)} currently active" - ), + description=(f"{len(warnings)} total | {len(active_warns)} currently active"), fields=fields[i : i + 5], ) embed.set_author( @@ -136,9 +127,7 @@ class WarningCog(ModcaseCog): icon_url=user.display_avatar.url, ) embed.set_thumbnail(url=ctx.guild.icon.url) - embed.set_footer( - text=f"{user.username}#{user.discriminator} | {user.id}" - ) + embed.set_footer(text=f"{user.username}#{user.discriminator} | {user.id}") pages.append(embed) else: fields = [] @@ -156,9 +145,7 @@ class WarningCog(ModcaseCog): for i in range(0, len(fields), 5): embed = build_embed( title="Warnings", - description=( - f"{len(warnings)} total | {len(active_warns)} currently active" - ), + description=(f"{len(warnings)} total | {len(active_warns)} currently active"), fields=fields[i : i + 5], ) embed.set_author( diff --git a/jarvis/cogs/core/botutil.py b/jarvis/cogs/core/botutil.py index 9efd90c..e48d719 100644 --- a/jarvis/cogs/core/botutil.py +++ b/jarvis/cogs/core/botutil.py @@ -1,6 +1,5 @@ """JARVIS bot utility commands.""" -import asyncio import logging import platform from io import BytesIO @@ -49,9 +48,7 @@ class BotutilCog(Extension): file_bytes.write(log.encode("UTF8")) file_bytes.seek(0) log = File(file_bytes, file_name=f"tail_{count}.log") - await ctx.reply( - content=f"Here's the last {count} lines of the log", file=log - ) + await ctx.reply(content=f"Here's the last {count} lines of the log", file=log) else: await ctx.reply(content=f"```\n{log}\n```") @@ -80,17 +77,13 @@ class BotutilCog(Extension): inline=False, ), EmbedField(name="Version", value=platform.release() or "N/A", inline=False), - EmbedField( - name="System Start Time", value=f" ()" - ), + EmbedField(name="System Start Time", value=f" ()"), EmbedField(name="Python Version", value=platform.python_version()), EmbedField(name="Bot Start Time", value=f" ()"), ) embed = build_embed(title="System Info", description="", fields=fields) embed.set_image(url=self.bot.user.avatar.url) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) diff --git a/jarvis/cogs/core/data.py b/jarvis/cogs/core/data.py index ad49016..7ef340e 100644 --- a/jarvis/cogs/core/data.py +++ b/jarvis/cogs/core/data.py @@ -36,13 +36,9 @@ class DataCog(Extension): data = SlashCommand(name="data", description="Data commands") - @data.subcommand( - sub_cmd_name="usage", sub_cmd_description="View data usage information" - ) + @data.subcommand(sub_cmd_name="usage", sub_cmd_description="View data usage information") async def _data_usage(self, ctx: SlashContext) -> None: - await ctx.send( - "Please review our [Privacy Policy](https://s.zevs.me/jarvis-privacy)" - ) + await ctx.send("Please review our [Privacy Policy](https://s.zevs.me/jarvis-privacy)") @data.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete my data") async def _data_delete(self, ctx: SlashContext) -> None: @@ -91,9 +87,7 @@ class DataCog(Extension): await message.edit( content="❌ There was an error. Please report it to the help server, or DM `@zevaryx` for help" ) - self.logger.error( - f"Encountered error while deleting data: {e}", exc_info=True - ) + self.logger.error(f"Encountered error while deleting data: {e}", exc_info=True) else: for row in components: diff --git a/jarvis/cogs/core/remindme.py b/jarvis/cogs/core/remindme.py index d40129a..595c678 100644 --- a/jarvis/cogs/core/remindme.py +++ b/jarvis/cogs/core/remindme.py @@ -1,4 +1,5 @@ """JARVIS Remind Me Cog.""" + import asyncio import logging import re @@ -28,7 +29,7 @@ from jarvis.utils import build_embed valid = re.compile(r"[\w\s\-\\/.!@?#$%^*()+=<>:'\",\u0080-\U000E0FFF]*") time_pattern = re.compile(r"(\d+\.?\d?[s|m|h|d|w]{1})\s?", flags=re.IGNORECASE) invites = re.compile( - r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", # noqa: E501 + r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", flags=re.IGNORECASE, ) @@ -60,12 +61,10 @@ class RemindmeCog(Extension): self, ctx: InteractionContext, timezone: str = "UTC", - private: bool = None, + private: bool = False, ) -> None: - if private is None and ctx.guild: + if not private and ctx.guild: private = ctx.guild.member_count >= 5000 - elif private is None and not ctx.guild: - private = False timezone = pytz.timezone(timezone) modal = Modal( *[ @@ -96,9 +95,7 @@ class RemindmeCog(Extension): await ctx.send_modal(modal) try: - response = await self.bot.wait_for_modal( - modal, author=ctx.author.id, timeout=60 * 5 - ) + response = await self.bot.wait_for_modal(modal, author=ctx.author.id, timeout=60 * 5) message = response.responses.get("message").strip() delay = response.responses.get("delay").strip() cron = response.responses.get("cron").strip() @@ -107,7 +104,7 @@ class RemindmeCog(Extension): if len(message) > 500: await response.send("Reminder cannot be > 500 characters.", ephemeral=True) return - elif invites.search(message): + if invites.search(message): await response.send( "Listen, don't use this to try and bypass the rules", ephemeral=True, @@ -118,12 +115,10 @@ class RemindmeCog(Extension): # "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 - ) + if len(message) == 0: + await response.send("Hey, you should probably add content to your reminder", ephemeral=True) return - elif cron and not croniter.is_valid(cron): + if cron and not croniter.is_valid(cron): await response.send( f"Invalid cron: {cron}\n\nUse https://crontab.guru to help", ephemeral=True, @@ -136,9 +131,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) @@ -165,7 +158,7 @@ class RemindmeCog(Extension): ) return - elif remind_at < datetime.now(tz=timezone): + if remind_at < datetime.now(tz=timezone): pass r = Reminder( @@ -217,17 +210,13 @@ class RemindmeCog(Extension): ) components = [delete_button] if not r.guild == ctx.author.id: - copy_button = Button( - style=ButtonStyle.GREEN, emoji="📋", custom_id=f"copy|rme|{r.id}" - ) + copy_button = Button(style=ButtonStyle.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: @@ -264,22 +253,16 @@ class RemindmeCog(Extension): @reminders.subcommand(sub_cmd_name="list", sub_cmd_description="List reminders") async def _list(self, ctx: InteractionContext) -> None: - reminders = await Reminder.find( - Reminder.user == ctx.author.id, Reminder.active == True - ).to_list() + reminders = await Reminder.find(Reminder.user == ctx.author.id, Reminder.active == True).to_list() if not reminders: await ctx.send("You have no reminders set.", ephemeral=True) return embed = await self.get_reminders_embed(ctx, reminders) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.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" - ) + @reminders.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a reminder") @slash_option( name="content", description="Content of the reminder", @@ -309,9 +292,7 @@ class RemindmeCog(Extension): ) embed.set_thumbnail(url=ctx.author.display_avatar.url) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") try: await reminder.delete() except Exception: @@ -343,18 +324,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, icon_url=ctx.author.display_avatar.url, ) embed.set_thumbnail(url=ctx.author.display_avatar.url) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.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: @@ -366,10 +343,7 @@ class RemindmeCog(Extension): @_delete.autocomplete("content") async def _search_reminders(self, ctx: AutocompleteContext) -> None: reminders = await Reminder.find(Reminder.user == ctx.author.id).to_list() - lookup = { - f"[{r.created_at.strftime('%d/%m/%Y %H:%M.%S')}] {r.message}": str(r.id) - for r in reminders - } + lookup = {f"[{r.created_at.strftime('%d/%m/%Y %H:%M.%S')}] {r.message}": str(r.id) for r in reminders} results = process.extract(ctx.input_text, list(lookup.keys()), limit=5) choices = [{"name": r[0], "value": lookup[r[0]]} for r in results] await ctx.send(choices=choices) diff --git a/jarvis/cogs/core/util.py b/jarvis/cogs/core/util.py index c856ca2..6432d6b 100644 --- a/jarvis/cogs/core/util.py +++ b/jarvis/cogs/core/util.py @@ -55,9 +55,7 @@ class UtilCog(Extension): bot = SlashCommand(name="bot", description="Bot commands") - @bot.subcommand( - sub_cmd_name="donate", sub_cmd_description="Support the development of JARVIS" - ) + @bot.subcommand(sub_cmd_name="donate", sub_cmd_description="Support the development of JARVIS") async def _donate(self, ctx: SlashContext) -> None: await ctx.send( """Want to support JARVIS? Donate here: @@ -68,9 +66,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh """ ) - @bot.subcommand( - sub_cmd_name="donate", sub_cmd_description="Support the development of JARVIS" - ) + @bot.subcommand(sub_cmd_name="donate", sub_cmd_description="Support the development of JARVIS") async def _donate(self, ctx: SlashContext) -> None: await ctx.send( """Want to support JARVIS? Donate here: @@ -111,10 +107,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh ) ) self.bot.logger.debug("Getting repo information") - repo_url = "https://git.zevaryx.com/stark-industries/jarvis/jarvis-bot/" - fields.append( - EmbedField(name="Online Since", value=f"", inline=False) - ) + fields.append(EmbedField(name="Online Since", value=f"", inline=False)) num_domains = len(self.bot.phishing_domains) fields.append( EmbedField( @@ -123,9 +116,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh ) ) embed = build_embed(title=title, description=desc, fields=fields, color=color) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @bot.subcommand( @@ -188,9 +179,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh embed = build_embed(title="Avatar", description="", fields=[], color="#00FFEE") embed.set_image(url=avatar) embed.set_author(name=f"{user.username}", icon_url=avatar) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @slash_command(name="emotes", description="Get all emotes") @@ -246,9 +235,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh EmbedField(name="Name", value=role.mention, inline=True), EmbedField(name="Color", value=str(role.color.hex), inline=True), EmbedField(name="Mention", value=f"`{role.mention}`", inline=True), - EmbedField( - name="Hoisted", value="Yes" if role.hoist else "No", inline=True - ), + EmbedField(name="Hoisted", value="Yes" if role.hoist else "No", inline=True), EmbedField(name="Position", value=str(role.position), inline=True), EmbedField( name="Mentionable", @@ -256,9 +243,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh inline=True, ), EmbedField(name="Member Count", value=str(len(role.members)), inline=True), - EmbedField( - name="Created At", value=f"" - ), + EmbedField(name="Created At", value=f""), ] embed = build_embed( title="", @@ -331,18 +316,14 @@ Tips will be used to pay server costs, and any excess will go to local animal sh ), EmbedField( name=f"Roles [{len(user_roles)}]", - value=( - " ".join([x.mention for x in user_roles]) if user_roles else "None" - ), + value=(" ".join([x.mention for x in user_roles]) if user_roles else "None"), inline=False, ), ] if muted: ts = int(user.communication_disabled_until.timestamp()) - fields.append( - EmbedField(name="Muted Until", value=f" ()") - ) + fields.append(EmbedField(name="Muted Until", value=f" ()")) embed = build_embed( title="", @@ -357,9 +338,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh ) embed.set_thumbnail(url=user.display_avatar.url) embed.set_footer(text=f"ID: {user.id}") - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @slash_command(name="lmgtfy", description="Let me Google that for you") @@ -396,9 +375,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh owner = await guild.fetch_owner() - owner = ( - f"{owner.username}#{owner.discriminator}" if owner else "||`[redacted]`||" - ) + owner = f"{owner.username}#{owner.discriminator}" if owner else "||`[redacted]`||" categories = len([x for x in guild.channels if isinstance(x, GuildCategory)]) text_channels = len([x for x in guild.channels if isinstance(x, GuildText)]) @@ -417,45 +394,31 @@ Tips will be used to pay server costs, and any excess will go to local animal sh EmbedField(name="Threads", value=str(threads), inline=True), EmbedField(name="Members", value=str(members), inline=True), EmbedField(name="Roles", value=str(roles), inline=True), - EmbedField( - name="Created At", value=f"" - ), + EmbedField(name="Created At", value=f""), ] role_embeds = [] if len(comma_role_list) < 1024: - fields.append( - EmbedField( - name=f"Role List [{roles}]", value=comma_role_list, inline=False - ) - ) + fields.append(EmbedField(name=f"Role List [{roles}]", value=comma_role_list, inline=False)) else: current_role_list = role_list[0].mention for role in role_list[1:]: if len(current_role_list + ", " + role.mention) > 3192: - role_embed = build_embed( - title="", description=current_role_list, fields=[] - ) + role_embed = build_embed(title="", description=current_role_list, fields=[]) role_embeds.append(role_embed) current_role_list = role.mention else: current_role_list += ", " + role.mention if len(current_role_list) > 0: - role_embed = build_embed( - title="", description=current_role_list, fields=[] - ) + role_embed = build_embed(title="", description=current_role_list, fields=[]) role_embeds.append(role_embed) - embed = build_embed( - title="", description="", fields=fields, timestamp=guild.created_at - ) + embed = build_embed(title="", description="", fields=fields, timestamp=guild.created_at) embed.set_author(name=guild.name, icon_url=guild.icon.url) embed.set_thumbnail(url=guild.icon.url) embed.set_footer(text=f"ID: {guild.id} | Server Created") - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @slash_command( @@ -482,9 +445,7 @@ Tips will be used to pay server costs, and any excess will go to local animal sh ], ) @cooldown(bucket=Buckets.USER, rate=1, interval=15) - async def _pw_gen( - self, ctx: SlashContext, length: int = 32, chars: int = 3 - ) -> None: + async def _pw_gen(self, ctx: SlashContext, length: int = 32, chars: int = 3) -> None: if length > 256: await ctx.send("Please limit password to 256 characters", ephemeral=True) return @@ -541,18 +502,14 @@ Tips will be used to pay server costs, and any excess will go to local animal sh opt_type=OptionType.BOOLEAN, required=False, ) - async def _timestamp( - self, ctx: SlashContext, string: str, private: bool = False - ) -> None: + async def _timestamp(self, ctx: SlashContext, string: str, private: bool = False) -> None: timestamp = parse(string) if not timestamp: await ctx.send("Valid time not found, try again", ephemeral=True) return if not timestamp.tzinfo: - timestamp = timestamp.replace(tzinfo=get_localzone()).astimezone( - tz=timezone.utc - ) + timestamp = timestamp.replace(tzinfo=get_localzone()).astimezone(tz=timezone.utc) timestamp_utc = timestamp.astimezone(tz=timezone.utc) @@ -565,12 +522,8 @@ Tips will be used to pay server costs, and any excess will go to local animal sh EmbedField(name="Relative Time", value=f"\n``"), EmbedField(name="ISO8601", value=timestamp.isoformat()), ] - embed = build_embed( - title="Converted Time", description=f"`{string}`", fields=fields - ) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + embed = build_embed(title="Converted Time", description=f"`{string}`", fields=fields) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, ephemeral=private, components=components) @bot.subcommand(sub_cmd_name="support", sub_cmd_description="Got issues?") diff --git a/jarvis/cogs/extra/__init__.py b/jarvis/cogs/extra/__init__.py index 2ca49ce..a3b2eb4 100644 --- a/jarvis/cogs/extra/__init__.py +++ b/jarvis/cogs/extra/__init__.py @@ -1,4 +1,5 @@ """JARVIS extra, optional cogs""" + from interactions import Client from jarvis.cogs.extra import calc, dev, image, pinboard, rolegiver, tags diff --git a/jarvis/cogs/extra/calc.py b/jarvis/cogs/extra/calc.py index 18db39f..eb57880 100644 --- a/jarvis/cogs/extra/calc.py +++ b/jarvis/cogs/extra/calc.py @@ -1,4 +1,5 @@ """JARVIS Calculator Cog.""" + from calculator import calculate from erapi import const from interactions import AutocompleteContext, Client, Extension, InteractionContext @@ -38,9 +39,7 @@ class CalcCog(Extension): calc = SlashCommand(name="calc", description="Calculate some things") - @calc.subcommand( - sub_cmd_name="math", sub_cmd_description="Do a basic math calculation" - ) + @calc.subcommand(sub_cmd_name="math", sub_cmd_description="Do a basic math calculation") @slash_option( name="expression", description="Expression to calculate", @@ -77,16 +76,12 @@ class CalcCog(Extension): ) embed = build_embed(title="Calculator", description=None, fields=fields) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) convert = calc.group(name="convert", description="Conversion helpers") - @convert.subcommand( - sub_cmd_name="temperature", sub_cmd_description="Convert between temperatures" - ) + @convert.subcommand(sub_cmd_name="temperature", sub_cmd_description="Convert between temperatures") @slash_option( name="value", description="Value to convert", @@ -136,9 +131,7 @@ class CalcCog(Extension): description=f"°{TEMP_LOOKUP.get(from_unit)} -> °{TEMP_LOOKUP.get(to_unit)}", fields=fields, ) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @convert.subcommand( @@ -201,9 +194,7 @@ class CalcCog(Extension): ) await ctx.send(embeds=embed, components=components) - async def _convert( - self, ctx: InteractionContext, from_: str, to: str, value: int - ) -> Embed: + async def _convert(self, ctx: InteractionContext, from_: str, to: str, value: int) -> Embed: *_, which = ctx.invoke_target.split(" ") which = getattr(units, which.capitalize(), None) ratio = which.get_rate(from_, to) @@ -212,12 +203,8 @@ class CalcCog(Extension): EmbedField(name=from_, value=f"{value:0.2f}"), EmbedField(name=to, value=f"{converted:0.2f}"), ) - embed = build_embed( - title="Conversion", description=f"{from_} -> {to}", fields=fields - ) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + embed = build_embed(title="Conversion", description=f"{from_} -> {to}", fields=fields) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @convert.subcommand(sub_cmd_name="angle", sub_cmd_description="Convert angles") @@ -241,9 +228,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_angle( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_angle(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="area", sub_cmd_description="Convert areas") @@ -267,9 +252,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_area( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_area(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="data", sub_cmd_description="Convert data sizes") @@ -293,9 +276,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_data( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_data(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="energy", sub_cmd_description="Convert energy") @@ -319,9 +300,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_energy( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_energy(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="length", sub_cmd_description="Convert lengths") @@ -345,9 +324,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_length( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_length(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="power", sub_cmd_description="Convert powers") @@ -371,14 +348,10 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_power( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_power(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) - @convert.subcommand( - sub_cmd_name="pressure", sub_cmd_description="Convert pressures" - ) + @convert.subcommand(sub_cmd_name="pressure", sub_cmd_description="Convert pressures") @slash_option( name="value", description="Pressure to convert", @@ -399,9 +372,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_pressure( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_pressure(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="speed", sub_cmd_description="Convert speeds") @@ -425,9 +396,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_speed( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_speed(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="time", sub_cmd_description="Convert times") @@ -451,9 +420,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_time( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_time(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="volume", sub_cmd_description="Convert volumes") @@ -477,9 +444,7 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_volume( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_volume(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) @convert.subcommand(sub_cmd_name="weight", sub_cmd_description="Convert weights") @@ -503,17 +468,13 @@ class CalcCog(Extension): required=True, autocomplete=True, ) - async def _calc_convert_weight( - self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str - ) -> None: + async def _calc_convert_weight(self, ctx: InteractionContext, value: int, from_unit: str, to_unit: str) -> None: await self._convert(ctx, from_unit, to_unit, value) - def _unit_autocomplete( - self, which: units.Converter, unit: str - ) -> list[dict[str, str]]: + def _unit_autocomplete(self, which: units.Converter, unit: str) -> list[dict[str, str]]: options = list(which.CONVERSIONS.keys()) results = process.extract(unit, options, limit=25) - if any([r[1] > 0 for r in results]): + if any(r[1] > 0 for r in results): return [{"name": r[0], "value": r[0]} for r in results if r[1] > 50] return [{"name": r[0], "value": r[0]} for r in results] @@ -564,8 +525,8 @@ class CalcCog(Extension): if r[1] > results[name]: results[name] = r[1] - results = sorted(list(results.items()), key=lambda x: -x[1])[:10] - if any([r[1] > 0 for r in results]): + results = sorted(results.items(), key=lambda x: -x[1])[:10] + if any(r[1] > 0 for r in results): return [{"name": r[0], "value": lookup_name[r[0]]} for r in results if r[1]] return [{"name": r[0], "value": lookup_name[r[0]]} for r in results] diff --git a/jarvis/cogs/extra/dev.py b/jarvis/cogs/extra/dev.py index e82eba9..6e5a6d7 100644 --- a/jarvis/cogs/extra/dev.py +++ b/jarvis/cogs/extra/dev.py @@ -1,12 +1,14 @@ """JARVIS Developer Cog.""" + import base64 import hashlib import logging import re -import subprocess # noqa: S404 +import subprocess import uuid as uuidpy from datetime import datetime from io import BytesIO +from typing import ClassVar import nanoid import pytz @@ -40,11 +42,9 @@ from jarvis.utils import build_embed supported_hashes = {x for x in hashlib.algorithms_guaranteed if "shake" not in x} OID_VERIFY = re.compile(r"^([1-9][0-9]{0,3}|0)(\.([1-9][0-9]{0,3}|0)){5,13}$") -URL_VERIFY = re.compile( - r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+" -) +URL_VERIFY = re.compile(r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+") DN_VERIFY = re.compile( - r"^(?:(?PCN=(?P[^,]*)),)?(?:(?P(?:(?:CN|OU)=[^,]+,?)+),)?(?P(?:DC=[^,]+,?)+)$" # noqa: E501 + r"^(?:(?PCN=(?P[^,]*)),)?(?:(?P(?:(?:CN|OU)=[^,]+,?)+),)?(?P(?:DC=[^,]+,?)+)$" ) ULID_VERIFY = re.compile(r"^[0-9a-z]{26}$", re.IGNORECASE) UUID_VERIFY = re.compile( @@ -127,7 +127,7 @@ class DevCog(Extension): self, ctx: InteractionContext, method: str, - data: str = None, + data: str = None, # noqa: RUF013 attach: Attachment = None, ) -> None: if not data and not attach: @@ -146,12 +146,8 @@ class DevCog(Extension): elif url.match(data): try: if (size := await get_size(data)) > MAX_FILESIZE: - await ctx.send( - "Please hash files that are <= 5GB in size", ephemeral=True - ) - self.logger.debug( - f"Refused to hash file of size {convert_bytesize(size)}" - ) + await ctx.send("Please hash files that are <= 5GB in size", ephemeral=True) + self.logger.debug(f"Refused to hash file of size {convert_bytesize(size)}") return except Exception as e: await ctx.send(f"Failed to retrieve URL: ```\n{e}\n```", ephemeral=True) @@ -174,9 +170,7 @@ class DevCog(Extension): ] embed = build_embed(title=title, description=description, fields=fields) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @dev.subcommand(sub_cmd_name="uuid", sub_cmd_description="Generate a UUID") @@ -193,9 +187,7 @@ class DevCog(Extension): opt_type=OptionType.STRING, required=False, ) - async def _uuid( - self, ctx: InteractionContext, version: str, data: str = None - ) -> None: + async def _uuid(self, ctx: InteractionContext, version: str, data: str = None) -> None: # noqa: RUF013 version = int(version) if version in [3, 5] and not data: await ctx.send(f"UUID{version} requires data.", ephemeral=True) @@ -220,7 +212,7 @@ class DevCog(Extension): ) @cooldown(bucket=Buckets.USER, rate=1, interval=2) async def _objectid(self, ctx: InteractionContext) -> None: - await ctx.send(f"ObjectId: `{str(ObjectId())}`") + await ctx.send(f"ObjectId: `{ObjectId()!s}`") @dev.subcommand( sub_cmd_name="ulid", @@ -266,7 +258,7 @@ class DevCog(Extension): else: await ctx.send("Invalid ULID.") - base64_methods = ["b64", "b16", "b32", "a85", "b85"] + base64_methods: ClassVar[list[str]] = ["b64", "b16", "b32", "a85", "b85"] @dev.subcommand(sub_cmd_name="encode", sub_cmd_description="Encode some data") @slash_option( @@ -301,9 +293,7 @@ class DevCog(Extension): EmbedField(name=mstr, value=f"`{encoded}`", inline=False), ] embed = build_embed(title="Encoded Data", description="", fields=fields) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @dev.subcommand(sub_cmd_name="decode", sub_cmd_description="Decode some data") @@ -339,18 +329,14 @@ class DevCog(Extension): EmbedField(name=mstr, value=f"`{decoded}`", inline=False), ] embed = build_embed(title="Decoded Data", description="", fields=fields) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @dev.subcommand(sub_cmd_name="cloc", sub_cmd_description="Get JARVIS lines of code") @cooldown(bucket=Buckets.CHANNEL, rate=1, interval=30) async def _cloc(self, ctx: InteractionContext) -> None: await ctx.defer() - output = subprocess.check_output(["tokei", "-C", "--sort", "code"]).decode( - "UTF-8" - ) # noqa: S603, S607 + output = subprocess.check_output(["tokei", "-C", "--sort", "code"]).decode("UTF-8") console = Console() with console.capture() as capture: console.print(output) diff --git a/jarvis/cogs/extra/image.py b/jarvis/cogs/extra/image.py index 6c996d5..081c4d4 100644 --- a/jarvis/cogs/extra/image.py +++ b/jarvis/cogs/extra/image.py @@ -1,4 +1,5 @@ """JARVIS image processing cog.""" + import logging import re from io import BytesIO @@ -62,7 +63,7 @@ class ImageCog(Extension): required=False, ) async def _resize( - self, ctx: InteractionContext, target: str, attachment: Attachment = None, url: str = None + self, ctx: InteractionContext, target: str, attachment: Attachment = None, url: str = None # noqa: RUF013 ) -> None: await ctx.defer() if not attachment and not url: diff --git a/jarvis/cogs/extra/pinboard.py b/jarvis/cogs/extra/pinboard.py index 20bcdf2..3f2a468 100644 --- a/jarvis/cogs/extra/pinboard.py +++ b/jarvis/cogs/extra/pinboard.py @@ -1,4 +1,5 @@ """JARVIS Starboard Cog.""" + import asyncio import logging @@ -44,9 +45,7 @@ class PinboardCog(Extension): async def _purge_starboard(self, ctx: InteractionContext, board: Pinboard) -> None: channel = await ctx.guild.fetch_channel(board.channel) - async for pin in Pin.find( - Pin.pinboard == channel.id, Pin.guild == ctx.guild.id - ): + async for pin in Pin.find(Pin.pinboard == channel.id, Pin.guild == ctx.guild.id): if message := await channel.fetch_message(pin.message): try: await message.delete() @@ -91,13 +90,9 @@ class PinboardCog(Extension): await ctx.send("Channel must be a GuildText", ephemeral=True) return - exists = await Pinboard.find_one( - Pinboard.channel == channel.id, Pinboard.guild == ctx.guild.id - ) + exists = await Pinboard.find_one(Pinboard.channel == channel.id, Pinboard.guild == ctx.guild.id) if exists: - await ctx.send( - f"Pinboard already exists at {channel.mention}.", ephemeral=True - ) + await ctx.send(f"Pinboard already exists at {channel.mention}.", ephemeral=True) return count = await Pinboard.find(Pinboard.guild == ctx.guild.id).count() @@ -121,17 +116,16 @@ class PinboardCog(Extension): ) @check(admin_or_permissions(Permissions.MANAGE_GUILD, Permissions.MANAGE_MESSAGES)) async def _delete(self, ctx: InteractionContext, channel: GuildText) -> None: - found = await Pinboard.find_one( - Pinboard.channel == channel.id, Pinboard.guild == ctx.guild.id - ) + found = await Pinboard.find_one(Pinboard.channel == channel.id, Pinboard.guild == ctx.guild.id) if found: await found.delete() - asyncio.create_task(self._purge_starboard(ctx, found)) + task = asyncio.create_task(self._purge_starboard(ctx, found)) await ctx.send(f"Pinboard deleted from {channel.mention}.") + await asyncio.wait([task]) else: await ctx.send(f"Pinboard not found in {channel.mention}.", ephemeral=True) - async def _star_add( + async def _star_add( # noqa: C901 self, ctx: InteractionContext, message: str, @@ -166,9 +160,7 @@ class PinboardCog(Extension): channel_list.append(c) channel_to_pinboard[c.id] = pinboard else: - self.logger.warning( - f"Pinboard {pinboard.channel} no longer valid in {ctx.guild.name}" - ) + self.logger.warning(f"Pinboard {pinboard.channel} no longer valid in {ctx.guild.name}") to_delete.append(pinboard) for pinboard in to_delete: @@ -182,10 +174,7 @@ class PinboardCog(Extension): if x: select_channels.append(StringSelectOption(label=x.name, value=str(idx))) - select_channels = [ - StringSelectOption(label=x.name, value=str(idx)) - for idx, x in enumerate(channel_list) - ] + select_channels = [StringSelectOption(label=x.name, value=str(idx)) for idx, x in enumerate(channel_list)] select = StringSelectMenu( *select_channels, @@ -219,9 +208,7 @@ class PinboardCog(Extension): ) return - count = await Pin.find( - Pin.guild == ctx.guild.id, Pin.pinboard == pinboard.id - ).count() + count = await Pin.find(Pin.guild == ctx.guild.id, Pin.pinboard == pinboard.id).count() content = message.content attachments = message.attachments diff --git a/jarvis/cogs/extra/rolegiver.py b/jarvis/cogs/extra/rolegiver.py index 167b04a..16d76a6 100644 --- a/jarvis/cogs/extra/rolegiver.py +++ b/jarvis/cogs/extra/rolegiver.py @@ -1,4 +1,5 @@ """JARVIS Role Giver Cog.""" + import asyncio import logging @@ -69,15 +70,11 @@ class RolegiverCog(Extension): rolegiver.roles = roles await rolegiver.save() - rolegiver = SlashCommand( - name="rolegiver", description="Allow users to choose their own roles" - ) + rolegiver = SlashCommand(name="rolegiver", description="Allow users to choose their own roles") rg_group = rolegiver.group(name="group", description="Manage rolegiver groups") - @rg_group.subcommand( - sub_cmd_name="create", sub_cmd_description="Create a rolegiver group" - ) + @rg_group.subcommand(sub_cmd_name="create", sub_cmd_description="Create a rolegiver group") @slash_option( name="group", description="Group to create", @@ -86,9 +83,7 @@ class RolegiverCog(Extension): ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) async def _group_create(self, ctx: InteractionContext, group: str): - if await Rolegiver.find_one( - Rolegiver.guild == ctx.guild.id, Rolegiver.group == group - ): + if await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id, Rolegiver.group == group): await ctx.send("Group already exists!", ephemeral=True) return @@ -102,9 +97,7 @@ class RolegiverCog(Extension): elif rolegiver.group not in self._group_cache[ctx.guild.id]: self._group_cache[ctx.guild.id][rolegiver.group] = {} - @rg_group.subcommand( - sub_cmd_name="delete", sub_cmd_description="DDelete a rolegiver group" - ) + @rg_group.subcommand(sub_cmd_name="delete", sub_cmd_description="DDelete a rolegiver group") @slash_option( name="group", description="Group to delete", @@ -114,9 +107,7 @@ class RolegiverCog(Extension): ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) async def _group_delete(self, ctx: InteractionContext, group: str): - if rolegiver := await Rolegiver.find_one( - Rolegiver.guild == ctx.guild.id, Rolegiver.group == group - ): + if rolegiver := await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id, Rolegiver.group == group): await rolegiver.delete() await ctx.send(f"Rolegiver group {group} deleted!") del self._group_cache[ctx.guild.id][rolegiver.group] @@ -127,9 +118,7 @@ class RolegiverCog(Extension): sub_cmd_name="add", sub_cmd_description="Add a role to rolegiver", ) - @slash_option( - name="role", description="Role to add", opt_type=OptionType.ROLE, required=True - ) + @slash_option(name="role", description="Role to add", opt_type=OptionType.ROLE, required=True) @slash_option( name="group", description="Group to add to", @@ -138,9 +127,7 @@ class RolegiverCog(Extension): autocomplete=True, ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) - async def _rolegiver_add( - self, ctx: InteractionContext, role: Role, group: str = "Default" - ) -> None: + async def _rolegiver_add(self, ctx: InteractionContext, role: Role, group: str = "Default") -> None: if role.id == ctx.guild.id: await ctx.send("Cannot add `@everyone` to rolegiver", ephemeral=True) return @@ -152,14 +139,12 @@ class RolegiverCog(Extension): ) return - rolegiver = await Rolegiver.find_one( - Rolegiver.guild == ctx.guild.id, Rolegiver.group == group - ) + rolegiver = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id, Rolegiver.group == group) if rolegiver and rolegiver.roles and role.id in rolegiver.roles: await ctx.send("Role already in rolegiver", ephemeral=True) return - elif rolegiver and len(rolegiver.roles) >= 15: + if rolegiver and len(rolegiver.roles) >= 15: await ctx.send( f"Maximum roles in group {group}. Please make a new group", ephemeral=True, @@ -200,18 +185,14 @@ class RolegiverCog(Extension): embed.set_thumbnail(url=ctx.guild.icon.url) embed.set_footer(text=f"{ctx.author.username} | {ctx.author.id}") - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) if ctx.guild.id not in self._group_cache: self._group_cache[ctx.guild.id] = {group: {}} self._group_cache[ctx.guild.id][group].update({role.name: role.id}) - @rolegiver.subcommand( - sub_cmd_name="remove", sub_cmd_description="Remove a role from rolegiver" - ) + @rolegiver.subcommand(sub_cmd_name="remove", sub_cmd_description="Remove a role from rolegiver") @slash_option( name="group", description="Name of group to remove from", @@ -220,9 +201,7 @@ class RolegiverCog(Extension): ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) async def _rolegiver_remove(self, ctx: InteractionContext, group: str) -> None: - rolegiver = await Rolegiver.find_one( - Rolegiver.guild == ctx.guild.id, Rolegiver.group == group - ) + rolegiver = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id, Rolegiver.group == group) if not rolegiver or (rolegiver and not rolegiver.roles): await ctx.send(f"Rolegiver {group} has no roles", ephemeral=True) return @@ -234,11 +213,9 @@ class RolegiverCog(Extension): if role: roles[int(role.id)] = role - rolegiver.roles = [r for r in roles.keys()] + rolegiver.roles = list(roles.keys()) - options = [ - StringSelectOption(label=v.name, value=str(k)) for k, v in roles.items() - ][:25] + options = [StringSelectOption(label=v.name, value=str(k)) for k, v in roles.items()][:25] select = StringSelectMenu( *options, placeholder="Select roles to remove", @@ -247,9 +224,7 @@ class RolegiverCog(Extension): ) components = [ActionRow(select)] - message = await ctx.send( - content=f"Removing roles from {group}", components=components - ) + message = await ctx.send(content=f"Removing roles from {group}", components=components) try: resp = await self.bot.wait_for_component( @@ -279,9 +254,7 @@ class RolegiverCog(Extension): ), EmbedField( name="Remaining Role(s)", - value="\n".join( - x.mention for x in roles.values() if x not in removed_roles - ), + value="\n".join(x.mention for x in roles.values() if x not in removed_roles), ), ] @@ -297,13 +270,9 @@ class RolegiverCog(Extension): embeds=embed, ) - self._group_cache[ctx.guild.id].update( - {group: {v.name: k for k, v in roles.items() if v not in removed_roles}} - ) + self._group_cache[ctx.guild.id].update({group: {v.name: k for k, v in roles.items() if v not in removed_roles}}) - @rolegiver.subcommand( - sub_cmd_name="list", sub_cmd_description="List rolegiver roles" - ) + @rolegiver.subcommand(sub_cmd_name="list", sub_cmd_description="List rolegiver roles") @slash_option( name="group", description="Name of group to list", @@ -311,12 +280,8 @@ class RolegiverCog(Extension): required=False, autocomplete=True, ) - async def _rolegiver_list( - self, ctx: InteractionContext, group: str = "Default" - ) -> None: - setting = await Rolegiver.find_one( - Rolegiver.guild == ctx.guild.id, Rolegiver.group == group - ) + async def _rolegiver_list(self, ctx: InteractionContext, group: str = "Default") -> None: + setting = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id, Rolegiver.group == group) if not setting or (setting and not setting.roles): await ctx.send("Rolegiver has no roles", ephemeral=True) return @@ -342,9 +307,7 @@ class RolegiverCog(Extension): embed.set_thumbnail(url=ctx.guild.icon.url) embed.set_footer(text=f"{ctx.author.username} | {ctx.author.id}") - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) role = SlashCommand(name="role", description="Get roles!") @@ -359,9 +322,7 @@ class RolegiverCog(Extension): ) @cooldown(bucket=Buckets.USER, rate=1, interval=10) async def _role_get(self, ctx: InteractionContext, group: str = "Default") -> None: - rolegiver = await Rolegiver.find_one( - Rolegiver.guild == ctx.guild.id, Rolegiver.group == group - ) + rolegiver = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id, Rolegiver.group == group) if not rolegiver or (rolegiver and not rolegiver.roles): await ctx.send(f"Rolegiver group {group} has no roles", ephemeral=True) return @@ -409,9 +370,7 @@ class RolegiverCog(Extension): added_roles.append(role) await ctx.author.add_role(role, reason="Rolegiver") - avalue = ( - "\n".join([r.mention for r in added_roles]) if added_roles else "None" - ) + avalue = "\n".join([r.mention for r in added_roles]) if added_roles else "None" fields = [ EmbedField(name="Added Role(s)", value=avalue), ] @@ -434,9 +393,7 @@ class RolegiverCog(Extension): for component in row.components: component.disabled = True - await response.ctx.edit_origin( - embeds=embed, content="\u200b", components=components - ) + await response.ctx.edit_origin(embeds=embed, content="\u200b", components=components) except asyncio.TimeoutError: for row in components: for component in row.components: @@ -452,21 +409,15 @@ class RolegiverCog(Extension): autocomplete=True, ) @cooldown(bucket=Buckets.USER, rate=1, interval=10) - async def _role_remove( - self, ctx: InteractionContext, group: str = "Default" - ) -> None: + async def _role_remove(self, ctx: InteractionContext, group: str = "Default") -> None: user_roles = ctx.author.roles - rolegiver = await Rolegiver.find_one( - Rolegiver.guild == ctx.guild.id, Rolegiver.group == group - ) + rolegiver = await Rolegiver.find_one(Rolegiver.guild == ctx.guild.id, Rolegiver.group == group) if not rolegiver or (rolegiver and not rolegiver.roles): await ctx.send("Rolegiver has no roles", ephemeral=True) return - elif not any(x.id in rolegiver.roles for x in user_roles): - await ctx.send( - f"You have no rolegiver roles from group {group}", ephemeral=True - ) + if not any(x.id in rolegiver.roles for x in user_roles): + await ctx.send(f"You have no rolegiver roles from group {group}", ephemeral=True) return valid = list(filter(lambda x: x.id in rolegiver.roles, user_roles)) @@ -500,11 +451,7 @@ class RolegiverCog(Extension): user_roles.remove(role) removed_roles.append(role) - rvalue = ( - "\n".join([r.mention for r in removed_roles]) - if removed_roles - else "None" - ) + rvalue = "\n".join([r.mention for r in removed_roles]) if removed_roles else "None" fields = [ EmbedField(name="Removed Role(s)", value=rvalue), ] @@ -516,9 +463,7 @@ class RolegiverCog(Extension): ) embed.set_thumbnail(url=ctx.guild.icon.url) - embed.set_author( - name=ctx.author.display_name, icon_url=ctx.author.display_avatar.url - ) + embed.set_author(name=ctx.author.display_name, icon_url=ctx.author.display_avatar.url) embed.set_footer(text=f"{ctx.author.username} | {ctx.author.id}") @@ -526,9 +471,7 @@ class RolegiverCog(Extension): for component in row.components: component.disabled = True - await context.ctx.edit_origin( - embeds=embed, components=components, content="\u200b" - ) + await context.ctx.edit_origin(embeds=embed, components=components, content="\u200b") except asyncio.TimeoutError: for row in components: @@ -574,9 +517,7 @@ class RolegiverCog(Extension): if rolegivers: await self._update_cache_from_autocomplete(ctx, rolegivers) - async def _update_cache_from_autocomplete( - self, ctx: AutocompleteContext, rolegivers: list[Rolegiver] - ) -> None: + async def _update_cache_from_autocomplete(self, ctx: AutocompleteContext, rolegivers: list[Rolegiver]) -> None: """Update the cache with a lock to prevent multiple simultaneous updates""" lock = self._cache_update_locks.get(ctx.guild.id) if not lock: @@ -595,9 +536,7 @@ class RolegiverCog(Extension): continue roles.append(role) await r.save() - self._group_cache[ctx.guild.id][r.group] = { - role.name: role.role.id for role in roles - } + self._group_cache[ctx.guild.id][r.group] = {role.name: role.role.id for role in roles} def setup(bot: Client) -> None: diff --git a/jarvis/cogs/extra/tags.py b/jarvis/cogs/extra/tags.py index 5599465..3e67fba 100644 --- a/jarvis/cogs/extra/tags.py +++ b/jarvis/cogs/extra/tags.py @@ -1,4 +1,5 @@ """JARVIS Tags Cog.""" + import asyncio import re from datetime import datetime, timezone @@ -26,7 +27,7 @@ from thefuzz import process from jarvis.utils import build_embed invites = re.compile( - r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", # noqa: E501 + r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", flags=re.IGNORECASE, ) tag_name = re.compile(r"^[\w\ \-]{1,40}$") @@ -82,17 +83,13 @@ class TagCog(Extension): await ctx.send_modal(modal) try: - response = await self.bot.wait_for_modal( - modal, author=ctx.author.id, timeout=60 * 5 - ) + response = await self.bot.wait_for_modal(modal, author=ctx.author.id, timeout=60 * 5) name = response.responses.get("name").replace("`", "") content = response.responses.get("content") except asyncio.TimeoutError: return - noinvite = await Setting.find_one( - Setting.guild == ctx.guild.id, Setting.setting == "noinvite" - ) + noinvite = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "noinvite") if ( (invites.search(content) or invites.search(name)) @@ -102,17 +99,13 @@ class TagCog(Extension): or ctx.author.has_permission(Permissions.MANAGE_MESSAGES) ) ): - await response.send( - "Listen, don't use this to try and bypass the rules", ephemeral=True - ) + await response.send("Listen, don't use this to try and bypass the rules", ephemeral=True) return - elif not content.strip() or not name.strip(): + if not content.strip() or not name.strip(): await response.send("Content and name required", ephemeral=True) return - elif not tag_name.match(name): - await response.send( - "Tag name must only contain: [A-Za-z0-9_- ]", ephemeral=True - ) + if not tag_name.match(name): + await response.send("Tag name must only contain: [A-Za-z0-9_- ]", ephemeral=True) return tag = await Tag.find_one(Tag.guild == ctx.guild.id, Tag.name == name) @@ -144,9 +137,7 @@ class TagCog(Extension): icon_url=ctx.author.display_avatar.url, ) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await response.send(embeds=embed, components=components) if ctx.guild.id not in self.cache: @@ -167,13 +158,11 @@ class TagCog(Extension): if not tag: await ctx.send("Tag not found", ephemeral=True) return - elif tag.creator != ctx.author.id and not ( + if tag.creator != ctx.author.id and not ( ctx.author.has_permission(Permissions.ADMINISTRATOR) or ctx.author.has_permission(Permissions.MANAGE_MESSAGES) ): - await ctx.send( - "You didn't create this tag, ask the creator to edit it", ephemeral=True - ) + await ctx.send("You didn't create this tag, ask the creator to edit it", ephemeral=True) return modal = Modal( @@ -198,9 +187,7 @@ class TagCog(Extension): await ctx.send_modal(modal) try: - response = await self.bot.wait_for_modal( - modal, author=ctx.author.id, timeout=60 * 5 - ) + response = await self.bot.wait_for_modal(modal, author=ctx.author.id, timeout=60 * 5) name = response.responses.get("name").replace("`", "") content = response.responses.get("content") except asyncio.TimeoutError: @@ -214,9 +201,7 @@ class TagCog(Extension): ) return - noinvite = await Setting.find_one( - Setting.guild == ctx.guild.id, Setting.setting == "noinvite" - ) + noinvite = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "noinvite") if ( (invites.search(content) or invites.search(name)) @@ -226,17 +211,13 @@ class TagCog(Extension): or ctx.author.has_permission(Permissions.MANAGE_MESSAGES) ) ): - await response.send( - "Listen, don't use this to try and bypass the rules", ephemeral=True - ) + await response.send("Listen, don't use this to try and bypass the rules", ephemeral=True) return - elif not content.strip() or not name.strip(): + if not content.strip() or not name.strip(): await response.send("Content and name required", ephemeral=True) return - elif not tag_name.match(name): - await response.send( - "Tag name must only contain: [A-Za-z0-9_- ]", ephemeral=True - ) + if not tag_name.match(name): + await response.send("Tag name must only contain: [A-Za-z0-9_- ]", ephemeral=True) return tag.content = re.sub(r"\\?([@<])", r"\\\g<1>", content) @@ -259,9 +240,7 @@ class TagCog(Extension): name=ctx.author.username + "#" + ctx.author.discriminator, icon_url=ctx.author.display_avatar.url, ) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await response.send(embeds=embed, components=components) if tag.name not in self.cache[ctx.guild.id]: self.cache[ctx.guild.id].remove(old_name) @@ -280,7 +259,7 @@ class TagCog(Extension): if not tag: await ctx.send("Tag not found", ephemeral=True) return - elif tag.creator != ctx.author.id and not ( + if tag.creator != ctx.author.id and not ( ctx.author.has_permission(Permissions.ADMINISTRATOR) or ctx.author.has_permission(Permissions.MANAGE_MESSAGES) ): @@ -341,9 +320,7 @@ class TagCog(Extension): name=f"{username}#{discrim}" if username else "Unknown User", icon_url=url, ) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @tag.subcommand(sub_cmd_name="list", sub_cmd_description="List tag names") @@ -351,9 +328,7 @@ class TagCog(Extension): tags = await Tag.find(Tag.guild == ctx.guild.id).to_list() names = "\n".join(f"`{t.name}`" for t in tags) embed = build_embed(title="All Tags", description=names, fields=[]) - components = Button( - style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}" - ) + components = Button(style=ButtonStyle.DANGER, emoji="🗑️", custom_id=f"delete|{ctx.author.id}") await ctx.send(embeds=embed, components=components) @_get.autocomplete("name") @@ -364,9 +339,7 @@ class TagCog(Extension): if not self.cache.get(ctx.guild.id): tags = await Tag.find(Tag.guild == ctx.guild.id).to_list() self.cache[ctx.guild.id] = [tag.name for tag in tags] - results = process.extract( - ctx.input_text, self.cache.get(ctx.guild.id), limit=25 - ) + results = process.extract(ctx.input_text, self.cache.get(ctx.guild.id), limit=25) choices = [{"name": r[0], "value": r[0]} for r in results] await ctx.send(choices=choices) diff --git a/jarvis/cogs/unique/__init__.py b/jarvis/cogs/unique/__init__.py index 11ced79..1234287 100644 --- a/jarvis/cogs/unique/__init__.py +++ b/jarvis/cogs/unique/__init__.py @@ -1,4 +1,5 @@ """JARVIS guild-specific cogs""" + from interactions import Client from jarvis.cogs.unique import ctc2, dbrand, gl diff --git a/jarvis/cogs/unique/ctc2.py b/jarvis/cogs/unique/ctc2.py index 0824252..7aea4d0 100644 --- a/jarvis/cogs/unique/ctc2.py +++ b/jarvis/cogs/unique/ctc2.py @@ -5,12 +5,13 @@ This cog is now abandoned due to conflict with the dbrand moderators. Please do not file feature requests related to this cog; they will be closed. -This cog has been abandoned by @zevaryx and any support must come through PRs. +This cog has been abandoned by @zevaryx and any support must come through PRs. No longer being a part of the community and hearing about *certain users* talking about me behind my back that request said features, means that I am no longer putting any energy into this. If you want to keep it running, make a PR to fix things. """ + import logging import re @@ -35,7 +36,7 @@ guild_ids = [] # [578757004059738142, 520021794380447745, 862402786116763668] valid = re.compile(r"[\w\s\-\\/.!@#$%^*()+=<>,\u0080-\U000E0FFF]*") invites = re.compile( - r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", # noqa: E501 + r"(?:https?://)?(?:www.)?(?:discord.(?:gg|io|me|li)|discord(?:app)?.com/invite)/([^\s/]+?)(?=\b)", flags=re.IGNORECASE, ) @@ -52,9 +53,7 @@ class CTCCog(Extension): def __del__(self): self._session.close() - ctc2 = SlashCommand( - name="ctc2", description="CTC2 related commands", scopes=guild_ids - ) + ctc2 = SlashCommand(name="ctc2", description="CTC2 related commands", scopes=guild_ids) @ctc2.subcommand(sub_cmd_name="about") @cooldown(bucket=Buckets.USER, rate=1, interval=30) @@ -87,23 +86,17 @@ class CTCCog(Extension): async def _pw(self, ctx: InteractionContext, guess: str) -> None: if len(guess) > 800: await ctx.send( - ( - "Listen here, dipshit. Don't be like <@256110768724901889>. " - "Make your guesses < 800 characters." - ), + ("Listen here, dipshit. Don't be like <@256110768724901889>. " "Make your guesses < 800 characters."), ephemeral=True, ) return - elif not valid.fullmatch(guess): + if not valid.fullmatch(guess): await ctx.send( - ( - "Listen here, dipshit. Don't be like <@256110768724901889>. " - "Make your guesses *readable*." - ), + ("Listen here, dipshit. Don't be like <@256110768724901889>. " "Make your guesses *readable*."), ephemeral=True, ) return - elif invites.search(guess): + if invites.search(guess): await ctx.send( "Listen here, dipshit. No using this to bypass sending invite links.", ephemeral=True, diff --git a/jarvis/cogs/unique/dbrand.py b/jarvis/cogs/unique/dbrand.py index 15998af..b5d09fb 100644 --- a/jarvis/cogs/unique/dbrand.py +++ b/jarvis/cogs/unique/dbrand.py @@ -5,7 +5,7 @@ This cog is now abandoned due to conflict with the dbrand moderators. Please do not file feature requests related to this cog; they will be closed. -This cog has been abandoned by @zevaryx and any support must come through PRs. +This cog has been abandoned by @zevaryx and any support must come through PRs. No longer being a part of the community and hearing about *certain users* talking about me behind my back that request said features, means that I am no longer putting any energy into this. If you want to keep @@ -22,16 +22,13 @@ from interactions import Client, Extension, InteractionContext from interactions.client.utils import find from interactions.models.discord.embed import EmbedField from interactions.models.internal.application_commands import ( - OptionType, SlashCommand, - slash_option, ) from interactions.models.internal.command import cooldown from interactions.models.internal.cooldowns import Buckets from thefuzz import process from jarvis.branding import CUSTOM_EMOJIS -from jarvis.config import load_config from jarvis.data.dbrand import shipping_lookup from jarvis.utils import build_embed @@ -59,9 +56,7 @@ async def parse_db_status() -> dict: cells = row.find_all("td") for cell in cells: if "column--comment" in cell["class"]: - status_title, detail, *_ = [ - x.get_text() for x in cell.find_all("div") - ] + status_title, detail, *_ = [x.get_text() for x in cell.find_all("div")] text = status_title if cell != "Unavailable": text += ": " + detail @@ -79,9 +74,7 @@ async def parse_db_status() -> dict: else: cell = cell.get_text().strip() row_data.append(cell) - data[data_key].append( - {headers[idx]: value for idx, value in enumerate(row_data)} - ) + data[data_key].append({headers[idx]: value for idx, value in enumerate(row_data)}) return data @@ -106,24 +99,17 @@ class DbrandCog(Extension): db = SlashCommand(name="db", description="dbrand commands", scopes=guild_ids) - @db.subcommand( - sub_cmd_name="status", sub_cmd_description="Get dbrand operational status" - ) + @db.subcommand(sub_cmd_name="status", sub_cmd_description="Get dbrand operational status") async def _status(self, ctx: InteractionContext) -> None: try: status = self.cache.get("status") if not status or status["cache_expiry"] <= datetime.now(tz=timezone.utc): status = await parse_db_status() - status["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta( - hours=2 - ) + status["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=2) self.cache["status"] = status status = status.get("operations") emojies = [x["Status"] for x in status] - fields = [ - EmbedField(name=f'{x["Status"]} {x["Service"]}', value=x["Detail"]) - for x in status - ] + fields = [EmbedField(name=f'{x["Status"]} {x["Service"]}', value=x["Detail"]) for x in status] color = "#FBBD1E" if all("green" in x for x in emojies): color = "#38F657" @@ -144,7 +130,7 @@ class DbrandCog(Extension): ) await ctx.send(embeds=embed) - except: + except Exception: self.bot.logger.error("Encountered error", exc_info=True) async def _db_support_cmd(self, ctx: InteractionContext) -> None: @@ -245,7 +231,7 @@ class DbrandCog(Extension): # required=True, # ) # @cooldown(bucket=Buckets.USER, rate=1, interval=2) - async def _shipping(self, ctx: InteractionContext, search: str) -> None: + async def _shipping(self, ctx: InteractionContext, search: str) -> None: # noqa: C901 if not re.match(r"^[A-Z- ]+$", search, re.IGNORECASE): if re.match( r"^[\U0001f1e6-\U0001f1ff]{2}$", @@ -254,15 +240,11 @@ class DbrandCog(Extension): ): # Magic number, subtract from flag char to get ascii char uni2ascii = 127365 - search = chr(ord(search[0]) - uni2ascii) + chr( - ord(search[1]) - uni2ascii - ) + search = chr(ord(search[0]) - uni2ascii) + chr(ord(search[1]) - uni2ascii) elif search == "🏳️": search = "fr" else: - await ctx.send( - "Please use text to search for shipping.", ephemeral=True - ) + await ctx.send("Please use text to search for shipping.", ephemeral=True) return if len(search) > 3: countries = {x["country"]: x["alpha-2"] for x in shipping_lookup} @@ -287,9 +269,7 @@ class DbrandCog(Extension): data = await self._session.get(api_link) if 200 <= data.status < 400: data = await data.json() - data["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta( - hours=24 - ) + data["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=24) self.cache[dest] = data else: data = None @@ -298,18 +278,12 @@ class DbrandCog(Extension): fields = [] for service in data["shipping_services_available"]: service_data = self.cache.get(f"{dest}-{service}") - if not service_data or service_data["cache_expiry"] < datetime.now( - tz=timezone.utc - ): - service_data = await self._session.get( - self.api_url + dest + "/" + service["url"] - ) + if not service_data or service_data["cache_expiry"] < datetime.now(tz=timezone.utc): + service_data = await self._session.get(self.api_url + dest + "/" + service["url"]) if service_data.status > 400: continue service_data = await service_data.json() - service_data["cache_expiry"] = datetime.now( - tz=timezone.utc - ) + timedelta(hours=24) + service_data["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=24) self.cache[f"{dest}-{service}"] = service_data title = f'{service_data["carrier"]} {service_data["tier-title"]} | {service_data["costs-min"]}' message = service_data["time-title"] @@ -320,9 +294,7 @@ class DbrandCog(Extension): status = self.cache.get("status") if not status or status["cache_expiry"] <= datetime.now(tz=timezone.utc): status = await parse_db_status() - status["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta( - hours=2 - ) + status["cache_expiry"] = datetime.now(tz=timezone.utc) + timedelta(hours=2) self.cache["status"] = status status = status["countries"] @@ -335,10 +307,10 @@ class DbrandCog(Extension): description = "" color = "#FFBB00" if shipping_info: - description = f'{shipping_info["Status"]}\u200b \u200b {shipping_info["Est. Delivery Time"].split(":")[0]}' - created = self.cache.get("status").get("cache_expiry") - timedelta( - hours=2 + description = ( + f'{shipping_info["Status"]}\u200b \u200b {shipping_info["Est. Delivery Time"].split(":")[0]}' ) + created = self.cache.get("status").get("cache_expiry") - timedelta(hours=2) ts = int(created.timestamp()) description += f" \u200b | \u200b Last updated: \n\u200b" if "green" in shipping_info["Status"]: @@ -367,8 +339,7 @@ class DbrandCog(Extension): embed = build_embed( title="Check Shipping Times", description=( - "Country not found.\nYou can [view all shipping " - "destinations here](https://dbrand.com/shipping)" + "Country not found.\nYou can [view all shipping " "destinations here](https://dbrand.com/shipping)" ), fields=[], url="https://dbrand.com/shipping", diff --git a/jarvis/cogs/unique/gl.py b/jarvis/cogs/unique/gl.py index 1595fa8..d9bf8db 100644 --- a/jarvis/cogs/unique/gl.py +++ b/jarvis/cogs/unique/gl.py @@ -1,4 +1,5 @@ """JARVIS GitLab Cog.""" + import asyncio import logging from datetime import datetime diff --git a/jarvis/config.py b/jarvis/config.py index 7705b51..aa2417a 100644 --- a/jarvis/config.py +++ b/jarvis/config.py @@ -51,13 +51,9 @@ class Config(BaseSettings, case_sensitive=False): log_level: str = "INFO" jurigged: bool = False - model_config = SettingsConfigDict( - env_file=".env", env_file_encoding="utf-8", env_nested_delimiter="." - ) + model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8", env_nested_delimiter=".") def load_config() -> Config: - """ - Load the config using the specified method first - """ + """Load the config.""" return Config() diff --git a/jarvis/const.py b/jarvis/const.py index 2b33135..270d979 100644 --- a/jarvis/const.py +++ b/jarvis/const.py @@ -1,5 +1,3 @@ """JARVIS constants.""" -from importlib.metadata import version as _v - __version__ = "2.5.4" diff --git a/jarvis/data/dbrand.py b/jarvis/data/dbrand.py index 3b93c0c..1acaac3 100644 --- a/jarvis/data/dbrand.py +++ b/jarvis/data/dbrand.py @@ -1,4 +1,5 @@ """dbrand-specific data.""" + shipping_lookup = [ {"country": "Afghanistan", "alpha-2": "AF", "alpha-3": "AFG", "numeric": "0004"}, {"country": "Aland Islands", "alpha-2": "AX", "alpha-3": "ALA", "numeric": "0248"}, diff --git a/jarvis/data/pigpen.py b/jarvis/data/pigpen.py index 272391f..4cfaea3 100644 --- a/jarvis/data/pigpen.py +++ b/jarvis/data/pigpen.py @@ -1,4 +1,5 @@ """Pigpen lookup.""" + lookup = { "a": "⌟", "b": "⊔", diff --git a/jarvis/data/robotcamo.py b/jarvis/data/robotcamo.py index 3577833..9f21ca8 100644 --- a/jarvis/data/robotcamo.py +++ b/jarvis/data/robotcamo.py @@ -1,4 +1,5 @@ """Robot Camo emote lookups.""" + emotes = { "A": 852317928572715038, "B": 852317954975727679, diff --git a/jarvis/data/unicode.py b/jarvis/data/unicode.py index ed0fba5..9f842a1 100644 --- a/jarvis/data/unicode.py +++ b/jarvis/data/unicode.py @@ -1,4 +1,5 @@ """Unicode emoji data.""" + import json from os import getcwd from os import sep as s diff --git a/jarvis/data/units.py b/jarvis/data/units.py index e452cf1..b19696c 100644 --- a/jarvis/data/units.py +++ b/jarvis/data/units.py @@ -3,39 +3,41 @@ Unit Converter utilities. Rates based on https://github.com/microsoft/calculator """ + from dataclasses import dataclass, field +from typing import ClassVar @dataclass class Converter: BASE: str = "sample" - CONVERSIONS: dict[str, int] = field(default_factory=dict) + CONVERSIONS: ClassVar[dict[str, float]] = field(default_factory=dict) @classmethod - def get_rate(cls, from_: str, to: str) -> int: + def get_rate(cls, from_: str, to: str) -> float: """ Get the conversion rate Args: from_: Convert from this to: Convert to this + """ if from_ == cls.BASE: return cls.CONVERSIONS.get(to, None) - else: - from_rate = cls.CONVERSIONS.get(from_) - to_rate = cls.CONVERSIONS.get(to) - return (1 / from_rate) * to_rate + from_rate = cls.CONVERSIONS.get(from_) + to_rate = cls.CONVERSIONS.get(to) + return (1 / from_rate) * to_rate class Angle(Converter): BASE = "degree" - CONVERSIONS = {"degree": 1, "radian": 57.29577951308233, "gradian": 0.9} + CONVERSIONS: ClassVar[dict[str, float]] = {"degree": 1, "radian": 57.29577951308233, "gradian": 0.9} class Area(Converter): BASE = "square meter" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "acre": 4046.8564224, "square meter": 1, "square foot": 0.09290304, @@ -56,7 +58,7 @@ class Area(Converter): class Data(Converter): BASE = "megabyte" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "bit": 0.000000125, "byte": 0.000001, "kilobyte": 0.001, @@ -99,7 +101,7 @@ class Data(Converter): class Energy(Converter): BASE = "joule" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "calorie": 4.184, "kilocalorie": 4184, "british thermal unit": 1055.056, @@ -115,7 +117,7 @@ class Energy(Converter): class Length(Converter): BASE = "meter" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "inch": 0.0254, "foot": 0.3048, "yard": 0.9144, @@ -135,7 +137,7 @@ class Length(Converter): class Power(Converter): BASE = "watt" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "british thermal unit per minute": 17.58426666666667, "foot pound per minute": 0.0225969658055233, "watt": 1, @@ -149,7 +151,7 @@ class Power(Converter): class Pressure(Converter): BASE = "atmosphere" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "atmosphere": 1, "bar": 0.9869232667160128, "kilopascal": 0.0098692326671601, @@ -161,7 +163,7 @@ class Pressure(Converter): class Speed(Converter): BASE = "centimeters per second" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "centimeters per second": 1, "feet per second": 30.48, "kilometers per hour": 27.777777777777777777778, @@ -177,7 +179,7 @@ class Speed(Converter): class Time(Converter): BASE = "second" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "day": 86400, "second": 1, "week": 604800, @@ -190,7 +192,7 @@ class Time(Converter): class Volume(Converter): BASE = "millileter" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "cup (US)": 236.588237, "pint (US)": 473.176473, "pint (UK)": 568.26125, @@ -219,7 +221,7 @@ class Volume(Converter): class Weight(Converter): BASE = "kilogram" - CONVERSIONS = { + CONVERSIONS: ClassVar[dict[str, float]] = { "kilogram": 1, "hectogram": 0.1, "decagram": 0.01, diff --git a/jarvis/embeds/admin.py b/jarvis/embeds/admin.py index 34e2bf0..cb4b1b7 100644 --- a/jarvis/embeds/admin.py +++ b/jarvis/embeds/admin.py @@ -1,4 +1,5 @@ """JARVIS bot-specific embeds.""" + from typing import Optional from interactions.models.discord.embed import Embed, EmbedField @@ -29,6 +30,7 @@ def ban_embed( guild: Guild to ban from duration: Optional temporary ban duration dm: If the embed should be a user embed + """ fields = [EmbedField(name="Reason", value=reason), EmbedField(name="Type", value=type)] if duration: @@ -64,6 +66,7 @@ def unban_embed(user: User, admin: User, reason: str) -> Embed: user: User to unban admin: Admin to execute unban reason: Reason for unban + """ fields = ( EmbedField(name="Reason", value=reason), @@ -92,6 +95,7 @@ def kick_embed(user: Member, admin: Member, reason: str, guild: Guild, dm: bool reason: Reason for kick guild: Guild to kick from dm: If the embed should be a user embed + """ fields = [ EmbedField(name="Reason", value="A valid reason"), @@ -129,6 +133,7 @@ def mute_embed(user: Member, admin: Member, reason: str, guild: Guild) -> Embed: user: User to mute admin: Admin to execute mute reason: Reason for mute + """ until = int(user.communication_disabled_until.timestamp()) fields = ( @@ -161,6 +166,7 @@ def unmute_embed(user: Member, admin: Member, reason: str, guild: Guild) -> Embe user: User to unmute admin: Admin to execute unmute reason: Reason for unmute + """ fields = ( EmbedField(name="Reason", value=reason), @@ -191,6 +197,7 @@ def warning_embed(user: Member, reason: str, admin: Member) -> Embed: user: User to warn reason: Warning reason admin: Admin who sent the warning + """ fields = ( EmbedField(name="Reason", value=reason, inline=False), diff --git a/jarvis/utils/__init__.py b/jarvis/utils/__init__.py index aa7aa5d..0cc129a 100644 --- a/jarvis/utils/__init__.py +++ b/jarvis/utils/__init__.py @@ -2,6 +2,7 @@ from datetime import datetime, timezone from pkgutil import iter_modules +from typing import Optional import pytz from beanie.operators import Set @@ -19,7 +20,7 @@ def build_embed( description: str, fields: list, color: str = PRIMARY_COLOR, - timestamp: datetime = None, + timestamp: Optional[datetime] = None, **kwargs: dict, ) -> Embed: """Embed builder utility function.""" @@ -42,8 +43,8 @@ def modlog_embed( admin: Member, title: str, desc: str, - log: AuditLogEntry = None, - reason: str = None, + log: Optional[AuditLogEntry] = None, + reason: Optional[str] = None, ) -> Embed: """Get modlog embed.""" fields = [ @@ -76,9 +77,7 @@ def get_extensions(path: str) -> list: async def cleanup_user(bot: Client, user_id: int): for model in models.all_models: if hasattr(model, "admin"): - await model.find(model.admin == user_id).update( - Set({model.admin: bot.user.id}) - ) + await model.find(model.admin == user_id).update(Set({model.admin: bot.user.id})) if hasattr(model, "user"): await model.find(model.user == user_id).delete() if hasattr(model, "creator"): diff --git a/jarvis/utils/cogs.py b/jarvis/utils/cogs.py index ae53619..cba891b 100644 --- a/jarvis/utils/cogs.py +++ b/jarvis/utils/cogs.py @@ -1,4 +1,5 @@ """Cog wrapper for command caching.""" + import logging from datetime import timedelta @@ -30,12 +31,13 @@ class ModcaseCog(Extension): self.logger = logging.getLogger(__name__) self.add_extension_postrun(self.log) - async def log(self, ctx: InteractionContext, *_args: list, **kwargs: dict) -> None: + async def log(self, ctx: InteractionContext, *_args: list, **kwargs: dict) -> None: # noqa: C901 """ Log a moderation activity in a moderation case. Args: ctx: Command context + """ name = self.__name__.replace("Cog", "") @@ -101,13 +103,9 @@ class ModcaseCog(Extension): ) if name == "Mute": mts = int(user.communication_disabled_until.timestamp()) - embed.add_field( - name="Muted Until", value=f" ()" - ) + embed.add_field(name="Muted Until", value=f" ()") guild_url = f"https://discord.com/channels/{ctx.guild.id}" - embed.set_author( - name=ctx.guild.name, icon_url=ctx.guild.icon.url, url=guild_url - ) + embed.set_author(name=ctx.guild.name, icon_url=ctx.guild.icon.url, url=guild_url) embed.set_thumbnail(url=ctx.guild.icon.url) try: await user.send(embeds=embed) @@ -126,9 +124,7 @@ class ModcaseCog(Extension): await modlog.save() return - modlog = await Setting.find_one( - Setting.guild == ctx.guild.id, Setting.setting == "modlog" - ) + modlog = await Setting.find_one(Setting.guild == ctx.guild.id, Setting.setting == "modlog") if not modlog: return @@ -148,31 +144,23 @@ class ModcaseCog(Extension): description=f"Admin action has been taken against {user.mention}", fields=fields, ) - embed.set_author( - name=f"{user.username}", icon_url=user.display_avatar.url - ) + embed.set_author(name=f"{user.username}", icon_url=user.display_avatar.url) embed.set_footer(text=f"User ID: {user.id}") if name == "Mute": mts = int(user.communication_disabled_until.timestamp()) - embed.add_field( - name="Muted Until", value=f" ()" - ) + embed.add_field(name="Muted Until", value=f" ()") await channel.send(embeds=embed) lookup_key = f"{user.id}|{ctx.guild.id}" async with self.bot.redis.lock("lock|" + lookup_key): if await self.bot.redis.get(lookup_key): - self.logger.debug( - f"User {user.id} in {ctx.guild.id} already has pending case" - ) + self.logger.debug(f"User {user.id} in {ctx.guild.id} already has pending case") return channel = await ctx.guild.fetch_channel(modlog.value) if not channel: - self.logger.warn( - f"Guild {ctx.guild.id} modlog channel no longer exists, deleting" - ) + self.logger.warn(f"Guild {ctx.guild.id} modlog channel no longer exists, deleting") await modlog.delete() return @@ -187,19 +175,11 @@ class ModcaseCog(Extension): embed.set_author(name=user.username, icon_url=avatar_url) components = [ ActionRow( - Button( - style=ButtonStyle.RED, emoji="✖️", custom_id="modcase|no" - ), - Button( - style=ButtonStyle.GREEN, emoji="✔️", custom_id="modcase|yes" - ), + Button(style=ButtonStyle.RED, emoji="✖️", custom_id="modcase|no"), + Button(style=ButtonStyle.GREEN, emoji="✔️", custom_id="modcase|yes"), ) ] message = await channel.send(embeds=embed, components=components) - await self.bot.redis.set( - lookup_key, f"{name.lower()}|{action.id}", ex=timedelta(days=7) - ) - await self.bot.redis.set( - f"msg|{message.id}", user.id, ex=timedelta(days=7) - ) + await self.bot.redis.set(lookup_key, f"{name.lower()}|{action.id}", ex=timedelta(days=7)) + await self.bot.redis.set(f"msg|{message.id}", user.id, ex=timedelta(days=7)) diff --git a/jarvis/utils/permissions.py b/jarvis/utils/permissions.py index bcf207f..12e5a6d 100644 --- a/jarvis/utils/permissions.py +++ b/jarvis/utils/permissions.py @@ -1,4 +1,5 @@ """Permissions wrappers.""" + from interactions import InteractionContext, Permissions @@ -6,7 +7,7 @@ def admin_or_permissions(*perms: list) -> bool: """Check if a user is an admin or has other perms.""" async def predicate(ctx: InteractionContext) -> bool: - """Extended check predicate.""" # noqa: D401 + """Extended check predicate.""" is_admin = ctx.author.has_permission(Permissions.ADMINISTRATOR) has_other = any(ctx.author.has_permission(perm) for perm in perms) return is_admin or has_other diff --git a/jarvis/utils/updates.py b/jarvis/utils/updates.py index 305e1e7..afaf825 100644 --- a/jarvis/utils/updates.py +++ b/jarvis/utils/updates.py @@ -1,5 +1,5 @@ """JARVIS update handler.""" -import logging + from dataclasses import dataclass from importlib import import_module from inspect import getmembers, isclass diff --git a/pyproject.toml b/pyproject.toml index b97fd4f..4945494 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -128,7 +128,8 @@ ignore = [ # ... function "D104", # ... package - + "E712", + # Ignore == True because of Beanie # Plugins we don't currently include: flake8-return "RET503", # missing explicit return at the end of function ableto return non-None value. diff --git a/run.py b/run.py index 0dcb1ed..14230ff 100755 --- a/run.py +++ b/run.py @@ -1,13 +1,12 @@ """Main run file for J.A.R.V.I.S.""" + import nest_asyncio nest_asyncio.apply() -import asyncio +import asyncio # noqa: E402 -import nest_asyncio - -from jarvis import run +from jarvis import run # noqa: E402 nest_asyncio.apply()