jarvis-bot/jarvis/cogs/admin/lock.py

122 lines
4 KiB
Python

"""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")