I want to run a command on my discord bot and add a secondary role to all members which have the predefined role.
Its gonna be like this. All members have the X role are gonna be assigned to the Y role.
I tried to write to code but I failed so I am writing my code as pseudo-code below any help will be great.
const userID = "1234"; //this is my userid so only I will be able to use this command
let roleID1 = "xxxx";
let roleID2 = "yyyy";
client.on("message", function (message) {
if (message.author.id === userID) {
if (message.content === "!setrole") {
// Code for taking the list of all members with role xxxx.
// Code for assigning all those people to the role yyyy.
message.channel.send("Roles assigned");
}
}
});
Try this:
// iterate a function through all members of the guild
message.guild.members.cache.forEach((member) => {
if (member.roles.cache.has(roleID1) // if member has x role
member.roles.add(roleID2); // give y role
});
You could also use Array.prototype.filter(); although there's no difference in execution, it might be faster (but I really have no idea):
message.guild.members
.filter((member) => member.roles.cache.has(roleID1))
.forEach((member) => member.roles.add(roleID2))
Related
Hey so my i want my bot to temporarily assign a role when the client (user) uses a certain word. I have the code for the words ready but i dont have any clue on how to temprole them the role.
bot.on('message', message=>{
const swearWords = ["xyz"];
if( swearWords.some(word => message.content.toLowerCase().includes(word)) ) {
message.reply("Oh no you said a bad word!!!");
You can use <member>.roles.add() method to add the role and assign a timeout function to remove the role after a specific time using <member>.roles.remove()
bot.on('message', message=>{
const swearWords = ["xyz"];
if( swearWords.some(word => message.content.toLowerCase().includes(word)) ) {
message.reply("Oh no you said a bad word!!!");
const role = message.guild.roles.cache.find(x => x.name == 'rolenamehere'); // finding the role
message.member.roles.add(role); // adding the role
setTimeout(() => message.member.roles.remove(role), 3000); // second param is time in milliseconds
});
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 have a code where if someone joins the bot gives a Privat message and a Role but when a user joins, the bot does not give the message and the Role.
TypeError: memb.guild.roles.find
const AUTOROLEID = "689098211536666624"
client.on('guildMemberAdd', (memb) => {
var role = memb.guild.roles.find(r => r.id == "689098211536666624")
if (role) {
memb.addRole(role).then(() => {
memb.send('', new Discord.MessageEmbed().setColor(0x18FFFF).setDescription(`Willkommen aufm Discord deine aktuelle rolle ist ${role.name}!`))
})
}
})
As Discord.js v12 docs you need to access the property cache after <GuildMember>.guild.roles which is a collection of all roles in the guild so you can try this:
var role = memb.guild.roles.cache.find(r => r.id == "689098211536666624")
From the given code, I assume you are using discord.js v11 which got deprecated. So update to v12. v12 introduced the concept of managers/cache. In v11 you were able to use collection methods like get() and find()on collection structures, but now you need to ask for cache on a manager before trying to use collection methods.
Eg:
var role = memb.guild.roles.cache.find(r => r.id == "689098211536666624") //find requires a function
var var role = memb.guild.roles.cache.get("689098211536666624"); //get requires an ID as string.
and <GuildMember>.addRole() method got deprecated. You need to pass through the managers(GuildMemberRoleManager) and then call then .add() method.
Eg:
var role = memb.guild.roles.cache.find(r => r.id == "689098211536666624")
if(role){
memb.roles.add(role).then(()=>{
//do things.
}
}
I'm trying to remove a role from one person, and give that role to the person who initiated the command.
It works the first time, when person A does it. But when someone else tries call the command for the second time, the code doesn't find person A. Any help would be cool.
//Just some startup stuff
const { error, timeStamp } = require('console'),
client = new Discord.Client(),
client.login('How About No?')
var command, role, person
//Check if it's alive
client.once('ready', () => {
console.log(`${client.user.tag} is online`)
})
//When a message is sent
client.on('message', message => {
command = message.content.toLowerCase()
if(command === 'test' && message.guild.id === 'the server ID'){
role = message.guild.roles.cache.find(r => r.id === 'the role ID') //Find the correct role
person = role.members.first()
/* I can use ".first()" here, because there's never supposed to be more than one person with this role.
The problem is here. On the second run, it outputs "undefined" even though a person has the role. */
//If a person has the role, remove it from them.
if(typeof person !== 'undefined') person.roles.remove(role).catch(error => console.log(error))
//Give the role
person = message.member
person.roles.add(role).catch(error => console.log(error))
}
})
It can happen sometimes because the cache won't update fast enough.
What you can do is fetch the role instead with API request.
message.guild.roles.fetch('the role ID',true,true)
So I wrote the following code that is supposed to mute all the members in a given channel:
client.on('message', message => {
if (message.content == 'sh!') {
let channel = message.member.voice.channel
for (let member of channel.members) {
member[1].setMute(true)
}
}
})
But it does not work and I cannot find out why because I do not really know how the setMute() function works.
EDIT: I am not sure about how I can access every member and mute it
The 'setMute' function is part of the member's voice state object. You're using it directly from the GuildMember object itself. As you may already know, the voice state object is the property 'voice' of the GuildMember object. So here's the solution:
// change this
member[1].setMute(true);
// to this
member[1].voice.setMute(true);
The property Members of a VoiceChannel is a Discord Collection (which extends from Javascript Map), I would iterate using a forEach loop so I could avoid Downlevel Iteration.
This should work:
client.on('message', message => {
if (message.content == 'sh!') {
const members = message.member.voice.channel.members;
members.forEach(member => {
member.voice.setMute(true);
});
}
});
Here's some useful links:
TextChannel#members | discord.js
Collection | discord.js
Map - JavaScript | MDN