showing user with multiple roles discord.js - node.js

with this command set to only one role. I want to set more than one role. how can I do it ?
let rolid = "663047983675342849";
let tokuchi = client.guilds
.get(sunucuid)
.roles.get(rolid)
.members.filter(o => !o.voiceChannel).map(member => member.user);
.setDescription(tokuchi.join("\n"))```

You can get all members with multiple role somethink like this, but other code shown leaves questions
let sGuild = client.guilds.get(sunucuid)
let membersWithRoles = sunucuid.members.filter(member => {
return member.roles.some(r=>['ROLEID','ROLEID'].includes(r.id))
})
console.log(membersWithRoles)
v2 version
At the fist you dont need get guild in all comands, use message.guild for this.
This code will return array of users usernames with any of your roles and if they dont have voiceconnection now.
exports.run = async (client, message, args) => {
if(message.channel.type === 'dm') return
if (!message.member.hasPermission("ADMINISTRATOR"))
return message.channel.send(" Missing Permission");
let tokuchi = message.guild.members.filter(member => {
return member.roles.some(r=>['ROLEID','ROLEID'].includes(r.id)) && !member.voiceChannel
}).map(member => (member.user.username))
const basarili = new Discord.RichEmbed()
.setColor('RANDOM')
.setAuthor(`Seste Olmayan Yetkililer`, client.user.avatarURL)
.setDescription(tokuchi.join("\n"))
.setFooter("Created by Tokuchi")
.setTimestamp()
.addField(`İşlemi Gerçekleştiren Kişi:`, `${message.author.username}#${message.author.discriminator}`)
return message.channel.send(basarili)
};
its return a users.username because you cant .join('\n) users, its a collection, not array.

Related

Dropdown failed after restart - discord.js

This is my interaction reaction roles code.FYI i have used the new node.js so it couldnt be error because of the version. The problem is dropdown failed after restarting my bot. The "secret" at my code is the role id so just ignore it.
Here is my code:
client.on("message", async message => {
if (message.content == prefix + "rr") {
let option1 = new MessageMenuOption()
.setLabel("Black Charcoal")
.setValue("Option 1")
.setDefault()
.setEmoji("🌑")
let option2 = new MessageMenuOption()
.setLabel("Love Magenta")
.setValue("Option 2")
.setDefault()
.setEmoji("❤️")
let selection = new MessageMenu()
.setID("Selection")
.setMaxValues(1)
.setMinValues(0)
.setPlaceholder("Select Role")
.addOption(option1)
.addOption(option2)
let embed = new Discord.MessageEmbed()
.setColor("0x00a6ff")
.setTitle("VIP Colour Role")
.setDescription(`<#&secret>\n<#&secret>\n<#&secret>\n<#&secret>\n<#&secret>`)
let menumsg = await message.channel.send(embed, selection)
const role1 = message.guild.roles.cache.find(r => r.id === "secret")
const role2 = message.guild.roles.cache.find(r => r.id === "secret")
async function menuselection(menu) {
switch(menu.values[0]) {
case "Option 1":
if(message.member.roles.cache.has("secret")){
await message.member.roles.add(role1)
await message.member.roles.remove([role2])
await menu.reply.send("Claimed Black Charcoal!", true)}
break;
case "Option 2":
if(message.member.roles.cache.has("secret")){
await message.member.roles.add(role2)
await message.member.roles.remove([role1])
menu.reply.send("Claimed Love Magenta!", true)}
break;
}
}
client.on("clickMenu", (menu) => {
if(menu.message.id == menumsg.id) {
if(menu.clicker.user.id == message.author.id) menuselection(menu)
else menu.reply.send(":x: you are not allowed to pick something", true)
}
})
}
})
You seem to be using the now archived discord-buttons library. Looking through its source code, it looks like it does not store information about which messages have menus anywhere other than the bot's memory. When you restart your bot, that information is lost, and your bot stops watching for menu clicks.
To keep it working after restarts, you would have to store such information somewhere external to your bot, like a file or some database, and start the menus again when the bot starts.

nodejs discord get nickname from a users ID

My goals are to obtain the users nickname by using their ID.
Their ID's are stored as variables which are being collected from a reaction collector.
I have tried a few methods and failed, most of which either return nothing or errors.
The below code returns nothing, the getnames() function is empty. This method was recommended to me buy 2 people from a nodejs discord server which aims to help solve issues, similar to here.
// returns player ID's
function getPlayers() {
let players = [];
players.push(queue.tank[0]); // First (1) in TANK queue
players.push(queue.heal[0]); // First (1) in HEAL queue
players.push(queue.dps[0]); // First (2) in DPS queue
players.push(queue.dps[1]);
return players;
}
// get nick names from ID's
function getnames() {
let players = getPlayers();
let playerNicks = [];
let newPlayer = "";
players.forEach(async player => {
newPlayer = await message.guild.members.fetch(player).then(function (user) {return user.displayName });
playerNicks.push(newPlayer)
return playerNicks;
})}
//formats nicknames into string
function formatnicknames() {
let formatted_string2 = '';
let playerNicks = getnames();
if (playerNicks)
formatted_string2 = `${playerNicks[0]} \n${playerNicks[1]} \n${playerNicks[2]} \n${playerNicks[3]}`;
return formatted_string2;
}
I have also tried a few variations of the below code, still unable to obtain nickname.
message.guild.members.cache.get(user.id)
Edit #1
now tried the following code with no success. (boost1ID contains the ID of 1 user)
var mem1 = message.guild.members.fetch(boost1ID).nickname
Edit #2
tried a new method of obtaining displayname from ID.
var guild = client.guilds.cache.get('guildid');
var mem1 = guild.member(boost1ID);
var mem2 = guild.member(boost2ID);
var mem3 = guild.member(boost3ID);
var mem4 = guild.member(boost4ID);
var nickname1 = mem1 ? mem1.displayName : null;
var nickname2 = mem2 ? mem2.displayName : null;
var nickname3 = mem3 ? mem3.displayName : null;
var nickname4 = mem4 ? mem4.displayName : null;
var Allnicknames = `${nickname1} ${nickname2} ${nickname3} ${nickname4}`
message.channel.send(`testing nicknames: ${Allnicknames}`)
I managed to only return my own name since i dont have a nickname on this server, but the other three users who does have a nickname returned null.
This is the simplest solution:
// your users ids
const IDs = [ '84847448498748974', '48477847847844' ];
const promises = IDs.map((userID) => {
return new Promise(async (resolve) => {
const member = message.guild.member(userID) || await message.guild.members.fetch(userID);
resolve(member.displayName || member.user.username);
});
});
const nicknames = await Promise.all(promises);
// you now have access to ALL the nicknames, even if the members were not cached!
The members you are trying to get the nicknames of are not necessarily cached, and this fixes that.
I made an example that could help you.
let testUsers = [];
module.exports = class extends Command {
constructor(...args) {
super(...args, {
description: 'Testing.',
category: "Information",
});
}
async run(message) {
function getNicknames(userArr, guild) {
let playerNicks = [];
for(var i = 0; i < userArr.length; i++) {
playerNicks.push(guild.member(userArr[i]).displayName);
}
return playerNicks;
}
let testUser = message.guild.members.cache.get(message.author.id);
testUsers.push(testUser);
let guild = message.guild;
console.log(getNicknames(testUsers, guild));
}
}
I created a function getNicknames that takes in two parameters. The first one is an Array of users (as you get one from your function getPlayers()) and the second one is the guild you are playing in. You need to provide the guild, because every user should be a GuildMember, because you want to use .displayName. I created a user Array outside of my command code, because otherwise there will only be one user in the Array everytime you use the command. Inside of the getNicknames() function I have created a new Array playerNicks that I basically fill with the user nicknames we get from our provided user Array.
Now you have to implement that into your code.
The call of the function getNicknames(), for your code should look like this:
getNicknames(getPlayers(), message.guild);

Discord.js AutoRole Reaction do nothing

my little problem is the next one :
When i react a message, my bot do nothing :D and it's not the objectives.
My events :
module.exports = async(client, messageReaction, user) => {
const message = messageReaction.message;
const member = message.guild.members.cache.get(user.id);
const emoji = messageReaction.emoji.name;
const channel = message.guild.channels.cache.find(c => c.id === '739163072064651296');
const lol = message.guild.roles.cache.get("763104201588473896"); //id role lol
const wz = message.guild.roles.cache.get("763104236119785584"); //id role wz
if (["lol", "wz"].includes(emoji) && message.channel.id === channel.id) {// lol = emoji name and wz too
switch (emoji) {
case "lol":
member.roles.add(lol);
message.channel.send('test')
break;
case "wz":
member.roles.add(wz);
message.channel.send('test')
break;
};
};
};
My events handler :
fs.readdir("./Events/",(error , f) => {
if(error) console.log(error);
console.log(`${f.length} events chargés`);
f.forEach((f) => {
const events = require(`./Events/${f}`);
const event = f.split(".")[0];
client.on(event, events.bind(null, client));
});
});
If someone can help it's perfect ! Thank you !
I tried to understand what you wanted to make but couln't understand you at all, your trying to make a autoRole sytem that listen's to reactions? AutoRole is supposed to be in a guildMemberAdd event, so if a member join's, you add a role automatically, but from the code you provided, it looks like it listen's to reactions on some message? If your trying to make a Reaction Role system, then follow this. Other than that, i can't help you.
If your trying to make a autoRole system follow this
From what i know, when you add a role to someone, you will have to do the following
member.roles.add("roleid")
But what your doing is basically this:
member.roles.add(message.guild.roles.cache.get("763104201588473896")) //as lol is defined like that
So, to fix it, instead of getting the role object, then trying to add the role to the user, do this, and be sure to make the file name "guildMemberAdd.js":
module.exports = async(client, member) => {
const lol = "763104201588473896" //id role lol
const wz = "763104236119785584"; //id role wz
member.roles.add(lol);
member.roles.add(wz);
};

How can I resolve this problem (node.js, discord.js)

if (!args[1]) return message.channel.send('You need to specify a person!')
if (!args[2]) return message.channel.send('Please specify a time for how long the ban council will last.')
var tim = args[2]
const sweden = message.mentions.users.first()
message.react('👍').then(() => message.react('👎'))
const mappo = ['👍', '👎']
if (!args[1]) return message.channel.send('Please specify a person!')
if(message.guild){ //this will check if the command is being called from a server
const embad = new Discord.MessageEmbed()
.setTitle('Ban Council')
.addField('The Convicted:', `${sweden.tag}`)
.addField('Rules:', 'Vote on whether the convicted is guilty or not with the prompted reactions. The ban will end automatically in 5 seconds.')
message.channel.send(embad)
setTimeout(function(){
if(sweden){
const lyft = message.guild.member(sweden)
if(lyft){
if(message.reactions.cache.map(r => `${'👍'} ${r.users.cache.size}`)[0] > message.reactions.cache.map(r => `${'👍'} ${r.users.cache.size}`)[1]){
lyft.ban({ ression: 'Majority has exiled you from server. '}).then(() => {
message.reply(`The user ${december.tag} was banned as a result of a majority vote.`)
})
} else {
message.channel.send('The ban was cancelled.')
}
}else{
message.reply('The user is not in this server.')
}
}else{
message.reply('You need to specify a person!')
}
}, tim)
} else {
message.channel.send('Banning does not work here!')
}
It sends the "Ban cancelled" before it actually has the chance to take input. I've tried collectors, and it doesn't work because of the max: part, how can I resolve this problem? (Also it returns no errors)
This is in a case. (appending onto what feedback I got)
Firstly you should beautify your code before you post on stackoverflow, you could have removed the break keyword and just explain it was inside of a switch case
The reason it does not work is because you are checking the message's reaction, and not the embed that you send, so to fix this you need to assign a variable to message.channel.send(embad), but this is a promise so you need to await it, which requires an async function
lastly awaitReactions and createReactionCollector are probably better options,
So here's the new code:
(async () => {
if (!args[1]) return message.channel.send('You need to specify a person!');
if (!args[2]) return message.channel.send('Please specify a time for how long the ban council will last.')
if (!message.guild) return message.channel.send('Banning does not work here');
var tim = args[2]
const sweden = message.mentions.member.first()
const mappo = ['👍', '👎']
message.react('👍').then(() => message.react('👎'))
const embad = new Discord.MessageEmbed()
.setTitle('Ban Council')
.addField('The Convicted:', `${sweden.tag}`)
.addField('Rules:', 'Vote on whether the convicted is guilty or not with the prompted reactions. The ban will end automatically in 5 seconds.')
const embedMessage = await message.channel.send(embad);
setTimeout(function () {
if (!sweden) return message.reply('You need to mention a person');
const filter = (reaction) => mappo.includes(reaction.emoji.name);
embad.awaitReactions(filter, { time: 5000 })
.then(collection => {
//not the most optimal way to do it
const emoji1 = collection.find(e => e.emoji.name === '👍');
const emoji2 = collection.find(e => e.emoji.name === '👎');
//both default to 0
const upvotes = emoji1 && emoji1.users.size || 0;
const downvotes = emoji2 && emoji2.users.size || 0;
if (upvotes > downvotes) {
lyft.ban({ reason: 'Majority has exiled you from server. ' })
.then(() => message.reply(`The user ${december.tag} was banned as a result of a majority vote.`));
} else {
message.channel.send('The ban was cancelled.');
}
})
.catch(console.error);
}, tim);
})();
It's been around 8 months since I made this post, and I found the answer, and an even more effective way to do it. I won't post the entire code, as it's pretty long and not very neat. However, this is a much more effective way of counting reactions.
My Original Code was:
const upvotes = message.reactions.cache.map(r => ${'👍'} ${r.users.cache.size})[0]
const downvotes = message.reactions.cache.map(r => ${'👎'} ${r.users.cache.size})[1]
It doesn't work very well either.
const [upvoteReaction, downvoteReaction] = message.reactions.cache.first(2);
const upvotes = upvoteReaction.users.cache.size;
const downvotes = downvoteReaction.users.cache.size;
It takes the number of reactions from the first two reactions on the message. Seeing as how the only reactions are thumbs up and thumbs down, it will get the numbers from both of them. From there, you can just compare the two.

Discord.JS: How to get first channel of a guild?

I am creating a Discord bot. I want to create invite by guild ID. Creating invite needs a channel. I want to bot to select the first channel. How can I do this?
I used this but did not work:
guild.channels[Object.keys(guild.channels)[0]]
//returns undefined
for v12 try
var chx = guild.channels.cache.filter(chx => chx.type === "text").find(x => x.position === 0);
If you mean first by position, you can look the channels up by type and position using the guild channels collection.
const channel = guild.channels.filter(c => c.type === 'text').find(x => x.position == 0);
I don't know what you're meaning by first channel, but you could use this :
const randomChannel = (guild) => {
guild.channels.random().then(channel => {
if (channel.type === 'text') return channel;
else return randomChannel(guild);
}
}
To get a channel to create an invite you should probably only use ones where the Bot has permissions in, eg:
const invitechannels = guild.channels.filter(c=> c.permissionsFor(guild.me).has('CREATE_INSTANT_INVITE'));
invitechannels.random().createInvite()
.then(invite=> console.log('Create Invite:\n' + invite.code))
Alternatively you could also check for existing invites:
guild.fetchInvites()
.then(invites => console.log('Found Invites:\n' + invites.map(invite => invite.code).join('\n')))
Each channel has a calculatedPosition property, which you can use to get the first channel.
const channel = Array.from(guild.channels).sort((a,b) => a.calculatedPosition - b.calculatedPosition)[0];
Alright let's break down what is happening in the above code:
Array.from(guild.channels) //returns an Array of GuildChannels (Textchannels and Voicechannels)
.sort((a,b) => a.calculatedPosition - b.calculatedPosition) //sorts the elements in the collection by their calculatedPosition property in ascending order and returns the array
[0] //returns the first element of the array
For Discord.js v13 try:
var chx = guild.channels.cache.filter(chx => chx.type === "GUILD_TEXT").find(x => x.position === 0);
Use "GUILD_TEXT" instead of "text".
For multiple types use this:
const _arr = ["GUILD_TEXT", "GUILD_NEWS", "UNKNOWN"];
var chx = guild.channels.cache.filter(chx => _arr.includes(chx.type)).keys());
More about channels' types read here:
https://discord.js.org/#/docs/discord.js/stable/class/GuildChannel?scrollTo=type

Resources