Merge pull request 'v3.6.0 GIF Fix' (#31) from v3.6.0 into main

Reviewed-on: #31
This commit is contained in:
Skylar Grant 2026-10-01 14:14:12 +00:00
commit fb963cc153
9 changed files with 43 additions and 73 deletions

View File

@ -1,3 +1,7 @@
## v3.6.x
#### v3.6.0 (#31) Fixing GIF APIs
* Switch from Tenor to Giphy for GIFs
## v3.5.x ## v3.5.x
#### v3.5.0 (#30) The April Fools Update #### v3.5.0 (#30) The April Fools Update
* Add April Fools stuff * Add April Fools stuff

View File

@ -1,5 +1,5 @@
# About Nodbot # About Nodbot
Nodbot is a content saving and serving Discord bot. Nodbot is able to search Tenor for GIFs, save custom copypastas, and look up marijuana strain information. Nodbot is in semi-active development by voidf1sh. It's buggy as hell and very shoddily built. Don't use it. Nodbot is a content saving and serving Discord bot. Nodbot is able to search GIPHY for GIFs, save custom copypastas, and look up marijuana strain information. Nodbot is in semi-active development by voidf1sh. It's buggy as hell and very shoddily built. Don't use it.
# Nodbot Help # Nodbot Help
@ -16,7 +16,7 @@ Use the `/help` command to see the bot's help message.
1. Create an application at the [Discord Developer Portal](https://discord.com/developers/applications) 1. Create an application at the [Discord Developer Portal](https://discord.com/developers/applications)
2. Convert the application into a Bot 2. Convert the application into a Bot
3. Note down the token provided and keep this safe. You cannot view this token again, only regenerate a new one. 3. Note down the token provided and keep this safe. You cannot view this token again, only regenerate a new one.
4. Create a Tenor account and obtain an API key. 4. Create a GIPHY account and obtain an API key.
5. Install and configure MySQL or MariaDB with a user for the bot and a datbase 5. Install and configure MySQL or MariaDB with a user for the bot and a datbase
* Create the table structure as outlined below (* Nodbot will soon create its own table structure) * Create the table structure as outlined below (* Nodbot will soon create its own table structure)
6. Configure your environment variables as outlined below. 6. Configure your environment variables as outlined below.
@ -84,7 +84,7 @@ dbPort=<mySQL port (3306)>
dbUser=<mySQL username> dbUser=<mySQL username>
dbPass=<mySQL user password> dbPass=<mySQL user password>
dbName=<mySQL table name> dbName=<mySQL table name>
tenorAPIKey=<Tenor API Key> giphyAPIKey=<GIPHY API Key>
ownerId=<your Discord user ID> ownerId=<your Discord user ID>
statusChannelId=<Discord channel ID of channel used for status messages> statusChannelId=<Discord channel ID of channel used for status messages>
clientId=<Discord user ID of your bot> clientId=<Discord user ID of your bot>

View File

@ -2,10 +2,6 @@ const fn = require('../functions');
const axios = require('axios'); const axios = require('axios');
const dotenv = require('dotenv').config(); const dotenv = require('dotenv').config();
// TODO: Tenor has changed API versions, switch from TenorJS (unmaintained) to axios for
// general API usage. See: https://github.com/Jinzulen/TenorJS/issues/12
// see also: https://developers.google.com/tenor/guides/migrate-from-v1
module.exports = { module.exports = {
name: 'gif', name: 'gif',
description: 'Send a GIF', description: 'Send a GIF',
@ -15,11 +11,12 @@ module.exports = {
// if (message.deletable) message.delete(); // if (message.deletable) message.delete();
const client = message.client; const client = message.client;
if (!client.gifs.has(commandData.args.toLowerCase())) { if (!client.gifs.has(commandData.args.toLowerCase())) {
if (process.env.isDev) console.log('https://tenor.googleapis.com/v2/search?' + `&q=${commandData.args}` + `&key=${process.env.tenorAPIKey}` + '&limit=1&contentfilter=off'); // TODO: Implement proper logging
if (process.env.isDev) console.log('https://api.giphy.com/v2/search?' + `&q=${commandData.args}` + `&key=${process.env.giphyAPIKey}` + '&limit=1&contentfilter=off');
const q = await axios.get( const q = await axios.get(
'https://tenor.googleapis.com/v2/search?' + 'https://api.giphy.com/v2/search?' +
`&q=${commandData.args}` + `&q=${commandData.args}` +
`&key=${process.env.tenorAPIKey}` + `&key=${process.env.giphyAPIKey}` +
'&limit=1' + '&limit=1' +
`&contentfilter=off` `&contentfilter=off`
).then(async (res) => { ).then(async (res) => {
@ -45,17 +42,6 @@ module.exports = {
await message.reply(commandData.embed_url); await message.reply(commandData.embed_url);
} }
}).catch(err => console.error(err)); }).catch(err => console.error(err));
// tenor.Search.Query(commandData.args, "1").then(res => {
// if (res[0] == undefined) {
// message.reply('Sorry I was unable to find a GIF of ' + commandData.args);
// return;
// };
// commandData.embed_url = res[0].media[0].gif.url;
// // message.reply(fn.embeds.gif(commandData));
// // message.channel.send(`> ${commandData.author} - ${commandData.args}.gif`);
// // message.channel.send(commandData.embed_url);
// message.reply(commandData.embed_url);
// }).catch(err => console.error(err));
} else { } else {
// message.reply(commandData.args + ' requested by ' + message.author.username + '\n' + client.gifs.get(commandData.args).embed_url); // message.reply(commandData.args + ' requested by ' + message.author.username + '\n' + client.gifs.get(commandData.args).embed_url);
const gifData = client.gifs.get(commandData.args.toLowerCase()); const gifData = client.gifs.get(commandData.args.toLowerCase());

View File

@ -26,6 +26,7 @@ const axios = require('axios');
// 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');
const appVersion = require('./package.json').version;
const slashCommandFiles = fs.readdirSync('./slash-commands/').filter(file => file.endsWith('.js')); const slashCommandFiles = fs.readdirSync('./slash-commands/').filter(file => file.endsWith('.js'));
const dotCommandFiles = fs.readdirSync('./dot-commands/').filter(file => file.endsWith('.js')); const dotCommandFiles = fs.readdirSync('./dot-commands/').filter(file => file.endsWith('.js'));
const customEmbeds = require('./CustomModules/Embeds.js'); const customEmbeds = require('./CustomModules/Embeds.js');
@ -182,7 +183,8 @@ const functions = {
const helpEmbed = new Discord.MessageEmbed() const helpEmbed = new Discord.MessageEmbed()
.setColor('BLUE') .setColor('BLUE')
.setAuthor({name: 'Help Page'}) .setAuthor({name: 'Help Page'})
.setThumbnail(strings.urls.avatar); .setThumbnail(strings.urls.avatar)
.setFooter(`v${appVersion}`);
// Construct the Slash Commands help // Construct the Slash Commands help

View File

@ -6,6 +6,9 @@ dotenv.config();
const token = process.env.TOKEN; const token = process.env.TOKEN;
const statusChannelId = process.env.statusChannelId; const statusChannelId = process.env.statusChannelId;
// Dump the env vars to log in dev environment:
if (process.env.isDev === "true") console.log(JSON.stringify(process.env));
// Discord.JS // Discord.JS
const { Client, Intents } = require('discord.js'); const { Client, Intents } = require('discord.js');
const client = new Client({ const client = new Client({

View File

@ -1,6 +1,6 @@
{ {
"name": "nodbot", "name": "nodbot",
"version": "3.5.0", "version": "3.6.0",
"description": "Nods and Nod Accessories", "description": "Nods and Nod Accessories",
"main": "main.js", "main": "main.js",
"dependencies": { "dependencies": {
@ -12,8 +12,7 @@
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"fuzzy-search": "^3.2.1", "fuzzy-search": "^3.2.1",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"openai": "^4.12.0", "openai": "^4.12.0"
"tenorjs": "^1.0.10"
}, },
"engines": { "engines": {
"node": "18.x" "node": "18.x"

View File

@ -1,11 +1,3 @@
const tenor = require('tenorjs').client({
'Key': process.env.tenorAPIKey, // https://tenor.com/developer/keyregistration
'Filter': 'off', // "off", "low", "medium", "high", not case sensitive
'Locale': 'en_US',
'MediaFilter': 'minimal',
'DateFormat': 'D/MM/YYYY - H:mm:ss A',
});
const { SlashCommandBuilder } = require('@discordjs/builders'); const { SlashCommandBuilder } = require('@discordjs/builders');
const { MessageActionRow, MessageButton } = require('discord.js'); const { MessageActionRow, MessageButton } = require('discord.js');
const { GifData, PastaData } = require('../CustomModules/NodBot'); const { GifData, PastaData } = require('../CustomModules/NodBot');

View File

@ -1,11 +1,3 @@
const tenor = require('tenorjs').client({
'Key': process.env.tenorAPIKey, // https://tenor.com/developer/keyregistration
'Filter': 'off', // "off", "low", "medium", "high", not case sensitive
'Locale': 'en_US',
'MediaFilter': 'minimal',
'DateFormat': 'D/MM/YYYY - H:mm:ss A',
});
const { SlashCommandBuilder } = require('@discordjs/builders'); const { SlashCommandBuilder } = require('@discordjs/builders');
const { Collection } = require('discord.js'); const { Collection } = require('discord.js');
const fn = require('../functions.js'); const fn = require('../functions.js');
@ -24,7 +16,7 @@ module.exports = {
.addSubcommand(subcommand => .addSubcommand(subcommand =>
subcommand subcommand
.setName('gifsearch') .setName('gifsearch')
.setDescription('Search Tenor for a GIF.') .setDescription('Search GIPHY for a GIF.')
.addStringOption(option => .addStringOption(option =>
option option
.setName('query') .setName('query')
@ -154,34 +146,34 @@ module.exports = {
iStorage.gifName = gifName; iStorage.gifName = gifName;
iStorage.query = query; iStorage.query = query;
interaction.editReply("Fuck off this is broken, come back later.");
// Search Tenor for the GIF // Search Tenor for the GIF
tenor.Search.Query(query, '20').then(res => { // tenor.Search.Query(query, '20').then(res => {
strings.temp.gifs = []; // strings.temp.gifs = [];
strings.temp.gifIndex = 0; // strings.temp.gifIndex = 0;
strings.temp.gifLimit = res.length - 1; // strings.temp.gifLimit = res.length - 1;
strings.temp.gifUserId = interaction.user.id; // strings.temp.gifUserId = interaction.user.id;
if (res[0] == undefined) { // if (res[0] == undefined) {
interaction.editReply('Sorry I was unable to find a GIF of ' + query); // interaction.editReply('Sorry I was unable to find a GIF of ' + query);
return; // return;
} // }
for (const row of res) { // for (const row of res) {
iStorage.gifsCollection.set(row.id, row); // iStorage.gifsCollection.set(row.id, row);
} // }
// Generate the initial action row // // Generate the initial action row
const actionRow = customEmbeds.actionRows.gifSearchAR('first'); // const actionRow = customEmbeds.actionRows.gifSearchAR('first');
// Get the index built // // Get the index built
const gifPage = Indexer(iStorage.gifsCollection, 0, 1); // const gifPage = Indexer(iStorage.gifsCollection, 0, 1);
gifPage.query = query; // gifPage.query = query;
gifPage.gifName = gifName; // gifPage.gifName = gifName;
// Generate the embed // // Generate the embed
const gifEmbed = Embeds.core.gifSearch({ author: interaction.user.username }, gifPage); // const gifEmbed = Embeds.core.gifSearch({ author: interaction.user.username }, gifPage);
interaction.editReply({ embeds: [gifEmbed], components: [actionRow], ephemeral: true }); // interaction.editReply({ embeds: [gifEmbed], components: [actionRow], ephemeral: true });
}); // });
break; break;
// GIF URL // GIF URL
case "gifurl": case "gifurl":

View File

@ -1,11 +1,3 @@
const tenor = require('tenorjs').client({
'Key': process.env.tenorAPIKey, // https://tenor.com/developer/keyregistration
'Filter': 'off', // "off", "low", "medium", "high", not case sensitive
'Locale': 'en_US',
'MediaFilter': 'minimal',
'DateFormat': 'D/MM/YYYY - H:mm:ss A',
});
const { SlashCommandBuilder } = require('@discordjs/builders'); const { SlashCommandBuilder } = require('@discordjs/builders');
const { Collection } = require('discord.js'); const { Collection } = require('discord.js');
const fn = require('../functions.js'); const fn = require('../functions.js');