jarvis-bot/jarvis/cogs/settings.py
2022-04-13 13:05:21 -06:00

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", inlilne=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)