0

I want to create a member count that excludes all bots. I've talked to a friend that told me the code looks to be correct. But it only gives me a count of 0. Perhaps you have better eyes than him!

module.exports = async(client) => {
    const guild = client.guilds.cache.get('912706237806829598');
    
    setInterval(() => {
        const memberCount = guild.members.cache.filter(member => !member.user.bot).size;
        const channel = guild.channels.cache.get('959556115383861298');
        channel.setName(`╭・Members: ${memberCount.toLocaleString()}`);
        console.log('Updating Member Count');
        console.log(memberCount);
    }, 5000);
}

Thanks.

Tried my code and expect a value representing the amount of humans on my server, but only got 0.

flx
  • 173
  • 9

2 Answers2

1

There are two potential problems with your code. First, you're not fetching the member collection and are instead interacting with the cache; if I remember correctly the cache usually only shows you online members and not offline ones. Second, the dreaded issue of rate limits.

The first issue is an easy fix. You just need to fetch the members instead of using the cache before all of your setInterval code:

setInterval(async () => {
    const memberCount = (await guild.members.fetch()).filter(member => !member.user.bot).size;
    const channel = guild.channels.cache.get('959556115383861298');
    channel.setName(`╭・Members: ${memberCount.toLocaleString()}`);
    console.log('Updating Member Count');
    console.log(memberCount);
}, 5000);

That was probably causing the issue you were having. However, there's an additional problem here, one you will run into if you use this code. Rate limits. The normal rate limit for most actions in the Discord API is, if I remember correctly, 10,000 requests per 10 mins. However, the rate limit for changing the name of a channel is just 2 requests per 10 mins (last I checked; I don't know if they've increased this limit since last year). Your code is changing the name of a channel every 5 seconds. In just 10-15 seconds, you'll surpass the rate limit.

I have created channels that keep track of server stats for my bots in the past as well, and ran into this issue when I was doing so. Luckily, I brewed up a way to bypass the rate limit issue back when I was creating my own stats system. Though changing channel names has an incredibly low rate limit, fully creating channels has the normal rate limit of 10,000 requests per 10 mins. Therefore, instead of changing the channel name directly, you could instead: a) clone the channel; b) change the clone's name while creating it; c) set the clone's position in the channel list to the same position as the actual channel; d) delete the original channel. The cloned channel will keep all of the perms, settings, etc of the original. This all assumes, of course, that the original channel isn't a text channel with important messages or such inside, as those messages would all disappear with this method. I used voice channels for my system.

Here's how this bypass could look:

setInterval(async () => {
    const memberCount = (await guild.members.fetch()).filter(member => !member.user.bot).size;
    const channel = guild.channels.cache.get('959556115383861298');
    const pos = channel.position;

    const clone = await channel.clone({
        name: `╭・Members: ${memberCount.toLocaleString()}`
    });
    await clone.setPosition(pos);
    console.log('Updating Member Count');
    console.log(memberCount);

    await channel.delete();
}, 5000);

With this approach, rate limits are no longer an issue. Note that this can still be further improved, however. For example, inside the interval you could check if the member count has changed from the previous count, and only modify the channel name if and only if the count has changed. The entire approach potentially could be changed as well; perhaps you could use guildMemberAdd and guildMemberRemove events to track when the member count increases or decreases, and only modify the name when one of those happens (and only if the member being added/removed is not a bot). But whether to add either of those optional potential improvements is up to you.

Note: Please try this code out on a test channel before using it on the actual channel you are using, just to be safe.

Cannicide
  • 4,360
  • 3
  • 22
  • 42
  • First off, the 5000ms is just for trying it out. I want to replace ServerStats with my own bot. I'm really happy for your thorough answer - much appreciated! Although I got an error saying *Error [GUILD_MEMBERS_TIMEOUT]: Members didn't arrive in time.* I will see if I can get more time to elaborate later. Tied up at the moment. – flx Apr 02 '22 at 15:04
  • I'm guessing that error is caused by trying to fetch all of the members every 5000ms. If your production code is going to have a larger interval, that error may not be a problem. You may want to try out the code outside of the interval to see if that works on its own, and then adjust the interval timing as needed. – Cannicide Apr 02 '22 at 20:54
  • Tried an interval of 10 minutes, still got the same error. Running the code outside of the interval block gives me the same error – flx Apr 03 '22 at 10:11
  • Oh, I think I know what the issue is. It is somewhat unrelated, see [this answer](https://stackoverflow.com/questions/65042476/guild-members-timeout-members-didnt-arrive-in-time). You're probably missing the Intent required to fetch guild members. That answer should fix that specific error, I believe. Lmk if it works after that fix. – Cannicide Apr 03 '22 at 20:19
  • Thank you! It’s working now and the fetch was vital to get the correct values. I added you on Discord - you can accept it if you’d like to hear my pitch for the server I’m creating. My biggest wish is to have someone who is like-minded to bounce ideas with. Lmk if it might be of any interest at all. – flx Apr 04 '22 at 11:24
  • I'd be down for that. Though you'll have to resend that friend req; I accidentally denied it out of habit. – Cannicide Apr 05 '22 at 03:49
  • Awesome! Sent it! – flx Apr 05 '22 at 07:25
0

If you wanted to get to all members including the bot you can use memberCount

const totalCount = guild.memberCount

If you wanted to get only the members size

const memberCount = guild.members.cache.filter(member => !member.user.bot).size;

And if you only wanted to get the bot size

const botCount = guild.members.cache.filter(member => member.user.bot).size;

Full code:

 const guild = client.guilds.cache.get('912706237806829598')

    const memberCount = guild.members.cache.filter(member => !member.user.bot).size;
    const botCount = guild.members.cache.filter(member => member.user.bot).size;
    const totalCount = guild.memberCount

    console.log(memberCount, botCount, totalCount)

Just like this

新Acesyyy
  • 1,152
  • 1
  • 3
  • 22
  • 1
    This is a nice answer, but unfortunately does not solve the problem in the question. Your solution `const memberCount = guild.members.cache.filter(member => !member.user.bot).size;` is character-for-character *exactly* the same line of code the OP is using in their question. – Cannicide Apr 02 '22 at 05:02
  • As Cannicide said. It's the same code. Gives me 0, 1, 47 in the log - which is weird. Should be 34, 13, 47. – flx Apr 02 '22 at 14:59
  • The total count will be accurate when using this method, but the values for member and bot count depend on the cache. The cache isn't always up-to-date, and also doesn't contain users that are offline/invisible (unless fetched). That is probably why the values are off for you, while they could also simultaneously be accurate for the answerer. – Cannicide Apr 02 '22 at 20:59