Heimdallr/heimdallr/commands/__resources.py

242 lines
8.0 KiB
Python
Raw Normal View History

2023-02-06 20:11:44 +01:00
"""Deprecated module
This was intended to be the resources module. A user-submitted, curated directory of
resources for a guild. For the time being, forum channels serve as enough of an equivalent
for the needs of NLL. So this is to be considered deprecated.
"""
2023-05-31 20:07:39 +02:00
from interactions import (
2023-02-06 20:11:44 +01:00
slash_command,
slash_option,
Extension,
Client,
Permissions,
InteractionContext,
2023-05-31 20:07:39 +02:00
OptionType,
2023-02-06 20:11:44 +01:00
Embed,
Member,
EmbedAuthor,
Modal,
InputText,
TextStyles,
2023-05-31 20:07:39 +02:00
ChannelType,
2023-02-06 20:11:44 +01:00
GuildText,
)
import logging
from database import (
Resources as ResourcesModel,
ResourceTags as ResourceTagsModel,
ResourceAuthors as ResourceAuthorsModel,
ResourcesUnpublished as ResourcesUnpublishedModel,
ResourceChannels as ResourceChannelsModel,
)
class Resources(Extension):
def __init__(self, client: Client) -> None:
self.client = client
@slash_command(
name="adm",
group_name="set",
group_description="Set settings for this guild",
sub_cmd_name="submitted_resources_channel",
sub_cmd_description="Set whether or not to use the name filter",
dm_permission=False,
default_member_permissions=Permissions.MANAGE_GUILD,
)
@slash_option(
name="channel",
description="The channel in which submitted/unpublished resources should appear",
2023-05-31 20:07:39 +02:00
opt_type=OptionType.CHANNEL,
channel_types=[ChannelType.GUILD_TEXT],
2023-02-06 20:11:44 +01:00
)
async def adm_set_submitted_resources_channel(
2023-05-31 20:07:39 +02:00
self, ctx: InteractionContext, channel: GuildText | None = None
2023-02-06 20:11:44 +01:00
):
if channel is None:
resource_channel = ResourceChannelsModel.get_or_none(guild_id=ctx.guild.id)
if resource_channel is not None:
resource_channel.delete_instance()
await ctx.send(ephemeral=True, content="Submitted resource channel unset.")
return
resource_channel: ResourceChannelsModel
resource_channel, _ = ResourceChannelsModel.get_or_create(guild_id=ctx.guild.id)
resource_channel.channel_id = channel.id
resource_channel.save()
2023-05-31 20:07:39 +02:00
await ctx.send(
ephemeral=True,
content=f"Submitted resource channel set to {channel.mention}."
2023-02-06 20:11:44 +01:00
)
@slash_command(
name="resources",
description="Get or add resources",
default_member_permissions=Permissions.SEND_MESSAGES,
dm_permission=False,
)
async def resources(self, ctx: InteractionContext):
...
@resources.subcommand(
sub_cmd_name="list",
sub_cmd_description="List resources",
)
@slash_option(
name="page",
description="Page of resources to show",
2023-05-31 20:07:39 +02:00
opt_type=OptionType.INTEGER,
2023-02-06 20:11:44 +01:00
required=False,
)
async def resources_list(self, ctx: InteractionContext, page: int = 1):
await ctx.defer(ephemeral=True)
LIMIT = 10
resources: list[ResourcesModel] = (
ResourcesModel.select()
.paginate(page, LIMIT)
.order_by(ResourcesModel.id.asc())
)
embeds: list[Embed] = []
for resource in resources:
resource_authors: list[
ResourceAuthorsModel
] = ResourceAuthorsModel.select().where(
ResourceAuthorsModel.resource_id == resource.id
)
authors: list[str] = []
for author in resource_authors:
member = await self.client.fetch_member(author.user_id, ctx.guild_id)
if member is None:
authors.append(author.name)
else:
authors.append(
f"{member.display_name} ({member.username}#{member.discriminator})"
)
embed = Embed(title=resource.title, description=resource.description)
embed.add_field("**Authors**", "\n".join(authors))
no_resources = ResourcesModel.select().count()
pages = no_resources // LIMIT
if no_resources % LIMIT != 0:
pages += 1
await ctx.send(ephemeral=True, content=f"Page {page} of {pages}", embeds=embeds)
@resources.subcommand(
sub_cmd_name="submit",
sub_cmd_description="Submit a resource for approval",
)
async def resources_submit(self, ctx: InteractionContext):
modal_wait = await ctx.send_modal(
Modal(
title="New resource",
components=[
InputText(
label="Title",
custom_id="title",
style=TextStyles.SHORT,
placeholder="A title!",
min_length=8,
max_length=64,
),
InputText(
label="Content",
custom_id="content",
style=TextStyles.PARAGRAPH,
placeholder="A description of the resource.",
min_length=16,
),
InputText(
label="Tags",
custom_id="tags",
style=TextStyles.SHORT,
placeholder="Tags separated by spaces; e.g: grammar language-dialects tag",
max_length=128,
),
],
)
)
modal_ctx = await self.client.wait_for_modal(modal_wait, author=ctx.author.id)
await modal_ctx.defer(ephemeral=True)
title = modal_ctx.responses.get("title")
content = modal_ctx.responses.get("content")
tags = modal_ctx.responses.get("tags")
if title is None:
await modal_ctx.send("Title cannot be empty.")
return
if content is None:
await modal_ctx.send("Content cannot be empty.")
return
resource: ResourcesUnpublishedModel = ResourcesUnpublishedModel.create(
guild_id=modal_ctx.guild.id,
title=title,
description=content,
tags=tags,
author=modal_ctx.author.id,
)
await modal_ctx.send(f"Your resource *{title}* has been submitted!")
await self.__post_to_resources_submission_channel(resource)
async def __post_to_resources_submission_channel(self, resource: ResourcesUnpublishedModel):
res_unpublished_channel: ResourceChannelsModel | None = ResourceChannelsModel.get_or_none(
ResourceChannelsModel.guild_id == resource.guild_id
)
if res_unpublished_channel is None:
return # No unpublished resources channel has been set.
channel_id = int(res_unpublished_channel.channel_id)
channel = await self.client.fetch_channel(channel_id)
guild_id = int(resource.guild_id)
user_id = int(resource.author)
author: Member | None = await self.client.fetch_member(guild_id=guild_id, user_id=user_id)
author_text = None
author_icon_url = None
if author is None:
author_text = f"<@{int(resource.author)}>"
else:
author_icon_url = author.display_avatar.as_url()
if author.display_name != author.username:
author_text = f"{author.display_name} ({author.username}#{author.discriminator})"
else:
author_text = f"{author.username}#{author.discriminator}"
await channel.send(
embed=Embed(
title=str(resource.title),
description=str(resource.description),
author=EmbedAuthor(
name=author_text,
icon_url=author_icon_url,
)
)
)
def setup(bot: Client):
ResourcesModel.create_table(safe=True)
ResourceTagsModel.create_table(safe=True)
ResourcesUnpublishedModel.create_table(safe=True)
ResourceChannelsModel.create_table(safe=True)
Resources(bot)
logging.info("Resources extension loaded")