src/interactions/buttons/tickets/message.ts (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
import {
ActionRowBuilder,
ButtonBuilder,
ButtonStyle,
type ChatInputCommandInteraction,
type Client,
ContainerBuilder,
type GuildMember,
LabelBuilder,
ModalBuilder,
type ModalSubmitInteraction,
SlashCommandBuilder,
TextDisplayBuilder,
TextInputBuilder,
TextInputStyle,
} from "discord.js";
import { formatMessage } from "@/utils/formatting";
import { loggers } from "@/utils/logging";
import { hasManagerPermissions } from "@/utils/permissions";
import { getGuild } from "@/utils/queries";
const logger = loggers.interactions.child({ name: "messageCommand" });
const MODAL_ID = "ticket-message:message";
const INPUT_ID = "message_content";
const commandData = new SlashCommandBuilder()
.setName("ticket-message")
.setDescription("Send the ticket message in the designated channel")
.addChannelOption((c) =>
c
.setName("channel")
.setDescription("The channel to send the ticket message in")
.setRequired(true),
);
async function execute(
_client: Client,
interaction: ChatInputCommandInteraction,
) {
if (!interaction.guild || !interaction.member) {
await interaction.reply({
content: "❌ This command can only be used in a server.",
flags: ["Ephemeral"],
});
return;
}
const hasPerms = await hasManagerPermissions(
interaction.member as GuildMember,
);
if (!hasPerms) {
await interaction.reply({
content: "❌ You don't have permission to use this command.",
flags: ["Ephemeral"],
});
return;
}
const targetChannel = interaction.options.getChannel("channel", true);
// construct & show the modal
const textInput = new LabelBuilder()
.setLabel("Message Content")
.setTextInputComponent(
new TextInputBuilder()
.setCustomId(INPUT_ID)
.setStyle(TextInputStyle.Paragraph)
.setRequired(true),
);
await interaction.showModal(
new ModalBuilder()
.setCustomId(`${MODAL_ID}:${targetChannel.id}`)
.setTitle("Ticket Message")
.setLabelComponents(textInput),
);
}
async function modalExecute(
_client: Client,
interaction: ModalSubmitInteraction,
) {
if (!interaction.guild || !interaction.member) return;
const channelId = interaction.customId.split(":")[2];
const { data: guildData } = await getGuild(interaction.guild.id);
const channel = interaction.guild.channels.cache.get(channelId);
if (!channel) {
await interaction.reply({
content: "❌ The channel specified is invalid.",
flags: ["Ephemeral"],
});
return;
}
if (!channel.isSendable()) {
await interaction.reply({
content: "❌ I'm not able to send messages in the specified channel.",
flags: ["Ephemeral"],
});
return;
}
const message = interaction.fields.getTextInputValue(INPUT_ID);
const formatted = formatMessage(message, interaction);
const controls = new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId("ticket:create")
.setLabel("Open a Ticket")
.setEmoji("📩")
.setStyle(ButtonStyle.Success),
);
const container = new ContainerBuilder()
.addTextDisplayComponents(new TextDisplayBuilder().setContent(formatted))
.addActionRowComponents(controls);
const sent = await channel
.send({ components: [container], flags: ["IsComponentsV2"] })
.catch((err) => {
logger.error({ err, channelId }, "Failed to send ticket message");
return null;
});
if (!sent) {
await interaction.reply({
content: "❌ Failed to send the message in the specified channel.",
flags: ["Ephemeral"],
});
return;
}
await interaction.reply({
content: `✅ Message sent successfully! ${sent.url}`,
flags: ["Ephemeral"],
allowedMentions: {
users: [],
},
});
}
export default {
data: commandData,
execute,
modalExecute,
};
|