Discord.js online member count does not update instantly - discord

I use following code to get online member count every 1 sec,
guild.members.cache.filter(member => member.presence.status === 'online' && !member.user.bot).size;
It is not updated the channel name with member count instantly when I m hosting my bot on Heroku, but I run my bot on a local pc it will update the channel name instantly. What am I doing wrong?

Since you're using guild.members.cache, information about user presence won't be up-to-date (cache only updates sometimes so it doesn't have to bother the API server that much).
Here you can use the presenceUpdate event:
// you could run this once to get the initial number of online users
var onlineCount = guild.members.cache.filter(member => member.presence.status === 'online' && !member.user.bot).size;
// and only change the counter if there's a change
client.on("presenceUpdate", (old, new) => {
if(!new.user.bot && old.status != new.status){
if(new.status === "online"){onlineCount++;}
if(old.status === "online"){onlineCount--;}
}
});
Note: You'll probably need to enable 'Presence intent' in 'Privileged Gateway Intents' in your bot's settings page for this to work.
(https://discord.com/developers/applications)

Related

Give Role when a member joins the voice channel. discord.js

Im trying to make discord.js code. When a member joins the voice channnel I want the bot to give them a role, when the member leaves, i want the role to be removed. thanks for your help.
const newChannelID = newState.channelID;
const oldChannelID = oldState.channelID;
if (oldChannelID === "835280102764838942"){
member.send('role given');
let role = message.guild.roles.cache.find(r => r.id === "835279162293747774");
member.roles.add(835279162293747774);
} else if(newChannelID === "835280102764838942"){
member.send('role removed');
member.roles.remove(835279162293747774);
}
})
There's a couple of things you need to clean up in your code. I'm going to assume you're using the voiceStateUpdate event to trigger your command.
Most importantly, (logic-wise) you actually need to flip-flop the way you add and remove roles. Currently, the general code states that if the user left the voice channel (thus oldChannelID = actual vc ID), then it would actually give the user a role. This seems to be the opposite of your intention, thus you'd simply swap out the code in each if/else if statement.
Second, the way you're assigning roles and adding them is incorrect. I'd recommend this resource for more info.
Third, you cannot access message if you were indeed using voiceStateUpdate as your event, since it only emits an oldState and a newState.
Lastly, you need to designate a text channel to send the message to. In my code, I manually grabbed the ID of the channel I wanted and plugged it into the code. You'll have to do the same by replacing the number strings I have with your own specific ones.
With that being said, here's the correct modified code:
client.on('voiceStateUpdate', (oldState, newState) => {
const txtChannel = client.channels.cache.get('803359668054786118'); //manually input your own channel
const newChannelID = newState.channelID;
const oldChannelID = oldState.channelID;
if (oldChannelID === "800743802074824747") { //manually put the voice channel ID
txtChannel.send('role removed');
let role = newState.guild.roles.cache.get("827306356842954762"); //added this
newState.member.roles.remove(role).catch(console.error);
} else if (newChannelID === "800743802074824747") {
txtChannel.send('role given');
let role = oldState.guild.roles.cache.get("827306356842954762"); //change this somewhat
oldState.member.roles.add(role).catch(console.error); //adding a catch method is always good practice
}
})

Discord.js - Set doesn't affect the bot

I'm currently in the middle of writing a Quiz Bot and added a little set to make sure the quiz taker doesn't restart mid-quiz.
So I have basically added the set, and upon messaging the bot 'start', it will add the user to the set and won't remove him until 10 minutes later, which is the time span that you have to complete the quiz by.
While running the bot itself, the set doesn't really seem to affect the bot at all, and if you do happen to message him "start" mid-quiz he will restart it without any issues - I have also tested this by attempting at typing 'hello' in the console if the user attempts to do so, but nothing happens yet again.
Any kind of help would be appreciated!
client.on('message', async message => {
const midQuiz = new Set()
const filter = m => m.author.id === message.author.id
let mistakes = 0;
if (message.content === 'start') {
if (message.channel.type == "dm") {
if (midQuiz.has(message.author.id)) {
console.log('hello')
return message.author.send('You're currently mid-quiz! You may not restart it now.')
} else {
midQuiz.add(message.author.id)
setTimeout(() => {
midQuiz.delete(message.author.id)
message.author.send('10 minutes have gone by and you have not completed the quiz, therefore you have failed.')
}, 600000)
const Embed = new Discord.MessageEmbed()
.setTitle("Verification Quiz")
.setDescription("Question #1: What is the owner's name?")
.setColor(3426654)
.setFooter("You may type 'cancel' at any time to stop the quiz.")
message.author.send(Embed)
You're declaring midQuiz inside the message event, making it so that the set gets redeclared and reset every single message.
// outside of the event
const midQuiz = new Set();
client.on('message', ...);

Why doesn't Collection#find work for offline members who have no roles? (discord.js)

My Goal
My goal is to figure out why Collection#find returns undefined when I try to find a user in my server, but they're offline and have no roles.
Expectation
Usually the console logs an array of all the properties of the user
Actual Result
The console logs Collection#find, as undefined if the user in my server is offline and has no roles
What I've Tried
I've tried using Collection#get, but it turns out that it returns the same response. I've tried searching this up on Google, but no one has asked this question before.
Reproduction Steps
const Discord = require('discord.js');
const client = new Discord.Client();
const {prefix, token} = require('./config.json');
client.once('ready', () => {
console.log('Client is online');
const user = client.users.cache.find(user => user.tag === 'Someone#1234');
console.log(user);
};
client.login(token);
Make sure that whoever is helping you, whether it's an alt account or your friend, that they have no roles, and they're completely offline in your server
Output:
Client is online undefined
I had the same problem. I don't know why this happens, but I used this line to fix that:
((await m.guild.members.fetch()).filter(mb => mb.id === "The ID")).first()`
Basically, this collect all the members, then filters them with the property you want, and the first() at the end is to make it a single object instead of a collection.
Instead of the user.tag property, try using the user.username and the user.discriminator properties. This worked for me
const user = client.users.cache.find(user => user.username === 'Someone' && user.discriminator === '1234');
Also check spelling, capitalization, ect.
A simple solution to my problem is just create an async function and use await guild.members.fetch() to cache the users and then use Collection#find to get the user.

I'm having trouble with moving a user that is already in a voice channel to another voice channel

else if (command === 'move'){
const member = client.users.cache.find(user => user.username == "0.o");
const chan = client.channels.cache.get('761321016760336444');
member.setVoiceChannel(chan);
Error
TypeError: member.setVoiceChannel is not a function
i've seen setVoiceChannel used before, not sure why it's not working for me
If you're using discord.js v12 you should do this instead
member.voice.setChannel(chan);
you can read more about the voice state here

How to check if a user is writing a message in a shared channel and tell him or her to write in a bot-specific channel

How to check if a user is writing a message in a shared channel and tell him to write in a bot-specific channel?
This is the code I tried:
if (message.channel.id === "bot-playground"){
// write code here
}else {
message.channel.send("Write commands in #bot-playground.").then(msg => {
timeout(3000, msg);
});
}
if (message.channel.id === "bot-playground"){
This needs a channel ID, not a name. To get the ID of the channel, right-click it and select copy ID then use this. if you don't have the copy ID button you may need to Enable developer mode
Also, your mention may not work
message.channel.send("Write commands in #bot-playground.")
See
this question for more
Your issue is caused by the first line if (message.channel.id === "bot-playground") you are trying to use the channel name as an ID.
You either need to look it up using the ID of the channel, which you can get by enabling Developer Mode
Or, you could just use the channel name to find it like so:
message.guilds.channels.cache.find(channel => channel.name === 'bots-playground')
Replace client with whatever variable or constant used to assign the Discord#Client object.
client.on("typingStart", (channel, user) => {
const bot_channel = channel.guild.channels.cache.find(chan => chan.name == "bot-playground");
if (channel.id != bot_channel.id) {
return message.channel.send(`Write commands in <#${bot_channel.id}>`);
}
});

Resources