CODING LANGUAGE = DISCORD.JS
| COMMAND = R!MASSBAN
client.on('message', async(message) => {
if (message.content === 'r!massban') {
message.guild.members.cache.forEach (member => {
if (member.hasPermission("ADMINISTRATOR")) return;
member.ban();
});
}
})```
It only bans me. I get no errors in console. It will only ban me and no one else even though it is above all other roles. This is my first coding project using discord.js and js. Any help will be appreciated.
Looks mostly fine to me.
If you are the only person being banned, maybe console.log the cache to see who is in it. The cache only has people who were recently active, so if it's your test server, if you're the only active person, you may be the only person in the cache.
//edit:
Found out what it might be. replace cache with .fetch(), fetch also gets offline members.
client.on("message", (msg) => {
if(msg.content.trim().startsWith("r!")){
const [prefix, command] = msg.content.split("!");
switch(command){
case "massban":
msg.guild.members.cache.forEach(member => {
if(member.hasPermission("ADMINISTRATOR")) return;
member.ban();
});
break;
default:
msg.reply("That command doesn't exist");
}
}
})
Related
so i am creating a bot with a kick command and would like to be able to add a reason for said action, i've heard from somewhere that i may have to do string manipulation. currently i have a standalone reason as shown in the code below:
client.on("message", (message) => {
// Ignore messages that aren't from a guild
if (!message.guild) return;
// If the message starts with ".kick"
if (message.content.startsWith(".kick")) {
// Assuming we mention someone in the message, this will return the user
const user = message.mentions.users.first();
// If we have a user mentioned
if (user) {
// Now we get the member from the user
const member = message.guild.member(user);
// If the member is in the server
if (member) {
member
.kick("Optional reason that will display in the audit logs")
.then(() => {
// lets the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
.catch((err) => {
// An error happened
// This is generally due to the bot not being able to kick the member,
// either due to missing permissions or role hierarchy
message.reply(
"I was unable to kick the member (this could be due to missing permissions or role hierarchy"
);
// Log the error
console.error(err);
});
} else {
// The mentioned user isn't in this server
message.reply("That user isn't in this server!");
}
// Otherwise, if no user was mentioned
} else {
message.reply("You didn't mention the user to kick!");
}
}
});
Split message.content and slice the first 2 array elements, this will leave you with the elements that make up the reason. Join the remaining elements back to a string.
const user = message.mentions.users.first();
const reason = message.content.split(' ').slice(2).join(' ');
Here is something that could help:
const args = message.content.slice(1).split(" "); //1 is the prefix length
const command = args.shift();
//that works as a pretty good command structure
if(command === 'kick') {
const user = message.mentions.users.first();
args.shift();
const reason = args.join(" ");
user.kick(reason);
//really close to Elitezen's answer but you might have a very terrible problem
//if you mention a user inside the reason, depending on the users' id, the bot could kick
//the user in the reason instead!
}
Here's how you can take away that problem (with regex)
const userMention = message.content.match(/<#!?[0-9]+>/);
//you may have to do some more "escapes"
//this works since regex stops at the first one, unless you make it global
var userId = userMention.slice(2, userMention.length-1);
if(userId.startsWith("!")) userId = userId.slice(1);
const user = message.guild.members.cache.get(userId);
args.shift();
args.shift();
user.kick(args.join(" "))
.then(user => message.reply(user.username + " was kicked successfully"))
.catch(err => message.reply("An error occured: " + err.message))
I assume you want your full command to look something like
.kick #user Being hostile to other members
If you want to assume that everything in the command that isn't a mention or the ".kick" command is the reason, then to get the reason from that string, you can do some simple string manipulation to extract the command and mentions from the string, and leave everything else.
Never used the Discord API, but from what I've pieced from the documentation, this should work.
let reason = message.content.replaceAll(".kick", "")
message.mentions.forEach((mentionedUser) => reason.replaceAll("#" + mentionedUser.username, "")
// assume everything else left in `reason` is the sentence given by the user as a reason
if (member) {
member
.kick(reason)
.then(() => {
// lets the message author know we were able to kick the person
message.reply(`Successfully kicked ${user.tag}`);
})
}
I want to create a verify Command with discord.js v12 which gives you a verified Role which is defined in a Configfile.
Configfile:
{
"token": "my-token",
"status": "a game",
"statusurl": "",
"statustype": 0,
"botmanager": ["285470267549941761", "743136148293025864"],
"prefix": "m!",
"server": {
"343308714423484416": {
"active": true,
"hasBeta": true,
"adminroles": ["533646738813353984"],
"modroles": ["744589796361502774"],
"premiumtoken": "",
"welcomechannel": "653290718248435732",
"welcomemessage": "Hey Hey %user% at %server%",
"welcomemsgenabled": true,
"leavechannel": "653290718248435732",
"leavemessage": "Bye %user% at %server%",
"leavemsgenabled": true,
"verifiedrole": "533646700712296448",
"ruleschannel": "382197929605201920"
}
}
}
My Code:
const Discord = require('discord.js')
const client = new Discord.Client()
const config = require('./config.json')
client.on('ready', () => {
client.user.setStatus('online')
client.user.setActivity("m!help")
console.log(`Bot started successfully in ${client.guilds.cache.size} Guilds with ${client.users.cache.size} Users and ${client.channels.cache.size} Channels`)
})
client.on("message", async message => {
if(message.author.bot) return;
if(!message.content.startsWith(config.prefix)) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if(command === "verify") {
if(args.length == 0) {
let member = message.mentions.members.first();
if(message.member.roles.cache.some(r=>[config.server[(message.guild.id)].modroles].includes(r.id))) {
if(!member) {
return message.channel.send(new Discord.MessageEmbed().setColor(0xd35400).setTitle("Invalid User").setDescription("Please use the following Syntax:\n `m!verify <Nutzer>`"))
} else {
var role = message.guild.roles.find(role => role.id === config.server[(message.guild.id)].verifiedrole);
member.roles.cache.add(config.guild[(message.guild.id)].verifiedrole)
}
} else {
message.channel.send(new Discord.MessageEmbed().setTitle("Missing Perms!").setDescription("You're missing the permission to execute this command!").setColor(0xe74c3c))
}
}
}
console.log("Command used: " + command + " " + args + " | User: " + message.author.id + " | Guild: " + message.guild.id)
}
}
})
client.login(config.token)
I removed the most Code so only this command is left. Important is, that this Bot have to be able to use at multiple Servers at the time.
What is wrong here?
OK, so lets make this a multi part answer. First "What is wrong here?" Well, for the most part your current code does not work because you don't use the brackets correctly. You are trying to close brackets that you don't open anywhere. You also use a few too many "if" statements in places where you don't need them.
Next is your concern about multiple servers. This is really not a problem if you write the code to be dynamic. The execution of the command is quick enough that you don't need to worry about two people trying to use the command and the roles getting mixed up.
What I would really advise you to do is take a look at this https://discordjs.guide/ and this https://discord.js.org/#/docs/main/stable/general/welcome
Now to the topic of this question, this is how you could do such a "verify" command. I also added a few notations into the code to explain what we're doing 🙂
client.on("message", message => { // You don't need the async here
// This is all working correctly
if (message.author.bot) return;
if (!message.content.startsWith(config.prefix)) return;
const args = message.content.slice(config.prefix.length).trim().split(/ +/g);
const command = args.shift().toLowerCase();
if (command === "verify") {
// We define the server constant as the part of the JSON that deals with the server the message came from
// This makes accessing those values easier
const server = config.server[message.guild.id];
// Your code here was also working
let member = message.mentions.members.first();
// Here we first define the moderator role
// Technicaly this is not needed but it makes the whole code a little easier to understand
// We need modrole[0] here because the modrole entry in your JSON is an array
let modrole = message.guild.roles.cache.find(r => r.id === server.modroles[0]);
// Here we check if the member who calls this command has the needed role
// We need to use the ID of the role to check
if (!message.member.roles.cache.has(modrole.id)) {
// If the user does not have the required role we return here
// That way you don't need to use the 'else' statement
// Creating the embed object in multiple lines improves readability
return message.channel.send(new Discord.MessageEmbed()
.setTitle("Missing Perms!")
.setDescription("You're missing the permission to execute this command!")
.setColor(0xe74c3c)
);
}
if (!member) {
// Here we check if a member was tagged in the command and if that user exists
// Same reasons as above
return message.channel.send(new Discord.MessageEmbed()
.setColor(0xd35400)
.setTitle("Invalid User")
.setDescription(`Please use the following Syntax:\n '${config.prefix}verify <Nutzer>'`)
);
}
// Now we define the role that we want the bot to give
// Here we also don't need to do this but it improves readability and makes working with the role a little easier
var role = message.guild.roles.cache.find(role => role.id === server.verifiedrole);
// Here we add the role to the specified member
// We don't need to use the .cache here
member.roles.add(role.id);
// We can use something called "template strings" here so we don't need to combine multiple strings
// They allow us to put predefined values into the string
console.log(`Command used: ${command} ${args} | User: ${message.author.id} | Guild: ${message.guild.id}`)
}
})
If you want, that the command can be executed at multiple servers at the time you need to write the code in async/await. If you want to learn more about async you can get very good help especially for discord.js v12 here: Understanding async/await
you can get a command for a specifiq channel and give a role for acces to the server
I have been wondering how can I send messages when someone invites my bot to their server.
Please help me in this area I can't figure it out it's there in Python but I have not used to it.
Thank you for your help
All the above answers assume you know something about the server and in most cases you do not!
What you need to do is loop through the channels in the guild and find one that you have permission to text in.
You can get the channel cache from the guild.
Take the below example:
bot.on("guildCreate", guild => {
let defaultChannel = "";
guild.channels.cache.forEach((channel) => {
if(channel.type == "text" && defaultChannel == "") {
if(channel.permissionsFor(guild.me).has("SEND_MESSAGES")) {
defaultChannel = channel;
}
}
})
//defaultChannel will be the channel object that the bot first finds permissions for
defaultChannel.send('Hello, Im a Bot!')
});
You can of course do further checks to ensure you can text before texting but this will get you on the right path
Update discord.js 12+
Discord.JS now uses cache - here is the same answer for 12+
bot.on("guildCreate", guild => {
let found = 0;
guild.channels.cache.map((channel) => {
if (found === 0) {
if (channel.type === "text") {
if (channel.permissionsFor(bot.user).has("VIEW_CHANNEL") === true) {
if (channel.permissionsFor(bot.user).has("SEND_MESSAGES") === true) {
channel.send(`Hello - I'm a Bot!`);
found = 1;
}
}
}
}
});
})
You can simply send the owner for example a message using guild.author.send("Thanks for inviting my bot");
Or you can also send a message to a specific user:
client.users.get("USER ID").send("My bot has been invited to a new server!");
I'm not sure if you're using a command handler or not since you seem new to JS I'm going to assume you're not. The following is a code snippet for what you're trying to do:
client.on('guildCreate', (guild) => {
guild.channels.find(t => t.name == 'general').send('Hey their Im here now!'); // Change where it says 'general' if you wan't to look for a different channel name.
});
Is there any way to make a command send a private message to all members of the discord group using discord.js?
Exemple: /private TEST
This message is sent to everyone in the group in private chat instead of channel chat.
You can iterate through Guild.members.
When you receive a message that starts with /private, you take the rest and send it to every member of the guild by using Guild.members.forEach().
Here's a quick example:
client.on('message', msg => {
if (msg.guild && msg.content.startsWith('/private')) {
let text = msg.content.slice('/private'.length); // cuts off the /private part
msg.guild.members.forEach(member => {
if (member.id != client.user.id && !member.user.bot) member.send(text);
});
}
});
This is just a basic implementation, you can obviously use this concept with your command checks or modify that by adding additional text and so on.
Hope this solves the problem for you, let me know if you have any further questions :)
The updated code for discord.js v12 is just adding cache to the forEach.
client.on('message', msg => {
if (msg.guild && msg.content.startsWith('/private')) {
let text = msg.content.slice('/private'.length); // cuts off the /private part
msg.guild.members.cache.forEach(member => {
if (member.id != client.user.id && !member.user.bot) member.send(text);
});
}
});
How do you play an audio file from a Discord bot? Needs to play a local file, be in JS, and upon a certain message being sent it will join the user who typed the message, and will play the file to that channel.
GitHub Project: LINK
In order to do this there are a few things you have to make sure of first.
Have FFMPEG installed & the environment path set for it in Windows [link]
Have Microsoft Visual Studio (VS) installed [link]
Have Node.js installed.[link]
Have Discord.js installed in VS.
From there the steps are quite simple. After making your project index.js you will start typing some code. Here are the steps:
Add the Discord.js dependency to the project;
var Discord = require('discord.js');
Create out client variable called bot;
var bot = new Discord.Client();
3. Create a Boolean variable to make sure that the system doesn't overload of requests;
var isReady = true;
Next make the function to intercept the correct message;
bot.on('message', message =>{ENTER CODE HERE});
Create an if statement to check if the message is correct & if the bot is ready;
if (isReady && message.content === 'MESSAGE'){ENTER CODE HERE}
Set the bot to unready so that it cannot process events until it finishes;
isReady = false;
Create a variable for the channel that the message-sender is currently in;
var voiceChannel = message.member.voice.channel;
Join that channel and keep track of all errors;
voiceChannel.join().then(connection =>{ENTER CODE HERE}).catch(err => console.log(err));
Create a refrence to and play the audio file;
const dispatcher = connection.play('./audiofile.mp3');
Slot to wait until the audio file is done playing;
dispatcher.on("end", end => {ENTER CODE HERE});
Leave channel after audio is done playing;
voiceChannel.leave();
Login to the application;
bot.login('CLIENT TOKEN HERE');
After you are all finished with this, make sure to check for any un-closed brackets or parentheses. i made this because it took my hours until I finally found a good solution so I just wanted to share it with anybody who is out there looking for something like this.
thanks so much!
One thing I will say to help anyone else, is things like where it says ENTER CODE HERE on step 10, you put the code from step 11 IE:
dispatcher.on("end", end => voiceChannel.leave());
As a complete example, this is how I have used it in my message command IF block:
if (command === "COMMAND") {
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:/PAtH/TO/MP3/FILE.MP3');
dispatcher.on("end", end => {VC.leave()});
})
.catch(console.error);
};
I went ahead an included Nicholas Johnson's Github bot code here, but I made slight modifications.
He appears to be creating a lock; so I created a LockableClient that extends the Discord Client.
Never include an authorization token in the code
auth.json
{
"token" : "your-token-here"
}
lockable-client.js
const { Client } = require('discord.js')
/**
* A lockable client that can interact with the Discord API.
* #extends {Client}
*/
class LockableClient extends Client {
constructor(options) {
super(options)
this.locked = false
}
lock() {
this.setLocked(true)
}
unlock() {
this.setLocked(false)
}
setLocked(locked) {
return this.locked = locked
}
isLocked {
return this.locked
}
}
module.exports = LockableClient;
index.js
const auth = require('./auth.json')
const { LockableClient } = require('./lockable-client.js')
const bot = new LockableClient()
bot.on('message', message => {
if (!bot.isLocked() && message.content === 'Gotcha Bitch') {
bot.lock()
var voiceChannel = message.member.voiceChannel
voiceChannel.join().then(connection => {
const dispatcher = connection.playFile('./assets/audio/gab.mp3')
dispatcher.on('end', end => voiceChannel.leave());
}).catch(err => console.log(err))
bot.unlock()
}
})
bot.login(auth.token)
This is an semi old thread but I'm going to add code here that will hopefully help someone out and save them time. It took me way too long to figure this out but dispatcher.on('end') didn't work for me. I think in later versions of discord.js they changed it from end to finish
var voiceChannel = msg.member.voice.channel;
voiceChannel.join()
.then(connection => {
const dispatcher = connection.play(fileName);
dispatcher.on("finish", end => {
voiceChannel.leave();
deleteFile(fileName);
});
})
.catch(console.error);
Note that fileName is a string path for example: fileName = "/example.mp3". Hopefully that helps someone out there :)
Update: If you want to detect if the Audio has stopped, you must subscribe to the speaking event.
voiceChannel
.join()
.then((connection) => {
const dispatcher = connection.play("./audio_files/file.mp3");
dispatcher.on("speaking", (speaking) => {
if (!speaking) {
voiceChannel.leave();
}
});
})