From e91b774ffff8b557fcb79046e5ec5297e19a2cdc Mon Sep 17 00:00:00 2001 From: Zevaryx Date: Sat, 26 Mar 2022 21:00:07 -0600 Subject: [PATCH] Use new slash command syntax --- jarvis/cogs/admin/ban.py | 7 +- jarvis/cogs/admin/lockdown.py | 9 +- jarvis/cogs/admin/roleping.py | 44 +++--- jarvis/cogs/autoreact.py | 13 +- jarvis/cogs/ctc2.py | 16 +- jarvis/cogs/dbrand.py | 134 ++++------------ jarvis/cogs/gl.py | 28 ++-- jarvis/cogs/remindme.py | 10 +- jarvis/cogs/rolegiver.py | 24 +-- jarvis/cogs/settings.py | 290 ++++++++++++++++------------------ jarvis/cogs/starboard.py | 25 ++- jarvis/cogs/twitter.py | 14 +- 12 files changed, 252 insertions(+), 362 deletions(-) diff --git a/jarvis/cogs/admin/ban.py b/jarvis/cogs/admin/ban.py index 0f18c7d..242c624 100644 --- a/jarvis/cogs/admin/ban.py +++ b/jarvis/cogs/admin/ban.py @@ -9,6 +9,7 @@ from dis_snek.models.discord.embed import EmbedField from dis_snek.models.discord.user import User from dis_snek.models.snek.application_commands import ( OptionTypes, + SlashCommand, SlashCommandChoice, slash_command, slash_option, @@ -290,9 +291,9 @@ class BanCog(ModcaseCog): ).save() await ctx.send("Unable to find user in Discord, but removed entry from database.") - @slash_command( - name="bans", description="User bans", sub_cmd_name="list", sub_cmd_description="List bans" - ) + bans = SlashCommand(name="bans", description="User bans") + + @bans.subcommand(sub_cmd_name="list", sub_cmd_description="List bans") @slash_option( name="btype", description="Ban type", diff --git a/jarvis/cogs/admin/lockdown.py b/jarvis/cogs/admin/lockdown.py index e55b39e..527bfa5 100644 --- a/jarvis/cogs/admin/lockdown.py +++ b/jarvis/cogs/admin/lockdown.py @@ -9,7 +9,7 @@ from dis_snek.models.discord.guild import Guild from dis_snek.models.discord.user import Member from dis_snek.models.snek.application_commands import ( OptionTypes, - slash_command, + SlashCommand, slash_option, ) from dis_snek.models.snek.command import check @@ -99,9 +99,12 @@ class LockdownCog(Scale): self.bot = bot self.logger = logging.getLogger(__name__) - @slash_command( + lockdown = SlashCommand( name="lockdown", description="Manage server-wide lockdown", + ) + + @lockdown.subcommand( sub_cmd_name="start", sub_cmd_description="Lockdown the server", ) @@ -148,7 +151,7 @@ class LockdownCog(Scale): ).commit() await ctx.send("Server now in lockdown.") - @slash_command(name="lockdown", sub_cmd_name="end", sub_cmd_description="End a lockdown") + @lockdown.subcommand(sub_cmd_name="end", sub_cmd_description="End a lockdown") @check(admin_or_permissions(Permissions.MANAGE_CHANNELS)) async def _lockdown_end( self, diff --git a/jarvis/cogs/admin/roleping.py b/jarvis/cogs/admin/roleping.py index 47c0291..e1cb6d7 100644 --- a/jarvis/cogs/admin/roleping.py +++ b/jarvis/cogs/admin/roleping.py @@ -9,7 +9,7 @@ from dis_snek.models.discord.role import Role from dis_snek.models.discord.user import Member from dis_snek.models.snek.application_commands import ( OptionTypes, - slash_command, + SlashCommand, slash_option, ) from dis_snek.models.snek.command import check @@ -27,9 +27,11 @@ class RolepingCog(Scale): self.bot = bot self.logger = logging.getLogger(__name__) - @slash_command( - name="roleping", - description="Set up warnings for pinging specific roles", + roleping = SlashCommand( + name="roleping", description="Set up warnings for pinging specific roles" + ) + + @roleping.subcommand( sub_cmd_name="add", sub_cmd_description="Add a role to roleping", ) @@ -50,7 +52,7 @@ class RolepingCog(Scale): ).commit() await ctx.send(f"Role `{role.name}` added to roleping.") - @slash_command(name="roleping", sub_cmd_name="remove", sub_cmd_description="Remove a role") + @roleping.subcommand(sub_cmd_name="remove", sub_cmd_description="Remove a role") @slash_option( name="role", description="Role to remove", opt_type=OptionTypes.ROLE, required=True ) @@ -64,7 +66,7 @@ class RolepingCog(Scale): await roleping.delete() await ctx.send(f"Role `{role.name}` removed from roleping.") - @slash_command(name="roleping", sub_cmd_name="list", description="Lick all blocklisted roles") + @roleping.subcommand(sub_cmd_name="list", sub_cmd_description="Lick all blocklisted roles") async def _roleping_list(self, ctx: InteractionContext) -> None: rolepings = await Roleping.find(q(guild=ctx.guild.id)).to_list(None) @@ -123,11 +125,11 @@ class RolepingCog(Scale): await paginator.send(ctx) - @slash_command( - name="roleping", - description="Block roles from being pinged", - group_name="bypass", - group_description="Allow specific users/roles to ping rolepings", + bypass = roleping.group( + name="bypass", description="Allow specific users/roles to ping rolepings" + ) + + @bypass.subcommand( sub_cmd_name="user", sub_cmd_description="Add a user as a bypass to a roleping", ) @@ -170,11 +172,9 @@ class RolepingCog(Scale): await roleping.commit() await ctx.send(f"{bypass.display_name} user bypass added for `{role.name}`") - @slash_command( - name="roleping", - group_name="bypass", + @bypass.subcommand( sub_cmd_name="role", - description="Add a role as a bypass to roleping", + sub_cmd_description="Add a role as a bypass to roleping", ) @slash_option( name="bypass", description="Role to add", opt_type=OptionTypes.ROLE, required=True @@ -207,11 +207,9 @@ class RolepingCog(Scale): await roleping.commit() await ctx.send(f"{bypass.name} role bypass added for `{role.name}`") - @slash_command( - name="roleping", - description="Block roles from being pinged", - group_name="restore", - group_description="Remove a roleping bypass", + restore = roleping.group(name="restore", description="Remove a roleping bypass") + + @restore.subcommand( sub_cmd_name="user", sub_cmd_description="Remove a bypass from a roleping (restoring it)", ) @@ -238,11 +236,9 @@ class RolepingCog(Scale): await roleping.commit() await ctx.send(f"{bypass.display_name} user bypass removed for `{role.name}`") - @slash_command( - name="roleping", - group_name="restore", + @restore.subcommand( sub_cmd_name="role", - description="Remove a bypass from a roleping (restoring it)", + sub_cmd_description="Remove a bypass from a roleping (restoring it)", ) @slash_option( name="bypass", description="Role to remove", opt_type=OptionTypes.ROLE, required=True diff --git a/jarvis/cogs/autoreact.py b/jarvis/cogs/autoreact.py index 40a5012..9d421f2 100644 --- a/jarvis/cogs/autoreact.py +++ b/jarvis/cogs/autoreact.py @@ -8,7 +8,7 @@ from dis_snek.client.utils.misc_utils import find from dis_snek.models.discord.channel import GuildText from dis_snek.models.snek.application_commands import ( OptionTypes, - slash_command, + SlashCommand, slash_option, ) from dis_snek.models.snek.command import check @@ -72,8 +72,9 @@ class AutoReactCog(Scale): return True return False - @slash_command( - name="autoreact", + autoreact = SlashCommand(name="autoreact", description="Channel message autoreacts") + + @autoreact.subcommand( sub_cmd_name="add", sub_cmd_description="Add an autoreact emote to a channel", ) @@ -134,8 +135,7 @@ class AutoReactCog(Scale): message += f" Set autoreact thread creation to {thread} in {channel.mention}" await ctx.send(message) - @slash_command( - name="autoreact", + @autoreact.subcommand( sub_cmd_name="remove", sub_cmd_description="Remove an autoreact emote to a channel", ) @@ -178,8 +178,7 @@ class AutoReactCog(Scale): await self.delete_autoreact(ctx, channel) await ctx.send(f"Removed {emote} from {channel.mention} autoreact.") - @slash_command( - name="autoreact", + @autoreact.subcommand( sub_cmd_name="list", sub_cmd_description="List all autoreacts on a channel", ) diff --git a/jarvis/cogs/ctc2.py b/jarvis/cogs/ctc2.py index 8d4e71b..31658a9 100644 --- a/jarvis/cogs/ctc2.py +++ b/jarvis/cogs/ctc2.py @@ -7,7 +7,7 @@ from dis_snek import InteractionContext, Scale, Snake from dis_snek.ext.paginators import Paginator from dis_snek.models.discord.embed import EmbedField from dis_snek.models.discord.user import Member, User -from dis_snek.models.snek.application_commands import slash_command +from dis_snek.models.snek.application_commands import SlashCommand from dis_snek.models.snek.command import cooldown from dis_snek.models.snek.cooldowns import Buckets from jarvis_core.db import q @@ -36,18 +36,16 @@ class CTCCog(Scale): def __del__(self): self._session.close() - @slash_command( - name="ctc2", sub_cmd_name="about", description="CTC2 related commands", scopes=guild_ids - ) + ctc2 = SlashCommand(name="ctc2", description="CTC2 related commands", scopres=guild_ids) + + @ctc2.subcommand(sub_cmd_name="about") @cooldown(bucket=Buckets.USER, rate=1, interval=30) async def _about(self, ctx: InteractionContext) -> None: await ctx.send("See https://completethecode.com for more information") - @slash_command( - name="ctc2", + @ctc2.subcommand( sub_cmd_name="pw", sub_cmd_description="Guess a password for https://completethecodetwo.cards", - scopes=guild_ids, ) @cooldown(bucket=Buckets.USER, rate=1, interval=2) async def _pw(self, ctx: InteractionContext, guess: str) -> None: @@ -89,11 +87,9 @@ class CTCCog(Scale): await ctx.send("Nope.", ephemeral=True) _ = Guess(guess=guess, user=ctx.author.id, correct=correct).save() - @slash_command( - name="ctc2", + @ctc2.subcommand( sub_cmd_name="guesses", sub_cmd_description="Show guesses made for https://completethecodetwo.cards", - scopes=guild_ids, ) @cooldown(bucket=Buckets.USER, rate=1, interval=2) async def _guesses(self, ctx: InteractionContext) -> None: diff --git a/jarvis/cogs/dbrand.py b/jarvis/cogs/dbrand.py index 761ff12..5cea582 100644 --- a/jarvis/cogs/dbrand.py +++ b/jarvis/cogs/dbrand.py @@ -7,7 +7,7 @@ from dis_snek import InteractionContext, Scale, Snake from dis_snek.models.discord.embed import EmbedField from dis_snek.models.snek.application_commands import ( OptionTypes, - slash_command, + SlashCommand, slash_option, ) from dis_snek.models.snek.command import cooldown @@ -17,7 +17,7 @@ from jarvis.config import get_config from jarvis.data.dbrand import shipping_lookup from jarvis.utils import build_embed -guild_ids = [578757004059738142, 520021794380447745, 862402786116763668] +guild_ids = [862402786116763668] # [578757004059738142, 520021794380447745, 862402786116763668] class DbrandCog(Scale): @@ -39,121 +39,53 @@ class DbrandCog(Scale): def __del__(self): self._session.close() - @slash_command( - name="db", - sub_cmd_name="skin", - scopes=guild_ids, - sub_cmd_description="See what skins are available", - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _skin(self, ctx: InteractionContext) -> None: - await ctx.send(self.base_url + "/skins") + db = SlashCommand(name="db", description="dbrand commands", scopes=guild_ids) - @slash_command( - name="db", - sub_cmd_name="robotcamo", - scopes=guild_ids, - sub_cmd_description="Get some robot camo. Make Tony Stark proud", - ) + @db.subcommand(sub_cmd_name="info", sub_cmd_description="Get useful links") @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _camo(self, ctx: InteractionContext) -> None: - await ctx.send(self.base_url + "robot-camo") + async def _info(self, ctx: InteractionContext) -> None: + urls = [ + f"[Get Skins]({self.base_url + 'skins'})", + f"[Robot Camo]({self.base_url + 'robot-camo'})", + f"[Get a Grip]({self.base_url + 'grip'})", + f"[Shop All Products]({self.base_url + 'shop'})", + f"[Order Status]({self.base_url + 'order-status'})", + f"[dbrand Status]({self.base_url + 'status'})", + f"[Be (not) extorted]({self.base_url + 'not-extortion'})", + "[Robot Camo Wallpapers](https://db.io/wallpapers)", + ] + embed = build_embed( + title="Useful Links", description="\n\n".join(urls), fields=[], color="#FFBB00" + ) + embed.set_footer( + text="dbrand.com", + icon_url="https://dev.zevaryx.com/db_logo.png", + ) + embed.set_thumbnail(url="https://dev.zevaryx.com/db_logo.png") + embed.set_author( + name="dbrand", url=self.base_url, icon_url="https://dev.zevaryx.com/db_logo.png" + ) + await ctx.send(embed=embed) - @slash_command( - name="db", - sub_cmd_name="grip", - scopes=guild_ids, - sub_cmd_description="See devices with Grip support", - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _grip(self, ctx: InteractionContext) -> None: - await ctx.send(self.base_url + "grip") - - @slash_command( - name="db", + @db.subcommand( sub_cmd_name="contact", - scopes=guild_ids, sub_cmd_description="Contact support", ) @cooldown(bucket=Buckets.USER, rate=1, interval=30) async def _contact(self, ctx: InteractionContext) -> None: await ctx.send("Contact dbrand support here: " + self.base_url + "contact") - @slash_command( - name="db", + @db.subcommand( sub_cmd_name="support", - scopes=guild_ids, sub_cmd_description="Contact support", ) @cooldown(bucket=Buckets.USER, rate=1, interval=30) async def _support(self, ctx: InteractionContext) -> None: await ctx.send("Contact dbrand support here: " + self.base_url + "contact") - @slash_command( - name="db", - sub_cmd_name="orderstat", - scopes=guild_ids, - sub_cmd_description="Get your order status", - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _orderstat(self, ctx: InteractionContext) -> None: - await ctx.send(self.base_url + "order-status") - - @slash_command( - name="db", - sub_cmd_name="orders", - scopes=guild_ids, - sub_cmd_description="Get your order status", - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _orders(self, ctx: InteractionContext) -> None: - await ctx.send(self.base_url + "order-status") - - @slash_command( - name="db", - sub_cmd_name="status", - scopes=guild_ids, - sub_cmd_description="dbrand status", - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _status(self, ctx: InteractionContext) -> None: - await ctx.send(self.base_url + "status") - - @slash_command( - name="db", - sub_cmd_name="buy", - scopes=guild_ids, - sub_cmd_description="Give us your money!", - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _buy(self, ctx: InteractionContext) -> None: - await ctx.send("Give us your money! " + self.base_url + "shop") - - @slash_command( - name="db", - sub_cmd_name="extortion", - scopes=guild_ids, - sub_cmd_description="(not) extortion", - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _extort(self, ctx: InteractionContext) -> None: - await ctx.send("Be (not) extorted here: " + self.base_url + "not-extortion") - - @slash_command( - name="db", - sub_cmd_name="wallpapers", - sub_cmd_description="Robot Camo Wallpapers", - scopes=guild_ids, - ) - @cooldown(bucket=Buckets.USER, rate=1, interval=30) - async def _wallpapers(self, ctx: InteractionContext) -> None: - await ctx.send("Get robot camo wallpapers here: https://db.io/wallpapers") - - @slash_command( - name="db", + @db.subcommand( sub_cmd_name="ship", sub_cmd_description="Get shipping information for your country", - scopes=guild_ids, ) @slash_option( name="search", @@ -217,7 +149,7 @@ class DbrandCog(Scale): ) embed = build_embed( title="Shipping to {}".format(data["country"]), - sub_cmd_description=description, + description=description, color="#FFBB00", fields=fields, url=self.base_url + "shipping/" + country, @@ -231,7 +163,7 @@ class DbrandCog(Scale): elif not data["is_valid"]: embed = build_embed( title="Check Shipping Times", - sub_cmd_description=( + description=( "Country not found.\nYou can [view all shipping " "destinations here](https://dbrand.com/shipping)" ), @@ -248,7 +180,7 @@ class DbrandCog(Scale): elif not data["shipping_available"]: embed = build_embed( title="Shipping to {}".format(data["country"]), - sub_cmd_description=( + description=( "No shipping available.\nTime to move to a country" " that has shipping available.\nYou can [find a new country " "to live in here](https://dbrand.com/shipping)" diff --git a/jarvis/cogs/gl.py b/jarvis/cogs/gl.py index 6bb92d0..80c6a31 100644 --- a/jarvis/cogs/gl.py +++ b/jarvis/cogs/gl.py @@ -11,6 +11,7 @@ from dis_snek.models.discord.modal import InputText, Modal, TextStyles from dis_snek.models.discord.user import Member from dis_snek.models.snek.application_commands import ( OptionTypes, + SlashCommand, SlashCommandChoice, slash_command, slash_option, @@ -35,12 +36,11 @@ class GitlabCog(Scale): # J.A.R.V.I.S. GitLab ID is 29 self.project = self._gitlab.projects.get(29) - @slash_command( - name="gl", - description="Get GitLab info", + gl = SlashCommand(name="gl", description="Get GitLab info", scopes=guild_ids) + + @gl.subcommand( sub_cmd_name="issue", sub_cmd_description="Get an issue from GitLab", - scopes=guild_ids, ) @slash_option(name="id", description="Issue ID", opt_type=OptionTypes.INTEGER, required=True) async def _issue(self, ctx: InteractionContext, id: int) -> None: @@ -104,11 +104,9 @@ class GitlabCog(Scale): ) await ctx.send(embed=embed) - @slash_command( - name="gl", + @gl.subcommand( sub_cmd_name="milestone", sub_cmd_description="Get a milestone from GitLab", - scopes=guild_ids, ) @slash_option( name="id", description="Milestone ID", opt_type=OptionTypes.INTEGER, required=True @@ -160,11 +158,9 @@ class GitlabCog(Scale): ) await ctx.send(embed=embed) - @slash_command( - name="gl", + @gl.subcommand( sub_cmd_name="mr", sub_cmd_description="Get a merge request from GitLab", - scopes=guild_ids, ) @slash_option( name="id", description="Merge Request ID", opt_type=OptionTypes.INTEGER, required=True @@ -272,11 +268,9 @@ class GitlabCog(Scale): ) return embed - @slash_command( - name="gl", + @gl.subcommand( sub_cmd_name="issues", sub_cmd_description="Get issues from GitLab", - scopes=guild_ids, ) @slash_option( name="state", @@ -328,11 +322,9 @@ class GitlabCog(Scale): await paginator.send(ctx) - @slash_command( - name="gl", + @gl.subcommand( sub_cmd_name="mrs", sub_cmd_description="Get merge requests from GitLab", - scopes=guild_ids, ) @slash_option( name="state", @@ -386,11 +378,9 @@ class GitlabCog(Scale): await paginator.send(ctx) - @slash_command( - name="gl", + @gl.subcommand( sub_cmd_name="milestones", sub_cmd_description="Get milestones from GitLab", - scopes=guild_ids, ) async def _milestones(self, ctx: InteractionContext) -> None: await ctx.defer() diff --git a/jarvis/cogs/remindme.py b/jarvis/cogs/remindme.py index b03271b..cc7ea52 100644 --- a/jarvis/cogs/remindme.py +++ b/jarvis/cogs/remindme.py @@ -16,6 +16,7 @@ from dis_snek.models.discord.embed import Embed, EmbedField from dis_snek.models.discord.modal import InputText, Modal, TextStyles from dis_snek.models.snek.application_commands import ( OptionTypes, + SlashCommand, slash_command, slash_option, ) @@ -205,7 +206,9 @@ class RemindmeCog(Scale): return embed - @slash_command(name="reminders", sub_cmd_name="list", sub_cmd_description="List reminders") + reminders = SlashCommand(name="reminders", description="Manage reminders") + + @reminders.subcommand(sub_cmd_name="list", sub_cmd_description="List reminders") async def _list(self, ctx: InteractionContext) -> None: reminders = await Reminder.find(q(user=ctx.author.id, active=True)).to_list(None) if not reminders: @@ -216,7 +219,7 @@ class RemindmeCog(Scale): await ctx.send(embed=embed) - @slash_command(name="reminders", sub_cmd_name="delete", sub_cmd_description="Delete a reminder") + @reminders.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a reminder") async def _delete(self, ctx: InteractionContext) -> None: reminders = await Reminder.find(q(user=ctx.author.id, active=True)).to_list(None) if not reminders: @@ -303,8 +306,7 @@ class RemindmeCog(Scale): component.disabled = True await message.edit(components=components) - @slash_command( - name="reminders", + @reminders.subcommand( sub_cmd_name="fetch", sub_cmd_description="Fetch a reminder that failed to send", ) diff --git a/jarvis/cogs/rolegiver.py b/jarvis/cogs/rolegiver.py index 7269f3d..6ab9abe 100644 --- a/jarvis/cogs/rolegiver.py +++ b/jarvis/cogs/rolegiver.py @@ -9,7 +9,7 @@ from dis_snek.models.discord.embed import EmbedField from dis_snek.models.discord.role import Role from dis_snek.models.snek.application_commands import ( OptionTypes, - slash_command, + SlashCommand, slash_option, ) from dis_snek.models.snek.command import check, cooldown @@ -28,9 +28,9 @@ class RolegiverCog(Scale): self.bot = bot self.logger = logging.getLogger(__name__) - @slash_command( - name="rolegiver", - description="Allow users to choose their own roles", + rolegiver = SlashCommand(name="rolegiver", description="Allow users to choose their own roles") + + @rolegiver.subcommand( sub_cmd_name="add", sub_cmd_description="Add a role to rolegiver", ) @@ -82,9 +82,7 @@ class RolegiverCog(Scale): await ctx.send(embed=embed) - @slash_command( - name="rolegiver", 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") @check(admin_or_permissions(Permissions.MANAGE_GUILD)) async def _rolegiver_remove(self, ctx: InteractionContext) -> None: setting = await Rolegiver.find_one(q(guild=ctx.guild.id)) @@ -167,7 +165,7 @@ class RolegiverCog(Scale): component.disabled = True await message.edit(components=components) - @slash_command(name="rolegiver", sub_cmd_name="list", description="List rolegiver roles") + @rolegiver.subcommand(sub_cmd_name="list", description="List rolegiver roles") async def _rolegiver_list(self, ctx: InteractionContext) -> None: setting = await Rolegiver.find_one(q(guild=ctx.guild.id)) if not setting or (setting and not setting.roles): @@ -202,7 +200,9 @@ class RolegiverCog(Scale): await ctx.send(embed=embed) - @slash_command(name="role", sub_cmd_name="get", sub_cmd_description="Get a role") + role = SlashCommand(name="role", description="Get/Remove Rolegiver roles") + + @role.subcommand(sub_cmd_name="get", sub_cmd_description="Get a role") @cooldown(bucket=Buckets.USER, rate=1, interval=10) async def _role_get(self, ctx: InteractionContext) -> None: setting = await Rolegiver.find_one(q(guild=ctx.guild.id)) @@ -278,7 +278,7 @@ class RolegiverCog(Scale): component.disabled = True await message.edit(components=components) - @slash_command(name="role", sub_cmd_name="remove", sub_cmd_description="Remove a role") + @role.subcommand(sub_cmd_name="remove", sub_cmd_description="Remove a role") @cooldown(bucket=Buckets.USER, rate=1, interval=10) async def _role_remove(self, ctx: InteractionContext) -> None: user_roles = ctx.author.roles @@ -357,8 +357,8 @@ class RolegiverCog(Scale): component.disabled = True await message.edit(components=components) - @slash_command( - name="rolegiver", sub_cmd_name="cleanup", description="Removed deleted roles from rolegiver" + @rolegiver.subcommand( + sub_cmd_name="cleanup", description="Removed deleted roles from rolegiver" ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) async def _rolegiver_cleanup(self, ctx: InteractionContext) -> None: diff --git a/jarvis/cogs/settings.py b/jarvis/cogs/settings.py index 29afb7d..88cb3c5 100644 --- a/jarvis/cogs/settings.py +++ b/jarvis/cogs/settings.py @@ -4,22 +4,19 @@ from typing import Any from dis_snek import InteractionContext, Scale, Snake from dis_snek.models.discord.channel import GuildText +from dis_snek.models.discord.embed import EmbedField from dis_snek.models.discord.enums import Permissions +from dis_snek.models.discord.role import Role from dis_snek.models.snek.application_commands import ( OptionTypes, - slash_command, + SlashCommand, slash_option, ) from dis_snek.models.snek.command import check -from discord import Role, TextChannel -from discord.utils import find -from discord_slash import SlashContext, cog_ext -from discord_slash.utils.manage_commands import create_option from jarvis_core.db import q +from jarvis_core.db.models import Setting -from jarvis.db.models import Setting from jarvis.utils import build_embed -from jarvis.utils.field import Field from jarvis.utils.permissions import admin_or_permissions @@ -47,199 +44,175 @@ class SettingsCog(Scale): return await existing.delete() return False - @slash_command( - name="settings", - description="Control bot settings", + settings = SlashCommand(name="settings", description="Control guild settings") + set_ = settings.group(name="set", description="Set a setting") + unset = settings.group(name="unset", description="Unset a setting") + + @set_.subcommand( sub_cmd_name="modlog", - sub_cmd_description="Set ActivityLog channel", + sub_cmd_description="Set Moglod channel", ) @slash_option( name="channel", description="ModLog Channel", opt_type=OptionTypes.CHANNEL, required=True ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) - async def _set_modlog(self, ctx: InteractionContext(), channel: GuildText) -> None: + async def _set_modlog(self, ctx: InteractionContext, channel: GuildText) -> None: if not isinstance(channel, GuildText): await ctx.send("Channel must be a GuildText", ephemeral=True) return - self.update_settings("modlog", channel.id, ctx.guild.id) + await self.update_settings("modlog", channel.id, ctx.guild.id) await ctx.send(f"Settings applied. New modlog channel is {channel.mention}") - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="set", - name="activitylog", - description="Set activitylog channel", - choices=[ - create_option( - name="channel", - description="Activitylog channel", - opt_type=7, - required=True, - ) - ], + @set_.subcommand( + sub_cmd_name="activitylog", + sub_cmd_description="Set Activitylog channel", + ) + @slash_option( + name="channel", + description="Activitylog Channel", + opt_type=OptionTypes.CHANNEL, + required=True, ) @check(admin_or_permissions(Permissions.MANAGE_GUILD)) - async def _set_activitylog(self, ctx: SlashContext, channel: TextChannel) -> None: - if not isinstance(channel, TextChannel): - await ctx.send("Channel must be a TextChannel", ephemeral=True) + async def _set_activitylog(self, ctx: InteractionContext, channel: GuildText) -> None: + if not isinstance(channel, GuildText): + await ctx.send("Channel must be a GuildText", ephemeral=True) return - self.update_settings("activitylog", channel.id, ctx.guild.id) + await self.update_settings("activitylog", channel.id, ctx.guild.id) await ctx.send(f"Settings applied. New activitylog channel is {channel.mention}") - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="set", - name="massmention", - description="Set massmention amount", - choices=[ - create_option( - name="amount", - description="Amount of mentions (0 to disable)", - opt_type=4, - required=True, - ) - ], + @set_.subcommand(sub_cmd_name="massmention", sub_cmd_description="Set massmention output") + @slash_option( + name="amount", + description="Amount of mentions (0 to disable)", + opt_type=OptionTypes.INTEGER, + required=True, ) - @check(admin_or_permissions(manage_guild=True)) - async def _set_massmention(self, ctx: SlashContext, amount: int) -> None: + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _set_massmention(self, ctx: InteractionContext, amount: int) -> None: await ctx.defer() - self.update_settings("massmention", amount, ctx.guild.id) + await self.update_settings("massmention", amount, ctx.guild.id) await ctx.send(f"Settings applied. New massmention limit is {amount}") - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="set", - name="verified", - description="Set verified role", - choices=[ - create_option( - name="role", - description="verified role", - opt_type=8, - required=True, - ) - ], + @set_.subcommand(sub_cmd_name="verified", sub_cmd_description="Set verified role") + @slash_option( + name="role", description="Verified role", opt_type=OptionTypes.ROLE, required=True ) - @check(admin_or_permissions(manage_guild=True)) - async def _set_verified(self, ctx: SlashContext, role: Role) -> None: + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _set_verified(self, ctx: InteractionContext, role: Role) -> None: await ctx.defer() - self.update_settings("verified", role.id, ctx.guild.id) + await self.update_settings("verified", role.id, ctx.guild.id) await ctx.send(f"Settings applied. New verified role is `{role.name}`") - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="set", - name="unverified", - description="Set unverified role", - choices=[ - create_option( - name="role", - description="Unverified role", - opt_type=8, - required=True, - ) - ], + @set_.subcommand(sub_cmd_name="unverified", sub_cmd_description="Set unverified role") + @slash_option( + name="role", description="Unverified role", opt_type=OptionTypes.ROLE, required=True ) - @check(admin_or_permissions(manage_guild=True)) - async def _set_unverified(self, ctx: SlashContext, role: Role) -> None: + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _set_unverified(self, ctx: InteractionContext, role: Role) -> None: await ctx.defer() - self.update_settings("unverified", role.id, ctx.guild.id) + await self.update_settings("unverified", role.id, ctx.guild.id) await ctx.send(f"Settings applied. New unverified role is `{role.name}`") - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="set", - name="noinvite", - description="Set if invite deletion should happen", - choices=[ - create_option( - name="active", - description="Active?", - opt_type=OptionTypes.BOOLEAN, - required=True, - ) - ], + @set_.subcommand( + sub_cmd_name="noinvite", sub_cmd_description="Set if invite deletion should happen" ) - @check(admin_or_permissions(manage_guild=True)) - async def _set_invitedel(self, ctx: SlashContext, active: bool) -> None: + @slash_option(name="active", description="Active?", opt_type=OptionTypes.BOOLEAN, required=True) + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _set_invitedel(self, ctx: InteractionContext, active: bool) -> None: await ctx.defer() - self.update_settings("noinvite", active, ctx.guild.id) + await self.update_settings("noinvite", active, ctx.guild.id) await ctx.send(f"Settings applied. Automatic invite active: {active}") - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="unset", - name="modlog", - description="Unset modlog channel", + # Unset + @unset.subcommand( + sub_cmd_name="modlog", + sub_cmd_description="Set Moglod channel", ) - @check(admin_or_permissions(manage_guild=True)) - async def _unset_modlog(self, ctx: SlashContext) -> None: - self.delete_settings("modlog", ctx.guild.id) - await ctx.send("Setting removed.") - - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="unset", - name="activitylog", - description="Unset activitylog channel", + @slash_option( + name="channel", description="ModLog Channel", opt_type=OptionTypes.CHANNEL, required=True ) - @check(admin_or_permissions(manage_guild=True)) - async def _unset_activitylog(self, ctx: SlashContext) -> None: - self.delete_settings("activitylog", ctx.guild.id) - await ctx.send("Setting removed.") - - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="unset", - name="massmention", - description="Unet massmention amount", - ) - @check(admin_or_permissions(manage_guild=True)) - async def _massmention(self, ctx: SlashContext) -> None: + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _unset_modlog(self, ctx: InteractionContext, channel: GuildText) -> None: await ctx.defer() - self.delete_settings("massmention", ctx.guild.id) - await ctx.send("Setting removed.") + await self.delete_settings("modlog", channel.id, ctx.guild.id) + await ctx.send(f"Setting `{channel.mention}` unset") - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="unset", - name="verified", - description="Unset verified role", + @unset.subcommand( + sub_cmd_name="activitylog", + sub_cmd_description="Set Activitylog channel", ) - @check(admin_or_permissions(manage_guild=True)) - async def _verified(self, ctx: SlashContext) -> None: - await ctx.defer() - self.delete_settings("verified", ctx.guild.id) - await ctx.send("Setting removed.") - - @cog_ext.cog_subcommand( - base="settings", - subcommand_group="unset", - name="unverified", - description="Unset unverified role", + @slash_option( + name="channel", + description="Activitylog Channel", + opt_type=OptionTypes.CHANNEL, + required=True, ) - @check(admin_or_permissions(manage_guild=True)) - async def _unverified(self, ctx: SlashContext) -> None: + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _unset_activitylog(self, ctx: InteractionContext, channel: GuildText) -> None: await ctx.defer() - self.delete_settings("unverified", ctx.guild.id) - await ctx.send("Setting removed.") + await self.delete_settings("activitylog", channel.id, ctx.guild.id) + await ctx.send(f"Setting `{channel.mention}` unset") - @cog_ext.cog_subcommand(base="settings", name="view", description="View settings") - @check(admin_or_permissions(manage_guild=True)) - async def _view(self, ctx: SlashContext) -> None: - settings = Setting.objects(guild=ctx.guild.id) + @unset.subcommand(sub_cmd_name="massmention", sub_cmd_description="Set massmention output") + @slash_option( + name="amount", + description="Amount of mentions (0 to disable)", + opt_type=OptionTypes.INTEGER, + required=True, + ) + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _unset_massmention(self, ctx: InteractionContext, amount: int) -> None: + await ctx.defer() + await self.delete_settings("massmention") + await ctx.send(f"Setting `{amount}` unset") + + @unset.subcommand(sub_cmd_name="verified", sub_cmd_description="Set verified role") + @slash_option( + name="role", description="Verified role", opt_type=OptionTypes.ROLE, required=True + ) + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _unset_verified(self, ctx: InteractionContext, role: Role) -> None: + await ctx.defer() + await self.delete_settings("verified") + await ctx.send(f"Setting `{role.name} unset`") + + @unset.subcommand(sub_cmd_name="unverified", sub_cmd_description="Set unverified role") + @slash_option( + name="role", description="Unverified role", opt_type=OptionTypes.ROLE, required=True + ) + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _unset_unverified(self, ctx: InteractionContext, role: Role) -> None: + await ctx.defer() + await self.delete_settings("unverified") + await ctx.send(f"Setting `{role.name}` unset") + + @unset.subcommand( + sub_cmd_name="noinvite", sub_cmd_description="Set if invite deletion should happen" + ) + @slash_option(name="active", description="Active?", opt_type=OptionTypes.BOOLEAN, required=True) + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _unset_invitedel(self, ctx: InteractionContext, active: bool) -> None: + await ctx.defer() + await self.delete_settings("noinvite") + await ctx.send(f"Setting `{active}` unset") + + @settings.subcommand(sub_cmd_name="view", sub_cmd_description="View settings") + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _view(self, ctx: InteractionContext) -> None: + settings = Setting.find(q(guild=ctx.guild.id)) fields = [] - for setting in settings: + async for setting in settings: value = setting.value if setting.setting in ["unverified", "verified", "mute"]: - value = find(lambda x: x.id == value, ctx.guild.roles) + value = await ctx.guild.fetch_role(value) if value: value = value.mention else: value = "||`[redacted]`||" elif setting.setting in ["activitylog", "modlog"]: - value = find(lambda x: x.id == value, ctx.guild.text_channels) + value = await ctx.guild.fetch_channel(value) if value: value = value.mention else: @@ -247,22 +220,23 @@ class SettingsCog(Scale): elif setting.setting == "rolegiver": value = "" for _role in setting.value: - nvalue = find(lambda x: x.id == value, ctx.guild.roles) + nvalue = await ctx.guild.fetch_role(value) if value: value += "\n" + nvalue.mention else: value += "\n||`[redacted]`||" - fields.append(Field(name=setting.setting, value=value or "N/A")) + fields.append(EmbedField(name=setting.setting, value=value or "N/A", inlilne=False)) embed = build_embed(title="Current Settings", description="", fields=fields) await ctx.send(embed=embed) - @cog_ext.cog_subcommand(base="settings", name="clear", description="Clear all settings") - @check(admin_or_permissions(manage_guild=True)) - async def _clear(self, ctx: SlashContext) -> None: - deleted = Setting.objects(guild=ctx.guild.id).delete() - await ctx.send(f"Guild settings cleared: `{deleted is not None}`") + @settings.subcommand(sub_cmd_name="clear", sub_cmd_description="Clear all settings") + @check(admin_or_permissions(Permissions.MANAGE_GUILD)) + async def _clear(self, ctx: InteractionContext) -> None: + async for setting in Setting.find(q(guild=ctx.guild.id)): + await setting.delete() + await ctx.send("Guild settings cleared") def setup(bot: Snake) -> None: diff --git a/jarvis/cogs/starboard.py b/jarvis/cogs/starboard.py index b74afb4..b0bfccf 100644 --- a/jarvis/cogs/starboard.py +++ b/jarvis/cogs/starboard.py @@ -9,8 +9,8 @@ from dis_snek.models.discord.message import Message from dis_snek.models.snek.application_commands import ( CommandTypes, OptionTypes, + SlashCommand, context_menu, - slash_command, slash_option, ) from dis_snek.models.snek.command import check @@ -36,9 +36,9 @@ class StarboardCog(Scale): self.bot = bot self.logger = logging.getLogger(__name__) - @slash_command( - name="starboard", - description="Extra pins! Manage starboards", + starboard = SlashCommand(name="starboard", description="Extra pins! Manage starboards") + + @starboard.subcommand( sub_cmd_name="list", sub_cmd_description="List all starboards", ) @@ -53,9 +53,7 @@ class StarboardCog(Scale): else: await ctx.send("No Starboards available.") - @slash_command( - name="starboard", sub_cmd_name="create", sub_cmd_description="Create a starboard" - ) + @starboard.subcommand(sub_cmd_name="create", sub_cmd_description="Create a starboard") @slash_option( name="channel", description="Starboard channel", @@ -91,9 +89,7 @@ class StarboardCog(Scale): ).commit() await ctx.send(f"Starboard created. Check it out at {channel.mention}.") - @slash_command( - name="starboard", sub_cmd_name="delete", sub_cmd_description="Delete a starboard" - ) + @starboard.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a starboard") @slash_option( name="channel", description="Starboard channel", @@ -229,9 +225,12 @@ class StarboardCog(Scale): async def _star_message(self, ctx: InteractionContext) -> None: await self._star_add(ctx, message=str(ctx.target_id)) - @slash_command( + star = SlashCommand( name="star", description="Manage stars", + ) + + @star.subcommand( sub_cmd_name="add", sub_cmd_description="Star a message", ) @@ -250,9 +249,7 @@ class StarboardCog(Scale): ) -> None: await self._star_add(ctx, message, channel) - @slash_command( - name="star", sub_cmd_name="delete", sub_cmd_description="Delete a starred message" - ) + @star.subcommand(sub_cmd_name="delete", sub_cmd_description="Delete a starred message") @slash_option( name="id", description="Star ID to delete", opt_type=OptionTypes.INTEGER, required=True ) diff --git a/jarvis/cogs/twitter.py b/jarvis/cogs/twitter.py index aec012f..d3e7af4 100644 --- a/jarvis/cogs/twitter.py +++ b/jarvis/cogs/twitter.py @@ -9,7 +9,7 @@ from dis_snek.models.discord.channel import GuildText from dis_snek.models.discord.components import ActionRow, Select, SelectOption from dis_snek.models.snek.application_commands import ( OptionTypes, - slash_command, + SlashCommand, slash_option, ) from dis_snek.models.snek.command import check @@ -34,9 +34,12 @@ class TwitterCog(Scale): self._guild_cache = {} self._channel_cache = {} - @slash_command( + twitter = SlashCommand( name="twitter", description="Manage Twitter follows", + ) + + @twitter.subcommand( sub_cmd_name="follow", sub_cmd_description="Follow a Twitter acount", ) @@ -108,9 +111,7 @@ class TwitterCog(Scale): await ctx.send(f"Now following `@{handle}` in {channel.mention}") - @slash_command( - name="twitter", sub_cmd_name="unfollow", sub_cmd_description="Unfollow Twitter accounts" - ) + @twitter.subcommand(sub_cmd_name="unfollow", sub_cmd_description="Unfollow Twitter accounts") @check(admin_or_permissions(Permissions.MANAGE_GUILD)) async def _twitter_unfollow(self, ctx: InteractionContext) -> None: t = TwitterFollow.find(q(guild=ctx.guild.id)) @@ -164,8 +165,7 @@ class TwitterCog(Scale): component.disabled = True await message.edit(components=components) - @slash_command( - name="twitter", + @twitter.subcommand( sub_cmd_name="retweets", sub_cmd_description="Modify followed Twitter accounts", )