Skip to content

Commit

Permalink
Merge branch 'main' into dependabot/pip/pip-e4c74ab98f
Browse files Browse the repository at this point in the history
  • Loading branch information
dimoschi authored Nov 21, 2024
2 parents 07971e4 + d9f6d5c commit d978b8d
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 59 deletions.
6 changes: 5 additions & 1 deletion .test.env
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,8 @@ HTB_API_KEY=CHANGE_ME

#Feedback Webhook

SLACK_WEBHOOK="https://hook.slack.com/sdfsdfsf"
SLACK_FEEDBACK_WEBHOOK="https://hook.slack.com/sdfsdfsf"

#Spoilers Webhook

JIRA_SPOILER_WEBHOOK="https://automation.atlassian.com/sdfsdfsf"
1 change: 1 addition & 0 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

110 changes: 63 additions & 47 deletions src/cmds/core/other.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import logging

import aiohttp
import discord
from discord import ApplicationContext, Embed, Interaction, Message, WebhookMessage, slash_command
from discord import ApplicationContext, Interaction, Message, slash_command
from discord.ext import commands
from discord.ui import InputText, Modal
from slack_sdk.webhook import WebhookClient
Expand All @@ -13,28 +14,29 @@


class FeedbackModal(Modal):
"""Modal for collecting user feedback."""

def __init__(self, *args, **kwargs) -> None:
"""Initialize the Feedback Modal with input fields."""
super().__init__(*args, **kwargs)

self.add_item(InputText(label="Title"))
self.add_item(InputText(label="Feedback", style=discord.InputTextStyle.long))

async def callback(self, interaction: discord.Interaction):

async def callback(self, interaction: discord.Interaction) -> None:
"""Handle the modal submission by sending feedback to Slack."""
await interaction.response.send_message("Thank you, your feedback has been recorded.", ephemeral=True)

webhook = WebhookClient(settings.SLACK_WEBHOOK) # Establish Slack Webhook
if interaction.user: # Protects against some weird edge-cases
webhook = WebhookClient(settings.SLACK_FEEDBACK_WEBHOOK)

if interaction.user:
title = f"{self.children[0].value} - {interaction.user.name}"
else:
title = f"{self.children[0].value}"
title = self.children[0].value

message_body = self.children[1].value
# Slack has no way to disallow @(@everyone calls), so we strip it out and replace it with a safe version
title = title.replace("@", "[at]").replace("<", "[bracket]")
message_body = message_body.replace("@", "[at]").replace("<", "[bracket]")

title = title.replace("@", "[at]").replace("<", "[bracket]")
message_body = message_body.replace("@", "[at]").replace("<", "[bracket]")

response = webhook.send(
text=f"{title} - {message_body}",
blocks=[
Expand All @@ -51,56 +53,70 @@ async def callback(self, interaction: discord.Interaction):
assert response.body == "ok"


class SpoilerModal(Modal):
"""Modal for reporting a spoiler."""

def __init__(self, *args, **kwargs) -> None:
"""Initialize the Spoiler Modal with input fields."""
super().__init__(*args, **kwargs)
self.add_item(InputText(label="URL", placeholder="Enter the spoiler URL", style=discord.InputTextStyle.long))

async def callback(self, interaction: discord.Interaction) -> None:
"""Handle the modal submission by sending the spoiler report to JIRA."""
await interaction.response.send_message("Thank you, the spoiler has been reported.", ephemeral=True)

user_name = interaction.user.display_name
url = self.children[0].value

webhook_url = settings.JIRA_SPOILER_WEBHOOK

payload = {
"user": user_name,
"url": url,
}

async with aiohttp.ClientSession() as session:
try:
async with session.post(webhook_url, json=payload) as response:
if response.status != 200:
logger.error(f"Failed to send to JIRA: {response.status} - {await response.text()}")
except Exception as e:
logger.error(f"Error sending to JIRA: {e}")


class OtherCog(commands.Cog):
"""Ban related commands."""
"""Other commands related to the bot."""

def __init__(self, bot: Bot):
self.bot = bot

@slash_command(guild_ids=settings.guild_ids, description="A simple reply stating hints are not allowed.")
async def no_hints(
self, ctx: ApplicationContext
) -> Message:
"""A simple reply stating hints are not allowed."""
async def no_hints(self, ctx: ApplicationContext) -> Message:
"""Reply stating that hints are not allowed."""
return await ctx.respond(
"No hints are allowed for the duration the event is going on. This is a competitive event with prizes. "
"Once the event is over you are more then welcome to share solutions/write-ups/etc and try them in the "
"After Party event."
"No hints are allowed for the duration of the event. Once the event is over, feel free to share solutions."
)

@slash_command(guild_ids=settings.guild_ids,
description="A simple reply proving a link to the support desk article on how to get support")
@slash_command(guild_ids=settings.guild_ids, description="Link to the support desk article.")
@commands.cooldown(1, 60, commands.BucketType.user)
async def support(
self, ctx: ApplicationContext
) -> Message:
"""A simple reply proving a link to the support desk article on how to get support"""
return await ctx.respond(
"https://help.hackthebox.com/en/articles/5986762-contacting-htb-support"
)

@slash_command(guild_ids=settings.guild_ids, description="Add the URL which has spoiler link.")
async def spoiler(self, ctx: ApplicationContext, url: str) -> Interaction | WebhookMessage:
"""Add the URL which has spoiler link."""
if len(url) == 0:
return await ctx.respond("Please provide the spoiler URL.")

embed = Embed(title="Spoiler Report", color=0xB98700)
embed.add_field(name=f"{ctx.user} has submitted a spoiler.", value=f"URL: <{url}>", inline=False)

channel = self.bot.get_channel(settings.channels.SPOILER)
await channel.send(embed=embed)
return await ctx.respond("Thanks for the reporting the spoiler.", ephemeral=True, delete_after=15)
async def support(self, ctx: ApplicationContext) -> Message:
"""Provide a link to the support desk article."""
return await ctx.respond("https://help.hackthebox.com/en/articles/5986762-contacting-htb-support")

@slash_command(guild_ids=settings.guild_ids, description="Add a URL which contains a spoiler.")
async def spoiler(self, ctx: ApplicationContext) -> Interaction:
"""Report a URL that contains a spoiler."""
modal = SpoilerModal(title="Report Spoiler")
return await ctx.send_modal(modal)

@slash_command(guild_ids=settings.guild_ids, description="Provide feedback to HTB!")
@slash_command(guild_ids=settings.guild_ids, description="Provide feedback to HTB.")
@commands.cooldown(1, 60, commands.BucketType.user)
async def feedback(self, ctx: ApplicationContext) -> Interaction:
""" Provide Feedback to HTB """
# Send the Modal defined above in Feedback Modal, which handles the callback
"""Provide feedback to HTB."""
modal = FeedbackModal(title="Feedback")
return await ctx.send_modal(modal)


def setup(bot: Bot) -> None:
"""Load the `ChannelManageCog` cog."""
"""Load the OtherCog cog."""
bot.add_cog(OtherCog(bot))
3 changes: 2 additions & 1 deletion src/core/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ class Global(BaseSettings):
WEBHOOK_PORT: int = 1337
WEBHOOK_TOKEN: str = ""

SLACK_WEBHOOK: str = ""
SLACK_FEEDBACK_WEBHOOK: str = ""
JIRA_SPOILER_WEBHOOK: str = ""

ROOT: Path = None

Expand Down
15 changes: 5 additions & 10 deletions src/views/bandecisionview.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,8 @@ def __init__(self, ban_id: int, bot: Bot, guild: Guild, member: Member | User, e

# Disable all buttons and update the message to reflect the decision

async def disable_buttons_and_update_message(self, interaction: Interaction, decision: str) -> None:
"""Disable all buttons and update the message to reflect the decision."""
# Disable all buttons
for item in self.children:
if isinstance(item, Button):
item.disabled = True

async def update_message(self, interaction: Interaction, decision: str) -> None:
"""Update the message to reflect the decision. Decision can always be overturned."""
# Edit the original message to reflect the decision and who made it
admin_name = interaction.user.display_name
decision_message = f"{admin_name} has made a decision: **{decision}** for {self.member.display_name}."
Expand All @@ -56,7 +51,7 @@ async def approve_button(self, button: Button, interaction: Interaction) -> None
f"Ban duration for {self.member.display_name} has been approved by {interaction.user.display_name}."
)
# Disable buttons and update message after approval
await self.disable_buttons_and_update_message(interaction, "Approved Duration")
await self.update_message(interaction, "Approved Duration")

@discord.ui.button(label="Deny and unban", style=discord.ButtonStyle.danger, custom_id="deny_button")
async def deny_button(self, button: Button, interaction: Interaction) -> None:
Expand All @@ -70,7 +65,7 @@ async def deny_button(self, button: Button, interaction: Interaction) -> None:
f"Ban for {self.member.display_name} has been denied by {interaction.user.display_name} and the member has been unbanned."
)
# Disable buttons and update message after denial
await self.disable_buttons_and_update_message(interaction, "Denied and Unbanned")
await self.update_message(interaction, "Denied and Unbanned")

@discord.ui.button(label="Dispute", style=discord.ButtonStyle.primary, custom_id="dispute_button")
async def dispute_button(self, button: Button, interaction: Interaction) -> None:
Expand Down Expand Up @@ -139,4 +134,4 @@ async def callback(self, interaction: Interaction) -> None:
)

# Disable buttons and update message on the parent view after dispute
await self.parent_view.disable_buttons_and_update_message(interaction, "Disputed Duration")
await self.parent_view.update_message(interaction, "Disputed Duration")

0 comments on commit d978b8d

Please sign in to comment.