const { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } = require('discord.js'); const { select, query } = require('../db'); module.exports = { data: new SlashCommandBuilder() .setName('admin') .setDescription('Commands for administrators') .setDefaultMemberPermissions(PermissionFlagsBits.Administrator) .addSubcommandGroup(subcommandGroup => subcommandGroup .setName('emergency') .setDescription('Commands for emergency') .addSubcommand(subcommand => subcommand .setName('draft') .setDescription('Writing the draft for the emergency message') .addStringOption(option => option .setName('query') .setDescription('Phrase to search for') .setRequired(true) .setAutocomplete(true) ) ) .addSubcommand(subcommand => subcommand .setName('preview') .setDescription('Displaying the preview of the message draft') ) .addSubcommand(subcommand => subcommand .setName('insert') .setDescription('Insert sentence for autocomplete option') .addStringOption(option => option .setName('text') .setDescription('Sentence or phrase to add to search query results') .setRequired(true) ) .addStringOption(option => option .setName('term') .setDescription('Search term linked to the text') .setRequired(true) ) .addStringOption(option => option .setName('term2') .setDescription('Search term linked to the text. Secondary.') ) .addStringOption(option => option .setName('term3') .setDescription('Search term linked to the text. Tertiary.') ) .addStringOption(option => option .setName('term4') .setDescription('Search term linked to the text. Quaternary.') ) .addStringOption(option => option .setName('term5') .setDescription('Search term linked to the text. Quinary.') ) ) ) .addSubcommandGroup(subcommandGroup => subcommandGroup .setName('delete') .setDescription('Delete messages') .addSubcommand(subcommand => subcommand .setName('message') .setDescription('To have one message be deleted') .addChannelOption(option => option .setName('channel') .setDescription('Channel that includes the message') .setRequired(false) ) .addUserOption(option => option .setName('user') .setDescription('User\'s most recent message to be deleted') .setRequired(false) ) .addStringOption(option => option .setName('term') .setDescription('Most recent message containing term to delete') .setRequired(false) .setAutocomplete(true) ) ) .addSubcommand(subcommand => subcommand .setName('bulk') .setDescription('To have bulk messages be deleted') .addChannelOption(option => option .setName('channel') .setDescription('Channel to have bulk deleted') .setRequired(false) ) .addUserOption(option => option .setName('user') .setDescription('This user\'s messages to have bulk deleted') .setRequired(false) ) .addIntegerOption(option => option .setName('number') .setDescription('Number of messages to have bulk deleted') .setRequired(false) ) ) ), async execute(interaction) { // console.log('interaction in admin.js', interaction); let subgroup = interaction.options.getSubcommandGroup(); let sub = interaction.options.getSubcommand(); switch (subgroup) { case 'emergency': switch (sub) { case 'preview': await interaction.deferReply({ ephemeral: true }); let adminCheck = await select(`SELECT emergency.*, emergencyAdminMsg.* FROM emergency INNER JOIN emergencyAdminMsg ON emergency.threadId=emergencyAdminMsg.threadId WHERE emergencyAdminMsg.adminId='${interaction.user.id}' AND emergency.threadId='${interaction.channelId}';`); console.log('adminCheck', adminCheck); if (adminCheck[0]) { let message = adminCheck[0].draft; let preview = new EmbedBuilder() .setColor('ffae00') .setTitle(`Draft`) .setDescription(`**Here is your message preview:**\n\n${message}`) .setFooter({ text: `If you ever need this message again, use `, iconURL: 'https://i.imgur.com/DnWpDZT.png' }); interaction.editReply({ content: '', embeds: [preview], ephemeral: true }); } else { interaction.editReply({ content: 'There is no draft started yet. In order to begin, use ', ephemeral: true }); } break; case 'draft': await interaction.deferReply({ ephemeral: true }); let adminCheck1 = await select(`SELECT emergency.*, emergencyAdminMsg.* FROM emergency INNER JOIN emergencyAdminMsg ON emergency.threadId=emergencyAdminMsg.threadId WHERE emergencyAdminMsg.adminId='${interaction.user.id}' AND emergency.threadId='${interaction.channelId}';`); // STUFF AFTER AUTOCOMPLETE IS SELECTED console.log('interaction line 59', interaction.options._hoistedOptions[0].value); if (adminCheck1.length > 0) { await query(`UPDATE emergencyAdminMsg SET draft='${adminCheck1[0].draft + " " + interaction.options._hoistedOptions[0].value}';`); await interaction.editReply(`> ${adminCheck1[0].draft + " " + interaction.options._hoistedOptions[0].value}`); } else { await query(`INSERT INTO emergencyAdminMsg (threadId, adminId, draft) VALUES ('${interaction.channelId}', '${interaction.user.id}', '${interaction.options._hoistedOptions[0].value}');`); await interaction.editReply(`> ${interaction.options._hoistedOptions[0].value}`); } break; case 'insert': await interaction.deferReply({ ephemeral: true }); let terms = interaction.options._hoistedOptions.map(option => option.value).slice(1).join(', '); await query(`INSERT INTO adminInsertText (adminId, text, terms) VALUES ('${interaction.user.id}', '${interaction.options._hoistedOptions[0].value}', '${terms}');`); let message = new EmbedBuilder() .setColor('00FF2F') .setTitle('Insert completed') .setDescription('The following has been inserted into database:') .addFields({ name: 'Text', value: `${interaction.options._hoistedOptions[0].value}`, inline: false }) .addFields({ name: 'Terms', value: `${interaction.options._hoistedOptions.map(option => option.value).slice(1).join('\n')}` }) await interaction.editReply({ content: '', embeds: [message] }); break; } break; case 'delete': switch (sub) { case 'message': await interaction.deferReply({ ephemeral: true }); if (interaction.options.get('channel')) { let channel = await interaction.guild.channels.fetch(interaction.options.get('channel').value); if (interaction.options.get('user')) { let channelMessages = await channel.messages.fetch() // console.log('channelMessages', channelMessages); let messages = []; for (let message of channelMessages.values()) { // console.log('option user: ', interaction.options.get('user')); if (message.author == interaction.options.getUser('user')) { messages.push(message); console.log('messages: ', messages); } } let message; if (interaction.options.get('term')) { let content = interaction.options.getString('term').value; message = messages.find(msg => msg.content == content); } else { message = messages[0]; } await channel.messages.delete(message); await interaction.editReply('Message has been deleted.'); } else { let channelMessages = await channel.messages.fetch(); let message; if (interaction.options.get('term')) { let content = interaction.options.getString('term').value; message = channelMessages.values().find(msg => msg.content == content); } else { message = channelMessages[0].values(); } await channel.messages.delete(message); await interaction.editReply('Message has been deleted.'); } } } } }, async autocomplete(interaction) { //interaction.options.getFocused(true); //Use option.value to search for draft and return array of choices let subgroup = interaction.options.getSubcommandGroup(); let sub = interaction.options.getSubcommand(); switch (subgroup) { case 'emergency': switch (sub) { case 'draft': let check = await select(`SELECT * FROM adminInsertText`) console.log('check', check); let focusedValue = interaction.options.getFocused() // const choices = ['Popular Topics: Threads', 'Sharding: Getting started', 'Library: Voice Connections', 'Interactions: Replying to slash commands', 'Popular Topics: Embed preview']; // let choicesTerms = check.map(row => row.terms.split(', ')); // [['terms', 'stuff'], ['test', 'terms']] // let choicesTexts = check.map(row => row.text); // const filtered = choicesTexts.filter(choice => choice.includes(focusedValue)); let filtered = check.filter(row => row.terms.split(', ').includes(focusedValue) || row.text.includes(focusedValue)); let newFiltered = filtered.map(row => row.text); await interaction.respond( newFiltered.map(choice => ({ name: choice, value: choice })), ); break; } break; case 'delete': switch (sub) { case 'message': let focusedValue = interaction.options.getFocused(); if (interaction.options.getChannel('channel')) { let filtered = await interaction.options.getChannel('channel').messages.fetch().filter(message => message.content.includes(focusedValue)); if (interaction.options.get('user')) { let userFiltered = filtered.filter(value => value.member.id == interaction.options.get('user')); await interaction.respond(userFiltered.map(choice => ({ name: interaction.options.get('user').value, value: choice.content }))); } else { // if no user option await interaction.respond(filtered.map(choice => ({ name: interaction.options.get('channel').value, value: choice.content }))); } } else if (interaction.options.getUser('user')) { let guildChannels = await interaction.guild.channels.fetch(); let content = [] for (let channel of guildChannels.values()) { content.push(channel.messages.fetch().values().filter(message => message.content.includes(focusedValue))); } let userFiltered = content.filter(value => value.member.id == interaction.options.get('user')); await interaction.respond(userFiltered.map(choice => ({ name: interaction.options.get('user').value, value: choice.content }))); } else { let guildChannels = await interaction.guild.channels.fetch(); let content = []; for (let channel of guildChannels.values()) { content.push(channel.messages.fetch().values().filter(message => message.content.includes(focusedValue))); } await interaction.respond(content.map(choice => ({ name: focusedValue, value: choice.content }))); } break; } } //return [{name:"",value:""}] } }