Compare commits

...

9 Commits

Author SHA1 Message Date
28d0cc0446 Add bell curve generator
All checks were successful
NodBot Production Dockerization / build (push) Successful in 22s
2025-02-26 18:33:22 -05:00
14556a50c5 Fix surprised pika 2025-02-10 18:17:49 -05:00
445fa4e9f4 Fixing dynamic labels and prefilled values.
All checks were successful
NodBot PE Dockerization / build (push) Successful in 22s
2025-02-10 11:08:01 -05:00
80c23ca7db Added dynamic labels and default values.
All checks were successful
NodBot PE Dockerization / build (push) Successful in 9s
2025-02-09 21:12:27 -05:00
017eaddf9b Test improvements and dynamic modal labels 2025-02-09 20:53:22 -05:00
23c81305a0 Fix we are not the same
All checks were successful
NodBot PE Dockerization / build (push) Successful in 19s
2025-02-09 19:58:52 -05:00
4c5e265d2e Reply with only the url for good embed
All checks were successful
NodBot PE Dockerization / build (push) Successful in 19s
2025-02-09 19:51:15 -05:00
7df608e0e6 MVP for meme generation
All checks were successful
NodBot PE Dockerization / build (push) Successful in 1m23s
2025-02-09 19:43:06 -05:00
720366b04b Versioning 2025-02-09 17:39:05 -05:00
5 changed files with 318 additions and 2 deletions

View File

@ -1,4 +1,7 @@
## v3.4.x ## v3.4.x
#### v3.4.4 (#30)
* [WIP] Add Meme Generator
#### v3.4.3 (#29) #### v3.4.3 (#29)
* Fix `.gif` replies to redirect to the original replyee (#26) * Fix `.gif` replies to redirect to the original replyee (#26)

View File

@ -16,6 +16,7 @@ const zlib = require('zlib');
// Discord.js // Discord.js
const Discord = require('discord.js'); const Discord = require('discord.js');
const { MessageActionRow, Modal, TextInputComponent } = require('discord.js');
// Fuzzy text matching for db lookups // Fuzzy text matching for db lookups
const FuzzySearch = require('fuzzy-search'); const FuzzySearch = require('fuzzy-search');
@ -23,6 +24,16 @@ const FuzzySearch = require('fuzzy-search');
// Axios for APIs // Axios for APIs
const axios = require('axios'); const axios = require('axios');
// Imgflip API
let imgflip;
(async () => {
const Imgflip = (await import('imgflip')).default;
imgflip = new Imgflip({
username: process.env.imgflipUser,
password: process.env.imgflipPass,
});
})();
// Various imports from other files // Various imports from other files
const config = require('./config.json'); const config = require('./config.json');
const strings = require('./strings.json'); const strings = require('./strings.json');
@ -616,6 +627,173 @@ const functions = {
return pastaSearcher.search(query).slice(0,25); return pastaSearcher.search(query).slice(0,25);
} }
}, },
memes: {
generate(templateId, panelData) {
return new Promise((resolve, reject) => {
imgflip.meme(templateId, {
captions: panelData
}).then((res) => {
resolve(res);
}).catch((err) => {
reject(err);
});
});
},
oneFieldModal(templateId, labels, values) {
const fieldOneLabel = labels ? labels[0] : 'Text Field:';
const fieldOneValue = values ? values[0] : '';
// Create the modal
const modal = new Modal()
.setCustomId('oneFieldMemeModal')
.setTitle('Meme Generator');
// Create the text input
const textInput = new TextInputComponent()
.setCustomId('memeTextField')
.setLabel(fieldOneLabel)
.setValue(fieldOneValue)
.setStyle('SHORT');
// Create and pre-fill a template ID field
const templateIdField = new TextInputComponent()
.setCustomId('memeTemplateId')
.setLabel('Template ID: (advanced)')
.setValue(templateId)
.setStyle('SHORT');
// Add the components to the modal
const textRow = new MessageActionRow().addComponents(textInput);
const templateIdRow = new MessageActionRow().addComponents(templateIdField);
modal.addComponents(textRow, templateIdRow);
return modal;
},
twoFieldModal(templateId, labels, values) {
const fieldOneLabel = labels ? labels[0] : 'Text Field 1:';
const fieldTwoLabel = labels ? labels[1] : 'Text Field 2:';
const fieldOneValue = values ? values[0] : '';
const fieldTwoValue = values ? values[1] : '';
// Create the modal
const modal = new Modal()
.setCustomId('twoFieldMemeModal')
.setTitle('Meme Generator');
// Create the first text input
const fieldOneTextInput = new TextInputComponent()
.setCustomId('memeTextFieldOne')
.setLabel(fieldOneLabel)
.setValue(fieldOneValue)
.setStyle('SHORT');
// Create the second text input
const fieldTwoTextInput = new TextInputComponent()
.setCustomId('memeTextFieldTwo')
.setLabel(fieldTwoLabel)
.setValue(fieldTwoValue)
.setStyle('SHORT');
// Create and pre-fill a template ID field
const templateIdField = new TextInputComponent()
.setCustomId('memeTemplateId')
.setLabel('Template ID: (advanced)')
.setValue(templateId)
.setStyle('SHORT');
// Add the components to the modal
const fieldOneRow = new MessageActionRow().addComponents(fieldOneTextInput);
const fieldTwoRow = new MessageActionRow().addComponents(fieldTwoTextInput);
const templateIdRow = new MessageActionRow().addComponents(templateIdField);
modal.addComponents(fieldOneRow, fieldTwoRow, templateIdRow);
return modal;
},
threeFieldModal(templateId, labels, values) {
const fieldOneLabel = labels ? labels[0] : 'Text Field 1:';
const fieldTwoLabel = labels ? labels[1] : 'Text Field 2:';
const fieldThreeLabel = labels ? labels[2] : 'Text Field 3:';
const fieldOneValue = values ? values[0] : '';
const fieldTwoValue = values ? values[1] : '';
const fieldThreeValue = values ? values[2] : '';
// Create the modal
const modal = new Modal()
.setCustomId('threeFieldMemeModal')
.setTitle('Meme Generator');
// Create the first text input
const fieldOneTextInput = new TextInputComponent()
.setCustomId('memeTextFieldOne')
.setLabel(fieldOneLabel)
.setValue(fieldOneValue)
.setStyle('SHORT');
// Create the second text input
const fieldTwoTextInput = new TextInputComponent()
.setCustomId('memeTextFieldTwo')
.setLabel(fieldTwoLabel)
.setValue(fieldTwoValue)
.setStyle('SHORT');
// Create the third text input
const fieldThreeTextInput = new TextInputComponent()
.setCustomId('memeTextFieldThree')
.setLabel(fieldThreeLabel)
.setValue(fieldThreeValue)
.setStyle('SHORT');
// Create and pre-fill a template ID field
const templateIdField = new TextInputComponent()
.setCustomId('memeTemplateId')
.setLabel('Template ID: (advanced)')
.setValue(templateId)
.setStyle('SHORT');
// Add the components to the modal
const fieldOneRow = new MessageActionRow().addComponents(fieldOneTextInput);
const fieldTwoRow = new MessageActionRow().addComponents(fieldTwoTextInput);
const fieldThreeRow = new MessageActionRow().addComponents(fieldThreeTextInput);
const templateIdRow = new MessageActionRow().addComponents(templateIdField);
modal.addComponents(fieldOneRow, fieldTwoRow, fieldThreeRow, templateIdRow);
return modal;
},
fourFieldModal(templateId, labels, values) {
const fieldOneLabel = labels ? labels[0] : 'Text Field 1:';
const fieldTwoLabel = labels ? labels[1] : 'Text Field 2:';
const fieldThreeLabel = labels ? labels[2] : 'Text Field 3:';
const fieldFourLabel = labels ? labels[3] : 'Text Field 4:';
const fieldOneValue = values ? values[0] : '';
const fieldTwoValue = values ? values[1] : '';
const fieldThreeValue = values ? values[2] : '';
const fieldFourValue = values ? values[3] : '';
// Create the modal
const modal = new Modal()
.setCustomId('fourFieldMemeModal')
.setTitle('Meme Generator');
// Create the first text input
const fieldOneTextInput = new TextInputComponent()
.setCustomId('memeTextFieldOne')
.setLabel(fieldOneLabel)
.setValue(fieldOneValue)
.setStyle('SHORT');
// Create the second text input
const fieldTwoTextInput = new TextInputComponent()
.setCustomId('memeTextFieldTwo')
.setLabel(fieldTwoLabel)
.setValue(fieldTwoValue)
.setStyle('SHORT');
// Create the third text input
const fieldThreeTextInput = new TextInputComponent()
.setCustomId('memeTextFieldThree')
.setLabel(fieldThreeLabel)
.setValue(fieldThreeValue)
.setStyle('SHORT');
// Create the fourth text input
const fieldFourTextInput = new TextInputComponent()
.setCustomId('memeTextFieldFour')
.setLabel(fieldFourLabel)
.setValue(fieldFourValue)
.setStyle('SHORT');
// Create and pre-fill a template ID field
const templateIdField = new TextInputComponent()
.setCustomId('memeTemplateId')
.setLabel('Template ID: (advanced)')
.setValue(templateId)
.setStyle('SHORT');
// Add the components to the modal
const fieldOneRow = new MessageActionRow().addComponents(fieldOneTextInput);
const fieldTwoRow = new MessageActionRow().addComponents(fieldTwoTextInput);
const fieldThreeRow = new MessageActionRow().addComponents(fieldThreeTextInput);
const fieldFourRow = new MessageActionRow().addComponents(fieldFourTextInput);
const templateIdRow = new MessageActionRow().addComponents(templateIdField);
modal.addComponents(fieldOneRow, fieldTwoRow, fieldThreeRow, fieldFourRow, templateIdRow);
return modal;
},
},
// Parent-Level functions (miscellaneuous) // Parent-Level functions (miscellaneuous)
closeRequest(requestId, interaction) { closeRequest(requestId, interaction) {
if (interaction.user.id == ownerId) { if (interaction.user.id == ownerId) {

45
main.js
View File

@ -57,6 +57,7 @@ client.once('ready', async () => {
// slash-commands // slash-commands
client.on('interactionCreate', async interaction => { client.on('interactionCreate', async interaction => {
if (isDev) console.log('Interaction Type: ' + interaction.type);
if (interaction.isCommand()) { if (interaction.isCommand()) {
if (isDev) { if (isDev) {
console.log('Interaction ID: ' + interaction.id); console.log('Interaction ID: ' + interaction.id);
@ -118,6 +119,50 @@ client.on('interactionCreate', async interaction => {
break; break;
} }
} }
if (interaction.isModalSubmit()) {
if (isDev) console.log('Modal Submit ID: ' + interaction.id);
const template = interaction.fields.getTextInputValue('memeTemplateId');
let memeTextFieldOne, memeTextFieldTwo, memeTextFieldThree, memeTextFieldFour, memeUrl;
switch (interaction.customId) {
case 'oneFieldMemeModal':
memeTextFieldOne = interaction.fields.getTextInputValue('memeTextFieldOne');
console.log(`Text: ${memeTextFieldOne}`);
memeUrl = await fn.memes.generate(template, [memeTextFieldOne]);
console.log(memeUrl);
await interaction.reply({ content: memeUrl });
break;
case 'twoFieldMemeModal':
memeTextFieldOne = interaction.fields.getTextInputValue('memeTextFieldOne');
memeTextFieldTwo = interaction.fields.getTextInputValue('memeTextFieldTwo');
console.log(`Text: ${memeTextFieldOne}, ${memeTextFieldTwo}`);
memeUrl = await fn.memes.generate(template, [memeTextFieldOne, memeTextFieldTwo]);
console.log(memeUrl);
await interaction.reply({ content: memeUrl });
break;
case 'threeFieldMemeModal':
memeTextFieldOne = interaction.fields.getTextInputValue('memeTextFieldOne');
memeTextFieldTwo = interaction.fields.getTextInputValue('memeTextFieldTwo');
memeTextFieldThree = interaction.fields.getTextInputValue('memeTextFieldThree');
console.log(`Text: ${memeTextFieldOne}, ${memeTextFieldTwo}, ${memeTextFieldThree}`);
memeUrl = await fn.memes.generate(template, [memeTextFieldOne, memeTextFieldTwo, memeTextFieldThree]);
console.log(memeUrl);
await interaction.reply({ content: memeUrl });
break;
case 'fourFieldMemeModal':
memeTextFieldOne = interaction.fields.getTextInputValue('memeTextFieldOne');
memeTextFieldTwo = interaction.fields.getTextInputValue('memeTextFieldTwo');
memeTextFieldThree = interaction.fields.getTextInputValue('memeTextFieldThree');
memeTextFieldFour = interaction.fields.getTextInputValue('memeTextFieldFour');
console.log(`Text: ${memeTextFieldOne}, ${memeTextFieldTwo}, ${memeTextFieldThree}, ${memeTextFieldFour}`);
memeUrl = await fn.memes.generate(template, [memeTextFieldOne, memeTextFieldTwo, memeTextFieldThree, memeTextFieldFour]);
console.log(memeUrl);
await interaction.reply({ content: memeUrl });
break;
default:
break;
}
}
}); });
// dot-commands // dot-commands

View File

@ -1,6 +1,6 @@
{ {
"name": "nodbot", "name": "nodbot",
"version": "3.4.3", "version": "3.4.4",
"description": "Nods and Nod Accessories", "description": "Nods and Nod Accessories",
"main": "main.js", "main": "main.js",
"dependencies": { "dependencies": {
@ -11,6 +11,7 @@
"discord.js": "^13.15.1", "discord.js": "^13.15.1",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"fuzzy-search": "^3.2.1", "fuzzy-search": "^3.2.1",
"imgflip": "^4.0.0",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"openai": "^4.12.0", "openai": "^4.12.0",
"tenorjs": "^1.0.10" "tenorjs": "^1.0.10"

89
slash-commands/meme.js Normal file
View File

@ -0,0 +1,89 @@
const { SlashCommandBuilder } = require('@discordjs/builders');
const fn = require('../functions.js');
module.exports = {
data: new SlashCommandBuilder()
.setName('meme')
.setDescription('Generate a meme from a template')
.addStringOption(option =>
option.setName('template')
.setDescription('The meme template')
.setRequired(true)
.addChoices(
{ name: 'Drake Hotline Bling', value: '181913649' },
{ name: 'Anakin & Padme', value: '322841258' },
{ name: 'Y\'all Got Any More...', value: '124055727' },
{ name: 'We Are Not The Same', value: '342785297' },
{ name: 'Surprised Pikachu', value: '155067746' },
{ name: 'Two Buttons', value: '87743020' },
{ name: 'Uno Draw 25', value: '217743513' },
{ name: 'Bell Curve', value: '533936279' },
)),
async execute(interaction) {
try {
const template = interaction.options.getString('template');
let memeModal;
// Switch the template
switch (template) {
// One-Field Memes
// Two-Field Memes
// Drake Hotline Bling
case '181913649':
// Generate a modal with two text inputs
memeModal = fn.memes.twoFieldModal(template, ['Drake No', 'Drake Yes']);
await interaction.showModal(memeModal);
break;
// Y'all Got Any More...
case '124055727':
// Generate a modal with two text inputs
memeModal = fn.memes.twoFieldModal(template, ['Top', 'Bottom Text'], ['Y\'all got any more of ', '']);
await interaction.showModal(memeModal);
break;
// Uno Draw 25
case '217743513':
// Generate a modal with two text inputs
memeModal = fn.memes.twoFieldModal(template, ['<blank> or draw 25', 'Caption Above Person'], ['', 'Me']);
await interaction.showModal(memeModal);
break;
// Three-Field Memes
// Bell Curve
case '533936279':
// Generate a modal with two text inputs
memeModal = fn.memes.threeFieldModal(template, ['Left', 'Middle', 'Right']);
await interaction.showModal(memeModal);
break;
// Anakin & Padme
case '322841258':
// Generate a modal with three text inputs
memeModal = fn.memes.threeFieldModal(template, ['Anakin', 'Padme', 'Padme'], ['', '', 'Right?']);
await interaction.showModal(memeModal);
break;
// We are not the same
case '342785297':
// Generate a modal with three text inputs
memeModal = fn.memes.threeFieldModal(template, ['You...', 'I...', 'We...'], ['', '', 'We are not the same.']);
await interaction.showModal(memeModal);
break;
// Surprised Pikachu
case '155067746':
memeModal = fn.memes.threeFieldModal(template);
await interaction.showModal(memeModal);
break;
// Two Buttons
case '87743020':
// Generate a modal with three text inputs
memeModal = fn.memes.threeFieldModal(template, ['Button 1', 'Button 2', 'Person Caption']);
await interaction.showModal(memeModal);
break;
default:
await interaction.reply('Invalid meme template');
break;
}
}
catch (error) {
console.error(error);
await interaction.reply('There was an error while executing this command!');
}
},
};