I am making a discord bot and I'm trying to make a command that sends a message with all the members that are currently online.
You cannot reliably check whether a user is online or not. However you could use their presence.status and count all people that don't have a status of "offline". But as I said even online users are still able to set their status to "offline".
With cache:
const onlineMembers = message.guild.members.cache.filter(
member => !member.user.bot && member.user.presence.status !== "offline"
).size;
With fetch:
const onlineMembers = (await message.guild.members.fetch()).filter(
member => !member.user.bot && member.user.presence.status !== "offline"
).size;
According to the offical Discord.js docs these are all options a PresenceStatus can be set to:
The status of this presence:
online - user is online
idle - user is AFK
offline - user is offline or invisible
dnd - user is in Do Not Disturb
Also you may encounter some issues due to Discord Privileged Intent.
You might need to explicitly allow them like so:
const client = new Client({
ws: { intents: ["GUILD_PRESENCES", "GUILD_MEMBERS"] },
});
Edit
I really dislike that kind of spoonfeeding but there you go:
const Discord = require("discord.js");
const client = new Discord.Client();
client.on("message", async (message) => {
if (message.author.bot) return;
if (message.content === "!online") {
const onlineMembers = (await message.guild.members.fetch()).filter(
(member) => !member.user.bot && member.user.presence.status !== "offline"
).size;
return message.channel.send(`Online users: ${onlineMembers}`);
}
});
client.login("your-token");
Related
I want to change the name of a discord bot and I have read numerous tutorials and Stack Overflow posts and I still cannot get it. The code is primarily taken from open source bot code, so I know it works (something with my bot setup maybe?)
As I understand it, this code loops through each guild the bot is a member of and sets the nickname.
I found the botId by right clicking the bot in the channel and copying ID.
const { guildId } = require('../config');
module.exports = (client, botId, nickname) => {
client.guilds.cache.forEach((guild) => {
const { id } = guild;
client.guilds.cache
.get(id)
.members.cache.get(botId)
.setNickname(nickname);
});
};
The bot shows up in the channel (after using oauth2 url), so I'm assuming that means they are a member of the guild.
However, when running this code the bot is not found. I've tried several things from other posts like guild.array() to try and see a full list of the members in the guild, but nothing has worked.
const guild = client.guilds.cache.get('943284788004012072');
const bot = guild.members.cache.get('956373150864642159')
if (!bot) return console.log('bot not found');
Here is the full bot
require('dotenv').config();
const { Client, Intents } = require('discord.js');
const eventBus = require('../utils/events/eventBus');
const setNickname = require('../utils/setNickname');
const getPrice = require('../modules/statsGetters/getPriceDEX');
const { bots } = require('../config');
const client = new Client({
intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MESSAGES],
});
client.once('ready', async () => {
console.log('DEX Price Watch Bot Ready');
client.user.setPresence({
activities: [{ name: 'DEX Price', type: 'WATCHING' }],
status: 'online',
});
const price = await getPrice();
setNickname(client, bots.priceDEX, price);
eventBus.on(drip.update, async () => {
const price = await getPrice();
setNickname(client, bots.priceDEX, price); //update price in config file
});
});
client.login(process.env.DISCORD_PRICE_DEX);
This is the sample of changing bot's nickname for every guild that bot joined
client.guilds.cache.forEach((guild) => { //This is to get all guild that the bot joined
const nickname = args.slice(0).join(" ") //You wanted to change nickname
guild.me.setNickname(nickname); //setting the nickname of your bot
});
I believe you're doing it wrong.
Docs: https://discord.js.org/#/docs/discord.js/stable/class/GuildMember?scrollTo=setNickname
I would suggest using this module code:
const { guildId } = require('../config');
module.exports = (client, nickname) => {
client.guilds.cache
.get(guildId).me.setNickname(nickname);
};
And use it in this way in your main bot code: setNickname(client, price)
Edit:
Oh wait, I just realised you didn't use the correct intents (guild members), so you definitely need to use guild.me (as written above by me) or use guild.members.fetch() as it fetches members which aren't cached.
More info: https://discord.js.org/#/docs/discord.js/stable/class/GuildMemberManager?scrollTo=fetch
On the event guildmemberupdate, I am trying to see if the event is in my server and if the role is a certain role. If all things are true, it will send a message. It does not send a message though
Here is the code
this.on('guildMemberUpdate', function (guild, oldMember, newMember) {
if(guild.id !== '#') {
return
} else {
const wc = new Discord.WebhookClient("#', 'lG-###-7RIXy3LIup80X");
if (oldMember.roles.cache.size !== newMember.roles.cache.size) {
if (!oldMember.roles.cache.has("851156630748921927") && newMember.roles.cache.has("851156630748921927")) {
wc.send(`yo !`);
}
}
}
})
It doesn't send 'test'
The guildMemberUpdate event requires the server members intent. You can enable it in the Discord Developer Portal, and within your client instantiation
const { Intents } = require("discord.js")
const client = new Client({intents: [Intents.FLAGS.GUILDS, Intents.FLAGS.GUILD_MEMBERS]})
//other intents may be added. Make sure it has server members intent (Intents.FLAGS.GUILD_MEMBERS)
I have two servers with my bot on it with two groups of friends. On one server, the bot and I both have admin perms, and I can mute someone who doesn't have those perms. On the other server, I'm the owner and the bot has admin, but I can't mute anyone. I get the error 'Missing Permissions'.
Here's the code:
const Discord = require('discord.js')
const ms = require('ms')
module.exports = {
name: 'mute',
execute(message, args) {
if(!args.length) return message.channel.send("Please Specify a time and who to mute. For example, '!mute #antobot10 1d' And then send the command. Once the command is sent, type the reason like a normal message when I ask for it!")
const client = message.client
if (!message.member.hasPermission('MANAGE_ROLES')) return message.channel.send("You don't have permission to use that command!")
else {
const target = message.mentions.members.first();
const filter = (m) => m.author.id === message.author.id
const collector = new Discord.MessageCollector(message.channel, filter, { time: 600000, max: 1 })
const timeGiven = args[1]
message.channel.send('The reason?')
collector.on('collect', m => {
collector.on('end', d => {
const reason = m
message.channel.send(`${target} has been muted`)
target.send(`You have been muted on ${message.guild.name} for the following reason: ***${reason}*** for ${timeGiven}`)
if(message.author.client) return;
})
})
let mutedRole = message.guild.roles.cache.find(role => role.name === "MUTE");
target.roles.add(mutedRole)
setTimeout(() => {
target.roles.remove(mutedRole); // remove the role
target.send('You have been unmuted.')
}, (ms(timeGiven))
)
}
}
}
Ok, I'm not exactly sure what I did, but it's working now. I think I just changed it so that the MUTE role had 0 permissions instead of normal permissions but making it so that if you have the role you can't talk in that certain channel.
Thanks for the answers!
If your bot's role is below the role of the user you are attempting to mute, there will be a missing permissions error. In your server settings, drag and drop the bot role as high in the hierarchy it will go. This will solve your problem.
I would like to know how to integrate reaction roles in my discord.js bot. I have tried the traditional methods of messageReactionAdd but it seem's very hard to make it extendable and editable, and it just became unusuable after having my bot in many guilds...
I have been trying to search for node modules that make this possible, but the only thing i found was this, and when trying to integrate it in my bot, it just made my commands and stuff no longer work, i have tried to read how to make reaction roles using that package, but at no avail, nothing worked...
I did try this:
const ReactionRole = require("reaction-role");
const system = new ReactionRole("my-token");
let option1 = system.createOption("x:697809640147105878", "697809380137107478");
let option2 = system.createOption("emoji-1:720843460158698152", "708355720436777033");
let option3 = system.createOption("pepe:720623437466435626", "703908514887761930");
system.createMessage("725572782157898450", "702115562158948432", 2, null, option1, option2, option3);
system.init();
But as i said, it made all my commands unusable...
Hope someone can help me!
You can easily implement this using the discord.js-collector package, it supports MongoDB, which is a database, so you'll no longer have to edit your bot manually!
Here's how to do it:
const { ReactionRoleManager } = require('discord.js-collector'); //We import the discord.js-collector package that'll make reaction roles possible
const { Client } = require('discord.js'); // We import the client constructor to initialize a new client
const client = new Client(); //We create a new client
const reactionRoleManager = new ReactionRoleManager(client, {
//We create a reaction role manager that'll handle everything related to reaction roles
storage: true, // Enable reaction role store in a Json file
path: __dirname + '/roles.json', // Where will save the roles if store is enabled
mongoDbLink: 'url mongoose link', // See here to see how setup mongoose: https://github.com/IDjinn/Discord.js-Collector/tree/dev/examples/reaction-role-manager/Note.md & https://medium.com/#LondonAppBrewery/how-to-download-install-mongodb-on-windows-4ee4b3493514
});
client.on('ready', () => {
console.log('ready');
});
client.on('message', async (message) => {
const client = message.client;
const args = message.content.split(' ').slice(1);
// Example
// >createReactionRole #role :emoji: MessageId
if (message.content.startsWith('>createReactionRole')) {
const role = message.mentions.roles.first();
if (!role)
return message
.reply('You need mention a role')
.then((m) => m.delete({ timeout: 1_000 }));
const emoji = args[1];
if (!emoji)
return message
.reply('You need use a valid emoji.')
.then((m) => m.delete({ timeout: 1_000 }));
const msg = await message.channel.messages.fetch(args[2] || message.id);
if (!role)
return message
.reply('Message not found!')
.then((m) => m.delete({ timeout: 1_000 }));
reactionRoleManager.addRole({
message: msg,
role,
emoji,
});
message.reply('Done').then((m) => m.delete({ timeout: 500 }));
}
});
client.login('Token');
And here's a live preview:
You can also use this package to do some other really cool stuff! Like embed paginator, questions, Yes/No Questions...
You can find them all here!
I made a member status command for my discord bot. Here is my code:
const { stripIndent } = require('common-tags');
client.on("message", (message) => {
if (message.content.toLocaleLowerCase().startsWith("+members")) {
const members = message.guild.members.cache.array();
const online = members.filter((m) => m.presence.status === 'online').length;
const offline = members.filter((m) => m.presence.status === 'offline').length;
const dnd = members.filter((m) => m.presence.status === 'dnd').length;
const afk = members.filter((m) => m.presence.status === 'idle').length;
const streaming = members.filter((m) => m.presence.status === 'streaming').length;
const embed = new MessageEmbed()
.setTitle(`Member Status [${message.guild.members.cache.size}]`)
.setThumbnail(message.guild.iconURL({ dynamic: true }))
.setDescription(stripIndent`
**Online:** \`${online}\` members
**Busy:** \`${dnd}\` members
**AFK:** \`${afk}\` members
**Offline:** \`${offline}\` members
**Streaming:** \`${streaming}\` members
`)
.setFooter(message.member.displayName, message.author.displayAvatarURL({ dynamic: true }))
.setTimestamp()
.setColor(message.guild.me.displayHexColor);
message.channel.send(embed);
}
});
I want the number the number of people who are streaming to be shown too. However even when there are users who are streaming my bot shows 0 at the Streaming People count. Anyway to fix this out?
Thanks in Advance
PresenceStatus via member.presence.status can only be online, idle, offline or dnd.
To check if a user is streaming, you need to use the activities of a Presence.
member.presence.activities returns an Array<Activity>. You can use the ActivityType to check if a member is streaming.
To put it all together:
member.presence.activities.forEach(activity => {
if (activity.type == "STREAMING") {
// member is currently streaming
}
});