2023-09-01 19:37:50 -04:00
|
|
|
import discord
|
2023-09-01 22:02:15 -04:00
|
|
|
from discord import ui
|
2023-09-24 17:01:50 -04:00
|
|
|
from redbot.core import Config, commands
|
2023-09-01 19:37:50 -04:00
|
|
|
|
|
|
|
|
|
|
|
class Forums(commands.Cog):
|
|
|
|
"""Custom cog intended for use on the Galaxy discord server.
|
2024-09-16 09:20:13 -04:00
|
|
|
Developed by cswimr."""
|
2023-09-01 19:37:50 -04:00
|
|
|
|
|
|
|
def __init__(self, bot):
|
|
|
|
self.bot = bot
|
|
|
|
self.config = Config.get_conf(self, identifier=2352711325)
|
|
|
|
self.config.register_guild(
|
2023-09-07 18:30:57 -04:00
|
|
|
request_roles=[],
|
2023-09-08 13:56:44 -04:00
|
|
|
forum_channel=None,
|
|
|
|
forum_tag=None
|
2023-09-01 19:37:50 -04:00
|
|
|
)
|
|
|
|
|
2023-09-01 19:42:11 -04:00
|
|
|
@commands.command()
|
2023-09-08 13:56:44 -04:00
|
|
|
@commands.guild_only()
|
2023-09-07 19:50:51 -04:00
|
|
|
async def resolved(self, ctx: commands.Context, *, reason: str = None):
|
2023-09-01 19:37:50 -04:00
|
|
|
"""Marks a thread as resolved."""
|
2023-09-08 13:56:44 -04:00
|
|
|
channel_id = await self.config.guild(ctx.guild).forum_channel()
|
|
|
|
tag = await self.config.guild(ctx.guild).forum_tag()
|
|
|
|
request_role_ids = await self.config.guild(ctx.guild).request_roles()
|
|
|
|
if channel_id is None or tag is None or request_role_ids is None:
|
|
|
|
await ctx.reply(f"Configuration not set properly! Please set configuration options with `{ctx.prefix}resolvedset`.")
|
|
|
|
return
|
|
|
|
if isinstance(ctx.channel, discord.Thread) and ctx.channel.parent_id == channel_id:
|
2023-09-07 19:49:59 -04:00
|
|
|
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)
|
2023-09-01 22:02:15 -04:00
|
|
|
passed_info = {
|
2023-09-07 19:49:59 -04:00
|
|
|
"ctx": ctx
|
2023-09-01 22:02:15 -04:00
|
|
|
}
|
|
|
|
if match and reason:
|
|
|
|
passed_info.update({"reason": reason})
|
2023-09-07 19:20:07 -04:00
|
|
|
if match or ctx.author.id == ctx.channel.owner.id:
|
2023-09-01 22:02:15 -04:00
|
|
|
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))
|
2023-09-07 19:35:46 -04:00
|
|
|
else:
|
|
|
|
await ctx.message.add_reaction("❌")
|
2023-09-07 20:09:09 -04:00
|
|
|
await ctx.message.delete(delay=5)
|
2023-09-01 22:02:15 -04:00
|
|
|
|
|
|
|
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']
|
2023-09-07 19:17:42 -04:00
|
|
|
if 'reason' in passed_info:
|
2023-09-01 22:02:15 -04:00
|
|
|
self.reason: str = passed_info['reason']
|
2023-09-07 19:36:47 -04:00
|
|
|
else:
|
|
|
|
self.reason = False
|
2023-09-01 22:02:15 -04:00
|
|
|
self.config = Config.get_conf(None, cog_name='Forums', identifier=2352711325)
|
|
|
|
|
|
|
|
@ui.button(label="Yes", style=discord.ButtonStyle.success, emoji="✅")
|
2023-09-24 17:01:50 -04:00
|
|
|
async def resolved_button_yes(self, interaction: discord.Interaction, button: ui.Button): # pylint: disable=unused-argument
|
2023-09-07 19:49:59 -04:00
|
|
|
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)
|
2023-09-07 19:20:07 -04:00
|
|
|
if match or interaction.user.id == interaction.channel.owner.id:
|
2023-09-07 19:17:42 -04:00
|
|
|
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)
|
2023-09-07 19:51:36 -04:00
|
|
|
await self.ctx.message.delete()
|
2023-09-07 19:44:25 -04:00
|
|
|
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)
|
2023-09-07 19:17:42 -04:00
|
|
|
else:
|
|
|
|
await interaction.response.send_message(content="You cannot close this thread!", ephemeral=True)
|
|
|
|
|
2023-09-07 19:27:18 -04:00
|
|
|
@ui.button(label="No", style=discord.ButtonStyle.danger, emoji="✖️")
|
2023-09-24 17:01:50 -04:00
|
|
|
async def resolved_button_no(self, interaction: discord.Interaction, button: ui.Button): # pylint: disable=unused-argument
|
2023-09-07 19:49:59 -04:00
|
|
|
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)
|
2023-09-07 19:20:07 -04:00
|
|
|
if match or interaction.user.id == interaction.channel.owner.id:
|
2023-09-07 19:17:42 -04:00
|
|
|
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)
|
2023-09-01 22:02:15 -04:00
|
|
|
|
2023-09-07 20:03:16 -04:00
|
|
|
@commands.group(name='resolvedset', autohelp=True, aliases=['resolvedconfig'])
|
2023-09-01 22:02:15 -04:00
|
|
|
@commands.guild_only()
|
|
|
|
@commands.admin()
|
2023-09-07 20:03:16 -04:00
|
|
|
async def resolvedset(self, ctx: commands.Context):
|
|
|
|
"""Manages the configuration for the [p]resolved command."""
|
|
|
|
|
2023-09-08 16:13:10 -04:00
|
|
|
@resolvedset.command(name='show', aliases=['settings'])
|
2023-09-08 13:56:44 -04:00
|
|
|
async def resolvedset_show(self, ctx: commands.Context):
|
|
|
|
"""Shows the current cog configuration."""
|
|
|
|
channel_id = await self.config.guild(ctx.guild).forum_channel()
|
|
|
|
tag = await self.config.guild(ctx.guild).forum_tag()
|
|
|
|
request_role_ids = await self.config.guild(ctx.guild).request_roles()
|
|
|
|
split_content = ctx.message.content.split()
|
|
|
|
command = ' '.join(split_content[:1])
|
|
|
|
already_in_list = []
|
|
|
|
for role_id in request_role_ids:
|
|
|
|
role_obj = ctx.guild.get_role(role_id)
|
|
|
|
if role_obj:
|
|
|
|
already_in_list.append(role_obj.mention)
|
|
|
|
if already_in_list:
|
2023-09-08 14:00:38 -04:00
|
|
|
roles_list = "**Allowed Roles**:\n" + "\n".join(already_in_list)
|
2023-09-08 13:56:44 -04:00
|
|
|
else:
|
2023-09-08 14:10:11 -04:00
|
|
|
roles_list = f"No roles are currently in the allowed roles list.\n- Use `{command} add` to add some."
|
2023-09-08 13:56:44 -04:00
|
|
|
tag_str = None
|
|
|
|
if channel_id is not None:
|
|
|
|
channel_obj = ctx.guild.get_channel(channel_id)
|
|
|
|
if channel_obj is None:
|
2023-09-08 13:59:07 -04:00
|
|
|
channel = f"**Channel**: {channel_id}\n- ⚠️ This channel cannot be found in this guild. Is this the correct ID?\n\n"
|
2023-09-08 13:56:44 -04:00
|
|
|
else:
|
2023-09-08 13:59:07 -04:00
|
|
|
channel = f"**Channel**: {channel_obj.mention}\n\n"
|
2023-09-08 13:56:44 -04:00
|
|
|
if tag is not None:
|
|
|
|
tag_obj = channel_obj.get_tag(tag)
|
|
|
|
if tag_obj is None:
|
2023-09-08 13:59:07 -04:00
|
|
|
tag_str = f"**Tag**: {tag}\n- ⚠️ This tag cannot be found in the set forums channel. Is this the correct ID?\n\n"
|
2023-09-08 13:56:44 -04:00
|
|
|
else:
|
2023-09-08 13:59:07 -04:00
|
|
|
tag_str = f"**Tag**: {tag_obj.emoji} {tag_obj.name}\n\n"
|
2023-09-08 13:56:44 -04:00
|
|
|
else:
|
2023-09-08 13:59:07 -04:00
|
|
|
channel = f"**Channel**: Not set!\n- Use `{command} channel` to set the forums channel.\n\n"
|
2023-09-08 13:56:44 -04:00
|
|
|
if tag_str is None:
|
2023-09-08 13:59:07 -04:00
|
|
|
tag_str = f"**Tag**: Not set!\n- Use `{command} tag` to set the tag.\n\n"
|
|
|
|
embed = discord.Embed(title="Cog Settings", color=await self.bot.get_embed_color(None), description=channel + tag_str + roles_list)
|
2023-09-08 13:56:44 -04:00
|
|
|
await ctx.reply(embed=embed)
|
|
|
|
|
2023-09-08 13:59:35 -04:00
|
|
|
@resolvedset.group(name='role', autohelp=True, aliases=['roles'])
|
2023-09-07 20:03:16 -04:00
|
|
|
async def resolvedset_role(self, ctx: commands.Context):
|
|
|
|
"""Manages the allowed roles list."""
|
2023-09-01 22:02:15 -04:00
|
|
|
|
2023-09-07 20:03:16 -04:00
|
|
|
@resolvedset_role.command(name='add')
|
|
|
|
async def resolvedset_role_add(self, ctx: commands.Context, role: discord.Role = None):
|
|
|
|
"""Adds roles to the allowed roles list."""
|
2023-09-01 22:02:15 -04:00
|
|
|
current_list = await self.config.guild(ctx.guild).request_roles()
|
|
|
|
if role:
|
|
|
|
if role.id in current_list:
|
2023-09-07 20:03:16 -04:00
|
|
|
await ctx.send("This role is already in the allowed roles list!")
|
2023-09-01 22:02:15 -04:00
|
|
|
else:
|
|
|
|
current_list.append(role.id)
|
|
|
|
await self.config.guild(ctx.guild).request_roles.set(current_list)
|
2023-09-07 20:03:16 -04:00
|
|
|
await ctx.send(f"{role.mention} has been added to the allowed roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
|
2023-09-01 22:02:15 -04:00
|
|
|
else:
|
|
|
|
await ctx.send("Please provide a valid role.")
|
|
|
|
|
2023-09-07 20:03:16 -04:00
|
|
|
@resolvedset_role.command(name='remove')
|
|
|
|
async def resolvedset_role_remove(self, ctx: commands.Context, role: discord.Role = None):
|
|
|
|
"""Removes roles from the allowed roles list."""
|
2023-09-01 22:02:15 -04:00
|
|
|
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)
|
2023-09-07 20:03:16 -04:00
|
|
|
await ctx.send(f"{role.mention} has been removed from the allowed roles list.", allowed_mentions = discord.AllowedMentions(roles=False))
|
2023-09-01 19:56:41 -04:00
|
|
|
else:
|
2023-09-07 20:03:16 -04:00
|
|
|
await ctx.send("Please provide a valid role that exists in the allowed roles list.")
|
2023-09-01 22:02:15 -04:00
|
|
|
|
2023-09-01 22:04:59 -04:00
|
|
|
def create_select_options(self, ctx: commands.Context, data):
|
2023-09-01 22:02:15 -04:00
|
|
|
options = []
|
|
|
|
for tag in data:
|
2023-09-01 22:04:59 -04:00
|
|
|
emoji = ctx.guild.get_emoji(tag.emoji.id) if tag.emoji.id else str(tag.emoji.name)
|
2023-09-07 18:55:49 -04:00
|
|
|
options.append(discord.SelectOption(label=tag.name, emoji=emoji, description="", value=tag.id))
|
2023-09-01 22:02:15 -04:00
|
|
|
return options
|
|
|
|
|
2023-09-07 23:25:50 -04:00
|
|
|
@resolvedset.command(name="channel")
|
|
|
|
async def resolvedset_channel(self, ctx: commands.Context, channel: discord.abc.GuildChannel):
|
2023-09-08 14:01:36 -04:00
|
|
|
"""Sets the channel used by the [p]resolved command."""
|
2023-09-07 23:25:50 -04:00
|
|
|
if isinstance(channel, discord.ForumChannel):
|
|
|
|
await self.config.guild(ctx.guild).forum_channel.set(channel.id)
|
2023-09-08 14:18:15 -04:00
|
|
|
await ctx.reply(f"Forum channel has been set to {channel.mention}.")
|
2023-09-07 23:25:50 -04:00
|
|
|
else:
|
2023-09-08 14:18:15 -04:00
|
|
|
await ctx.reply(f"{channel.mention} is not a forums channel!")
|
2023-09-07 23:25:50 -04:00
|
|
|
|
2023-09-07 20:03:16 -04:00
|
|
|
@resolvedset.command(name="tag")
|
2023-09-08 14:18:15 -04:00
|
|
|
async def resolvedset_tag(self, ctx: commands.Context):
|
2023-09-07 20:03:16 -04:00
|
|
|
"""Sets the tag used by the [p]resolved command."""
|
2023-09-08 14:12:49 -04:00
|
|
|
channel: discord.ForumChannel = ctx.guild.get_channel(await self.config.guild(ctx.guild).forum_channel())
|
2023-09-08 14:18:15 -04:00
|
|
|
if channel is not None:
|
|
|
|
options = self.create_select_options(ctx, channel.available_tags)
|
|
|
|
msg = await ctx.reply("Select a forum tag below.")
|
|
|
|
await msg.edit(view=SelectView(msg, options))
|
|
|
|
else:
|
2023-09-24 16:55:47 -04:00
|
|
|
await ctx.reply("Configuration error! Channel does not exist.")
|
2023-09-01 22:02:15 -04:00
|
|
|
|
|
|
|
class Select(ui.Select):
|
2023-09-01 22:13:26 -04:00
|
|
|
def __init__(self, message, options):
|
|
|
|
self.message = message
|
2023-09-01 22:02:15 -04:00
|
|
|
super().__init__(placeholder="Select an option", max_values=1, min_values=1, options=options)
|
|
|
|
|
|
|
|
async def callback(self, interaction: discord.Interaction):
|
2023-09-01 22:13:26 -04:00
|
|
|
msg: discord.Message = self.message
|
|
|
|
config = Config.get_conf(None, cog_name='Forums', identifier=2352711325)
|
2023-09-07 18:55:49 -04:00
|
|
|
await config.guild(msg.guild).forum_tag.set(int(self.values[0]))
|
2023-09-08 14:19:23 -04:00
|
|
|
channel: discord.ForumChannel = msg.guild.get_channel(await config.guild(msg.guild).forum_channel())
|
2023-09-08 14:21:38 -04:00
|
|
|
tag = channel.get_tag(int(self.values[0]))
|
2023-09-08 14:18:15 -04:00
|
|
|
await msg.edit(content=f"Set resolved tag to {tag.emoji} {tag.name}", view=None)
|
2023-09-01 22:25:12 -04:00
|
|
|
await interaction.response.defer()
|
2023-09-01 22:02:15 -04:00
|
|
|
|
|
|
|
class SelectView(ui.View):
|
2023-09-01 22:25:12 -04:00
|
|
|
def __init__(self, message, options, *, timeout=180):
|
2023-09-01 22:02:15 -04:00
|
|
|
super().__init__(timeout=timeout)
|
2023-09-01 22:25:12 -04:00
|
|
|
self.add_item(Select(message, options))
|