Sending a random sound file as a response not working - javascript

I'm trying to make a talking ben command for my bot, and it just won't work. I want the bot to send an audio clip as a response whenever someone asks a question, and if they don't specify a question, the bot will send a "ben" sound effect. No response to the command in Discord at all.
Here's the code:
ben.js:
const Discord = require('discord.js');
const yes = new Discord.MessageAttachment(
'https://soundboardguy.com/sounds/talking-ben-yes_scachnw/',
);
const no = new Discord.MessageAttachment(
'https://soundboardguy.com/sounds/talking-ben-no/',
);
const laugh = new Discord.MessageAttachment(
'https://soundboardguy.com/sounds/talking-ben-laugh/',
);
const uhh = new Discord.MessageAttachment(
'https://www.101soundboards.com/sounds/726466-uhh',
);
const ben = new Discord.MessageAttachment(
'https://www.101soundboards.com/sounds/726450-ben',
);
module.exports = {
name: 'ben',
description: 'talking ben command',
async execute(client, message, args) {
if (!args[0]) return ben;
let benreplies = [yes, no, laugh, uhh];
let result = Math.floor(Math.random() * benreplies.length);
message.channel.send(replies[result]);
},
};
main.js:
const Discord = require('discord.js');
const client = new Discord.Client({ intents: ['GUILDS', 'GUILD_MESSAGES'] });
const prefix = '.';
const fs = require('fs');
client.commands = new Discord.Collection();
const commandFiles = fs
.readdirSync('./commands/')
.filter((file) => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
client.once('ready', () => {
console.log('Blueberry bot is online!');
});
client.on('messageCreate', (message) => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ + /);
const command = args.shift().toLowerCase();
// ...
else if (command === 'ben') {
client.commands.get('ben').execute(message, args, Discord);
}
});

First, you need to make sure that the links to the sound files are valid. You're currently using links pointing to an HTML page, not the mp3 files.
Second, you need to use an object with a files property to send a file. See the MessageOptions. files will also need to be an array. The following will work:
let sounds = [
{
id: 'ben',
link: 'https://soundboardguy.com/wp-content/uploads/2022/03/talking-ben-ben.mp3',
},
{
id: 'laugh',
link: 'https://soundboardguy.com/wp-content/uploads/2022/02/Talking-Ben-Laughing-Sound-Effect-1.mp3',
},
{
id: 'no',
link: 'https://soundboardguy.com/wp-content/uploads/2022/03/Talking-Ben-No-Sound-Effect.mp3',
},
{
id: 'uhh',
link: 'https://soundboardguy.com/wp-content/uploads/2021/06/huh-uhh.mp3',
},
{
id: 'yes',
link: 'https://soundboardguy.com/wp-content/uploads/2022/03/talking-ben-yes_SCacHNW.mp3',
},
];
let randomSound = sounds[Math.floor(Math.random() * sounds.length)];
message.channel.send({
files: [new MessageAttachment(randomSound.link, `${randomSound.id}.mp3`)],
});

The links are incorrect, you used the links that have a user interface, where the user can see the audio, login, see "related" audios etc.. not the actual source audio mp3 file.
For example, that link : https://www.101soundboards.com/sounds/726450-ben is incorrect. Replace it with https://www.101soundboards.com/storage/board_sounds_rendered/726450.mp3 Do the exact same thing with every file and you're ready to go !

Related

Why do I get "Invalid Form Body" when trying to embed a local image in a message?

Right now I'm working on making a bot that will post a random image from a local folder on my VSC. However, posting an embed message with the image results in an error:
DiscordAPIError: Invalid Form Body
embeds[0].image.url: Could not interpret "{'attachment': ['1.jpg', '2mkjR-3__400x400.jpg', '8921036_sa.jpg', '91Vk1mS1x3L.png'], 'name': None}" as string.
This can be reproduced with the sample code:
const Discord = require('discord.js');
const { Intents } = Discord;
const fs = require('fs');
const config = require('config');
const authToken = config.get('authToken');
const myIntents = new Intents([
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES
]);
const client = new Discord.Client({ intents: myIntents });
client.on("ready", (client) => {
console.log(`Logged in as ${client.user.tag}.`);
});
client.on("messageCreate", (message) => {
if ('.pic' === message.content) {
let files = fs.readdirSync('./assets/images/');
let chosenFile = files[Math.floor(Math.random() * files.length)];
const image = new Discord.MessageAttachment(files);
const embed = new Discord.MessageEmbed()
.setTitle('yeet')
.setImage(image)
.setFooter('By K4STOR','');
message.channel.send({embeds: [embed]});
}
});
client.login(authToken);
In addition to the above script, you'll need to:
create an 'assets/images' directory and
add at least one image;
create a configuration file (e.g. 'config/local.json') and
add an appropriate 'authToken' entry
How can the above code be fixed to send the image?
Try this:
var fs = require('fs');
client.on("ready", () => {
console.log("Why did I make this...")
command(client, 'pic', (message) => {
//choose one file from folder "./images" randomly
var files = fs.readdirSync("./images/")
let chosenFile = files[Math.floor(Math.random() * files.length)]
//create embed and use image from messageAttachments
const embed = new Discord.MessageEmbed()
.setTitle('yeet')
.setImage(`attachment://${chosenFile}`)
.setFooter('By K4STOR','')
//discord.js V13 variant of sending embeds
//necessary to set files, otherwise #setImage with localfile does not work
message.channel.send({
embeds: [embed],
files: [`./images/${chosenFile}`]
});
})
})
Main Issue
MessageEmbed.setImage() takes a URL, not a MessageAttachment. For attachments, you must pass them via the files option TextChannel.send(). Note the guide on attaching images to an embed message shows this.
Additionally, the path to the image directory must be combined with the chosen file name when the attachment object is created.
Minor issue
Note that all images appear in the error message. This is due to a minor issue: the attachment is set to files, rather than chosenFile. Note this sort of issue is considered on SO.
Changes
Just these changes would look like:
const path = require('path');
...
const imgDir = './assets/images/';
...
const image = new Discord.MessageAttachment(
path.join(imgDir, chosenFile),
chosenFile,
{url: 'attachment://' + chosenFile});
const embed = new Discord.MessageEmbed()
.setImage(image.url)
...
message.channel.send({embeds: [embed], files: [image]});
Full Sample
The sample with the above changes applied would be:
const Discord = require('discord.js');
const { Intents } = Discord;
const fs = require('fs');
const path = require('path');
const config = require('config');
const authToken = config.get('authToken');
const myIntents = new Intents([
Intents.FLAGS.GUILDS,
Intents.FLAGS.GUILD_MESSAGES
]);
const client = new Discord.Client({ intents: myIntents });
client.on("ready", (client) => {
console.log(`Logged in as ${client.user.tag}.`);
});
const imgDir = './assets/images/';
client.on("messageCreate", (message) => {
if ('.pic' === message.content) {
let files = fs.readdirSync(imgDir);
let chosenFile = files[Math.floor(Math.random() * files.length)];
const image = new Discord.MessageAttachment(
path.join(imgDir, chosenFile),
chosenFile,
{url: 'attachment://' + chosenFile});
const embed = new Discord.MessageEmbed()
.setTitle('yeet')
.setImage(image.url)
.setFooter('By K4STOR','');
console.log(`Sending ${chosenFile}.`);
message.channel.send({embeds: [embed], files: [image]});
}
});
client.login(authToken);

How do I schedule a message from a Discord bot to send every Friday?

I'm very very new to programming and I'm trying to set up a basic discord bot that sends a video every Friday. Currently I have:
Index.js which contains:
const Discord = require("discord.js");
const fs = require("fs");
require("dotenv").config()
const token = process.env.token;
const { prefix } = require("./config.js");
const client = new Discord.Client();
const commands = {};
// load commands
const commandFiles = fs.readdirSync("./commands").filter(file => file.endsWith(".js"));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
commands[command.name] = command;
}
// login bot
client.on("ready", () => {
console.log(`Logged in as ${client.user.tag}`);
});
client.on("message", message => {
if(!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).trim().split(/ +/);
const command = args.shift().toLowerCase();
let cmd = commands[command];
if(cmd)
cmd.execute(message, args)
});
client.login(token);
and a commands folder which contains beeame.js and that contains:
module.exports = {
name: "beeame",
description: "b",
execute: (message) => {
message.channel.send("It's Friday!", { files: ["./beeame.mp4"] });
}
}
I have heard about cron jobs and intervals but I'm not sure how to add these to the code I currently have.
Any help would be super appreciated!
Nate,
Here's some basics, to get you started. Your existing project you showed, sets up your bot to handle messages whenever they arrive. Everything there stays as is. You want to add a new section to deal with the timers.
First, here's a snippet of a utility file having to deal with Cron Jobs:
const CronJob = require('cron').CronJob;
const job = new CronJob('* * * * *', function() {
const d = new Date();
console.log('At each 1 Minute:', d);
});
job.start();
the thing to study and pay attention to is the ' * * * ' area. You will want to understand this, to set the timing correctly.
so replace the console logging with your messages, set your timing correctly and you should be good to go. The other thing to remember is that wherever your bot is running, the time zone might be different than where you (or others are)...so you might need to adjust for that if you have specific time of day needs.
Edit:
Based on subsequent questions....and note, I didn't set the time right. you need to really do more research to understand it.
const cron = require('cron').CronJob;
const sendMessageWeekly = new cron('* * * * *', async function() {
const guild = client.guilds.cache.get(server_id_number);
if (guild) {
const ch = guild.channels.cache.get(channel_id_number);
await ch.send({ content: 'This is friendly reminder it is Friday somewhere' })
.catch(err => {
console.error(err);
});
}
});
sendMessageWeekly.start();

How can I make my bot find the last message that matches a criteria, e.x ("joe") and send who sent it?

I am using node.js for my bot, and I, like the question stated, need to find the last message in the channel that matches the criteria specified in the code. For example, the command would say, ?joe, and it would find the last message that has "joe" in it, and return the member that sent it. In the server I am going to use it in, the message is very frequent, so I don't think it will hit any message reading limitations.
I did the code in main.js and the commands in separate js files, like this,
const Discord = require('discord.js');
const client = new Discord.Client();
const prefix = '?'
const fs = require('fs');
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands/').filter(file => file.endsWith('.js'));
for(const file of commandFiles){
const command = require(`./commands/${file}`);
client.commands.set(command.name, command)
}
client.once('ready', () => {
console.log('AbidBot is online!!');
});
client.on('message', message =>{
if(!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if(command === 'ping'){
client.commands.get('ping').execute(message, args);
}
});
client.login();
The ping command looks like this:
module.exports = {
name: 'ping',
description: "this is a ping command!",
execute(message, args){
message.channel.send('pong!')
}
}
Thanks for your help!
EDIT #1
Thanks, but it does not seem to be working for me #Lioness100. Can you take a look?
module.exports = {
name: 'joe',
description: "find joe",
execute(message, args){
message.channel.messages.fetch().then((messages) => {
// find the message that has 'joe' in it
const author = messages.find({ content } => content.includes(' joe ')).author.tag;
message.channel.send(author);
}
});
}
You can use MessageManager.fetch() and Collection.find()
// fetch the last 100 messages in the channel
message.channel.messages.fetch({ limit: 100 }).then((messages) => {
// find the message that has 'joe' in it
const msg = messages.find(({ content }) => content.includes(' joe '));
return msg
? message.channel.send(msg)
: message.channel.send('None of the last 100 messages include the word `joe`!');
});

Discord.js Cannot read property 'fetch' of undefined

I just started developing with Javascript and Discord.js a few days ago and got this Error:
TypeError: Cannot read property 'fetch' of undefined
I am trying to make a poll command. This is the Code (I deleted everything else and just wanted it to get the channel out of it):
const Discord = require('discord.js');
const client = new Discord.Collection();
module.exports = {
name: 'poll',
description: 'can make polls',
cooldown: 5,
usage: '[ask] [emoji1] [emoji 2]',
aliases: ['createpoll'],
execute(message, args) {
client.channels.fetch('744582158324072468')
.then (channel => console.log(channel.name))
.catch(console.error);
// message.react(args[1]).then(() => message.react(args[0]));
},
};
I already tried to put it in the Main.js which works:
client.on('message', message => {
if (message.content.startsWith('.poll')) {
client.channels.fetch('744582158324072468')
.then (channel => console.log(channel.name))
.catch(console.error);
}
}
But I want it ion the correct file. This is what I have above the client.on('message', etc.
const fs = require('fs');
const Discord = require('discord.js');
const { prefix, token, tprefix, welcomechannel, guildID } = require('./config.json');
const client = new Discord.Client({
fetchAllMembers: true,
});
client.commands = new Discord.Collection();
const commandFiles = fs.readdirSync('./commands').filter(file => file.endsWith('.js'));
for (const file of commandFiles) {
const command = require(`./commands/${file}`);
client.commands.set(command.name, command);
}
const cooldowns = new Discord.Collection();
// update
client.once('ready', () => {
console.log(`${tprefix}Paperbot got geupdated.`);
});
Of course, I googled around and read the documentation but that didn't help.
As I said, I am new to programming and it could be an easy fix, but I would love to fix this problem as fast as possible, thank you very much.
Figured it out. I just needed to add message to client.channels.fetch
Now it is working with this code:
const { tprefix, pollchannel, modchannel } = require('../config.json');
module.exports = {
name: 'poll',
description: 'can make polls',
cooldown: 5,
usage: '[ask] [emoji1] [emoji 2]',
aliases: ['createpoll'],
execute(message) {
message.client.channels.fetch('744582158324072468')
.then (channel => console.log(channel.name))
.catch(console.error);
},
};
Thank you #Jack Towns
You assign client to a new Discord collection at the top of your code.
You are essentially doing Collection.channels.fetch instead of client.channels.fetch.
You need to pass the client from your main file to your commands.

How to fix Discord API: Unknown Message error?

I'm trying to make a meme command but whenever I try to use it I get this error "DiscordAPIError: Unknown Message".
This was working earlier but when I came back to my PC it started glitching out.
Here's my code
const { RichEmbed } = require("discord.js");
const randomPuppy = require("random-puppy");
const usedCommandRecently = new Set();
module.exports = {
name: "meme",
aliases: ["memes", "reddit"],
category: "fun",
description: "Sends a random meme",
run: async (client, message, args) => {
if (message.deletable) message.delete();
var Channel = message.channel.name
//Check it's in the right channel
if(Channel != "memes") {
const channelembed = new RichEmbed()
.setColor("BLUE")
.setTitle(`Use me in #memes`)
.setDescription(`Sorry ${message.author.username} this command is only usable in #memes !`)
return message.channel.send(channelembed);
}
//Check cooldown
if(usedCommandRecently.has(message.author.id)){
const cooldownembed = new RichEmbed()
.setColor("GREEN")
.setTitle("Slow it down, pal")
.setDescription(`Sorry ${message.author.username} this command has a 30 second cooldown per member, sorry for any inconvenice this may cause`)
message.channel.send(cooldownembed)
} else{
//Post meme
const subReddits = ["dankmeme", "meme", "me_irl"];
const random = subReddits[Math.floor(Math.random() * subReddits.length)];
const img = await randomPuppy(random);
const embed = new RichEmbed()
.setColor("RANDOM")
.setImage(img)
.setTitle(`From /r/${random}`)
.setURL(`https://reddit.com/r/${random}`);
message.channel.send(embed);
}
}
}
Im not sure, but maybe problem in your require block.
const { RichEmbed } = require("discord.js");
the right way its:
const Discord = require("discord.js");
let cooldownembed = new Discord.RichEmbed();
and why you use return here
return message.channel.send(channelembed);

Categories

Resources