diff --git a/jarvis/cogs/admin/mute.py b/jarvis/cogs/admin/mute.py index 7bf851c..9261b18 100644 --- a/jarvis/cogs/admin/mute.py +++ b/jarvis/cogs/admin/mute.py @@ -1,48 +1,56 @@ """J.A.R.V.I.S. MuteCog.""" -from discord import Member -from discord.ext import commands -from discord.utils import get -from discord_slash import SlashContext, cog_ext -from discord_slash.utils.manage_commands import create_option +from datetime import datetime + +from dis_snek import InteractionContext, Permissions, Scale, Snek +from dis_snek.models.discord.embed import EmbedField +from dis_snek.models.discord.user import Member +from dis_snek.models.snek.application_commands import ( + OptionTypes, + SlashCommandChoice, + slash_command, + slash_option, +) -from jarvis.db.models import Mute, Setting from jarvis.utils import build_embed -from jarvis.utils.field import Field from jarvis.utils.permissions import admin_or_permissions -class MuteCog(commands.Cog): +class MuteCog(Scale): """J.A.R.V.I.S. MuteCog.""" - def __init__(self, bot: commands.Bot): + def __init__(self, bot: Snek): self.bot = bot - @cog_ext.cog_slash( - name="mute", - description="Mute a user", - options=[ - create_option( - name="user", - description="User to mute", - option_type=6, - required=True, - ), - create_option( - name="reason", - description="Reason for mute", - option_type=3, - required=True, - ), - create_option( - name="duration", - description="Duration of mute in minutes, default 30", - option_type=4, - required=False, - ), + @slash_command(name="mute", description="Mute a user") + @slash_option(name="user", description="User to mute", option_type=OptionTypes.USER, required=True) + @slash_option( + name="reason", + description="Reason for mute", + option_type=OptionTypes.STRING, + required=True, + ) + @slash_option( + name="time", + description="Duration of mute, default 1", + option_type=OptionTypes.INTEGER, + required=False, + ) + @slash_option( + name="scale", + description="Time scale, default Hour(s)", + option_type=OptionTypes.INTEGER, + required=False, + choices=[ + SlashCommandChoice(name="Minute(s)", value=1), + SlashCommandChoice(name="Hour(s)", value=60), + SlashCommandChoice(name="Day(s)", value=3600), + SlashCommandChoice(name="Week(s)", value=604800), ], ) - @admin_or_permissions(mute_members=True) - async def _mute(self, ctx: SlashContext, user: Member, reason: str, duration: int = 30) -> None: + @admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS) + async def _timeout( + self, ctx: InteractionContext, user: Member, reason: str, time: int = 1, scale: int = 60 + ) -> None: if user == ctx.author: await ctx.send("You cannot mute yourself.", hidden=True) return @@ -52,81 +60,45 @@ class MuteCog(commands.Cog): if len(reason) > 100: await ctx.send("Reason must be < 100 characters", hidden=True) return - mute_setting = Setting.objects(guild=ctx.guild.id, setting="mute").first() - if not mute_setting: - await ctx.send( - "Please configure a mute role with /settings mute first", - hidden=True, - ) + + # Max 4 weeks (2419200 seconds) per API + duration = time * scale + if duration > 2419200: + await ctx.send("Mute must be less than 4 weeks (2419200 seconds)", hidden=True) return - role = get(ctx.guild.roles, id=mute_setting.value) - if role in user.roles: - await ctx.send("User already muted", hidden=True) - return - await user.add_roles(role, reason=reason) - if duration < 0 or duration > 300: - duration = -1 - _ = Mute( - user=user.id, - reason=reason, - admin=ctx.author.id, - guild=ctx.guild.id, - duration=duration, - active=True if duration >= 0 else False, - ).save() + + await user.timeout(communication_disabled_until=duration, reason=reason) embed = build_embed( title="User Muted", description=f"{user.mention} has been muted", - fields=[Field(name="Reason", value=reason)], + fields=[EmbedField(name="Reason", value=reason)], ) embed.set_author( - name=user.nick if user.nick else user.name, + name=user.display_name, icon_url=user.avatar_url, ) embed.set_thumbnail(url=user.avatar_url) - embed.set_footer(text=f"{user.name}#{user.discriminator} | {user.id}") + embed.set_footer(text=f"{user.username}#{user.discriminator} | {user.id}") await ctx.send(embed=embed) - @cog_ext.cog_slash( - name="unmute", - description="Unmute a user", - options=[ - create_option( - name="user", - description="User to unmute", - option_type=6, - required=True, - ) - ], - ) - @admin_or_permissions(mute_members=True) - async def _unmute(self, ctx: SlashContext, user: Member) -> None: - mute_setting = Setting.objects(guild=ctx.guild.id, setting="mute").first() - if not mute_setting: - await ctx.send( - "Please configure a mute role with /settings mute first.", - hidden=True, - ) + @slash_command(name="unmute", description="Unmute a user") + @slash_option(name="user", description="User to unmute", option_type=OptionTypes.USER, required=True) + @admin_or_permissions(Permissions.MUTE_MEMBERS, Permissions.BAN_MEMBERS, Permissions.KICK_MEMBERS) + async def _unmute(self, ctx: InteractionContext, user: Member) -> None: + if not user.communication_disabled_until or user.communication_disabled_until < datetime.now(): + await ctx.send("User is not muted", hidden=True) return - role = get(ctx.guild.roles, id=mute_setting.value) - if role in user.roles: - await user.remove_roles(role, reason="Unmute") - else: - await ctx.send("User is not muted.", hidden=True) - return - - _ = Mute.objects(guild=ctx.guild.id, user=user.id).update(set__active=False) embed = build_embed( title="User Unmuted", description=f"{user.mention} has been unmuted", fields=[], ) embed.set_author( - name=user.nick if user.nick else user.name, + name=user.display_name, icon_url=user.avatar_url, ) embed.set_thumbnail(url=user.avatar_url) - embed.set_footer(text=f"{user.name}#{user.discriminator} | {user.id}") + embed.set_footer(text=f"{user.username}#{user.discriminator} | {user.id}") await ctx.send(embed=embed)