GalaxyCogs/forums/forums.py
SeaswimmerTheFsh 449123b6ee
Some checks reported warnings
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
feat(forums): vastly improved configuration commands
2023-09-07 20:03:16 -04:00

174 lines
9.1 KiB
Python

import discord
from discord import ui
from redbot.core import Config, checks, commands
class Forums(commands.Cog):
"""Custom cog intended for use on the Galaxy discord server.
Developed by SeaswimmerTheFsh."""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=2352711325)
self.config.register_guild(
request_roles=[],
forum_channel="",
forum_tag=""
)
@commands.command()
async def resolved(self, ctx: commands.Context, *, reason: str = None):
"""Marks a thread as resolved."""
if isinstance(ctx.channel, discord.Thread) and ctx.channel.parent_id == await self.config.guild(ctx.guild).forum_channel():
request_role_ids = await self.config.guild(ctx.guild).request_roles()
request_roles = [ctx.guild.get_role(role_id) for role_id in request_role_ids]
match = any(role in ctx.author.roles for role in request_roles)
passed_info = {
"ctx": ctx
}
if match and reason:
passed_info.update({"reason": reason})
if match or ctx.author.id == ctx.channel.owner.id:
msg = await ctx.send("Are you sure you'd like to mark this thread as resolved?")
passed_info.update({"msg": msg})
await msg.edit(view=self.ResolvedButtons(timeout=180, passed_info=passed_info))
else:
await ctx.message.add_reaction("")
await ctx.message.delete(5)
class ResolvedButtons(ui.View):
def __init__(self, timeout, passed_info: dict):
super().__init__()
self.timeout = timeout
self.ctx: commands.Context = passed_info['ctx']
self.msg: discord.Message = passed_info['msg']
if 'reason' in passed_info:
self.reason: str = passed_info['reason']
else:
self.reason = False
self.config = Config.get_conf(None, cog_name='Forums', identifier=2352711325)
@ui.button(label="Yes", style=discord.ButtonStyle.success, emoji="")
async def resolved_button_yes(self, interaction: discord.Interaction, button: ui.Button):
request_role_ids = await self.config.guild(interaction.guild).request_roles()
request_roles = [interaction.guild.get_role(role_id) for role_id in request_role_ids]
match = any(role in interaction.user.roles for role in request_roles)
if match or interaction.user.id == interaction.channel.owner.id:
await interaction.response.defer()
if self.reason:
response_reason = f"Thread closed by {interaction.user.mention} with reason: {self.reason}"
reason = f"Thread closed by {interaction.user.name} ({interaction.user.id}) with reason: {self.reason}"
else:
response_reason = f"Thread closed by {interaction.user.mention}"
reason = f"Thread closed by {interaction.user.name} ({interaction.user.id})"
await self.msg.edit(content=response_reason, view=None)
await self.ctx.message.delete()
tag = interaction.channel.parent.get_tag(await self.config.guild(interaction.guild).forum_tag())
if tag in interaction.channel.applied_tags:
await interaction.channel.edit(locked=True, archived=True, reason=reason)
else:
await interaction.channel.edit(locked=True, archived=True, applied_tags=interaction.channel.applied_tags + [tag], reason=reason)
else:
await interaction.response.send_message(content="You cannot close this thread!", ephemeral=True)
@ui.button(label="No", style=discord.ButtonStyle.danger, emoji="✖️")
async def resolved_button_no(self, interaction: discord.Interaction, button: ui.Button):
request_role_ids = await self.config.guild(interaction.guild).request_roles()
request_roles = [interaction.guild.get_role(role_id) for role_id in request_role_ids]
match = any(role in interaction.user.roles for role in request_roles)
if match or interaction.user.id == interaction.channel.owner.id:
await interaction.response.defer()
await self.msg.delete()
await self.ctx.message.delete()
else:
await interaction.response.send_message(content="You cannot close this thread!", ephemeral=True)
@commands.group(name='resolvedset', autohelp=True, aliases=['resolvedconfig'])
@commands.guild_only()
@commands.admin()
async def resolvedset(self, ctx: commands.Context):
"""Manages the configuration for the [p]resolved command."""
@resolvedset.group(name='role', invoke_without_command=True, aliases=['roles'])
@commands.guild_only()
@commands.admin()
async def resolvedset_role(self, ctx: commands.Context):
"""Manages the allowed roles list."""
current_list = await self.config.guild(ctx.guild).request_roles()
already_in_list = []
for role_id in current_list:
role_obj = ctx.guild.get_role(role_id)
if role_obj:
already_in_list.append(role_obj.mention)
if already_in_list:
await ctx.send("Roles already in the allowed roles list:\n" + "\n".join(already_in_list) + f"\nUse `{ctx.prefix}forumconfig add` to add roles to this list.\nUse `{ctx.prefix}forumconfig remove` to remove roles from this list.", allowed_mentions=discord.AllowedMentions(roles=False))
else:
await ctx.send(f"No roles are currently in the allowed roles list.\nUse `{ctx.prefix}forumconfig add` to add some!")
@resolvedset_role.command(name='add')
@commands.guild_only()
@commands.admin()
async def resolvedset_role_add(self, ctx: commands.Context, role: discord.Role = None):
"""Adds roles to the allowed roles list."""
current_list = await self.config.guild(ctx.guild).request_roles()
if role:
if role.id in current_list:
await ctx.send("This role is already in the allowed roles list!")
return
else:
current_list.append(role.id)
await self.config.guild(ctx.guild).request_roles.set(current_list)
await ctx.send(f"{role.mention} has been added to the allowed roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
else:
await ctx.send("Please provide a valid role.")
@resolvedset_role.command(name='remove')
@commands.guild_only()
@commands.admin()
async def resolvedset_role_remove(self, ctx: commands.Context, role: discord.Role = None):
"""Removes roles from the allowed roles list."""
current_list = await self.config.guild(ctx.guild).request_roles()
if role.id in current_list:
current_list.remove(role.id)
await self.config.guild(ctx.guild).request_roles.set(current_list)
await ctx.send(f"{role.mention} has been removed from the allowed roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
else:
await ctx.send("Please provide a valid role that exists in the allowed roles list.")
def create_select_options(self, ctx: commands.Context, data):
options = []
for tag in data:
emoji = ctx.guild.get_emoji(tag.emoji.id) if tag.emoji.id else str(tag.emoji.name)
options.append(discord.SelectOption(label=tag.name, emoji=emoji, description="", value=tag.id))
return options
@resolvedset.command(name="tag")
async def resolvedset_tag(self, ctx: commands.Context, channel: discord.ForumChannel):
"""Sets the tag used by the [p]resolved command."""
options = self.create_select_options(ctx, channel.available_tags)
tag = channel.get_tag(await self.config.guild(ctx.guild).forum_tag())
msg = await ctx.send(f"Forum tag is currently set to `{str(tag)}`.")
await msg.edit(view=SelectView(msg, options))
@resolvedset.command(name="channel")
async def resolvedset_channel(self, ctx: commands.Context, channel: discord.ForumChannel):
"""Sets the tag used by the [p]resolved command."""
await self.config.guild(ctx.guild).forum_channel.set(channel.id)
await ctx.send(f"Forum channel has been set to `{channel.name}`.")
class Select(ui.Select):
def __init__(self, message, options):
self.message = message
super().__init__(placeholder="Select an option", max_values=1, min_values=1, options=options)
async def callback(self, interaction: discord.Interaction):
msg: discord.Message = self.message
config = Config.get_conf(None, cog_name='Forums', identifier=2352711325)
await config.guild(msg.guild).forum_tag.set(int(self.values[0]))
await msg.edit(content=f"Set resolved tag to {self.values[0]}", view=None)
await interaction.response.defer()
class SelectView(ui.View):
def __init__(self, message, options, *, timeout=180):
super().__init__(timeout=timeout)
self.add_item(Select(message, options))