240 lines
10 KiB
Python
240 lines
10 KiB
Python
"""J.A.R.V.I.S. Settings Management Cog."""
|
|
import logging
|
|
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,
|
|
SlashCommand,
|
|
slash_option,
|
|
)
|
|
from dis_snek.models.snek.command import check
|
|
from jarvis_core.db import q
|
|
from jarvis_core.db.models import Setting
|
|
|
|
from jarvis.utils import build_embed
|
|
from jarvis.utils.permissions import admin_or_permissions
|
|
|
|
|
|
class SettingsCog(Scale):
|
|
"""J.A.R.V.I.S. Settings Management Cog."""
|
|
|
|
def __init__(self, bot: Snake):
|
|
self.bot = bot
|
|
self.logger = logging.getLogger(__name__)
|
|
|
|
async def update_settings(self, setting: str, value: Any, guild: int) -> bool:
|
|
"""Update a guild setting."""
|
|
existing = await Setting.find_one(q(setting=setting, guild=guild))
|
|
if not existing:
|
|
existing = Setting(setting=setting, guild=guild, value=value)
|
|
existing.value = value
|
|
updated = await existing.commit()
|
|
|
|
return updated is not None
|
|
|
|
async def delete_settings(self, setting: str, guild: int) -> bool:
|
|
"""Delete a guild setting."""
|
|
existing = await Setting.find_one(q(setting=setting, guild=guild))
|
|
if existing:
|
|
return await existing.delete()
|
|
return False
|
|
|
|
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 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:
|
|
if not isinstance(channel, GuildText):
|
|
await ctx.send("Channel must be a GuildText", ephemeral=True)
|
|
return
|
|
await self.update_settings("modlog", channel.id, ctx.guild.id)
|
|
await ctx.send(f"Settings applied. New modlog channel is {channel.mention}")
|
|
|
|
@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: InteractionContext, channel: GuildText) -> None:
|
|
if not isinstance(channel, GuildText):
|
|
await ctx.send("Channel must be a GuildText", ephemeral=True)
|
|
return
|
|
await self.update_settings("activitylog", channel.id, ctx.guild.id)
|
|
await ctx.send(f"Settings applied. New activitylog channel is {channel.mention}")
|
|
|
|
@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(Permissions.MANAGE_GUILD))
|
|
async def _set_massmention(self, ctx: InteractionContext, amount: int) -> None:
|
|
await ctx.defer()
|
|
await self.update_settings("massmention", amount, ctx.guild.id)
|
|
await ctx.send(f"Settings applied. New massmention limit is {amount}")
|
|
|
|
@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(Permissions.MANAGE_GUILD))
|
|
async def _set_verified(self, ctx: InteractionContext, role: Role) -> None:
|
|
await ctx.defer()
|
|
await self.update_settings("verified", role.id, ctx.guild.id)
|
|
await ctx.send(f"Settings applied. New verified role is `{role.name}`")
|
|
|
|
@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(Permissions.MANAGE_GUILD))
|
|
async def _set_unverified(self, ctx: InteractionContext, role: Role) -> None:
|
|
await ctx.defer()
|
|
await self.update_settings("unverified", role.id, ctx.guild.id)
|
|
await ctx.send(f"Settings applied. New unverified role is `{role.name}`")
|
|
|
|
@set_.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 _set_invitedel(self, ctx: InteractionContext, active: bool) -> None:
|
|
await ctx.defer()
|
|
await self.update_settings("noinvite", active, ctx.guild.id)
|
|
await ctx.send(f"Settings applied. Automatic invite active: {active}")
|
|
|
|
@set_.subcommand(sub_cmd_name="notify", sub_cmd_description="Notify users of admin action?")
|
|
@slash_option(name="active", description="Notify?", opt_type=OptionTypes.BOOLEAN, required=True)
|
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
|
async def _set_notify(self, ctx: InteractionContext, active: bool) -> None:
|
|
await ctx.defer()
|
|
await self.update_settings("notify", active, ctx.guild.id)
|
|
await ctx.send(f"Settings applied. Notifications active: {active}")
|
|
|
|
# Unset
|
|
@unset.subcommand(
|
|
sub_cmd_name="modlog",
|
|
sub_cmd_description="Unset Modlog channel",
|
|
)
|
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
|
async def _unset_modlog(self, ctx: InteractionContext) -> None:
|
|
await ctx.defer()
|
|
await self.delete_settings("modlog", ctx.guild.id)
|
|
await ctx.send("Setting `modlog` unset")
|
|
|
|
@unset.subcommand(
|
|
sub_cmd_name="activitylog",
|
|
sub_cmd_description="Unset Activitylog channel",
|
|
)
|
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
|
async def _unset_activitylog(self, ctx: InteractionContext) -> None:
|
|
await ctx.defer()
|
|
await self.delete_settings("activitylog", ctx.guild.id)
|
|
await ctx.send("Setting `activitylog` unset")
|
|
|
|
@unset.subcommand(sub_cmd_name="massmention", sub_cmd_description="Unset massmention output")
|
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
|
async def _unset_massmention(self, ctx: InteractionContext) -> None:
|
|
await ctx.defer()
|
|
await self.delete_settings("massmention", ctx.guild.id)
|
|
await ctx.send("Setting `massmention` unset")
|
|
|
|
@unset.subcommand(sub_cmd_name="verified", sub_cmd_description="Unset 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) -> None:
|
|
await ctx.defer()
|
|
await self.delete_settings("verified", ctx.guild.id)
|
|
await ctx.send("Setting `massmention` unset")
|
|
|
|
@unset.subcommand(sub_cmd_name="unverified", sub_cmd_description="Unset unverified role")
|
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
|
async def _unset_unverified(self, ctx: InteractionContext) -> None:
|
|
await ctx.defer()
|
|
await self.delete_settings("unverified", ctx.guild.id)
|
|
await ctx.send("Setting `unverified` unset")
|
|
|
|
@unset.subcommand(
|
|
sub_cmd_name="noinvite", sub_cmd_description="Unset if invite deletion should happen"
|
|
)
|
|
@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", ctx.guild.id)
|
|
await ctx.send(f"Setting `{active}` unset")
|
|
|
|
@unset.subcommand(sub_cmd_name="notify", sub_cmd_description="Unset admin action notifications")
|
|
@check(admin_or_permissions(Permissions.MANAGE_GUILD))
|
|
async def _unset_notify(self, ctx: InteractionContext) -> None:
|
|
await ctx.defer()
|
|
await self.delete_settings("notify", ctx.guild.id)
|
|
await ctx.send("Setting `notify` 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 = []
|
|
async for setting in settings:
|
|
value = setting.value
|
|
if setting.setting in ["unverified", "verified", "mute"]:
|
|
value = await ctx.guild.fetch_role(value)
|
|
if value:
|
|
value = value.mention
|
|
else:
|
|
value = "||`[redacted]`||"
|
|
elif setting.setting in ["activitylog", "modlog"]:
|
|
value = await ctx.guild.fetch_channel(value)
|
|
if value:
|
|
value = value.mention
|
|
else:
|
|
value = "||`[redacted]`||"
|
|
elif setting.setting == "rolegiver":
|
|
value = ""
|
|
for _role in setting.value:
|
|
nvalue = await ctx.guild.fetch_role(value)
|
|
if value:
|
|
value += "\n" + nvalue.mention
|
|
else:
|
|
value += "\n||`[redacted]`||"
|
|
fields.append(EmbedField(name=setting.setting, value=value or "N/A", inline=False))
|
|
|
|
embed = build_embed(title="Current Settings", description="", fields=fields)
|
|
|
|
await ctx.send(embed=embed)
|
|
|
|
@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:
|
|
"""Add SettingsCog to J.A.R.V.I.S."""
|
|
SettingsCog(bot)
|