Need to send message twice in order to get a response - node.js

When I have this code here:
client.on("message", msg => {
const args = msg.content.trim().split(/ +/g);
let second = args[1];
let x = Math.floor((Math.random() * second) + 1);
if(msg.content === "random") {
msg.channel.send(`${x}`)
console.log(x)
console.log(second)
}
})
I need to send "random 10 (example)" twice and it still doesn't work cause it uses the "random" as the input for "second¨ how do i make this work?

Since "msg" is a string, you need to parse it as an integer before preforming an operation on it. I recommend replacing the "let x" line with the following:
let x = Math.floor((Math.random() * parseInt(second)) + 1);
parseInt is an internal function that takes a string with number contents and turns it into an integer.

const triggerWords = ['random', 'Random'];
client.on("message", msg => {
if (msg.author.bot) return false;
const args = msg.content.trim().split(/ +/g);
let second = args[1];
let x = Math.floor((Math.random() * parseInt(second)) + 1);
triggerWords.forEach((word) => {
if (msg.content.includes(word)) {
msg.reply(`${x}`);
}
});
});

To add on to quandale dingle's answer, what you can do with your bot is to create a command handler, which will make the developing process much easier and will look nice. If you don't really want to create a command handler, you can also use the following code:
if (message.content.startsWith(prefix)){
//set a prefix before, and include this if statement in the on message
const args = message.content.slice(prefix.length).trim().split(/ +/g)
const commandName = args.shift().toLowerCase()
//use if statements for each command, make sure they are nested inside the startsWith statement
}
If you want to create a command handler, there's some sample code below. It works on discord.js v13, but I've no idea if it will work in v12. This is a more advanced command handler.
/*looks for commands in messages & according dependencies
or command handler in more simple terms*/
const fs = require("fs");
const prefix = "+"; //or anything that's to your liking
client.commands = new Discord.Collection();
fs.readdirSync("./commands/").forEach((dir) => {
const commandFiles = fs.readdirSync(`./commands/${dir}/`).filter((file) =>
file.endsWith(".js")
); //subfolders, like ./commands/helpful/help.js
//alternatively... for a simpler command handler
fs.readdirSync("./commands/").filter((file) =>
file.endsWith(".js")
);
for (const file of commandFiles) {
const commandName = file.split(".")[0]
const command = require(`./commands/${file}`);
client.commands.set(commandName, command);
}
});
//looks for commands in messages
client.on("messageCreate", message => {
if (message.author == client.user) return;
if (message.content.startsWith(prefix)){
const args = message.content.slice(prefix.length).trim().split(/ +/g)
const commandName = args.shift().toLowerCase()
const command = client.commands.get(commandName)
if (!command) return;
command.run(client, message, args)
}
});

Related

Trying to learn module.exports but having some problem

I'm using discord.js from some week and now I would like to do that when someone enter in a vocal chat, the bot will send a message in the console. I tried using this code in the main file of the bot and perfectly worked but when I try to put it in another file and export it in the main file it doesn't work. Someone that can help me and maybe explain it?
main.js:
const Discord = require('discord.js');
const fs = require("fs");
const client = new Discord.Client();
const { prefix, token } = require("../config.json");
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 a = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return a
}
test1.js:
const Discord = require('discord.js');
const fs = require("fs");
const client = new Discord.Client();
const { prefix, token } = require("../config.json");
module.exports = {
execute() {
client.on('voiceStateUpdate', (oldState, newState) => {
if (newState.channelID === null) console.log('Inside channel', oldState.channelID);
else if (oldState.channelID === null) console.log('Outside channel', newState.channelID);
else console.log('user moved channels', oldState.channelID, newState.channelID);
})}}
In this part in your main.js file:
const a = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return a
}
The a variable contains an object like { execute: function(){...} }. You not calling the execute function.
Try this:
const { execute } = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return execute();
}
Can you try adding the keyword function before the word execute()?
Alternatively, you could do:
// \/ you can put arguments here
module.exports.execute = () => {
// function here
}
and then in your index file..
const a = require("./commands/test1")
if(client.guilds.cache.get("<guild if>")){
return a.execute(this is where you would put your arguments)
}
Happy coding!

Making a simple music bot for discord server, not working

Working on making a bot for a personal discord server, wanting it to simply join general voicechat when command "Blyat" is detected, play mp3 file, when its done to leave. Code:
var Discord = require('discord.js');
var client = new Discord.Client();
var isReady = true;
client.on('message', message => {
if (command === "Blyat") {
var VC = message.member.voiceChannel;
if (!VC) return message.reply("MESSAGE IF NOT IN A VOICE CHANNEL")
VC.join()
.then(connection => {
const dispatcher = connection.playFile('C:\Users\Wyatt\Music\soviet-anthem.mp3');
dispatcher.on("finish", end => { VC.leave() });
})
.catch(console.error);
};
});
client.login('token, not putting in code, is there in real code');
Error: "ReferenceError: command is not defined
at Client. (C:\Users\jeffofBread\Desktop\Discord Bot\main.js:6:5)"
Any help or tips will be much appreciated, haven't coded in many years and have lost any knowledge I had once held.
Your problem comes from an unidentified variable. Fortunatly that is very easy to fix. All you have to do is define command before you call it.
For this we'll splice the message content into two parts. The command and any arguments that may be included like mentions or other words. We do that with:
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
Note: The args constant is an array.
Which would make your entire onMessage event look like this:
client.on('message', message => {
const prefix = "!";
const args = message.content.slice(prefix.length).split(/ +/);
const command = args.shift().toLowerCase();
if (command === "blyat") {
var VC = message.member.voice.channel;
if (!VC) return message.reply("MESSAGE IF NOT IN A VOICE CHANNEL")
VC.join()
.then(connection => {
const dispatcher = connection.play('C:\Users\Wyatt\Music\soviet-anthem.mp3');
dispatcher.on("finish", end => { VC.leave() });
})
.catch(console.error);
};
});

Doesn't create a channel

I want to use !test epicchannel (epicchannel being the name of the channel , for example if I want to use !test infinite , it will create a channel named testing-infinite ) but it doesn't work. it just makes a channel named testing-test
I've tried using message.content.startsWith, but if I do that, nothing happens.
const Discord = require("discord.js");
const client = new Discord.Client();
const prefix = '!';
client.on("message", async message => {
if(message.content.startsWith === '!test') {
if(message.author.id === '560761436058550273') {
const args = message.content.slice(prefix.length).trim().split(/ +/g);
message.guild.createChannel(`testing-${args}`).then(channel => {
channel.setTopic(`Today we will test: ${args}`)
})
}else{
if(!message.author.id === '560761436058550273') {
return;
}
}
}
});
client.login('login is here');
No errors, I just want it to use !test infinite to create a channel named testing-infinite
Simply change
const args = message.content.slice(prefix.length).trim().split(/ +/g);
to
const [_, args] = message.content.trim().split(' ')
That way we split the message by spaces after trimming it, and we actually save the second part in args variable by doing some array destructuring assignment.
args is an array, just join testing- and args[1] to get the name you want:
rodrigo:~:node
> const prefix = '!';
undefined
> var message = { content:'!test epicchannel'}
undefined
> message
{ content: '!test epicchannel' }
> const args = message.content.slice(prefix.length).trim().split(/ +/g);
undefined
> args
[ 'test', 'epicchannel' ]
> var channelName = `testing-${args[1]}`;
undefined
> channelName
'testing-epicchannel'

fs.writeFile not writing to file unless run twice

I'm trying to learn Node.js so I've been trying to write a simple Discord bot. It runs fine except when I try to write to a config file. It only writes to the file when I run the command twice or if another command is run right after it. I can't seem to figure out why it does that. It succeeds in posting a message in Discord after every command, but it's just the file that doesn't get updated. It doesn't output an error to the console either.
I have the code below and the config.json sample. Any help would be greatly appreciated.
config.json:
{
"ownerID": "1234567890",
"token": "insert-bot-token-here",
"prefix": "!",
"defaultStatus": "status-here"
}
const Discord = require("discord.js");
const client = new Discord.Client();
const fs = require("fs")
const config = require("./config.json");
client.on("ready", () => {
console.log("I am ready!");
client.user.setActivity(config.defaultStatus, {
type: 'WATCHING'
});
});
client.on("message", (message) => {
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (!message.content.startsWith(config.prefix) || message.author.bot) return;
if (command === "ping") {
message.channel.send("pong!");
} else
if (message.author.id !== config.ownerID) return message.reply("you must be the bot owner to run this command.");
let configData = JSON.stringify(config, null, 2);
// Command to change the prefix for commands
if (command === "prefix") {
let newPrefix = message.content.split(" ").slice(1, 2)[0];
config.prefix = newPrefix;
fs.writeFile("./config.json", configData, (err) => console.error);
message.channel.send("Prefix has been updated to \"" + newPrefix + "\"");
}
// Command to change the bot status
if (command === "status") {
let game = args.slice(0).join(" ");
client.user.setActivity(game, {
type: 'WATCHING'
});
message.channel.send("Status has been updated to \"" + game + "\"");
}
// Command to change the default bot status
if (command === "defaultstatus") {
let newStatus = args.slice(0).join(" ");
config.defaultStatus = newStatus;
client.user.setActivity(newStatus, {
type: 'WATCHING'
});
fs.writeFile("./config.json", configData, (err) => console.error);
message.channel.send("Default status has been updated to \"" + newStatus + "\"");
}
});
client.login(config.token);
That works only the second time because you're declaring configData before you change the config object.
configData = JSON.stringify(config, null, 2); //saves the config as a string
// you do all your stuff, including changing the prefix, for example
config.prefix = '-'; //this is stored in config, but not in configData
// then you write the file with the old data
fs.writeFile("./config.json", configData, (err) => console.error);
That causes the changes to be delayed every time.
You should create the configData after changing config:
...
config.prefix = '-'; // inside the command
...
let configData = JSON.stringify(config, null, 2);
fs.writeFile('./config.json', configData, err => console.error);

Deleting all messages in discord.js text channel

Ok, so I searched for a while, but I couldn't find any information on how to delete all messages in a discord channel. And by all messages I mean every single message ever written in that channel. Any clues?
Try this
async () => {
let fetched;
do {
fetched = await channel.fetchMessages({limit: 100});
message.channel.bulkDelete(fetched);
}
while(fetched.size >= 2);
}
Discord does not allow bots to delete more than 100 messages, so you can't delete every message in a channel. You can delete less then 100 messages, using BulkDelete.
Example:
const Discord = require("discord.js");
const client = new Discord.Client();
const prefix = "!";
client.on("ready" () => {
console.log("Successfully logged into client.");
});
client.on("message", msg => {
if (msg.content.toLowerCase().startsWith(prefix + "clearchat")) {
async function clear() {
msg.delete();
const fetched = await msg.channel.fetchMessages({limit: 99});
msg.channel.bulkDelete(fetched);
}
clear();
}
});
client.login("BOT_TOKEN");
Note, it has to be in a async function for the await to work.
Here's my improved version that is quicker and lets you know when its done in the console but you'll have to run it for each username that you used in a channel (if you changed your username at some point):
// Turn on Developer Mode under User Settings > Appearance > Developer Mode (at the bottom)
// Then open the channel you wish to delete all of the messages (could be a DM) and click the three dots on the far right.
// Click "Copy ID" and paste that instead of LAST_MESSAGE_ID.
// Copy / paste the below script into the JavaScript console.
var before = 'LAST_MESSAGE_ID';
var your_username = ''; //your username
var your_discriminator = ''; //that 4 digit code e.g. username#1234
var foundMessages = false;
clearMessages = function(){
const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
const channel = window.location.href.split('/').pop();
const baseURL = `https://discordapp.com/api/channels/${channel}/messages`;
const headers = {"Authorization": authToken };
let clock = 0;
let interval = 500;
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration);
});
}
fetch(baseURL + '?before=' + before + '&limit=100', {headers})
.then(resp => resp.json())
.then(messages => {
return Promise.all(messages.map((message) => {
before = message.id;
foundMessages = true;
if (
message.author.username == your_username
&& message.author.discriminator == your_discriminator
) {
return delay(clock += interval).then(() => fetch(`${baseURL}/${message.id}`, {headers, method: 'DELETE'}));
}
}));
}).then(() => {
if (foundMessages) {
foundMessages = false;
clearMessages();
} else {
console.log('DONE CHECKING CHANNEL!!!')
}
});
}
clearMessages();
The previous script I found for deleting your own messages without a bot...
// Turn on Developer Mode under User Settings > Appearance > Developer Mode (at the bottom)
// Then open the channel you wish to delete all of the messages (could be a DM) and click the three dots on the far right.
// Click "Copy ID" and paste that instead of LAST_MESSAGE_ID.
// Copy / paste the below script into the JavaScript console.
// If you're in a DM you will receive a 403 error for every message the other user sent (you don't have permission to delete their messages).
var before = 'LAST_MESSAGE_ID';
clearMessages = function(){
const authToken = document.body.appendChild(document.createElement`iframe`).contentWindow.localStorage.token.replace(/"/g, "");
const channel = window.location.href.split('/').pop();
const baseURL = `https://discordapp.com/api/channels/${channel}/messages`;
const headers = {"Authorization": authToken };
let clock = 0;
let interval = 500;
function delay(duration) {
return new Promise((resolve, reject) => {
setTimeout(() => resolve(), duration);
});
}
fetch(baseURL + '?before=' + before + '&limit=100', {headers})
.then(resp => resp.json())
.then(messages => {
return Promise.all(messages.map((message) => {
before = message.id;
return delay(clock += interval).then(() => fetch(`${baseURL}/${message.id}`, {headers, method: 'DELETE'}));
}));
}).then(() => clearMessages());
}
clearMessages();
Reference: https://gist.github.com/IMcPwn/0c838a6248772c6fea1339ddad503cce
This will work on discord.js version 12.2.0
Just put this inside your client on message event
and type the command: !nuke-this-channel
Every message on channel will get wiped
then, a kim jong un meme will be posted.
if (msg.content.toLowerCase() == '!nuke-this-channel') {
async function wipe() {
var msg_size = 100;
while (msg_size == 100) {
await msg.channel.bulkDelete(100)
.then(messages => msg_size = messages.size)
.catch(console.error);
}
msg.channel.send(`<#${msg.author.id}>\n> ${msg.content}`, { files: ['http://www.quickmeme.com/img/cf/cfe8938e72eb94d41bbbe99acad77a50cb08a95e164c2b7163d50877e0f86441.jpg'] })
}
wipe()
}
This will work so long your bot has appropriate permissions.
module.exports = {
name: "clear",
description: "Clear messages from the channel.",
args: true,
usage: "<number greater than 0, less than 100>",
execute(message, args) {
const amount = parseInt(args[0]) + 1;
if (isNaN(amount)) {
return message.reply("that doesn't seem to be a valid number.");
} else if (amount <= 1 || amount > 100) {
return message.reply("you need to input a number between 1 and 99.");
}
message.channel.bulkDelete(amount, true).catch((err) => {
console.error(err);
message.channel.send(
"there was an error trying to prune messages in this channel!"
);
});
},
};
In case you didn't read the DiscordJS docs, you should have an index.js file that looks a little something like this:
const Discord = require("discord.js");
const { prefix, token } = require("./config.json");
const client = new Discord.Client();
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 portion:
client.once("ready", () => {
console.log("Ready!");
});
client.on("message", (message) => {
if (!message.content.startsWith(prefix) || message.author.bot) return;
const args = message.content.slice(prefix.length).split(/ +/);
const commandName = args.shift().toLowerCase();
if (!client.commands.has(commandName)) return;
const command = client.commands.get(commandName);
if (command.args && !args.length) {
let reply = `You didn't provide any arguments, ${message.author}!`;
if (command.usage) {
reply += `\nThe proper usage would be: \`${prefix}${command.name} ${command.usage}\``;
}
return message.channel.send(reply);
}
try {
command.execute(message, args);
} catch (error) {
console.error(error);
message.reply("there was an error trying to execute that command!");
}
});
client.login(token);
Another approach could be cloning the channel and deleting the one with the messages you want deleted:
// Clears all messages from a channel by cloning channel and deleting old channel
async function clearAllMessagesByCloning(channel) {
// Clone channel
const newChannel = await channel.clone()
console.log(newChannel.id) // Do with this new channel ID what you want
// Delete old channel
channel.delete()
}
I prefer this method rather than the ones listed on this thread because it most likely takes less time to process and (I'm guessing) puts the Discord API under less stress. Also, channel.bulkDelete() is only able to delete messages that are newer than two weeks, which means you won't be able to delete every channel message in case your channel has messages that are older than two weeks.
The possible downside is the channel changing id. In case you rely on storing ids in a database or such, don't forget to update those documents with the id of the newly cloned channel!
Here's #Kiyokodyele answer but with some changes from #user8690818 answer.
(async () => {
let deleted;
do {
deleted = await channel.bulkDelete(100);
} while (deleted.size != 0);
})();

Resources