Files
dakiny-bot/cogs/commands/record.py
T

231 lines
7.8 KiB
Python

"""
Contained commands and views for record commands.
"""
import nextcord
from discord import TextInputStyle
from nextcord.ext import commands
from config import DakinyConfig
from utils import record_event_points
class RecordCog(commands.Cog, name="Record Commands"):
"""
Class holds record commands.
"""
def __init__(self, bot) -> None:
"""
Default constructor for RecordCog class. Does nothing.
"""
super().__init__()
self.bot: commands.Bot = bot
@nextcord.slash_command()
async def record(self, interaction: nextcord.Interaction):
"""
Parent slash command for record. Never called.
"""
@record.subcommand(description="Record an event and its participants.")
async def event(
self,
interaction: nextcord.Interaction,
name: str = nextcord.SlashOption(
required=True, description="Name of the event that was hosted."
),
host: nextcord.Member = nextcord.SlashOption(
required=False,
description="An alternative host if you are recording event for someone else.",
),
):
"""
This command creates the base event recording embed and sends a message with it and the EventView
for gathering more information on the event.
Args:
interaction (nextcord.Interaction): interaction with this command.
name (str): Name of the event.
host (nextcord.Member, optional): Alternative host to user using command.
"""
# check role
if (
interaction.guild.get_role(self.bot.config.params.event_host_role_id)
not in interaction.user.roles
):
await interaction.response.send_message(
f"You must have the <@&{self.bot.config.params.event_host_role_id}> role to record an event.",
ephemeral=True,
)
return
if host is None:
host = interaction.user
embed: nextcord.Embed = nextcord.Embed(title=name, description="")
embed.add_field(name="Participants", value="")
embed.add_field(name="Non-Discord Participants", value="")
embed.add_field(name="Hosted by", value=f"<@{host.id}>", inline=False)
await interaction.response.send_message(
"Fill out event details and select all members who participated!",
view=EventView(name, self.bot.config, host.id),
ephemeral=True,
embed=embed,
)
class EventView(nextcord.ui.View):
"""
Class handles gathering information on an event. Has buttons to edit the information, cancel, and submit.
Also contains a UserSelect object to pick discord members.
"""
def __init__(self, name: str, config: DakinyConfig, host_id: int):
super().__init__()
self.name: str = name
self.config: DakinyConfig = config
self.host_id: int = host_id
self.event_participants = ParticipantSelect()
self.add_item(self.event_participants)
@nextcord.ui.button(label="Cancel", style=nextcord.ButtonStyle.red, row=1)
async def cancel(
self, button: nextcord.ui.Button, interaction: nextcord.Interaction
):
"""
Cancels event submission. Removes embed and view.
"""
await interaction.response.edit_message(
"Canceled", ephemeral=True, embed=None, view=None
)
self.stop()
@nextcord.ui.button(label="Edit", style=nextcord.ButtonStyle.blurple, row=1)
async def edit(self, button: nextcord.ui.Button, interaction: nextcord.Interaction):
"""
Calls modal to update the text input information of the event.
"""
await interaction.response.send_modal(
ParticipantModal(interaction.message.embeds[0])
)
@nextcord.ui.button(label="Confirm", style=nextcord.ButtonStyle.green, row=1)
async def confirm(
self, button: nextcord.ui.Button, interaction: nextcord.Interaction
):
"""
Submits the event embed to the event channel. Removes view and embed from recording message.
Sends point information to database.
"""
discord_users = self.event_participants.values.members
if discord_users:
discord_users_list: list[str] = [
str(user.id) for user in discord_users if user.id is not self.host_id
]
record_event_points(
self.config,
discord_users_list,
True,
self.config.params.event_participate_points,
)
non_discord_users = interaction.message.embeds[0].fields[1].value
if non_discord_users:
non_discord_users_list: list[str] = non_discord_users.split("\n")
record_event_points(
self.config,
non_discord_users_list,
False,
self.config.params.event_participate_points,
)
record_event_points(
self.config, [self.host_id], True, self.config.params.event_host_points
)
event_channel: nextcord.TextChannel = interaction.guild.get_channel(
self.config.params.event_post_channel_id
)
await event_channel.send(embed=interaction.message.embeds[0])
await interaction.response.edit_message(
content="Event has been submitted.", view=None, embed=None
)
self.stop()
class ParticipantModal(nextcord.ui.Modal):
"""
This modal contains all the text edits for an event. You can change the name, description, and add the usernames
of participants who are not in the discord.
"""
# TODO turn this embed into a dict
def __init__(self, embed):
super().__init__(
"Edit the event.",
timeout=5 * 60,
)
self.embed: nextcord.Embed = embed
self.name: nextcord.ui.TextInput = nextcord.ui.TextInput(
required=True,
label="Event Name",
default_value=self.embed.title,
)
self.description: nextcord.ui.TextInput = nextcord.ui.TextInput(
required=False,
label="Event Description",
default_value=self.embed.description,
style=TextInputStyle.paragraph,
placeholder="Add a description if desired.",
max_length=1000,
)
self.participants: nextcord.ui.TextInput = nextcord.ui.TextInput(
required=False,
label="Non-Discord Usernames",
style=TextInputStyle.paragraph,
placeholder="Please separate usernames with a new line.",
default_value=self.embed.fields[1].value,
)
self.add_item(self.name)
self.add_item(self.description)
self.add_item(self.participants)
async def callback(self, interaction: nextcord.Interaction):
self.embed.title = self.name.value
self.embed.description = self.description.value
self.embed.set_field_at(
index=1, name="Non-Discord Participants", value=self.participants.value
)
await interaction.response.edit_message(embed=self.embed)
class ParticipantSelect(nextcord.ui.UserSelect):
"""
A selection drop down for discord members. Updates the embed with all users selected.
"""
def __init__(self) -> None:
super().__init__(
min_values=1,
max_values=25,
placeholder="Select all participants",
row=0,
)
async def callback(self, interaction: nextcord.Interaction):
embed: nextcord.Embed = interaction.message.embeds[0]
participants: str = "\n".join(
[f"<@{participant.id}>" for participant in self.values.members]
)
embed.set_field_at(0, name="Participants", value=participants)
await interaction.response.edit_message(embed=embed)