"""J.A.R.V.I.S. LockCog.""" import logging from typing import Union from dis_snek import InteractionContext, Scale, Snake from dis_snek.client.utils.misc_utils import get from dis_snek.models.discord.channel import GuildText, GuildVoice from dis_snek.models.discord.enums import Permissions from dis_snek.models.snek.application_commands import ( OptionTypes, slash_command, slash_option, ) from dis_snek.models.snek.command import check from jarvis_core.db import q from jarvis_core.db.models import Lock, Permission from jarvis.utils.permissions import admin_or_permissions class LockCog(Scale): """J.A.R.V.I.S. LockCog.""" def __init__(self, bot: Snake): self.bot = bot self.logger = logging.getLogger(__name__) @slash_command(name="lock", description="Lock a channel") @slash_option( name="reason", description="Lock Reason", opt_type=3, required=True, ) @slash_option( name="duration", description="Lock duration in minutes (default 10)", opt_type=4, required=False, ) @slash_option( name="channel", description="Channel to lock", opt_type=7, required=False, ) @check(admin_or_permissions(Permissions.MANAGE_CHANNELS)) async def _lock( self, ctx: InteractionContext, reason: str, duration: int = 10, channel: Union[GuildText, GuildVoice] = None, ) -> None: await ctx.defer(ephemeral=True) if duration <= 0: await ctx.send("Duration must be > 0", ephemeral=True) return elif duration > 60 * 12: await ctx.send("Duration must be <= 12 hours", ephemeral=True) return if len(reason) > 100: await ctx.send("Reason must be <= 100 characters", ephemeral=True) return if not channel: channel = ctx.channel # role = ctx.guild.default_role # Uncomment once implemented if isinstance(channel, GuildText): to_deny = Permissions.SEND_MESSAGES elif isinstance(channel, GuildVoice): to_deny = Permissions.CONNECT | Permissions.SPEAK current = get(channel.permission_overwrites, id=ctx.guild.id) if current: current = Permission(id=ctx.guild.id, allow=int(current.allow), deny=int(current.deny)) role = await ctx.guild.fetch_role(ctx.guild.id) await channel.add_permission(target=role, deny=to_deny, reason="Locked") await Lock( channel=channel.id, guild=ctx.guild.id, admin=ctx.author.id, reason=reason, duration=duration, original_perms=current, ).commit() await ctx.send(f"{channel.mention} locked for {duration} minute(s)") @slash_command(name="unlock", description="Unlock a channel") @slash_option( name="channel", description="Channel to unlock", opt_type=OptionTypes.CHANNEL, required=False, ) @check(admin_or_permissions(Permissions.MANAGE_CHANNELS)) async def _unlock( self, ctx: InteractionContext, channel: Union[GuildText, GuildVoice] = None, ) -> None: if not channel: channel = ctx.channel lock = await Lock.find_one(q(guild=ctx.guild.id, channel=channel.id, active=True)) if not lock: await ctx.send(f"{channel.mention} not locked.", ephemeral=True) return overwrite = get(channel.permission_overwrites, id=ctx.guild.id) if overwrite and lock.original_perms: overwrite.allow = lock.original_perms.allow overwrite.deny = lock.original_perms.deny await channel.edit_permission(overwrite, reason="Unlock") elif overwrite and not lock.original_perms: await channel.delete_permission(target=overwrite, reason="Unlock") lock.active = False await lock.commit() await ctx.send(f"{channel.mention} unlocked")