On some Discord servers my code to add/remove roles, however, on some it doesn't. I checked and they all have the correct permissions, so I'm kind of stumped.
Whenever I run the >addrole or >removerole command I always get the same Discord error message. It is ":x: Couldn't find mute role. Make sure you didn't make a typo (roles are case-sensitive too!)". I set this for when a user makes a typo while typing what role they want to add.
The format for the commands are as follows:
addrole [#User] [RoleName]
removerole [#User] [RoleName]
const Discord = require("discord.js");
exports.run = async(bot, message, args) => {
if (!message.member.hasPermission("MANAGE_ROLES")) return message.channel.send(":x: Insufficient permission.").then(msg => msg.delete(4000));
let rolemember = message.guild.member(message.mentions.users.first() || message.guild.members.get(args[0]));
if (!rolemember) return message.channel.send(":x: Could not find user.").then(msg => msg.delete(4000));
let role = args.join(" ").slice(22);
if (!role) return mesage.reply(":x: Specify a role.");
let gRole = message.guild.roles.find(`name`, role);
if (!gRole) return message.channel.send(":x: Couldn't find mute role. Make sure you didn't make a typo (roles are case-sensitive too!)");
if (!rolemember.roles.has(gRole.id)) return message.channel.send(`:x: User does not have role "${gRole.name}".`).then(msg => msg.delete(4000));
await (rolemember.removeRole(gRole.id));
try {
rolemember.send(`:white_check_mark: Your role "${gRole.name}" in`, message.guild.name, "has been removed :confused:.");
} catch (e) {
message.channel.send(`:white_check_mark: ${rolemember} Your role "${gRole.name}" has been removed :confused:.`);
}
let removeroleEmbed = new Discord.RichEmbed()
.setDescription("Role Changes")
.setColor("RANDOM")
.addField("Role Removed", gRole)
.addField("Removed From", rolemember)
.addField("Removed By", message.author);
let logChannel = message.guild.channels.find(`name`, "logs-reports");
if (!logChannel) return message.channel.send(":x: Couldn't find logs channel.").then(msg => msg.delete(4000));
logChannel.send(removeroleEmbed);
}
exports.help = {
name: "removerole"
}
I expect that the role should be added, however, it is not and the same error message is what I get every time.
As .find('name', 'name') is DEPRECATED. That thing you use may not work.. Instead, use let gRole = message.guild.roles.find(r => r.name === role). I am new to this community. So please fogive if I do something wrong.
Try replaceng the let gRole = message.guild.roles.find("name", role); with let gRole = message.guild.roles.find(r => r.name === role) This should work because it is how it is supposed to be, sorry I am not very good at explainin
Note:
Collection.find() is not totally deprecated, just format Collection.find("name", "yourName") is deprecated!
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'm making responses in commands. I made a response when trying to kick myself and works, but now i'm trying to make a response when trying to kick the bot and it doesnt work.
kick command code:
module.exports = {
name: 'kick',
aliases: ["k"],
description: "kick a member",
execute(message, Discord, client) {
if(message.member.permissions.has("KICK_MEMBERS")){
const member = message.mentions.members.first();
let mention = message.mentions.members.first();
if (message.mentions.members.size < 1) return message.reply('You must mention someone to kick them.').catch(console.error);
if (message.mentions.members.first().id === message.author.id) return message.reply("I can't let you do that, self-harm is bad:facepalm:");
if (message.mentions.members.id === client.member.id) return message.reply("You pleblord, how can you use a bot to kick itself?:joy:");
if (message.mentions.members.first().id === "521311050193436682") return message.reply("You can't kick my Developer:wink:");
if (reason.length < 1) reason = 'No reason supplied';
if (!message.guild.member(user).kickable) return message.reply('I cannot kick that member');
const embed = new Discord.MessageEmbed()
.setColor(0x0000FF)
.setTimestamp()
.addField('Action:', 'Kick')
.addField('User:', `${user.username}#${user.discriminator} (${user.id})`)
.addField('Moderator:', `${message.author.username}#${message.author.discriminator}`)
.addField('Reason', reason)
.setFooter(`© Cryptonix X Mod Bot by ${customisation.ownername}`);
if(user.bot) return;
message.mentions.users.first().send({embed}).catch(e =>{
if(e) return;
});
message.guild.member(user).kick();
let logchannel = message.guild.channels.cache.find(x => x.name = 'logs');
if (!logchannel){
message.channel.send({embed});
}else{
client.channels.cache.get(logchannel.id).send({embed});
message.channel.send({embed});
}
if(user.bot) return;
message.mentions.users.first().send({embed}).catch(e =>{
if(e) return ;
});
}
else{
let newEmbed = new MessageEmbed()
.setColor('#e4e265')
.setTitle('')
.setURL('')
.setDescription("Eeeh wait! You can't use that command <a:yepaa:797528125894295567>")
.setImage('')
.setFooter('');
message.channel.send(newEmbed).then(r => r.delete({ timeout: 10000 }));
}
}
};
and this is the error i get when trying to run the command in discord chat
TypeError: Cannot read property 'member' of undefined
at Object.execute (C:\Users\ayman\Desktop\sharky music\commands\kick.js:15:56)
(kick.js:15:16 is the line of the bot response when trying to kick the bot)
if (message.mentions.members.id === client.member.id)
This if condition is wrong because a property member doesn't exist on the client.
You have 2 ways to fix your problem:
Replace client.member.id with client.user.id (The ids are the same)
// The other code from above this if statement
if (message.mentions.members.id === client.user.id) return message.reply("You pleblord, how can you use a bot to kick itself?:joy:");
// The following code
Replace client.member.id with message.guild.me.id me is the Guild#GuildMember object from the client
// The other code from above this if statement
if (message.mentions.members.id === message.guild.me.id) return message.reply("You pleblord, how can you use a bot to kick itself?:joy:");
// The following code
if you look closely you have defined member at
const member = message.mentions.members.first(); and let mention = message.mentions.members.first();
!message.guild.member(user).kickable after you have changed the user value from their code you missed to change the (user).kickable which returned member undefined as the bot cannot find the "user" not the "mention"
member and mention are all defined value in djs. so i would say change it to something like mentioned.
you can try to :
delete const member = message.mentions.members.first();
change to:
const mentioned = message.mentions.members.first();
!message.guild.member(mentioned).kickable
if(mentioned.bot) return;
message.mentions.mentioned.first().send({embed}).catch(e =>{if(e) return;});
and finally kick it by message.guild.member(mentioned).kick();
didnt know it worked or not but hopefully afterall member is going to be defined!
think James might be answered as he have already posted in comments but i just leave what i think here. If im wrong, correct me.
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
the remove role error
my code:
bot.on('message', message => {
let prefix = "t?";
let args = message.content.substring(prefix.length).split(" ");
switch (args[0]) {
case 'mute':
let person = message.mentions.users.first(); message.guild.members.fetch(args[1])
if(!person) return message.reply("couldnt find member");
let mainrole = message.guild.fetch(role => role.name === "member");
let muterole = message.guild.fetch(role => role.name === "muted");
if(!muterole) return message.reply("couldn't find mute role");
let time = (args[2]);
if(!time) {
return message.reply("how long? <:Thonk:582005026470363137>");
}
person.removeRole(mainrole.id);
person.addRole(muterole.id);
channel.send(`#${person.user.tag} has now been muted for ${ms(ms(time))}`);
setTimeout(function(){
person.addRole(mainrole.id);
person.removeRole(muterole.id);
message.channel.send(`#${person.user.tag} has been unmuted.`);
}, ms(time));
break;
}
});
and it pops up and error that says remove Role is not a function
do anyone know how to solve these kinds of problem in discord
You are confusing GuildMember with User.
A user is a person on Discord, a GuildMemebr is a person on discord as pertaining to a specific guild. For example, you can DM a user or a guild member because direct messages don't have anything to do with guilds, but you can't remove a role from a user because a user isn't associated with a guild, there are no roles to remove.
So, you need to get message.mentions.members not message.mentions.users
The documentation for this is here in MessageMentions
The command requires a reason to work, however, it still does not ban even if I mention someone and give a reason. It's like the command isn't recognized!
bot.on('message', async message => {
if (message.content == prefix + "ban") {
if (!message.member.roles.some(r => ["Administrator", "Co-owner"].includes(r.name)))
return message.reply("Sorry, you don't have permissions to use this!");
let member = message.mentions.members.first();
if (!member)
return message.reply("Please mention a valid member of this server");
if (!member.bannable)
return message.reply("I cannot ban this user! Do they have a higher role? Do I have ban permissions?");
var reason = args.slice(1).join(' ');
if (!reason) reason = "No reason provided";
await member.ban(reason);
}
});
Finally got it to work! This was my code at the end:
bot.on('message', message => {
let member = message.mentions.members.first();
if (message.content.startsWith(prefix + "ban")) {
if (!message.member.hasPermission('BAN_MEMBERS'))
return message.reply("Sorry, you don't have permissions to use this!");
if (!member)
return message.reply("Please mention a valid member of this server");
if (!member.bannable)
return message.reply("I cannot ban this user! Do they have a higher role? Do I have ban permissions?");
// V This line has been changed V
var reason = message.content.split(' ').slice(2).join(' ');
if (!reason) return message.reply("Please specify a reason!");
member.ban(reason);
}
});
It was all because of the reason! Thanks to everyone who helped me, this opened doors for a lot more commands for me.
For the kick command, you have to put an argument as a reason. Like this:
var reason = args.slice(1).join(' ');
member.kick(reason);
This is just like the ban command in the second image.
If you need more help or clarification, ask me.
If this doesn't work, make sure your bot has a high enough role in the role hierarchy.