How do you code a purge command - javascript

So I have been search far and wide over the internet, trying to find a possible way to make a purge command. Now I have found quite a lot of different ways to make one, but none of them either suited me in the way I wanted, or simply worked for me.
SO to start off, here is my code
const Discord = require("discord.js"); // use discord.js
const BOT_TOKEN = "secret bot token :)" // bot's token
const PREFIX = "*" // bot's prefix
var eightball = [ // sets the answers to an eightball
"yes!",
"no...",
"maybe?",
"probably",
"I don't think so.",
"never!",
"you can try...",
"up to you!",
]
var bot = new Discord.Client(); // sets Discord.Client to bot
bot.on("ready", function() { // when the bot starts up, set its game to Use *help and tell the console "Booted up!"
bot.user.setGame("Use *info") // sets the game the bot is playing
console.log("Booted up!") // messages the console Booted up!
});
bot.on("message", function(message) { // when a message is sent
if (message.author.equals(bot.user)) return; // if the message is sent by a bot, ignore
if (!message.content.startsWith(PREFIX)) return; // if the message doesn't contain PREFIX (*), then ignore
var args = message.content.substring(PREFIX.length).split(" "); // removes the prefix from the message
var command = args[0].toLowerCase(); // sets the command to lowercase (making it incase sensitive)
var mutedrole = message.guild.roles.find("name", "muted");
if (command == "help") { // creates a command *help
var embedhelpmember = new Discord.RichEmbed() // sets a embed box to the variable embedhelpmember
.setTitle("**List of Commands**\n") // sets the title to List of Commands
.addField(" - help", "Displays this message (Correct usage: *help)") // sets the first field to explain the command *help
.addField(" - info", "Tells info about myself :grin:") // sets the field information about the command *info
.addField(" - ping", "Tests your ping (Correct usage: *ping)") // sets the second field to explain the command *ping
.addField(" - cookie", "Sends a cookie to the desired player! :cookie: (Correct usage: *cookie #username)") // sets the third field to explain the command *cookie
.addField(" - 8ball", "Answers to all of your questions! (Correct usage: *8ball [question])") // sets the field to the 8ball command
.setColor(0xFFA500) // sets the color of the embed box to orange
.setFooter("You need help, do you?") // sets the footer to "You need help, do you?"
var embedhelpadmin = new Discord.RichEmbed() // sets a embed box to the var embedhelpadmin
.setTitle("**List of Admin Commands**\n") // sets the title
.addField(" - say", "Makes the bot say whatever you want (Correct usage: *say [message])")
.addField(" - mute", "Mutes a desired member with a reason (Coorect usage: *mute #username [reason])") // sets a field
.addField(" - unmute", "Unmutes a muted player (Correct usage: *unmute #username)")
.addField(" - kick", "Kicks a desired member with a reason (Correct usage: *kick #username [reason])") //sets a field
.setColor(0xFF0000) // sets a color
.setFooter("Ooo, an admin!") // sets the footer
message.channel.send(embedhelpmember); // sends the embed box "embedhelpmember" to the chatif
if(message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.channel.send(embedhelpadmin); // if member is a botadmin, display this too
}
if (command == "info") { // creates the command *info
message.channel.send("Hey! My name is cookie-bot and I'm here to assist you! You can do *help to see all of my commands! If you have any problems with the Minecraft/Discord server, you can contact an administrator! :smile:") // gives u info
}
if (command == "ping") { // creates a command *ping
message.channel.send("Pong!"); // answers with "Pong!"
}
if (command == "cookie") { // creates the command cookie
if (args[1]) message.channel.send(message.author.toString() + " has given " + args[1].toString() + " a cookie! :cookie:") // sends the message saying someone has given someone else a cookie if someone mentions someone else
else message.channel.send("Who do you want to send a cookie to? :cookie: (Correct usage: *cookie #username)") // sends the error message if no-one is mentioned
}
if (command == "8ball") { // creates the command 8ball
if (args[1] != null) message.reply(eightball[Math.floor(Math.random() * eightball.length).toString(16)]); // if args[1], post random answer
else message.channel.send("Ummmm, what is your question? :rolling_eyes: (Correct usage: *8ball [question])"); // if not, error
}
if (command == "say") { // creates command say
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!");
var sayMessage = message.content.substring(4)
message.delete().catch(O_o=>{});
message.channel.send(sayMessage);
}
if(command === "purge") {
let messagecount = parseInt(args[1]) || 1;
var deletedMessages = -1;
message.channel.fetchMessages({limit: Math.min(messagecount + 1, 100)}).then(messages => {
messages.forEach(m => {
if (m.author.id == bot.user.id) {
m.delete().catch(console.error);
deletedMessages++;
}
});
}).then(() => {
if (deletedMessages === -1) deletedMessages = 0;
message.channel.send(`:white_check_mark: Purged \`${deletedMessages}\` messages.`)
.then(m => m.delete(2000));
}).catch(console.error);
}
if (command == "mute") { // creates the command mute
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!"); // if author has no perms
var mutedmember = message.mentions.members.first(); // sets the mentioned user to the var kickedmember
if (!mutedmember) return message.reply("Please mention a valid member of this server!") // if there is no kickedmmeber var
if (mutedmember.hasPermission("ADMINISTRATOR")) return message.reply("I cannot mute this member!") // if memebr is an admin
var mutereasondelete = 10 + mutedmember.user.id.length //sets the length of the kickreasondelete
var mutereason = message.content.substring(mutereasondelete).split(" "); // deletes the first letters until it reaches the reason
var mutereason = mutereason.join(" "); // joins the list kickreason into one line
if (!mutereason) return message.reply("Please indicate a reason for the mute!") // if no reason
mutedmember.addRole(mutedrole) //if reason, kick
.catch(error => message.reply(`Sorry ${message.author} I couldn't mute because of : ${error}`)); //if error, display error
message.reply(`${mutedmember.user} has been muted by ${message.author} because: ${mutereason}`); // sends a message saying he was kicked
}
if (command == "unmute") { // creates the command unmute
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!"); // if author has no perms
var unmutedmember = message.mentions.members.first(); // sets the mentioned user to the var kickedmember
if (!unmutedmember) return message.reply("Please mention a valid member of this server!") // if there is no kickedmmeber var
unmutedmember.removeRole(mutedrole) //if reason, kick
.catch(error => message.reply(`Sorry ${message.author} I couldn't mute because of : ${error}`)); //if error, display error
message.reply(`${unmutedmember.user} has been unmuted by ${message.author}!`); // sends a message saying he was kicked
}
if (command == "kick") { // creates the command kick
if (!message.member.roles.some(r=>["bot-admin"].includes(r.name)) ) return message.reply("Sorry, you do not have the permission to do this!"); // if author has no perms
var kickedmember = message.mentions.members.first(); // sets the mentioned user to the var kickedmember
if (!kickedmember) return message.reply("Please mention a valid member of this server!") // if there is no kickedmmeber var
if (!kickedmember.kickable) return message.reply("I cannot kick this member!") // if the member is unkickable
var kickreasondelete = 10 + kickedmember.user.id.length //sets the length of the kickreasondelete
var kickreason = message.content.substring(kickreasondelete).split(" "); // deletes the first letters until it reaches the reason
var kickreason = kickreason.join(" "); // joins the list kickreason into one line
if (!kickreason) return message.reply("Please indicate a reason for the kick!") // if no reason
kickedmember.kick(kickreason) //if reason, kick
.catch(error => message.reply(`Sorry #${message.author} I couldn't kick because of : ${error}`)); //if error, display error
message.reply(`${kickedmember.user.username} has been kicked by ${message.author.username} because: ${kickreason}`); // sends a message saying he was kicked
}
});
bot.login(BOT_TOKEN); // connects to the bot
It is the only file in my bot folder except the package.json, package-lock.json and all the node_modules.
What I'm trying to do is type in discord *purge [number of messages I want to purge] and get the bot to delete the amount of the messages I asked it to delete, PLUS the command I entered (for example, if I ask the bot to delete 5 messages, he deletes 6 including the *purge 5 message.
Any help would be much appreciated, thanks!

What you are looking for is this (bulkDelete()) method for Discord.js.
It bulk deletes a message, just simply pass in a collection of message in the method and it will do the job for you.
(You can use messages property from channel, otherwise if you prefer promises, then try fetchMessages() method. )
Just make sure that the channel is not a voice channel, or a DM channel. And finally, your bot needs to have permission too.
You can get your own bot's permission for the guild using message.guild.member(client).permissions, or you can just directly use message.guild.member(client).hasPermission(permission), which returns a boolean that determines if your bot have a desired permission.
(The method docs for hasPermission() is here)

note sure if this is still relevant but this what i use in my bots
if (!suffix) {
var newamount = "2";
} else {
var amount = Number(suffix);
var adding = 1;
var newamount = amount + adding;
}
let messagecount = newamount.toString();
msg.channel
.fetchMessages({
limit: messagecount
})
.then(messages => {
msg.channel.bulkDelete(messages);
// Logging the number of messages deleted on both the channel and console.
msg.channel
.send(
"Deletion of messages successful. \n Total messages deleted including command: " +
newamount
)
.then(message => message.delete(5000));
console.log(
"Deletion of messages successful. \n Total messages deleted including command: " +
newamount
);
})
.catch(err => {
console.log("Error while doing Bulk Delete");
console.log(err);
});
basic function is to specify number of messages to purge and it will delete that many plus the command used, the full example is here

Related

How to only check for messages after a specific person sent a message ? Discord JS

Hello I am trying to use a discord bot to wait for a message from an admin of my server and then check the following messages from users. My code waits for the admin message however it somehow caches it ?? At least it doesnt check the users messages. I made my bot write the message where it got triggered to make it more understandable:
const Discord = require("discord.js");
const bot = new Discord.Client();
const bot_config = require("./settings.json")
var token = bot_config.usertoken
var userid = bot_config.userid
var channel = "940800688219369483"; //
bot.on("ready", () => {
console.log(`SUCCESSFULLY LOGGED IN AS ${bot.user.tag}!`);
});
let counter = 0
bot.on("message", (msg) => {
//Waiting for mesage from specific admin
if(msg.author == "1011983215650672781"){
if(counter == 0){ // check if message has already been send
if (msg.channel.id != channel) return; // Checks valid Channel ID
if (msg.author == userid && msg.author == "703629528454660106" && msg.authot == "255396012045238222" && msg.authot == "142772377047199744" && msg.authot == "235748962103951360") { //CHECK IF NEXT MESSAGE IS NOT AN ADMIN
console.log("ADMIN MESSGAE");
}
else{
let answer = msg.content
bot.channels.cache.get(channel).send(answer)
counter ++
console.log("SUCCESSFULLY SENT MESSAGE")
}
}
else{
console.log("ALREADY SENT MESSAGE - CLOSE BOT")
}
}
})
bot.login(usertoken)
The problem is, the bot still writes the first admin message in the channel and not the onw from the first user
You might kick yourself for this, but you have used msg.authot instead of msg.author.id.
You may want to check out the docs, they come in handy when you need to know how to access properties.

Check if someone sent the message twice

On my server, we have a channel for just one word, "Oi".
If someone sends something other than the word "Oi", it gets deleted. But now I need a code that deletes the message if someone sends it twice in a row. They have to wait for someone else to send if they want to send.
This is my current code if you want to check it out for some reason:
if (message.channel.id === "ChannelIdWhichImNotGonnaTell") {
if (message.content === "Oi") {
let log = client.channels.cache.get("ChannelIdWhichImNotGonnaTell")
log.send(`New Oi By ${message.author.tag}`)
} else {
message.delete()
}
}
You can fetch() the last two messages by using the limit option and the last() in the returned collection will be the second last message in the channel (the one before the last one triggered your code).
Then you can compare the author's IDs; if they are the same, you can delete the message:
if (message.channel.id === oiChannelID) {
if (message.content === 'Oi') {
// fetch the last two messages
// this includes this one and the previous one too
let lastMessages = await message.channel.messages.fetch({ limit: 2 });
// this is the message sent before the one triggered this command
let previousMessage = lastMessages.last();
if (previousMessage.author.id === message.author.id) {
console.log('No two Ois, mate');
message.delete();
// don't execute the rest of the code
return;
}
let log = client.channels.cache.get(logChannelID);
log.send(`New Oi By ${message.author.tag}`);
} else {
message.delete();
}
}
There's some several work around for this. But I found this is the efficient way to do that.
As you said 'They have to wait for someone else to send oi' then you should fetch the "old message" before "the new message" that sent. and try to get the User ID. Then compare it with the new message one.
Here is the Example code :
if (message.content === 'Oi') {
message.channel.messages.fetch({limit: 2})
.then(map => {
let messages = Array.from(map.values());
let msg = messages[1];
if (msg.author.id === message.author.id){
message.delete();
// do something
} else {
let log = client.channels.cache.get("ChannelID")
log.send(`New Oi By ${message.author.tag}`)
}}).catch(error => console.log("Error fetching messages in channel"));
}
It will compare the "old messages" author UserID with the "new messages" author UserID. If it's match. Then it will be deleted.

How do I send a message to a channel in a specific Server

So I want a bot to await for a DM response, which would nab certain details from the response and paste it into a specific server. I can't figure out how to send the message to a channel in the specific server.
In order for you to send a message to a specific Channel on a specific Guild (server), you need to first know which Guild are we "talking about".
You can declare the Guild object in multiple ways, for example, if you have access to the Guild's name, you can declare it by finding it on the bot's cached guilds (which include the servers the bot is in).
Let's say the DM you receive always includes the Guild's name as its last "word" and the Channel name as its second to last one.
client.on("message", function(message) {
if(message.channel.type == "dm") { // Checks if the message was received through DM and not through some other channel
const words = message.content.split(' ');
const guildName = words[word.length - 1]; // Declares guildName as being the last word from the message
const channelName = words[word.length - 2]; // Equally, channelName is the second to last word
const recipientGuild = client.guilds.cache.find(guild => guild.name == guildName);
if(recipientGuild) {
const recipientChannel = guildName.channels.cache.find(channel => channel.name === channelName);
if(recipientChannel) recipientChannel.send(message.content);
else console.log("There is no channel with that name in that guild!");
}
else console.log("There is no cached guild with that name!");
}
});
Hopefully this will give you an idea on what you need to do.

TypeError: Cannot read property 'id' of undefined when trying to make discord bot

I'm trying to make a simple discord bot, however whenever I run the -setcaps command I get :
TypeError: Cannot read property 'id' of undefined.
I'm not exactly sure what is causing this. I would appreciate whatever help you can provide. Not exactly sure what to add to this to provide more details, I'm using the latest stable version of node.js and editing with notpad++
// Call Packages
const Discord = require('discord.js');
const economy = require('discord-eco');
// Define client for Discord
const client = new Discord.Client();
// We have to define a moderator role, the name of a role you need to run certain commands
const modRole = 'Sentinel';
// This will run when a message is recieved...
client.on('message', message => {
// Variables
let prefix = '-';
let msg = message.content.toUpperCase();
// Lets also add some new variables
let cont = message.content.slice(prefix.length).split(" "); // This slices off the prefix, then stores everything after that in an array split by spaces.
let args = cont.slice(1); // This removes the command part of the message, only leaving the words after it seperated by spaces
// Commands
// Ping - Let's create a quick command to make sure everything is working!
if (message.content.toUpperCase() === `${prefix}PING`) {
message.channel.send('Pong!');
}
// Add / Remove Money For Admins
if (msg.startsWith(`${prefix}SETCAPS`)) {
// Check if they have the modRole
if (!message.member.roles.find("name", modRole)) { // Run if they dont have role...
message.channel.send('**You need the role `' + modRole + '` to use this command...**');
return;
}
// Check if they defined an amount
if (!args[0]) {
message.channel.send(`**You need to define an amount. Usage: ${prefix}SETCAPS <amount> <user>**`);
return;
}
// We should also make sure that args[0] is a number
if (isNaN(args[0])) {
message.channel.send(`**The amount has to be a number. Usage: ${prefix}SETCAPS <amount> <user>**`);
return; // Remember to return if you are sending an error message! So the rest of the code doesn't run.
}
// Check if they defined a user
let defineduser = '';
if (!args[1]) { // If they didn't define anyone, set it to their own.
defineduser = message.author.id;
} else { // Run this if they did define someone...
let firstMentioned = message.mentions.users.first();
defineduser = firstMentioned.id;
}
// Finally, run this.. REMEMBER IF you are doing the guild-unique method, make sure you add the guild ID to the end,
economy.updateBalance(defineduser + message.guild.id, parseInt(args[0])).then((i) => { // AND MAKE SURE YOU ALWAYS PARSE THE NUMBER YOU ARE ADDING AS AN INTEGER
message.channel.send(`**User defined had ${args[0]} added/subtraction from their account.**`)
});
}
// Balance & Money
if (msg === `${prefix}BALANCE` || msg === `${prefix}MONEY`) { // This will run if the message is either ~BALANCE or ~MONEY
// Additional Tip: If you want to make the values guild-unique, simply add + message.guild.id whenever you request.
economy.fetchBalance(message.author.id + message.guild.id).then((i) => { // economy.fetchBalance grabs the userID, finds it, and puts the data with it into i.
// Lets use an embed for This
const embed = new Discord.RichEmbed()
.setDescription(`**${message.guild.name} Stash**`)
.setColor(0xff9900) // You can set any HEX color if you put 0x before it.
.addField('Stash Owner',message.author.username,true) // The TRUE makes the embed inline. Account Holder is the title, and message.author is the value
.addField('Stash Contents',i.money,true)
// Now we need to send the message
message.channel.send({embed})
})
}
});
client.login('TOKEN HIDDEN');
I'm not sure if this was causing your error but let's give it a try. I edited the check if the user mentioned someone.
// Call Packages
const Discord = require('discord.js');
const economy = require('discord-eco');
// Define client for Discord
const client = new Discord.Client();
// We have to define a moderator role, the name of a role you need to run certain commands
const modRole = 'Sentinel';
// This will run when a message is recieved...
client.on('message', message => {
// Variables
let prefix = '-';
let msg = message.content.toUpperCase();
// Lets also add some new variables
let cont = message.content.slice(prefix.length).split(" "); // This slices off the prefix, then stores everything after that in an array split by spaces.
let args = cont.slice(1); // This removes the command part of the message, only leaving the words after it seperated by spaces
// Commands
// Ping - Let's create a quick command to make sure everything is working!
if (message.content.toUpperCase() === `${prefix}PING`) {
message.channel.send('Pong!');
}
// Add / Remove Money For Admins
if (msg.startsWith(`${prefix}SETCAPS`)) {
// Check if they have the modRole
if (!message.member.roles.find("name", modRole)) { // Run if they dont have role...
message.channel.send('**You need the role `' + modRole.name + '` to use this command...**');
return;
}
// Check if they defined an amount
if (!args[0]) {
message.channel.send(`**You need to define an amount. Usage: ${prefix}SETCAPS <amount> <user>**`);
return;
}
// We should also make sure that args[0] is a number
if (isNaN(args[0])) {
message.channel.send(`**The amount has to be a number. Usage: ${prefix}SETCAPS <amount> <user>**`);
return; // Remember to return if you are sending an error message! So the rest of the code doesn't run.
}
// Check if they defined a user
let defineduser = '';
let user = message.mentions.users.first() || msg.author;
defineduser = user.id
// Finally, run this.. REMEMBER IF you are doing the guild-unique method, make sure you add the guild ID to the end,
economy.updateBalance(defineduser + message.guild.id, parseInt(args[0])).then((i) => { // AND MAKE SURE YOU ALWAYS PARSE THE NUMBER YOU ARE ADDING AS AN INTEGER
message.channel.send(`**User defined had ${args[0]} added/subtraction from their account.**`)
});
}
// Balance & Money
if (msg === `${prefix}BALANCE` || msg === `${prefix}MONEY`) { // This will run if the message is either ~BALANCE or ~MONEY
// Additional Tip: If you want to make the values guild-unique, simply add + message.guild.id whenever you request.
economy.fetchBalance(message.author.id + message.guild.id).then((i) => { // economy.fetchBalance grabs the userID, finds it, and puts the data with it into i.
// Lets use an embed for This
const embed = new Discord.RichEmbed()
.setDescription(`**${message.guild.name} Stash**`)
.setColor(0xff9900) // You can set any HEX color if you put 0x before it.
.addField('Stash Owner', message.author.username, true) // The TRUE makes the embed inline. Account Holder is the title, and message.author is the value
.addField('Stash Contents', i.money, true)
// Now we need to send the message
message.channel.send({
embed
})
})
}
});
client.login('TOKEN HIDDEN')

Discord.js deleteMessage() doesn't work

I am creating a Discord bot with discord.js and I'd like to create a command that can clear messages. For now, I have this code (only the interesting part) and I can't figure out why it doesn't work:
// Importing discord.js, creating bot and setting the prefix
const Discord = require('discord.js');
const bot = new Discord.Client();
const prefix = "/";
// Array that stores all messages sent
messages = [];
bot.on('message', (message) => {
// Store the new message in the messages array
messages.push(message);
// Split the command so that "/clear all" becames args["clear", "all"]
var args = message.content.substring(prefix.length).split(" ");
// If the command is "/clear all"
if(args[0] == "clear" && args[1] == "all") {
bot.deleteMessages(messages); // Code that doesn't work
// Resets the array
messages = [];
}
}
// CONNECT !!!
bot.login('LOGING TOKEN HERE');
Can you help me ?
You should use <TextChannel>.bulkDelete instead.
Example:
msg.channel.bulkDelete(100).then(() => {
msg.channel.send("Purged 100 messages.").then(m => m.delete(3000));
});
This would delete 2 - 100 messages in a channel for every call to this method so you would not receive 429 (Too many Requests) Error frequently which might result in your token being revoked.
I see two problems:
the messages array is always empty; there is no code that adds items to the array, so the call to bot.deleteMessages will always get an empty array;
it does not appear that deleteMessages is an available method on Discord.Client;
Based on the documentation, I think what you want is sweepMessages. The description of that states:
Sweeps all text-based channels' messages and removes the ones older than the max message lifetime. If the message has been edited, the time of the edit is used rather than the time of the original message.
Try changing the code to instead call bot.sweepMessages(1);, which I think will tell the client to clear all messages older than one second.
Another way to do this, without sweepMessages is by using fetchMessages:
let user = message.mentions.users.first();
let amount = !!parseInt(message.content.split(' ')[1]) ? parseInt(message.content.split(' ')[1]) : parseInt(message.content.split(' ')[2])
var prefix = '!'
if (message.content.startsWith(prefix + 'clear') && !amount)
return message.reply('Must specify an amount to clear!');
if (message.content.startsWith(prefix + 'clear') && !amount && !user) return message.reply('Must specify a user and amount, or just an amount, of messages to clear!');
message.channel.fetchMessages({
limit: amount,
}).then((messages) => {
if (user) {
const filterBy = user ? user.id : bot.user.id;
messages = messages.filter(m => m.author.id === filterBy).array().slice(0, amount);
}
message.channel.bulkDelete(messages).catch(error => console.log(error.stack));
});
This will allow users to use the command !clear [#] to delete that number of messages when sent. If it is run as just !clear you can set how many get deleted, without a specified number.
discord.js Documentation - TextChannel#fetchMessages
You can swap
bot.deleteMessages()
to:
messages.forEach(x => x.delete())
Its not like that. you should fetch the messages first then use bulkDelete to delete them
, here is a simple example
// Normal Javascript
<Message>.channel.fetchMessages()
.then(messages => {
// Here you can use bulkDelete(101) to delete 100 messages instead of using fetchMessages and deleting only 50
<Message>.channel.bulkDelete(messages);
});
// ES6
let messages = await <Message>.channel.fetchMessages();
// Here you can use bulkDelete(101) to delete 100 messages instead of using fetchMessages and deleting only 50
await <Message>.channel.bulkDelete(messages);

Categories