SeaCogs/moderation/utils.py

199 lines
6.4 KiB
Python

import json
from typing import Union
from discord import Color, User, Member, Interaction, Guild
from discord.errors import NotFound, Forbidden
from redbot.core import commands
from .config import config
from .database import connect, fetch_case
async def check_conf(config_list: list):
"""Checks if any required config options are not set."""
not_found_list = []
for item in config_list:
if await config.item() == " ":
not_found_list.append(item)
return not_found_list
def check_permissions(
user: User,
permissions: list,
ctx: Union[commands.Context, Interaction] = None,
guild: Guild = None,
):
"""Checks if a user has a specific permission (or a list of permissions) in a channel."""
if ctx:
member = ctx.guild.get_member(user.id)
resolved_permissions = ctx.channel.permissions_for(member)
elif guild:
member = guild.get_member(user.id)
resolved_permissions = member.guild_permissions
else:
raise (KeyError)
for permission in permissions:
if (
not getattr(resolved_permissions, permission, False)
and not resolved_permissions.administrator is True
):
return permission
return False
async def check_moddable(
target: Union[User, Member], interaction: Interaction, permissions: list
):
"""Checks if a moderator can moderate a target."""
if check_permissions(interaction.client.user, permissions, guild=interaction.guild):
await interaction.response.send_message(
f"I do not have the `{permissions}` permission, required for this action.",
ephemeral=True,
)
return False
if await config.guild(interaction.guild).use_discord_permissions() is True:
if check_permissions(interaction.user, permissions, guild=interaction.guild):
await interaction.response.send_message(
f"You do not have the `{permissions}` permission, required for this action.",
ephemeral=True,
)
return False
if interaction.user.id == target.id:
await interaction.response.send_message(
content="You cannot moderate yourself!", ephemeral=True
)
return False
if target.bot:
await interaction.response.send_message(
content="You cannot moderate bots!", ephemeral=True
)
return False
if isinstance(target, Member):
if interaction.user.top_role <= target.top_role:
await interaction.response.send_message(
content="You cannot moderate members with a higher role than you!",
ephemeral=True,
)
return False
if (
interaction.guild.get_member(interaction.client.user.id).top_role
<= target.top_role
):
await interaction.response.send_message(
content="You cannot moderate members with a role higher than the bot!",
ephemeral=True,
)
return False
immune_roles = await config.guild(target.guild).immune_roles()
for role in target.roles:
if role.id in immune_roles:
await interaction.response.send_message(
content="You cannot moderate members with an immune role!",
ephemeral=True,
)
return False
return True
async def get_next_case_number(guild_id: str, cursor=None):
"""This method returns the next case number from the MySQL table for a specific guild."""
if not cursor:
database = await connect()
cursor = database.cursor()
cursor.execute(
f"SELECT moderation_id FROM `moderation_{guild_id}` ORDER BY moderation_id DESC LIMIT 1"
)
return cursor.fetchone()[0] + 1
def generate_dict(result):
case: dict = {
"moderation_id": result[0],
"timestamp": result[1],
"moderation_type": result[2],
"target_id": result[3],
"moderator_id": result[4],
"role_id": result[5],
"duration": result[6],
"end_timestamp": result[7],
"reason": result[8],
"resolved": result[9],
"resolved_by": result[10],
"resolve_reason": result[11],
"expired": result[12],
"changes": json.loads(result[13]),
"metadata": json.loads(result[14]),
}
return case
async def fetch_user_dict(interaction: Interaction, user_id: str):
"""This method returns a dictionary containing either user information or a standard deleted user template."""
if user_id == "?":
user_dict = {"id": "?", "name": "Unknown User", "discriminator": "0"}
else:
try:
user = interaction.client.get_user(user_id)
if user is None:
user = await interaction.client.fetch_user(user_id)
user_dict = {
"id": user.id,
"name": user.name,
"discriminator": user.discriminator,
}
except NotFound:
user_dict = {
"id": user_id,
"name": "Deleted User",
"discriminator": "0",
}
return user_dict
async def fetch_role_dict(interaction: Interaction, role_id: str):
"""This method returns a dictionary containing either role information or a standard deleted role template."""
try:
role = interaction.guild.get_role(role_id)
role_dict = {"id": role.id, "name": role.name}
except NotFound:
role_dict = {"id": role_id, "name": "Deleted Role"}
return role_dict
async def log(interaction: Interaction, moderation_id: int, color: Color, resolved: bool = False):
"""This method sends a message to the guild's configured logging channel when an infraction takes place."""
from .embed_factory import embed_factory
logging_channel_id = await config.guild(interaction.guild).log_channel()
if logging_channel_id != " ":
logging_channel = interaction.guild.get_channel(logging_channel_id)
case = await fetch_case(moderation_id, interaction.guild.id)
if case:
embed = await embed_factory(
"log", color, interaction=interaction, case_dict=case, resolved=resolved
)
try:
await logging_channel.send(embed=embed)
except Forbidden:
return