diff --git a/README.md b/README.md
index 119bf2a..8f33d87 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@

-# Just Another Very Intelligent System (J.A.R.V.I.S.)
+# Just AnotheR Very Intelligent System (J.A.R.V.I.S.)
@@ -38,19 +38,17 @@ If you wish to contribute to the J.A.R.V.I.S codebase or documentation, join the
Join the [Stark R&D Department Discord server](https://discord.gg/VtgZntXcnZ) to be kept up-to-date on code updates and issues.
## Requirements
-- MongoDB 4.4 or higher
-- Python 3.8 or higher
+- MongoDB 5.0 or higher
+- Python 3.10 or higher
- [tokei](https://github.com/XAMPPRocky/tokei) 12.1 or higher
On top of the above requirements, the following pip packages are also required:
-- `discord-py>=1.7, <2`
+- `dis-snek>=5.0.0`
- `psutil>=5.8, <6`
- `GitPython>=3.1, <4`
- `PyYaml>=5.4, <6`
-- `discord-py-slash-command>=2.3.2, <3`
- `pymongo>=3.12.0, <4`
- `opencv-python>=4.5, <5`
-- `ButtonPaginator>=0.0.3`
- `Pillow>=8.2.0, <9`
- `python-gitlab>=2.9.0, <3`
- `ulid-py>=1.1.0, <2`
diff --git a/jarvis/cogs/autoreact.py b/jarvis/cogs/autoreact.py
index 6d1263f..06c0ed3 100644
--- a/jarvis/cogs/autoreact.py
+++ b/jarvis/cogs/autoreact.py
@@ -1,46 +1,44 @@
"""J.A.R.V.I.S. Autoreact Cog."""
import re
+from typing import Optional, Tuple
-from discord import TextChannel
-from discord.ext import commands
-from discord.utils import find
-from discord_slash import SlashContext, cog_ext
-from discord_slash.utils.manage_commands import create_option
+from dis_snek import InteractionContext, Permissions, Scale, Snek
+from dis_snek.models.discord.channel import GuildText
+from dis_snek.models.snek.application_commands import (
+ OptionTypes,
+ slash_command,
+ slash_option,
+)
from jarvis.data.unicode import emoji_list
from jarvis.db.models import Autoreact
+from jarvis.utils import find
from jarvis.utils.permissions import admin_or_permissions
-class AutoReactCog(commands.Cog):
+class AutoReactCog(Scale):
"""J.A.R.V.I.S. Autoreact Cog."""
- def __init__(self, bot: commands.Bot):
+ def __init__(self, bot: Snek):
self.bot = bot
self.custom_emote = re.compile(r"^<:\w+:(\d+)>$")
- @cog_ext.cog_subcommand(
- base="autoreact",
- name="create",
- description="Add an autoreact to a channel",
- options=[
- create_option(
- name="channel",
- description="Channel to monitor",
- option_type=7,
- required=True,
- )
- ],
- )
- @admin_or_permissions(manage_guild=True)
- async def _autoreact_create(self, ctx: SlashContext, channel: TextChannel) -> None:
- if not isinstance(channel, TextChannel):
- await ctx.send("Channel must be a text channel", hidden=True)
- return
+ async def create_autoreact(
+ self, ctx: InteractionContext, channel: GuildText
+ ) -> Tuple[bool, Optional[str]]:
+ """
+ Create an autoreact monitor on a channel.
+
+ Args:
+ ctx: Interaction context of command
+ channel: Channel to monitor
+
+ Returns:
+ Tuple of success? and error message
+ """
exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
if exists:
- await ctx.send(f"Autoreact already exists for {channel.mention}.", hidden=True)
- return
+ return False, f"Autoreact already exists for {channel.mention}."
_ = Autoreact(
guild=ctx.guild.id,
@@ -48,50 +46,38 @@ class AutoReactCog(commands.Cog):
reactions=[],
admin=ctx.author.id,
).save()
- await ctx.send(f"Autoreact created for {channel.mention}!")
- @cog_ext.cog_subcommand(
- base="autoreact",
- name="delete",
- description="Delete an autoreact from a channel",
- options=[
- create_option(
- name="channel",
- description="Channel to stop monitoring",
- option_type=7,
- required=True,
- )
- ],
- )
- @admin_or_permissions(manage_guild=True)
- async def _autoreact_delete(self, ctx: SlashContext, channel: TextChannel) -> None:
- exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).delete()
- if exists:
- await ctx.send(f"Autoreact removed from {channel.mention}")
- else:
- await ctx.send(f"Autoreact not found on {channel.mention}", hidden=True)
+ return True, None
- @cog_ext.cog_subcommand(
- base="autoreact",
- name="add",
- description="Add an autoreact emote to an existing autoreact",
- options=[
- create_option(
- name="channel",
- description="Autoreact channel to add emote to",
- option_type=7,
- required=True,
- ),
- create_option(
- name="emote",
- description="Emote to add",
- option_type=3,
- required=True,
- ),
- ],
+ async def delete_autoreact(self, ctx: InteractionContext, channel: GuildText) -> bool:
+ """
+ Remove an autoreact monitor on a channel.
+
+ Args:
+ ctx: Interaction context of command
+ channel: Channel to stop monitoring
+
+ Returns:
+ Success?
+ """
+ return Autoreact.objects(guild=ctx.guild.id, channel=channel.id).delete() is not None
+
+ @slash_command(
+ name="autoreact",
+ sub_cmd_name="add",
+ sub_cmd_description="Add an autoreact emote to a channel",
)
- @admin_or_permissions(manage_guild=True)
- async def _autoreact_add(self, ctx: SlashContext, channel: TextChannel, emote: str) -> None:
+ @slash_option(
+ name="channel",
+ description="Autoreact channel to add emote to",
+ option_type=OptionTypes.CHANNEL,
+ required=True,
+ )
+ @slash_option(
+ name="emote", description="Emote to add", option_type=OptionTypes.STRING, required=True
+ )
+ @admin_or_permissions(Permissions.MANAGE_GUILD)
+ async def _autoreact_add(self, ctx: InteractionContext, channel: GuildText, emote: str) -> None:
await ctx.defer()
custom_emoji = self.custom_emote.match(emote)
standard_emoji = emote in emoji_list
@@ -106,85 +92,86 @@ class AutoReactCog(commands.Cog):
if not find(lambda x: x.id == emoji_id, ctx.guild.emojis):
await ctx.send("Please use a custom emote from this server.", hidden=True)
return
- exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
- if not exists:
- await ctx.send(
- f"Please create autoreact first with /autoreact create {channel.mention}"
- )
- return
- if emote in exists.reactions:
+ autoreact = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
+ if not autoreact:
+ self.create_autoreact(ctx, channel)
+ autoreact = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
+ if emote in autoreact.reactions:
await ctx.send(
f"Emote already added to {channel.mention} autoreactions.",
hidden=True,
)
return
- if len(exists.reactions) >= 5:
+ if len(autoreact.reactions) >= 5:
await ctx.send(
"Max number of reactions hit. Remove a different one to add this one",
hidden=True,
)
return
- exists.reactions.append(emote)
- exists.save()
+ autoreact.reactions.append(emote)
+ autoreact.save()
await ctx.send(f"Added {emote} to {channel.mention} autoreact.")
- @cog_ext.cog_subcommand(
- base="autoreact",
- name="remove",
- description="Remove an autoreact emote from an existing autoreact",
- options=[
- create_option(
- name="channel",
- description="Autoreact channel to remove emote from",
- option_type=7,
- required=True,
- ),
- create_option(
- name="emote",
- description="Emote to remove",
- option_type=3,
- required=True,
- ),
- ],
+ @slash_command(
+ name="autoreact",
+ sub_cmd_name="remove",
+ sub_cmd_description="Remove an autoreact emote to a channel",
)
- @admin_or_permissions(manage_guild=True)
- async def _autoreact_remove(self, ctx: SlashContext, channel: TextChannel, emote: str) -> None:
- exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
- if not exists:
+ @slash_option(
+ name="channel",
+ description="Autoreact channel to remove emote from",
+ option_type=OptionTypes.CHANNEL,
+ required=True,
+ )
+ @slash_option(
+ name="emote",
+ description="Emote to remove (use all to delete)",
+ option_type=OptionTypes.STRING,
+ required=True,
+ )
+ @admin_or_permissions(Permissions.MANAGE_GUILD)
+ async def _autoreact_remove(
+ self, ctx: InteractionContext, channel: GuildText, emote: str
+ ) -> None:
+ autoreact = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
+ if not autoreact:
await ctx.send(
- f"Please create autoreact first with /autoreact create {channel.mention}",
+ f"Please create autoreact first with /autoreact add {channel.mention} {emote}",
hidden=True,
)
return
- if emote not in exists.reactions:
+ if emote.lower() == "all":
+ self.delete_autoreact(ctx, channel)
+ await ctx.send(f"Autoreact removed from {channel.mention}")
+ elif emote not in autoreact.reactions:
await ctx.send(
f"{emote} not used in {channel.mention} autoreactions.",
hidden=True,
)
return
- exists.reactions.remove(emote)
- exists.save()
- await ctx.send(f"Removed {emote} from {channel.mention} autoreact.")
+ else:
+ autoreact.reactions.remove(emote)
+ autoreact.save()
+ if len(autoreact.reactions) == 0:
+ self.delete_autoreact(ctx, channel)
+ await ctx.send(f"Removed {emote} from {channel.mention} autoreact.")
- @cog_ext.cog_subcommand(
- base="autoreact",
- name="list",
- description="List all autoreacts on a channel",
- options=[
- create_option(
- name="channel",
- description="Autoreact channel to list",
- option_type=7,
- required=True,
- ),
- ],
+ @slash_command(
+ name="autoreact",
+ sub_cmd_name="list",
+ sub_cmd_description="List all autoreacts on a channel",
)
- @admin_or_permissions(manage_guild=True)
- async def _autoreact_list(self, ctx: SlashContext, channel: TextChannel) -> None:
+ @slash_option(
+ name="channel",
+ description="Autoreact channel to list",
+ option_type=OptionTypes.CHANNEL,
+ required=True,
+ )
+ async def _autoreact_list(self, ctx: InteractionContext, channel: GuildText) -> None:
exists = Autoreact.objects(guild=ctx.guild.id, channel=channel.id).first()
if not exists:
await ctx.send(
- f"Please create autoreact first with /autoreact create {channel.mention}",
+ f"Please create autoreact first with /autoreact add {channel.mention}
",
hidden=True,
)
return
@@ -198,6 +185,6 @@ class AutoReactCog(commands.Cog):
await ctx.send(message)
-def setup(bot: commands.Bot) -> None:
+def setup(bot: Snek) -> None:
"""Add AutoReactCog to J.A.R.V.I.S."""
bot.add_cog(AutoReactCog(bot))