diff --git a/cogs/message_listener/__init__.py b/cogs/message_listener/__init__.py index 846fdf2..93a1792 100644 --- a/cogs/message_listener/__init__.py +++ b/cogs/message_listener/__init__.py @@ -19,11 +19,14 @@ class SubmissionListener(commands.Cog, name="Message Listener"): async def on_message(self, proof_message: nextcord.Message): """Listener for message creation. Adds score and attachments to submission.""" if proof_message.author.id in submission_messages: - message_id = submission_messages[proof_message.author.id] + message_id = submission_messages[proof_message.author.id]["message_id"] submission_message: nextcord.Message = await self.bot.get_channel( highscores_data["submission_channel_id"] ).fetch_message(message_id) + # TODO only want to do things when on certain steps + # want to regex score to ensure it is correct. here is also where score can be standardized in look + # need check if correct user and correct channel if proof_message.channel.id == highscores_data["submission_channel_id"]: diff --git a/cogs/submission/submission_views.py b/cogs/submission/submission_views.py index 4d5ef2f..149ddb4 100644 --- a/cogs/submission/submission_views.py +++ b/cogs/submission/submission_views.py @@ -23,12 +23,136 @@ class SubmissionState(Enum): SUBMIT = 5 -def embedFromState(state: SubmissionState) -> nextcord.Embed: - embed = Embed(title="submission for thingy", description="a description i guess") - embed.add_field(name="State", value=state) +def get_submission_embed(userid: int) -> nextcord.Embed: + """Creates an embed based off of the submission state and fields filled out.""" + usersubmission: dict = submission_messages[userid] + state: SubmissionState = usersubmission["submission_state"] + + if state is SubmissionState.CATEGORY: + description = "Step 1: Choose your category!" + elif state is SubmissionState.SCORE: + description = "Step 2: Input your score!" + elif state is SubmissionState.PROOF: + description = "Step 3: Submit your proof!" + elif state is SubmissionState.NAME: + description = "Step 4 (Optional): Change name on submission! (proceed to next if skipping)" + elif state is SubmissionState.SUBMIT: + description = "Step 5: Submit if everything looks correct!" + + embed = Embed(title="Highscores Submission", description=description) + embed.add_field(name="User Name", value=usersubmission["username"], inline=False) + embed.add_field(name="Boss", value=usersubmission["boss_name"], inline=False) + if usersubmission["category"]: + embed.add_field(name="Category", value=usersubmission["category"], inline=False) + if usersubmission["score"]: + embed.add_field(name="Score", value=usersubmission["score"], inline=False) return embed +def category_select_options(boss_name: str) -> "list[nextcord.SelectOption]": + """Returns list of categories for a given boss.""" + options: "list[nextcord.SelectOption]" = [] + boss_dict = highscores_data[boss_name] + for category in boss_dict["categories"].items(): + options.append(nextcord.SelectOption(label=category[0])) + + return options + + +############ Items used in submission process ############ + + +class SubmissionDropdown(nextcord.ui.Select): + """Defines dropdown menu for submission""" + + def __init__( + self, + bot: commands.Bot, + options: "list[nextcord.SelectOption]", + ): + super().__init__( + placeholder="Choose submission category.", min_values=1, max_values=1, options=options + ) + self._bot = bot + + async def callback(self, interaction: nextcord.Interaction): + submission_messages[interaction.user.id]["category"] = self.values[0] + embed = get_submission_embed(interaction.user.id) + await interaction.message.edit( + embed=embed, + ) + + +class BackButton(nextcord.ui.Button): + """Defines view for back button.""" + + def __init__(self, bot: commands.Bot): + super().__init__(label="Back", style=nextcord.ButtonStyle.primary, custom_id="back") + self._bot = bot + + async def callback(self, interaction: nextcord.Interaction): + state: SubmissionState = submission_messages[interaction.user.id]["submission_state"] + state = SubmissionState(state.value - 1) + submission_messages[interaction.user.id]["submission_state"] = state + embed = get_submission_embed(interaction.user.id) + await interaction.edit(embed=embed, view=SubmissionView(self._bot, interaction.user.id)) + + +class CancelButton(nextcord.ui.Button): + """Deletes message to cancel interaction..""" + + def __init__(self): + super().__init__(label="Cancel", style=nextcord.ButtonStyle.red, custom_id="cancel") + + async def callback(self, interaction: nextcord.Interaction): + submission_messages.pop(interaction.user.id) + await interaction.message.delete() + + +class NextButton(nextcord.ui.Button): + """Defines view for next button.""" + + def __init__(self, bot: commands.Bot): + super().__init__(label="Next", style=nextcord.ButtonStyle.primary, custom_id="next") + self._bot = bot + + # TODO verify proper information has been gathered + async def callback(self, interaction: nextcord.Interaction): + state: SubmissionState = submission_messages[interaction.user.id]["submission_state"] + state = SubmissionState(state.value + 1) + submission_messages[interaction.user.id]["submission_state"] = state + embed = get_submission_embed(interaction.user.id) + await interaction.edit(embed=embed, view=SubmissionView(self._bot, interaction.user.id)) + + +class SubmitButton(nextcord.ui.Button): + """Defines button to submit a user's score.""" + + def __init__(self, bot: commands.Bot): + super().__init__(label="Submit", style=nextcord.ButtonStyle.green, custom_id="submit") + self._bot = bot + + async def callback(self, interaction: nextcord.Interaction): + verification_channel_id = highscores_data["verification_channel_id"] + channel = self._bot.get_channel(verification_channel_id) + + error_response = "Registered Verification channel does not exist or was never registered. \ + Contact server admins." + assert channel is not None, await channel.send(error_response) + + await channel.send( + files=[await attch.to_file() for attch in interaction.message.attachments], + view=VerificationView(), + embed=interaction.message.embeds[0], + content=f"Submission from {interaction.user.display_name}", + ) + await interaction.message.edit(content=f"<@{interaction.user.id}> Submitted!", view=None) + submission_messages.pop(interaction.user.id) + + +############ Submission Views ############ + + class SubmissionCreateButton(nextcord.ui.View): """Defines view for score submission button.""" @@ -49,154 +173,64 @@ class SubmissionCreateButton(nextcord.ui.View): # embed.add_field(name="Boss", value=boss_name, inline=False) # embed.add_field(name="User", value=interaction.user.display_name, inline=False) channel = self._bot.get_channel(highscores_data["submission_channel_id"]) - embed = embedFromState(SubmissionState.CATEGORY) + + # a user should only have 1 submission active at once. + # submitting with dummy message_id until message created + submission_messages[interaction.user.id] = { + "message_id": 0, + "submission_state": SubmissionState.CATEGORY, + "boss_name": boss_name, + "score": "", + "category": "", + "username": interaction.user.display_name.split("|")[0][:12], + } + + embed = get_submission_embed(interaction.user.id) + submission_message = await channel.send( f"<@{interaction.user.id}>", view=SubmissionView( - self._bot, interaction, await self._category_select_options(boss_name) + self._bot, + interaction.user.id, ), embed=embed, ) - # a user should only have 1 submission active at once. - submission_messages[interaction.user.id] = { - "message_id": submission_message.id, - "submission_state": SubmissionState.CATEGORY, - } - - async def _category_select_options(self, boss_name: str) -> "list[nextcord.SelectOption]": - options: "list[nextcord.SelectOption]" = [] - boss_dict = highscores_data[boss_name] - for category in boss_dict["categories"].items(): - options.append(nextcord.SelectOption(label=category[0])) - - return options - - -class SubmissionDropdown(nextcord.ui.Select): - """Defines dropdown menu for submission""" - - def __init__( - self, - bot: commands.Bot, - options: "list[nextcord.SelectOption]", - ): - super().__init__( - placeholder="Choose submission category.", min_values=1, max_values=1, options=options - ) - self._bot = bot - - async def callback(self, interaction: nextcord.Interaction): - embed = interaction.message.embeds[0] - embed.add_field(name="Category", value=self.values[0], inline=False) - await interaction.message.edit( - embed=embed, - ) + # update the message_id once its created + submission_messages[interaction.user.id]["message_id"] = submission_message.id class SubmissionView(nextcord.ui.View): - """Defines submission dropdown process view""" + """Defines view submitting. Adjusts to all states.""" def __init__( self, bot: commands.Bot, - creation_interaction: nextcord.Interaction, - options: "list[nextcord.SelectOption]", + submission_user: int, *, timeout: Optional[float] = 180, ): super().__init__(timeout=timeout) - # self.add_item(SubmissionDropdown(bot, options)) - self.add_item(CancelButton(bot)) - self.add_item(NextButton(bot)) - self._creation_interaction = creation_interaction - self.bot = bot + self._submission_user = submission_user + self._bot = bot + self._state = submission_messages[self._submission_user]["submission_state"] + self._boss_name = submission_messages[self._submission_user]["boss_name"] + + # add items depending on given state + if self._state is SubmissionState.CATEGORY: + self.add_item(SubmissionDropdown(bot, category_select_options(self._boss_name))) + self.add_item(CancelButton()) + self.add_item(NextButton(self._bot)) + elif ( + self._state is SubmissionState.SCORE + or self._state is SubmissionState.PROOF + or self._state is SubmissionState.NAME + ): + self.add_item(BackButton(self._bot)) + self.add_item(NextButton(self._bot)) + elif self._state is SubmissionState.SUBMIT: + self.add_item(BackButton(self._bot)) + self.add_item(SubmitButton(self._bot)) async def interaction_check(self, interaction: nextcord.Interaction) -> bool: - return self._creation_interaction.user == interaction.user - - # @nextcord.ui.button( - # label="Submit Score", style=nextcord.ButtonStyle.green, custom_id="submit-score" - # ) - # async def submit_button( - # self, button: nextcord.ui.Button, interaction: nextcord.Interaction - # ): # pylint: disable=unused-argument - # """Defines button to submit a user's score.""" - # verification_channel_id = highscores_data["verification_channel_id"] - # channel = self.bot.get_channel(verification_channel_id) - - # error_response = "Registered Verification channel does not exist or was never registered. \ - # Contact server admins." - # assert channel is not None, await channel.send(error_response) - - # await channel.send( - # files=[await attch.to_file() for attch in interaction.message.attachments], - # view=VerificationView(), - # embed=interaction.message.embeds[0], - # ) - # await interaction.message.edit(content=f"<@{interaction.user.id}> Submitted!", view=None) - # submission_messages.pop(interaction.user.id) - - # @nextcord.ui.button( - # label="Cancel", style=nextcord.ButtonStyle.red, custom_id="cancel-submission" - # ) - # async def cancel_button( - # self, button: nextcord.ui.Button, interaction: nextcord.Interaction - # ): # pylint: disable=unused-argument - # """Deletes message to cancel interaction.""" - # submission_messages.pop(interaction.user.id) - # await interaction.message.delete() - - -# class BackButton(nextcord.ui.View): -# """Defines view for back button.""" - -# def __init__(self, bot: commands.Bot): -# super().__init__(timeout=None) -# self._bot = bot - -# @nextcord.ui.button(label="Back", style=nextcord.ButtonStyle.primary, custom_id="back") -# async def back_button( -# self, button: nextcord.ui.Button, interaction: nextcord.Interaction -# ): # pylint: disable=unused-argument -# pass - - -class CancelButton(nextcord.ui.Button): - """Defines view for cancel button.""" - - def __init__(self, bot: commands.Bot): - super().__init__(label="Cancel", style=nextcord.ButtonStyle.red, custom_id="cancel") - self._bot = bot - - async def callback(self, interaction: nextcord.Interaction): # pylint: disable=unused-argument - pass - - -class NextButton(nextcord.ui.Button): - """Defines view for next button.""" - - def __init__(self, bot: commands.Bot): - super().__init__(label="Next", style=nextcord.ButtonStyle.primary, custom_id="next") - self._bot = bot - - async def callback(self, interaction: nextcord.Interaction): # pylint: disable=unused-argument - state: SubmissionState = submission_messages[interaction.user.id]["submission_state"] - state = SubmissionState(state.value + 1) - submission_messages[interaction.user.id]["submission_state"] = state - embed = embedFromState(state) - await interaction.edit(embed=embed) - - -# class SubmitButton(nextcord.ui.View): -# """Defines view for submit button.""" - -# def __init__(self, bot: commands.Bot): -# super().__init__(timeout=None) -# self._bot = bot - -# @nextcord.ui.button(label="Submit", style=nextcord.ButtonStyle.green, custom_id="submit") -# async def submit_button( -# self, button: nextcord.ui.Button, interaction: nextcord.Interaction -# ): # pylint: disable=unused-argument -# pass + return self._submission_user == interaction.user.id