GalaxyCogs/issues/issues.py
SeaswimmerTheFsh 1f26e32852
Some checks reported warnings
Gitea Actions Demo / Explore-Gitea-Actions (push) Has been cancelled
feat(issues): added url to embed title
2023-08-19 17:36:58 -04:00

251 lines
13 KiB
Python

import asyncio
import aiohttp
import discord
from discord.interactions import Interaction
from redbot.core import Config, app_commands, commands, checks
class Issues(commands.Cog):
"""This cog allows you to create Gitea issues through a Discord modal.
Developed by SeaswimmerTheFsh."""
def __init__(self, bot):
self.bot = bot
self.config = Config.get_conf(self, identifier=4285273314713, force_registration=True)
self.config.register_global(
request_channel = None,
gitea_repository_url = None,
gitea_token = None
)
@commands.command()
@checks.is_owner()
async def issuesconfig(self, ctx: commands.Context, channel: discord.TextChannel = None):
if channel:
await self.config.request_channel.set(channel.id)
await ctx.send(content=f"Channel set to {channel.mention}.\nRun this command again without a channel argument to configure the other settings.")
else:
await ctx.channel.send(content="Click the button below to configure the cog.", view=self.IssueConfigurationButton(self.config, ctx))
@app_commands.command()
async def issuestest(self, interaction: discord.Interaction):
color = await self.bot.get_embed_color(None)
await interaction.response.send_message(content="Hello world!", view=self.IssueButtons(color, self, interaction), ephemeral=True)
async def submit_issue_request(self, interaction: discord.Interaction, original_interaction: discord.Interaction, embed: discord.Embed):
channel = self.bot.get_channel(await self.config.request_channel())
if channel is None:
await original_interaction.edit_original_response(content="Command cancelled.", view=None)
await interaction.response.send_message(content=f"The cog is misconfigured, please report this error.", ephemeral=True)
try:
message = await channel.send(content=".")
await message.edit(content="", embed=embed, view=self.IssueResponseButtons(channel, message.id, interaction.user))
await original_interaction.edit_original_response(content=f"Issue request sent!", embed=embed, view=None)
await interaction.response.defer()
except (discord.HTTPException, discord.Forbidden) as error:
await original_interaction.edit_original_response(content="Command cancelled.", view=None)
await interaction.response.send_message(content=f"The cog is misconfigured, please report this error.\n```{error}```", ephemeral=True)
class IssueButtons(discord.ui.View):
def __init__(self, color, cog_instance, original_interaction):
super().__init__()
self.color = color
self.cog_instance = cog_instance
self.original_interaction = original_interaction
@discord.ui.button(label="Bot Bug", style=discord.ButtonStyle.danger, row=0)
async def issue_button_bot_bug(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Issues.BotBugModal(self.color, self.cog_instance, self.original_interaction))
@discord.ui.button(label="Cog Bug", style=discord.ButtonStyle.danger, row=1)
async def issue_button_cog_bug(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Issues.BotBugModal(self.color, self.cog_instance, self.original_interaction))
@discord.ui.button(label="Bot Suggestion", style=discord.ButtonStyle.blurple, row=0)
async def issue_button_bot_suggestion(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Issues.BotBugModal(self.color, self.cog_instance, self.original_interaction))
@discord.ui.button(label="Cog Suggestion", style=discord.ButtonStyle.blurple, row=1)
async def issue_button_cog_suggestion(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Issues.BotBugModal(self.color, self.cog_instance, self.original_interaction))
class BotBugModal(discord.ui.Modal, title="Creating issue..."):
def __init__(self, color, cog_instance, original_interaction):
super().__init__()
self.color = color
self.cog_instance = cog_instance
self.original_interaction = original_interaction
bug_description = discord.ui.TextInput(
label="Describe the bug",
placeholder="A clear and concise description of what the bug is.",
style=discord.TextStyle.paragraph,
max_length=2048
)
reproduction_steps = discord.ui.TextInput(
label="To Reproduce",
placeholder="What caused the bug?",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
expected_behavior = discord.ui.TextInput(
label="Expected Behavior",
placeholder="A clear and concise description of what you expected to happen.",
style=discord.TextStyle.paragraph,
required=True,
max_length=2048
)
additional_context = discord.ui.TextInput(
label="Additional Context",
placeholder="Add any other context about the problem here.",
style=discord.TextStyle.paragraph,
required=False,
max_length=2048
)
async def on_submit(self, interaction: discord.Interaction):
embed = discord.Embed(title = "Issue Request", color = self.color)
fields = [self.bug_description, self.reproduction_steps, self.expected_behavior, self.additional_context]
for item in fields:
title = item.label
value = item.value
if value is not None:
if len(value) > 1024:
words = value.split()
split_value = []
current_part = ""
for word in words:
if len(current_part) + len(word) + 1 <= 1024:
current_part += word + " "
else:
split_value.append(current_part.strip())
current_part = word + " "
if current_part:
split_value.append(current_part.strip())
for i, part in enumerate(split_value):
embed.add_field(name=title if i == 0 else "\u200b", value=part, inline=False)
else:
embed.add_field(name=title, value=value, inline=False)
if interaction.user.discriminator == '0':
username = interaction.user.name
else:
username = f"{interaction.user.name}#{interaction.user.discriminator}"
embed.set_footer(text=f"Submitted by {username} ({interaction.user.id})", icon_url=interaction.user.display_avatar.url)
embed.set_author(name="Bot Bug Report")
await self.cog_instance.submit_issue_request(interaction=interaction, original_interaction=self.original_interaction, embed=embed)
class IssueConfigurationButton(discord.ui.View):
def __init__(self, config, ctx):
super().__init__()
self.config = config
self.ctx = ctx
@discord.ui.button(label="Change Configuration", style=discord.ButtonStyle.blurple, row=0)
async def issue_configuration_button(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Issues.IssuesConfigurationModal(self.config, self.ctx))
class IssuesConfigurationModal(discord.ui.Modal, title="Modifying configuration..."):
def __init__(self, config, ctx):
super().__init__()
self.config = config
self.ctx = ctx
gitea_repository_url = discord.ui.TextInput(
label="Gitea Repository URL",
placeholder="https://try.gitea.io/owner/repository",
style=discord.TextStyle.short,
max_length=200
)
gitea_token = discord.ui.TextInput(
label="Gitea User Access Token",
placeholder="Generate one from your user settings page.",
style=discord.TextStyle.short,
max_length=200
)
async def on_submit(self, interaction: discord.Interaction):
if self.gitea_token.value is not None:
await self.config.gitea_token.set(self.gitea_token.value)
if self.gitea_repository_url.value is not None:
await self.config.gitea_repository_url.set(self.gitea_repository_url.value)
await interaction.response.send_message(content="Configuration changed!")
class IssueResponseButtons(discord.ui.View):
def __init__(self, channel, message_id, user):
super().__init__()
self.channel = channel
self.message_id = message_id
self.user = user
@discord.ui.button(label="Approve", style=discord.ButtonStyle.green)
async def issue_response_button_approve(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Issues.IssueResponseModal(self.channel, self.message_id, self.user, True))
@discord.ui.button(label="Deny", style=discord.ButtonStyle.danger)
async def issue_response_button_deny(self, interaction: discord.Interaction, button: discord.ui.Button):
await interaction.response.send_modal(Issues.IssueResponseModal(self.channel, self.message_id, self.user, False))
class IssueResponseModal(discord.ui.Modal, title="Sending response message..."):
def __init__(self, channel, message_id, user, approved):
super().__init__()
self.channel = channel
self.message_id = message_id
self.user = user
self.approved = approved
self.config = Config.get_conf(None, cog_name='Issues', identifier=4285273314713)
response = discord.ui.TextInput(
label="Response",
placeholder="",
style=discord.TextStyle.paragraph,
required=False,
max_length=1024
)
async def on_submit(self,interaction: discord.Interaction):
message: discord.Message = await self.channel.fetch_message(self.message_id)
embed = message.embeds[0]
field_values = []
field_names = []
if self.approved:
embed.color = 1226519
embed.title = "Issue Request Approved"
status = "accepted"
else:
embed.color = 15671552
embed.title = "Issue Request Denied"
status = "denied"
await interaction.response.send_message(content=f"Issue request {status}.")
if self.response.value is not None:
embed.add_field(name=f"Response from {interaction.user.name}", value=self.response.value, inline=False)
if self.approved:
for field in embed.fields:
field_names.append(f"**{field.name}**")
field_values.append(field.value)
if embed.author.name == "Bot Bug Report":
issue_title = f"[BOT BUG] Automatically generated issue"
elif embed.author.name == "Bot Suggestion":
issue_title = f"[BOT SUGGESTION] Automatically generated issue"
elif embed.author.name == "Cog Bug Report" or embed.author.name == "Cog Suggestion":
issue_title = f"[{field_values[0]}] Automatically generated issue"
headers = {
"Authorization": f"Bearer {await self.config.gitea_token()}",
"Accept": "application/json"
}
url = await self.config.gitea_repository_url()
issue_body = "\n".join([f"{name}\n{value}" for name, value in zip(field_names, field_values)])
issue_data = {
"title": issue_title,
"body": issue_body
}
async def create_issue():
async with aiohttp.ClientSession(headers=headers) as session:
async with session.post(url, json=issue_data) as response:
return await response.json(), response.status
response_json, status_code = await create_issue()
if status_code == 201:
await interaction.response.send_message(content=f"Issue request {status}.\n[Issue successfully created.]({response_json.get('html_url')})", ephemeral=True)
embed.url = response_json.get('html_url')
await message.edit(embed=embed, view=None)
await self.user.send(embed=embed)