I'm trying to make a discord Vouch System but when i do -Vouch it runs 2 commands one is -Vouch And the other is -Vouches ```
client.on("message", (message) => {
if (message.content.startsWith("-Vouches")) {
const user = message.mentions.users.first();
if (user === undefined) {
return; }
If you always uses startsWith it will surely execute two commands if one of the command name is contained into another one.
For example, if we have this code :
client.on("message", (message) => {
if (message.content.startsWith("!test")) console.log("test command");
if (message.content.startsWith("!test2")) console.log("test2 command");
});
Both command will be executed if we write !test.
So a solution vastly used is to split the message by spaces, then take the first word, and test it, not if it starts with a string, test the entire string, like this.
client.on("message", (message) => {
const [commandName, ...arguments] = message.content.split(/\s+/);
// commandName is the first word
// arguments is an array of the other words of the message
if (commandName === "!test") console.log("test command");
if (commandName === "!test2") console.log("test2 command");
});
Here we split the message by spaces, using the regular expression \s+, then took the first word and tested it directly.
You can also then use the array arguments for your commands stuff.
Related
I'm currently looking at getting a soundboard in Discord.js by using emojis to act as the controls to the soundboard, it should then respond with an appropriate sound based on the emoji sent. However, I'm having issues with at least testing if I can receive different types of emojis based on the emojis array.
main.js
var soundBoard;
client.on('message', async message => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
switch (command) {
...
case 'soundboard':
client.commands.get('soundboard').execute(message, args, soundBoard);
break;
...
}
}
soundboard.js
module.exports = {
name: 'soundboard',
description: "Soundboard",
async execute(message, args, sb) {
const emojis = [
'😄',
'✋'
];
if (!sb) {
sb = await message.channel.send('Soundboard Active');
const filter = (reaction, user) => {
return emojis.includes(reaction.emoji.name);
};
sb.awaitReactions(filter)
.then(collected => {
console.log("Collected: " + collected);
sb.react('✅');
})
.catch(console.error);
for (let e of emojis) {
sb.react(e);
}
}
else {
console.log(sb);
}
}
}
sb is passed from a global variable declared in my main.js. Unfortunately at the moment all that seems to happen is the message appears but whenever I click the emojis to respond the expected result of adding a ✅ to the original message fails.
First of all, I would recommend limiting your reaction collector by a specific amount of time and by only allowing the user who sent the message to interact with it. I would also recommend using a reactionCollector instead of awaitReactions here.
I believe the problem you are having is that .then() is only called on awaitReactions() after the time limit of awaitReactions() has ended. In other words, your current reaction collector is attempting to react with a check emoji after a certain period of time has passed, instead of attempting to do so after one reaction has been collected. You are essentially attempting to listen to the equivalent of a reactionCollector's "end" event instead of its "collect" event.
By using a reactionCollector, you can specifically run code every time an individual emoji is clicked on by listening to the "collect" event. Here's an example:
let collector = sb.createReactionCollector((r, user) => emojis.includes(r.emoji.name) && user.id === message.author.id, { time: 120000 });
//This is the event you need to use
collector.on("collect", r => {
console.log("This message is logged when we receive a reaction.");
sb.react('✅');
});
//This is the equivalent of the event you are currently using
collector.on("end", collected => {
console.log("This is where your current code is trying to add ✅");
console.log("This would only be logged after 120 secs in this example.")
})
Relevant resources:
https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=createReactionCollector
https://discord.js.org/#/docs/main/stable/class/Message?scrollTo=awaitReactions
I planned to create a discord server with bots. There are quite a lot (6 in total) and are just supposed to be fictional characters with some background story. I'm quite new and all of that is way too complicated for me to code myself, therefor I ask for your help! I just want to have a nice server for my friends and I with enjoyable bots and all of these desperate hours of trying to get some useful code is driving me nuts..
I only managed to get one bot to do stuff, using the prefix "-".
It can change it's status (watching, listening, playing) and the name of the thing he's doing.
I'm not quite sure why streaming doesn't work or if that's possible in general but it would be really cool if it would.
My status code: (1st Problem)
client.once('ready', () => {
console.log('Bot is ready!');
if (config.activity.streaming == true) {
client.user.setActivity(config.activity.game, {type: 'WATCHING'}); //STREAMING, PLAYING, LISTENING
} else {
client.user.setActivity(config.activity.game, {url: 'https://twitch.tv/usrname'});
client.user.setStatus('idle'); //dnd, idle, online, invisible
}
});
config.json
"activity": {
"streaming": true,
"game": "Whatevergame"
}
}
As I said, streaming is not working for some reason and the status (idle, dnd..) is also not working.
2nd Problem
If I try to add other bots with the login, it will log both bots on, but only one of them will work, what's actually pretty logical since the commands are all made for only one bot. So I'm trying to figure out how to get them all packed into the main file.
3rd Problem
I used the try - catch function to execute commands, which I pre- set up, and if theres none, it sends an error message. See for yourself:
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();
try {
client.commands.get(command).execute(message, args);
}
catch {
message.channel.send("I don't know that, sorry.");
}
});
So everytime I type another command, from which I do not want the bot to respond to, it will respond with "I don't know[...]" It would be sufficient to just set up another prefix for the "other command" to fix that problem so the bot knows that for every prefix starting with a.e "-", it has to send an error message if that command is not existing. But for other prefixes, a.e "?", it's supposed to execute the other command/s.
4th Problem
My (current) last problems are the welcome messages. My code:
index.js
const welcome = require("./welcome");
welcome (client)
welcome.js
module.exports = (client) => {
const channelId = '766761508427530250' // welcome channel
const targetChannelId = '766731745960919052' //rules and info
client.on('guildMemberAdd', (member) => {
console.log(member)
const message = `New user <#${member.id}> joined the server. Please read through ${member.guild.channels.cache.get(targetChannelId).toString()} to gain full access to the server!`
const channel = member.guild.channels.cache.get(channelId)
channel.send(message)
})
}
The code is working perfectly fine, however it would be way more exciting with a little more variety. I'm trying to get multiple welcome messages that get randomly chosen by the bot.. I thought about a Mathfloor as an approach but I'm not quite sure how that would work..
Thank you for reading through my text and I hope that I will soon be able to enjoy the server with my guys!
Cheers!
First problem
I'm not sure why ClientUser.setActivity() and ClientUser.setStatus is not working. In the STREAMING example, it might be because you didn't specify the type of activity. Either way, there's an easier way to what you're doing, which is ClientUser.setPresence(). This method is kind of like a combination of the other two.
client.once('ready', () => {
console.log('Bot is ready!');
config.activity.streaming
? client.user.setPresence({
activity: { name: config.activity.game, type: 'WATCHING' },
})
: client.user.setPresence({
activity: {
name: config.activity.game,
type: 'STREAMING',
url: 'https://twitch.tv/usrname',
},
status: 'idle', // note: the idle icon is overwritten by the STREAMING icon, so this won't do much
});
});
Second Problem
It's pretty hard to make multiple bots, both duplicates of each other, in one file. I would recommend just using a lot of Array.prototype.forEach() loops to apply all events and such to both clients.
[1, 2, 3].forEach((num) =>
console.log(`The element I'm currently iterating a function through is ${num}`)
);
// example main file
const { Client, Collection } = require('discord.js');
const [roseClient, sunflowerClient] = [new Client(), new Client()];
// adding properties:
[roseClient, sunflowerClient].forEach((client) => client.commands = new Collection())
// events
[roseClient, sunflowerClient].forEach((client) =>
client.on('message', (message) => {
// ...
});
);
// login
roseClient.login('token1');
sunflowerClient.login('token2');
Third problem
Again, forEach() loops save the day (❁´◡`❁). This time, however, you should actually use Array.prototype.every(), which will return true if every element of an array passes the given test.
Basically, if we were to use a normal forEach() loop, then even if one of the prefixes found the match, the other wouldn't and the error message would always be sent out. So instead we'll use every() to only send out an error message if both prefixes find no match.
// what if we ony wanted the error message if *every* number was 3
[1, 2, 3].forEach((num) => {
if (num === 3) console.error('Error message');
});
console.log('--------------------');
// now it will only send if all numbers were three (they're not)
if ([1, 2, 3].every((num) => num === 3))
console.error('Error message');
client.on('message', (message) => {
if (['-', '?'].every((prefix) => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
try {
// it did not pass the test (the test being finding no match), and the error message should not be displayed
return false;
client.commands.get(command).execute(message, args);
} catch {
// it did pass the test (by finding no match). if the next test is failed too, the error message should be displayed
return true;
message.channel.send("I don't know that, sorry.");
}
});
});
Fourth Problem
You're on the right track! Math.floor() is definitely the right way to get a random element from an array.
function chooseFood() {
// make an array
const foods = ['eggs', 'waffles', 'cereal', "nothing (●'◡'●)", 'yogurt'];
// produce a random integer from 0 to the length of the array
const index = Math.floor(Math.random() * foods.length);
// find the food at that index
console.log(`Today I will eat ${foods[index]}`);
};
<button onClick="chooseFood()">Choose What to Eat</button>
module.exports = (client) => {
client.on('guildMemberAdd', (member) => {
console.log(member);
const welcomes = [
`Welcome ${member}!`,
`Woah! Didn't see you there ${member}; welcome to the server!`,
`${member} enjoy your stay at ${member.guild}!`,
];
const message = `${
welcomes[Math.floor(Math.random() * welcomes.length)]
} Please read through ${member.guild.channels.cache.get(
'766731745960919052'
)} to gain full access to the server!`;
member.guild.channels.cache.get('766761508427530250').send(message);
});
};
That was a mouthful (╯°□°)╯︵ ┻━┻
I am trying to make a discord bot that sends a message, then repeats a code the user gives.
For example:
User: !play <code>
Bot: #everyone a new game has been started with the code <code>
I also want it to remember this variable until it's reset so that this could be possible:
User: !code
Bot: the current game code is <code>
Is it possible to do this, and if so, how? I cannot find anything showing what I'm looking for in a simple .js script
Here's what I have at the moment:
client.on('message', (msg) => {
if (msg.content === '!play') {
msg.reply('#everyone A new game has been started with the code');
}
});
client.on('message', (msg) => {
if (msg.content === '!code') {
msg.reply('The current game code is');
}
});
oh and also it gives me TypeError: msg.startsWith is not a function
Use message.content.startsWith()
That might work for !play, however I want !code to reply the code that was already defined in !play
True, to get the arguments of a message without a command it's
let args = message
.content // We need the content of the message
.split(' ') // Then we creates an array with the message separated with a space.
.slice(1) // We remove the command from the array
then you can use args as you want.
message.channel.send(args.join(' ')) // We join with a space to transform the array with a string
You could do it like this:
var code = '';
client.on('message', (msg) => {
if (msg.content.startsWith('!play ')) {
code = msg.content.substr(6); // Remove first 6 characters of message
msg.reply(`#everyone A new game has been started with the code ${code}`);
}
if (msg.content.startsWith('!code ') && code.length > 0) {
msg.reply(`The current game code is ${code}`);
}
});
I want the user to input !fn maxtl and the bot would reply by putting out this link
https://fortnitetracker.com/profile/all/maxtl/event
This is what I am thinking it would look like. Can someone provide me with any suggestions on how to improve this Discord bot API usage?
bot.on("message", (msg) => {
if (msg.content === `!fn ${Username}`) {
msg.reply(`https://fortnitetracker.com/profile/all/${Username}/events`);
}
});
Assuming you aren't doing any other processing of the message, this is what you'll probably need to do.
bot.on("message", (msg) => {
if (!msg.content.startsWith('!')) return;
const arguments = msg.content.split(' ');
const command = arguments.shift();
if (command === '!fn') {
msg.reply(`https://fortnitetracker.com/profile/all/${arguments[0]}/events`);
}
});
This will
Check and see that the message begins with your command identifier (assuming it's "!")
Split the message in to an array of arguments;
Remove and store the command in a command variable
Check to see if the command is equal to "!fn"
Reply with a url that includes argument[0] which at this point would be equal to the username if one was provided.
I think this block of code is something you are looking for, I am not 100% because I don't know what the rest of your bot is doing.
This code will
Listen for a message
The bailout of the code execution if the message doesn't start with !fn
Attempts to find the message with mentioned Username (your snippet shows this variable
available so I assume it's known beforehand, if not we can figure that out too)
The Bot tries to post the message
bot.on('message', async (msg) => {
if (!msg.content.startsWith('!fn')) return;
const commandFound = msg.content.find(mentioned => mentioned === `!fn ${Username}`)
const arguments = commandFound.split(' ');
const userName = arguments.shift();
if (userName) {
try {
await msg.reply(`https://fortnitetracker.com/profile/all/${userName}/events`);
} catch (err) {
console.warn('Failed to respond to mention.');
console.warn(err);
}
}
});
I've been working on a simple help command that's supposed to give in depth help with certain commands when the argument for the command is put in, if it's not put in it's supposed to throw out a general command list.
Function snippet:
function help(helpcomm) {
if (helpcomm == "say") {
message.channel.send("Say command makes me repeat the words you type. EG. if you type `p!say Hello World!` I'm going to delete your message and say `Hello world!`.");
} else
if (helpcomm == "ping") {
message.channel.send("Ping command checks the latency between me, the node I'm hosted on and the API latency.");
} else
if (helpcomm == "purge") {
message.channel.send("Purge command deletes a number of latest messages you choose from 2 to 99. EG. if you type `p!purge 20` I will delete the last 20 messages.");
} else
if (helpcomm == "joke") {
message.channel.send("Joke sends a random joke from my database.");
} else
if (helpcomm == "roll") {
message.channel.send("Roll makes me roll a dice from 1 to 20 sides. Basically a random number generator.");
} else
if (helpcomm == "creator") {
message.channel.send("Gives info about my creator. Currently outdated.");
} else
message.channel.send("For specific command help type: `p!help [command]` \nHere are my commands: `p!say [words], p!ping, p!purge [number], p!joke, p!roll [number], p!creator`");
}
And command that's supposed to take the argument:
if (command === "help") {
let text = args.join(' ');
await message.channel.send(help(text));
}
I can node the bot with no errors thrown, but when i actually input the prefix with the command with or without an argument it throws an error saying "Message not defined."
Help would be very much appriciated, if you can explain what I'm doing wrong and how to fix it that would be amazing, no spoon feeding.
If I need to provide any additional information I will put it into comments.
That error indicates that the message variable does not exist in the scope of the help function. If you want to be calling message.channel.send inside your help function, then you'll need to pass message into it:
function help (helpComm, message) {
if (helpcomm == "say") {
return message.channel.send("Say command makes me repeat the words you type. [etc]');
}
//...
return message.channel.send("For specific command help [etc]")
}
// called like:
client.on('message', async function(message) {
//...
if (command === "help") {
let text = args.join(' ');
await help(text, message);
}
});
That said though, It's not clear to me that that's what you intend to do, since this line is already calling message.channel.send, and is apparently expecting help to return a string:
await message.channel.send(help(text));
If you just want help to produce a string, then there's no need to pass message to it, since only the main code needs to interact with the message object:
function help (helpComm) {
if (helpcomm == "say") {
return "Say command makes me repeat the words you type. [etc]';
}
// ...
return "For specific command help [etc]";
}
// called like:
client.on('message', async function(message) {
//...
if (command === "help") {
let text = args.join(' ');
await message.channel.send(help(text));
}
});