2022-08-06 02:01:29 +02:00
|
|
|
from copy import deepcopy
|
|
|
|
import json
|
|
|
|
from json.decoder import JSONDecodeError
|
|
|
|
import logging
|
2023-05-31 20:07:39 +02:00
|
|
|
from interactions import (
|
2022-08-06 02:01:29 +02:00
|
|
|
Client,
|
|
|
|
Extension,
|
|
|
|
slash_command,
|
|
|
|
InteractionContext,
|
|
|
|
Modal,
|
|
|
|
ParagraphText,
|
|
|
|
ModalContext,
|
|
|
|
context_menu,
|
|
|
|
Permissions,
|
2023-05-31 20:07:39 +02:00
|
|
|
CommandType,
|
2022-08-06 02:01:29 +02:00
|
|
|
Message,
|
|
|
|
)
|
|
|
|
|
|
|
|
from database import BotMessages as BotMessagesModel
|
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Template modal for creating/editing bot messages.
|
2022-08-06 02:01:29 +02:00
|
|
|
message_creation_modal = Modal(
|
|
|
|
custom_id="bot-message-create",
|
2022-10-15 03:35:42 +02:00
|
|
|
title="Create a message as the bot",
|
2023-05-31 20:07:39 +02:00
|
|
|
*[
|
2022-08-06 02:01:29 +02:00
|
|
|
ParagraphText(
|
|
|
|
custom_id="embeds",
|
|
|
|
label="Embeds",
|
|
|
|
placeholder="Embeds as JSON",
|
|
|
|
required=False,
|
|
|
|
),
|
|
|
|
ParagraphText(
|
|
|
|
custom_id="content",
|
|
|
|
label="Text",
|
|
|
|
placeholder="Lorem ipsum dolor sit amet and so on",
|
|
|
|
required=False,
|
|
|
|
),
|
|
|
|
]
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
class BotMessages(Extension):
|
|
|
|
def __init__(self, client: Client) -> None:
|
|
|
|
self.client = client
|
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Create a new bot message.
|
2022-08-06 02:01:29 +02:00
|
|
|
@slash_command(
|
|
|
|
name="bot-message-create",
|
|
|
|
description="Create a message as the bot.",
|
|
|
|
dm_permission=False,
|
|
|
|
default_member_permissions=Permissions.MANAGE_GUILD,
|
|
|
|
)
|
|
|
|
async def bot_message_create_command(self, ctx: InteractionContext):
|
2022-08-11 01:39:15 +02:00
|
|
|
# Respond with the template modal. No values have been set in the modal, as it is
|
|
|
|
# a new message.
|
2022-08-06 02:01:29 +02:00
|
|
|
await ctx.send_modal(message_creation_modal)
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Wait for the user to submit the modal, and ensure that we are receiving the
|
|
|
|
# correct modal.
|
2022-08-06 02:01:29 +02:00
|
|
|
modal_ctx: ModalContext = await self.client.wait_for_modal(message_creation_modal, author=ctx.author)
|
|
|
|
if modal_ctx.custom_id != "bot-message-create":
|
|
|
|
return
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Retrieve the values from the modal.
|
|
|
|
# Ensure that at least one of the fields is filled in, as a message cannot be
|
|
|
|
# empty.
|
2022-08-06 02:01:29 +02:00
|
|
|
embeds_string: str = modal_ctx.responses["embeds"]
|
|
|
|
content_string: str = modal_ctx.responses["content"]
|
|
|
|
if (
|
|
|
|
(embeds_string is None or embeds_string == "")
|
|
|
|
and (content_string is None or content_string == "")
|
|
|
|
):
|
|
|
|
await modal_ctx.send(
|
|
|
|
"You must provide either an embed or text.",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Attempt to parse the embed(s) JSON into a Python object.
|
|
|
|
# Try loading it as a single or multiple embeds depending on if the object
|
|
|
|
# returned is a list or a dictionary.
|
|
|
|
# If the JSON is invalid, return an error.
|
2022-08-06 02:01:29 +02:00
|
|
|
embed: dict | None = None
|
|
|
|
embeds: list | None = None
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-06 02:01:29 +02:00
|
|
|
try:
|
|
|
|
if embeds_string:
|
|
|
|
embeds_temp = json.loads(embeds_string)
|
|
|
|
if isinstance(embeds_temp, list):
|
|
|
|
embeds = embeds_temp
|
|
|
|
elif isinstance(embeds_temp, dict):
|
|
|
|
embed = embeds_temp
|
|
|
|
except JSONDecodeError:
|
|
|
|
await modal_ctx.send(
|
|
|
|
"The embeds were not valid JSON.",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
return
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Send the bot message in the channel.
|
2022-08-06 02:01:29 +02:00
|
|
|
msg = await ctx.channel.send(
|
|
|
|
content=content_string if content_string else None,
|
|
|
|
embed=embed,
|
|
|
|
embeds=embeds,
|
|
|
|
)
|
2022-08-11 01:39:15 +02:00
|
|
|
|
|
|
|
# Add an entry of the message in the database.
|
2022-08-06 02:01:29 +02:00
|
|
|
BotMessagesModel.create(
|
|
|
|
guild_id=msg.guild.id,
|
|
|
|
channel_id=msg.channel.id,
|
|
|
|
message_id=msg.id,
|
|
|
|
)
|
2022-08-11 01:39:15 +02:00
|
|
|
|
|
|
|
# Send a confirmation message, as Discord requires us to respond to the interaction.
|
2022-08-06 02:01:29 +02:00
|
|
|
await modal_ctx.send(
|
|
|
|
"Message created!",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# A context menu to allow moderators to edit a bot message.
|
2022-08-06 02:01:29 +02:00
|
|
|
@context_menu(
|
|
|
|
name="Edit bot message",
|
2023-05-31 20:07:39 +02:00
|
|
|
context_type=CommandType.MESSAGE,
|
2022-08-06 02:01:29 +02:00
|
|
|
dm_permission=False,
|
|
|
|
default_member_permissions=Permissions.MANAGE_GUILD,
|
|
|
|
)
|
|
|
|
async def edit_bot_message_context_menu(self, ctx: InteractionContext):
|
|
|
|
message: Message = ctx.target
|
2022-08-11 01:39:15 +02:00
|
|
|
|
|
|
|
# Ensure that the target message is from the bot.
|
|
|
|
# If it is not, return an error.
|
2022-08-06 02:01:29 +02:00
|
|
|
if message.author.id != self.client.user.id:
|
|
|
|
await ctx.send(
|
|
|
|
"This is not a bot message.",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Retrieve the bot message from the database, if any.
|
|
|
|
bot_message: BotMessagesModel | None = BotMessagesModel.get_or_none(
|
2022-08-06 02:01:29 +02:00
|
|
|
BotMessagesModel.guild_id == message.channel.guild.id,
|
|
|
|
BotMessagesModel.channel_id == message.channel.id,
|
|
|
|
BotMessagesModel.message_id == message.id,
|
|
|
|
)
|
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# If there is no bot message, return an error.
|
2022-08-06 02:01:29 +02:00
|
|
|
if bot_message is None:
|
|
|
|
await ctx.send(
|
|
|
|
"This is not an editable bot message.",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
return
|
2022-08-11 01:39:15 +02:00
|
|
|
|
|
|
|
# Create a copy of the template modal, and insert the contents of the bot message.
|
2022-08-06 02:01:29 +02:00
|
|
|
modal = deepcopy(message_creation_modal)
|
|
|
|
modal.title = "Edit bot message"
|
2022-08-11 01:39:15 +02:00
|
|
|
modal.custom_id = "bot-message-edit"
|
2022-08-06 02:01:29 +02:00
|
|
|
modal.components[0].value = json.dumps(
|
|
|
|
[e.to_dict() for e in message.embeds] if message.embeds else "",
|
|
|
|
indent=4,
|
|
|
|
)
|
|
|
|
modal.components[1].value = message.content
|
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Send the modal to the user
|
2022-08-06 02:01:29 +02:00
|
|
|
await ctx.send_modal(modal)
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-11 01:39:15 +02:00
|
|
|
# Wait for the user to submit the modal, and ensure that we are receiving the
|
|
|
|
# correct modal.
|
2022-08-06 02:01:29 +02:00
|
|
|
modal_ctx: ModalContext = await self.client.wait_for_modal(modal, author=ctx.author)
|
2022-08-11 01:39:15 +02:00
|
|
|
if modal_ctx.custom_id != "bot-message-edit":
|
2022-08-06 02:01:29 +02:00
|
|
|
return
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-06 02:01:29 +02:00
|
|
|
embeds_string: str = modal_ctx.responses["embeds"]
|
|
|
|
content_string: str = modal_ctx.responses["content"]
|
|
|
|
if (
|
|
|
|
(embeds_string is None or embeds_string == "")
|
|
|
|
and (content_string is None or content_string == "")
|
|
|
|
):
|
|
|
|
await modal_ctx.send(
|
|
|
|
"You must provide either an embed or text.",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
return
|
|
|
|
|
|
|
|
embed: dict | None = None
|
|
|
|
embeds: list | None = None
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-06 02:01:29 +02:00
|
|
|
try:
|
|
|
|
if embeds_string:
|
|
|
|
embeds_temp = json.loads(embeds_string)
|
|
|
|
if isinstance(embeds_temp, list):
|
|
|
|
embeds = embeds_temp
|
|
|
|
elif isinstance(embeds_temp, dict):
|
|
|
|
embed = embeds_temp
|
|
|
|
except JSONDecodeError:
|
|
|
|
await modal_ctx.send(
|
|
|
|
"The embeds were not valid JSON.",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
return
|
2022-10-15 03:35:42 +02:00
|
|
|
|
2022-08-06 02:01:29 +02:00
|
|
|
await message.edit(
|
|
|
|
content=content_string if content_string else None,
|
|
|
|
embed=embed,
|
|
|
|
embeds=embeds,
|
|
|
|
)
|
|
|
|
await modal_ctx.send(
|
|
|
|
"Message edited!",
|
|
|
|
ephemeral=True,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
def setup(client: Client):
|
|
|
|
BotMessagesModel.create_table()
|
|
|
|
BotMessages(client)
|
|
|
|
logging.info("BotMessages extension loaded")
|