468 lines
15 KiB
JavaScript
468 lines
15 KiB
JavaScript
const {
|
|
ApplicationCommandType,
|
|
ApplicationCommandOptionType,
|
|
ActionRowBuilder,
|
|
ButtonBuilder,
|
|
EmbedBuilder,
|
|
StringSelectMenuBuilder,
|
|
ModalBuilder,
|
|
TextInputBuilder,
|
|
TextInputStyle,
|
|
ButtonStyle,
|
|
ComponentType,
|
|
MessageFlags,
|
|
} = require('discord.js');
|
|
const Command = require('../../Structures/Command.js');
|
|
const fs = require('fs');
|
|
const yaml = require('js-yaml');
|
|
|
|
const supportbot = yaml.load(fs.readFileSync('./Configs/supportbot.yml', 'utf8'));
|
|
const cmdconfig = yaml.load(fs.readFileSync('./Configs/commands.yml', 'utf8'));
|
|
const msgconfig = yaml.load(fs.readFileSync('./Configs/messages.yml', 'utf8'));
|
|
|
|
function parseColor(color) {
|
|
if (!color) return 0x5865F2;
|
|
if (typeof color === 'number') return color;
|
|
if (typeof color !== 'string') return 0x5865F2;
|
|
color = color.replace('#', '');
|
|
if (/^[0-9A-F]{6}$/i.test(color)) {
|
|
return parseInt(color, 16);
|
|
}
|
|
return 0x5865F2;
|
|
}
|
|
|
|
module.exports = new Command({
|
|
name: cmdconfig.Embed.Command,
|
|
description: cmdconfig.Embed.Description,
|
|
type: ApplicationCommandType.ChatInput,
|
|
options: [
|
|
{
|
|
name: 'channel',
|
|
description: 'Select channel to send the message',
|
|
type: ApplicationCommandOptionType.Channel,
|
|
required: true
|
|
}
|
|
],
|
|
permissions: cmdconfig.Embed.Permission,
|
|
|
|
async run(interaction) {
|
|
const { getRole } = interaction.client;
|
|
let SupportStaff = await getRole(supportbot.Roles.StaffMember.Staff, interaction.guild);
|
|
let Admin = await getRole(supportbot.Roles.StaffMember.Admin, interaction.guild);
|
|
|
|
if (!SupportStaff || !Admin) {
|
|
return interaction.reply('Some roles seem to be missing!\nPlease check for errors when starting the bot.');
|
|
}
|
|
|
|
if (!interaction.member.roles.cache.has(SupportStaff.id) &&
|
|
!interaction.member.roles.cache.has(Admin.id)) {
|
|
const NoPerms = new EmbedBuilder()
|
|
.setTitle('Invalid Permissions!')
|
|
.setDescription(`${msgconfig.Error.IncorrectPerms}\n\nRole Required: \`${supportbot.Roles.StaffMember.Staff}\` or \`${supportbot.Roles.StaffMember.Admin}\``)
|
|
.setColor(0xFF0000);
|
|
return interaction.reply({ embeds: [NoPerms], flags: MessageFlags.Ephemeral });
|
|
}
|
|
|
|
const channel = interaction.options.getChannel('channel');
|
|
|
|
const messageData = {
|
|
type: 'embed',
|
|
title: 'New Embed',
|
|
description: 'Click the buttons below to edit this embed',
|
|
color: 0x5865F2,
|
|
fields: [],
|
|
footer: null,
|
|
thumbnail: null,
|
|
image: null,
|
|
timestamp: false
|
|
};
|
|
|
|
function createEmbed() {
|
|
const embed = new EmbedBuilder()
|
|
.setTitle(messageData.title)
|
|
.setDescription(messageData.description)
|
|
.setColor(messageData.color);
|
|
|
|
if (messageData.fields.length > 0) {
|
|
embed.addFields(messageData.fields);
|
|
}
|
|
if (messageData.footer) {
|
|
embed.setFooter({ text: messageData.footer });
|
|
}
|
|
if (messageData.thumbnail) {
|
|
embed.setThumbnail(messageData.thumbnail);
|
|
}
|
|
if (messageData.image) {
|
|
embed.setImage(messageData.image);
|
|
}
|
|
if (messageData.timestamp) {
|
|
embed.setTimestamp();
|
|
}
|
|
|
|
return embed;
|
|
}
|
|
|
|
const typeRow = new ActionRowBuilder()
|
|
.addComponents(
|
|
new StringSelectMenuBuilder()
|
|
.setCustomId('message_type')
|
|
.setPlaceholder('Select message type')
|
|
.addOptions([
|
|
{
|
|
label: 'Embed Message',
|
|
description: 'Send as an embedded message',
|
|
value: 'embed'
|
|
},
|
|
{
|
|
label: 'Text Message',
|
|
description: 'Send as a plain text message',
|
|
value: 'text'
|
|
}
|
|
])
|
|
);
|
|
|
|
function createButtons(messageType) {
|
|
const buttons = [];
|
|
|
|
if (messageType === 'embed') {
|
|
const row1 = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('edit_title')
|
|
.setLabel('Edit Title')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('edit_description')
|
|
.setLabel('Edit Description')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('edit_color')
|
|
.setLabel('Edit Color')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('add_field')
|
|
.setLabel('Add Field')
|
|
.setStyle(ButtonStyle.Secondary)
|
|
);
|
|
|
|
const row2 = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('edit_footer')
|
|
.setLabel('Edit Footer')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('edit_image')
|
|
.setLabel('Add Image')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('edit_thumbnail')
|
|
.setLabel('Add Thumbnail')
|
|
.setStyle(ButtonStyle.Secondary),
|
|
new ButtonBuilder()
|
|
.setCustomId('toggle_timestamp')
|
|
.setLabel('Toggle Timestamp')
|
|
.setStyle(ButtonStyle.Secondary)
|
|
);
|
|
|
|
buttons.push(row1, row2);
|
|
} else {
|
|
const textRow = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('edit_description')
|
|
.setLabel('Edit Text')
|
|
.setStyle(ButtonStyle.Secondary)
|
|
);
|
|
|
|
buttons.push(textRow);
|
|
}
|
|
|
|
// Send button always shows
|
|
const sendRow = new ActionRowBuilder()
|
|
.addComponents(
|
|
new ButtonBuilder()
|
|
.setCustomId('send_message')
|
|
.setLabel('Send')
|
|
.setStyle(ButtonStyle.Success)
|
|
);
|
|
|
|
buttons.push(sendRow);
|
|
return buttons;
|
|
}
|
|
|
|
async function updatePreview(i) {
|
|
if (messageData.type === 'embed') {
|
|
await i.update({
|
|
content: 'Customize your message:',
|
|
embeds: [createEmbed()],
|
|
components: [typeRow, ...createButtons('embed')]
|
|
});
|
|
} else {
|
|
await i.update({
|
|
content: messageData.description,
|
|
embeds: [],
|
|
components: [typeRow, ...createButtons('text')]
|
|
});
|
|
}
|
|
}
|
|
|
|
const message = await interaction.reply({
|
|
content: messageData.type === 'text' ? messageData.description : 'Customize your message:',
|
|
components: [typeRow, ...createButtons(messageData.type)],
|
|
embeds: messageData.type === 'embed' ? [createEmbed()] : [],
|
|
flags: MessageFlags.Ephemeral
|
|
});
|
|
|
|
const collector = message.createMessageComponentCollector({
|
|
time: 900000
|
|
});
|
|
|
|
collector.on('collect', async (i) => {
|
|
if (i.user.id !== interaction.user.id) {
|
|
return i.reply({
|
|
content: 'You cannot edit this message.',
|
|
flags: MessageFlags.Ephemeral
|
|
});
|
|
}
|
|
|
|
switch (i.customId) {
|
|
case 'message_type':
|
|
messageData.type = i.values[0];
|
|
await updatePreview(i);
|
|
break;
|
|
|
|
case 'edit_description':
|
|
const descModal = new ModalBuilder()
|
|
.setCustomId('desc_modal')
|
|
.setTitle(messageData.type === 'embed' ? 'Edit Description' : 'Edit Text');
|
|
|
|
descModal.addComponents(
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('desc_input')
|
|
.setLabel(messageData.type === 'embed' ? 'Description' : 'Message Text')
|
|
.setStyle(TextInputStyle.Paragraph)
|
|
.setValue(messageData.description)
|
|
.setMaxLength(4000)
|
|
)
|
|
);
|
|
|
|
await i.showModal(descModal);
|
|
break;
|
|
|
|
case 'edit_title':
|
|
const titleModal = new ModalBuilder()
|
|
.setCustomId('title_modal')
|
|
.setTitle('Edit Title');
|
|
|
|
titleModal.addComponents(
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('title_input')
|
|
.setLabel('Title')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setValue(messageData.title)
|
|
.setMaxLength(256)
|
|
)
|
|
);
|
|
|
|
await i.showModal(titleModal);
|
|
break;
|
|
|
|
case 'edit_color':
|
|
const colorModal = new ModalBuilder()
|
|
.setCustomId('color_modal')
|
|
.setTitle('Edit Color');
|
|
|
|
colorModal.addComponents(
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('color_input')
|
|
.setLabel('Color (HEX)')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setPlaceholder('#FF0000')
|
|
.setMinLength(6)
|
|
.setMaxLength(7)
|
|
.setValue(messageData.color.toString(16).padStart(6, '0'))
|
|
)
|
|
);
|
|
|
|
await i.showModal(colorModal);
|
|
break;
|
|
|
|
case 'add_field':
|
|
const fieldModal = new ModalBuilder()
|
|
.setCustomId('field_modal')
|
|
.setTitle('Add Field');
|
|
|
|
fieldModal.addComponents(
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('field_name')
|
|
.setLabel('Field Name')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setMaxLength(256)
|
|
),
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('field_value')
|
|
.setLabel('Field Value')
|
|
.setStyle(TextInputStyle.Paragraph)
|
|
.setMaxLength(1024)
|
|
),
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('field_inline')
|
|
.setLabel('Inline? (true/false)')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setValue('false')
|
|
.setPlaceholder('true or false')
|
|
)
|
|
);
|
|
|
|
await i.showModal(fieldModal);
|
|
break;
|
|
|
|
case 'edit_footer':
|
|
const footerModal = new ModalBuilder()
|
|
.setCustomId('footer_modal')
|
|
.setTitle('Edit Footer');
|
|
|
|
footerModal.addComponents(
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('footer_input')
|
|
.setLabel('Footer Text')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setValue(messageData.footer || '')
|
|
.setMaxLength(2048)
|
|
)
|
|
);
|
|
|
|
await i.showModal(footerModal);
|
|
break;
|
|
|
|
case 'edit_image':
|
|
const imageModal = new ModalBuilder()
|
|
.setCustomId('image_modal')
|
|
.setTitle('Add Image');
|
|
|
|
imageModal.addComponents(
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('image_input')
|
|
.setLabel('Image URL')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setValue(messageData.image || '')
|
|
.setPlaceholder('https://example.com/image.png')
|
|
)
|
|
);
|
|
|
|
await i.showModal(imageModal);
|
|
break;
|
|
|
|
case 'edit_thumbnail':
|
|
const thumbnailModal = new ModalBuilder()
|
|
.setCustomId('thumbnail_modal')
|
|
.setTitle('Add Thumbnail');
|
|
|
|
thumbnailModal.addComponents(
|
|
new ActionRowBuilder()
|
|
.addComponents(
|
|
new TextInputBuilder()
|
|
.setCustomId('thumbnail_input')
|
|
.setLabel('Thumbnail URL')
|
|
.setStyle(TextInputStyle.Short)
|
|
.setValue(messageData.thumbnail || '')
|
|
.setPlaceholder('https://example.com/thumbnail.png')
|
|
)
|
|
);
|
|
|
|
await i.showModal(thumbnailModal);
|
|
break;
|
|
|
|
case 'toggle_timestamp':
|
|
messageData.timestamp = !messageData.timestamp;
|
|
await updatePreview(i);
|
|
break;
|
|
|
|
case 'send_message':
|
|
try {
|
|
if (messageData.type === 'embed') {
|
|
await channel.send({ embeds: [createEmbed()] });
|
|
} else {
|
|
await channel.send(messageData.description);
|
|
}
|
|
await i.update({
|
|
content: 'Message sent successfully!',
|
|
components: [],
|
|
embeds: []
|
|
});
|
|
collector.stop();
|
|
} catch (error) {
|
|
await i.reply({
|
|
content: 'Failed to send message. Please check channel permissions.',
|
|
flags: MessageFlags.Ephemeral
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
|
|
// Handle modal submissions
|
|
interaction.client.on('interactionCreate', async (modal) => {
|
|
if (!modal.isModalSubmit()) return;
|
|
if (modal.user.id !== interaction.user.id) return;
|
|
|
|
switch (modal.customId) {
|
|
case 'title_modal':
|
|
messageData.title = modal.fields.getTextInputValue('title_input');
|
|
break;
|
|
case 'desc_modal':
|
|
messageData.description = modal.fields.getTextInputValue('desc_input');
|
|
break;
|
|
case 'color_modal':
|
|
messageData.color = parseColor(modal.fields.getTextInputValue('color_input'));
|
|
break;
|
|
case 'field_modal':
|
|
const inlineValue = modal.fields.getTextInputValue('field_inline').toLowerCase();
|
|
messageData.fields.push({
|
|
name: modal.fields.getTextInputValue('field_name'),
|
|
value: modal.fields.getTextInputValue('field_value'),
|
|
inline: inlineValue === 'true'
|
|
});
|
|
break;
|
|
case 'footer_modal':
|
|
messageData.footer = modal.fields.getTextInputValue('footer_input');
|
|
break;
|
|
case 'image_modal':
|
|
messageData.image = modal.fields.getTextInputValue('image_input');
|
|
break;
|
|
case 'thumbnail_modal':
|
|
messageData.thumbnail = modal.fields.getTextInputValue('thumbnail_input');
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
await updatePreview(modal);
|
|
});
|
|
|
|
collector.on('end', () => {
|
|
interaction.editReply({
|
|
content: 'Message editor timed out.',
|
|
components: [],
|
|
embeds: []
|
|
}).catch(() => {});
|
|
});
|
|
}
|
|
}); |