Compare commits

..

4 Commits

Author SHA1 Message Date
3def31b0fb Moved all button handling to ButtonHandlers.js and cleaned up /save gifSearch
All checks were successful
NodBot Production Dockerization / build (pull_request) Successful in 18s
2024-09-26 19:30:41 -04:00
b536ebda5b Add ability to handle pages of different length, defaulting to 10 2024-09-26 19:30:01 -04:00
6175a30974 Add PR tag # 2024-09-26 14:28:11 -04:00
8d5f75e471 Add nested commands 2024-09-26 14:25:22 -04:00
7 changed files with 181 additions and 204 deletions

View File

@ -1,3 +1,7 @@
## v3.4.x
#### v3.4.0 (#25)
* Added nested commands, enclose a command in brackets, braces, or parenthesis inside a longer message: `You really don't get it do you? [that's the joke.gif] You're so dense` would return the results for just `that's the joke.gif`
## v3.3.x
#### v3.3.3 (#20)
* Fixed content-list slash commands `/gifs`, `/pastas`, `/joints`, `/requests` (#19)

View File

@ -3,6 +3,7 @@ const InteractionStorage = require('../CustomModules/InteractionStorage.js');
const indexer = require('../CustomModules/Indexer.js');
const fn = require('../functions.js');
const requests = require('../slash-commands/requests.js');
const { GifData } = require('./NodBot.js');
module.exports = {
baseEvent(interaction) {
@ -40,6 +41,18 @@ module.exports = {
case 'nextJointsPage':
module.exports.jointsPage(interaction);
break;
case 'prevGif':
module.exports.gifSearchPage(interaction);
break;
case 'nextGif':
module.exports.gifSearchPage(interaction);
break;
case 'confirmGif':
module.exports.gifSearchPage(interaction);
break;
case 'cancelGif':
module.exports.gifSearchPage(interaction);
break;
default:
return;
}
@ -147,5 +160,45 @@ module.exports = {
}
interaction.update(fn.embeds.joints({command: "/joints", author: interaction.member.displayName}, indexedJoints));
},
gifSearchPage(interaction) {
const iStorage = interaction.client.iStorage.get(interaction.message.interaction.id);
switch (interaction.component.customId) {
case 'prevGif':
if (iStorage.page > 0) {
iStorage.page = iStorage.page - 1;
}
break;
case 'nextGif':
if (iStorage.page < interaction.client.gifs.size / 10) {
iStorage.page = iStorage.page + 1;
}
break;
case 'confirmGif':
const gif = indexer(iStorage.gifsCollection, iStorage.page, 1).thisPage[0];
const gifData = new GifData().setInfo(iStorage.gifName, gif.media_formats.gif.url, gif.id);
fn.upload.gif(gifData, interaction.client);
interaction.update({ content: `I've saved the GIF as ${gifData.name}.gif`, components: [] });
fn.download.gifs(interaction.client);
return;
break;
case 'cancelGif':
interaction.update({ content: 'The GIF has been discarded.', components: [], embeds: [] });
return;
break;
default:
break;
}
// Generate the action row
const gifSearchAR = customEmbeds.actionRows.gifSearchAR(iStorage.state);
// Update the index
const indexedGifs = indexer(iStorage.gifsCollection, iStorage.page, 1);
indexedGifs.query = iStorage.query;
indexedGifs.gifName = iStorage.gifName;
// Generate the embed
const gifEmbed = customEmbeds.core.gifSearch({ author: interaction.member.displayName }, indexedGifs);
// Update the interaction
interaction.update({ embeds: [gifEmbed], components: [gifSearchAR], ephemeral: true });
}
}

View File

@ -1,139 +1,154 @@
const { MessageActionRow, MessageButton } = require('discord.js');
const { MessageActionRow, MessageButton, MessageEmbed } = require('discord.js');
module.exports = {
gifSearchAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
actionRows: {
gifSearchAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
.setCustomId('prevGif')
.setLabel('⬅️')
.setStyle('SECONDARY');
const confirmButton = new MessageButton()
const confirmButton = new MessageButton()
.setCustomId('confirmGif')
.setLabel('')
.setLabel('Select')
.setStyle('PRIMARY');
const nextButton = new MessageButton()
const nextButton = new MessageButton()
.setCustomId('nextGif')
.setLabel('➡️')
.setStyle('SECONDARY');
const cancelButton = new MessageButton()
const cancelButton = new MessageButton()
.setCustomId('cancelGif')
.setLabel('')
.setLabel('Cancel')
.setStyle('DANGER');
switch (state) {
case 'first':
switch (state) {
case 'first':
previousButton.setDisabled(true);
break;
case 'last':
case 'last':
nextButton.setDisabled(true);
break;
}
// Put the buttons into an ActionRow
return new MessageActionRow()
}
// Put the buttons into an ActionRow
return new MessageActionRow()
.addComponents(previousButton, confirmButton, nextButton, cancelButton);
},
gifsPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
},
gifsPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
.setCustomId('prevGifsPage')
.setLabel('⬅️')
.setStyle('SECONDARY');
const nextButton = new MessageButton()
const nextButton = new MessageButton()
.setCustomId('nextGifsPage')
.setLabel('➡️')
.setStyle('SECONDARY');
switch (state) {
case 'first':
switch (state) {
case 'first':
previousButton.setDisabled(true);
break;
case 'last':
case 'last':
nextButton.setDisabled(true);
break;
}
// Put the buttons into an ActionRow
return new MessageActionRow()
}
// Put the buttons into an ActionRow
return new MessageActionRow()
.addComponents(previousButton, nextButton);
},
requestsPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
},
requestsPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
.setCustomId('prevRequestsPage')
.setLabel('⬅️')
.setStyle('SECONDARY');
const nextButton = new MessageButton()
const nextButton = new MessageButton()
.setCustomId('nextRequestsPage')
.setLabel('➡️')
.setStyle('SECONDARY');
switch (state) {
case 'first':
switch (state) {
case 'first':
previousButton.setDisabled(true);
break;
case 'last':
case 'last':
nextButton.setDisabled(true);
break;
}
// Put the buttons into an ActionRow
return new MessageActionRow()
}
// Put the buttons into an ActionRow
return new MessageActionRow()
.addComponents(previousButton, nextButton);
},
pastasPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
},
pastasPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
.setCustomId('prevPastasPage')
.setLabel('⬅️')
.setStyle('SECONDARY');
const nextButton = new MessageButton()
const nextButton = new MessageButton()
.setCustomId('nextPastasPage')
.setLabel('➡️')
.setStyle('SECONDARY');
switch (state) {
case 'first':
switch (state) {
case 'first':
previousButton.setDisabled(true);
break;
case 'last':
case 'last':
nextButton.setDisabled(true);
break;
}
// Put the buttons into an ActionRow
return new MessageActionRow()
}
// Put the buttons into an ActionRow
return new MessageActionRow()
.addComponents(previousButton, nextButton);
},
jointsPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
},
jointsPageAR(state) {
// Setup the buttons
const previousButton = new MessageButton()
.setCustomId('prevJointsPage')
.setLabel('⬅️')
.setStyle('SECONDARY');
const nextButton = new MessageButton()
const nextButton = new MessageButton()
.setCustomId('nextJointsPage')
.setLabel('➡️')
.setStyle('SECONDARY');
switch (state) {
case 'first':
switch (state) {
case 'first':
previousButton.setDisabled(true);
break;
case 'last':
case 'last':
nextButton.setDisabled(true);
break;
}
// Put the buttons into an ActionRow
return new MessageActionRow()
}
// Put the buttons into an ActionRow
return new MessageActionRow()
.addComponents(previousButton, nextButton);
}
},
core: {
gifSearch(commandData, indexedGifs) {
return new MessageEmbed()
.setColor('#0099ff')
.setTitle('GIF Search')
.setImage(indexedGifs.thisPage[0].media_formats.gif.url)
.setFooter({ text: `Page ${indexedGifs.pagesString}` })
.addFields(
{ name: 'Query', value: `"${indexedGifs.query}"`, inline: true },
{ name: 'Saving As', value: `${indexedGifs.gifName}.gif`, inline: true },
);
}
}
}

View File

@ -1,5 +1,5 @@
module.exports = (collection, page) => {
const itemsPerPage = 10;
module.exports = (collection, page, qty) => {
const itemsPerPage = qty ? qty : 10;
const index = page * itemsPerPage;
const totalPages = Math.ceil(collection.size / itemsPerPage);
let state = page === 0 ? 'first' : 'middle';

View File

@ -270,7 +270,7 @@ const functions = {
.setFooter({text: `Page: ${indexedPastas.pagesString}`})
.setDescription(indexedPastas.pastasString);
const pastasPageAR = customEmbeds.pastasPageAR(indexedPastas.state);
const pastasPageAR = customEmbeds.actionRows.pastasPageAR(indexedPastas.state);
return { embeds: [pastasEmbed], components: [pastasPageAR], ephemeral: true };
},
gifs(commandData, indexedGifs) {
@ -280,7 +280,7 @@ const functions = {
.setFooter({text: `Page: ${indexedGifs.pagesString}`})
.setDescription(indexedGifs.gifsString);
const gifsPageAR = customEmbeds.gifsPageAR(indexedGifs.state);
const gifsPageAR = customEmbeds.actionRows.gifsPageAR(indexedGifs.state);
return { embeds: [gifsEmbed], components: [gifsPageAR], ephemeral: true };
},
joints(commandData, indexedJoints) {
@ -290,7 +290,7 @@ const functions = {
.setFooter({text: `Page: ${indexedJoints.pagesString}`})
.setDescription(indexedJoints.jointsString);
const jointsPageAR = customEmbeds.jointsPageAR(indexedJoints.state);
const jointsPageAR = customEmbeds.actionRows.jointsPageAR(indexedJoints.state);
return { embeds: [jointsEmbed], components: [jointsPageAR], ephemeral: true };
},
text(commandData) {
@ -307,7 +307,7 @@ const functions = {
.setFooter({text: `Page: ${indexedRequests.pagesString}`})
.setDescription(indexedRequests.requestsString);
const requestsPageAR = customEmbeds.requestsPageAR(indexedRequests.state);
const requestsPageAR = customEmbeds.actionRows.requestsPageAR(indexedRequests.state);
return { embeds: [requestsEmbed], components: [requestsPageAR], ephemeral: true };
},
strain(strainInfo, interaction) {

112
main.js
View File

@ -76,117 +76,7 @@ client.on('interactionCreate', async interaction => {
if (interaction.isButton()) {
if (isDev) console.log('Origin Interaction ID: ' + interaction.message.interaction.id);
if (isDev) console.log('Button ID: ' + interaction.component.customId);
// Get some meta info from strings
const index = strings.temp.gifIndex;
const limit = strings.temp.gifLimit;
let newIndex;
const buttonId = interaction.component.customId;
switch (buttonId) {
case 'prevGif':
newIndex = index - 1;
strings.temp.gifIndex = newIndex;
// If we're leaving the last GIF, enable the Next GIF button
if (index == limit) {
// Re-Send Previous GIF button
const prevButton = new MessageButton().setCustomId('prevGif').setLabel('Previous GIF').setStyle('SECONDARY');
// Re-Send Confirm GIF Button
const confirmButton = new MessageButton().setCustomId('confirmGif').setLabel('Confirm').setStyle('PRIMARY');
// Enable Next GIF Button
const nextButton = new MessageButton().setCustomId('nextGif').setLabel('Next GIF').setStyle('SECONDARY');
// Re-Send Cancel Button
const cancelButton = new MessageButton().setCustomId('cancelGif').setLabel('Cancel').setStyle('DANGER');
// Put all the above into an ActionRow to be sent as a component of the reply
const row = new MessageActionRow().addComponents(prevButton, confirmButton, nextButton, cancelButton);
interaction.update({ content: strings.temp.gifs[newIndex].embed_url, components: [row] });
break;
}
// If we're going into the first GIF, disable the Previous GIF button
if (newIndex == 0) {
// Disable Previous GIF button
const prevButton = new MessageButton().setCustomId('prevGif').setLabel('Previous GIF').setStyle('SECONDARY').setDisabled();
// Re-Send Confirm GIF Button
const confirmButton = new MessageButton().setCustomId('confirmGif').setLabel('Confirm').setStyle('PRIMARY');
// Re-Send Next GIF Button
const nextButton = new MessageButton().setCustomId('nextGif').setLabel('Next GIF').setStyle('SECONDARY');
// Re-Send Cancel Button
const cancelButton = new MessageButton().setCustomId('cancelGif').setLabel('Canceled').setStyle('DANGER');
// Put all the above into an ActionRow to be sent as a component of the reply
const row = new MessageActionRow().addComponents(prevButton, confirmButton, nextButton, cancelButton);
interaction.update({ content: strings.temp.gifs[newIndex].embed_url, components: [row] });
break;
}
interaction.update(strings.temp.gifs[newIndex].embed_url);
break;
case 'confirmGif':
// const gifData = {
// name: strings.temp.gifName,
// url: strings.temp.gifs[strings.temp.gifIndex].embed_url,
// };
const gifData = new GifData().setInfo(strings.temp.gifName, strings.temp.gifs[strings.temp.gifIndex].embed_url);
fn.upload.gif(gifData, client);
interaction.update({ content: `I've saved the GIF as ${gifData.name}.gif`, components: [] });
fn.download.gifs(interaction.client);
break;
case 'nextGif':
newIndex = index + 1;
strings.temp.gifIndex = newIndex;
// If we're leaving the first GIF, enable the Previous GIF button
if (index == 0) {
// Enable Previous GIF button
const prevButton = new MessageButton().setCustomId('prevGif').setLabel('Previous GIF').setStyle('SECONDARY').setDisabled(false);
// Re-Send Confirm GIF Button
const confirmButton = new MessageButton().setCustomId('confirmGif').setLabel('Confirm').setStyle('PRIMARY');
// Re-Send Next GIF Button
const nextButton = new MessageButton().setCustomId('nextGif').setLabel('Next GIF').setStyle('SECONDARY');
// Re-Send Cancel Button
const cancelButton = new MessageButton().setCustomId('cancelGif').setLabel('Cancel').setStyle('DANGER');
// Put all the above into an ActionRow to be sent as a component of the reply
const row = new MessageActionRow().addComponents(prevButton, confirmButton, nextButton, cancelButton);
interaction.update({ content: strings.temp.gifs[newIndex].embed_url, components: [row] });
break;
}
// If we're going into the last GIF, disable the Next GIF button
if (newIndex == strings.temp.gifLimit) {
// Re-Send Previous GIF button
const prevButton = new MessageButton().setCustomId('prevGif').setLabel('Previous GIF').setStyle('SECONDARY');
// Re-Send Confirm GIF Button
const confirmButton = new MessageButton().setCustomId('confirmGif').setLabel('Confirm').setStyle('PRIMARY');
// Disable Next GIF Button
const nextButton = new MessageButton().setCustomId('nextGif').setLabel('Next GIF').setStyle('SECONDARY').setDisabled();
// Re-Send Cancel Button
const cancelButton = new MessageButton().setCustomId('cancelGif').setLabel('Canceled').setStyle('DANGER');
// Put all the above into an ActionRow to be sent as a component of the reply
const row = new MessageActionRow().addComponents(prevButton, confirmButton, nextButton, cancelButton);
interaction.update({ content: strings.temp.gifs[newIndex].embed_url, components: [row] });
break;
}
interaction.update(strings.temp.gifs[newIndex].embed_url);
break;
case 'cancelGif':
// Previous GIF button
const prevButton = new MessageButton().setCustomId('prevGif').setLabel('Previous GIF').setStyle('SECONDARY').setDisabled();
// Confirm GIF Button
const confirmButton = new MessageButton().setCustomId('confirmGif').setLabel('Confirm').setStyle('PRIMARY').setDisabled();
// Next GIF Button
const nextButton = new MessageButton().setCustomId('nextGif').setLabel('Next GIF').setStyle('SECONDARY').setDisabled();
// Cancel Button
const cancelButton = new MessageButton().setCustomId('cancelGif').setLabel('Canceled').setStyle('DANGER');
// Put all the above into an ActionRow to be sent as a component of the reply
const row = new MessageActionRow().addComponents(prevButton, confirmButton, nextButton, cancelButton);
interaction.component.setDisabled(true);
interaction.update({ content: 'Canceled.', components: [row] });
break;
default:
ButtonHandlers.baseEvent(interaction);
break;
}
ButtonHandlers.baseEvent(interaction);
}
// Handle autocomplete requests

View File

@ -7,11 +7,13 @@ const tenor = require('tenorjs').client({
});
const { SlashCommandBuilder } = require('@discordjs/builders');
const { MessageActionRow, MessageButton } = require('discord.js');
const { Collection } = require('discord.js');
const fn = require('../functions.js');
const strings = require('../strings.json');
const { GifData } = require('../CustomModules/NodBot.js');
const customEmbeds = require('../CustomModules/Embeds.js');
const Indexer = require('../CustomModules/Indexer.js');
const Embeds = require('../CustomModules/Embeds.js');
const { emoji } = strings;
module.exports = {
@ -142,15 +144,21 @@ module.exports = {
switch (subcommand) {
// GIF Search
case "gifsearch":
// TODO Check on option names
const actionRow = customEmbeds.gifSearchAR();
// Get the query
// Grab the inputs from the command
const query = interaction.options.getString('query');
strings.temp.gifName = interaction.options.getString('name').toLowerCase();
const gifName = interaction.options.getString('name').toLowerCase();
const iStorage = interaction.client.iStorage.get(interaction.id);
iStorage.page = 0;
iStorage.gifsCollection = new Collection();
iStorage.gifName = gifName;
iStorage.query = query;
// Search Tenor for the GIF
tenor.Search.Query(query, '10').then(res => {
tenor.Search.Query(query, '20').then(res => {
strings.temp.gifs = [];
strings.temp.gifIndex = 0;
strings.temp.gifLimit = res.length - 1;
@ -161,11 +169,18 @@ module.exports = {
return;
}
for (const row of res) {
strings.temp.gifs.push({
embed_url: row.media_formats.gif.url,
});
iStorage.gifsCollection.set(row.id, row);
}
interaction.editReply({ content: strings.temp.gifs[0].embed_url, components: [actionRow], ephemeral: true });
// Generate the initial action row
const actionRow = customEmbeds.actionRows.gifSearchAR('first');
// Get the index built
const gifPage = Indexer(iStorage.gifsCollection, 0, 1);
gifPage.query = query;
gifPage.gifName = gifName;
// Generate the embed
const gifEmbed = Embeds.core.gifSearch({ author: interaction.member.displayName }, gifPage);
interaction.editReply({ embeds: [gifEmbed], components: [actionRow], ephemeral: true });
});
break;
// GIF URL