javascriptnode.jsdiscorddiscord.jssharding

Sharded Discord.js bot resets to initial presence status


I wrote a Discord.js bot in NodeJS that uses discord-hybrid-sharding to spawn my bot.js.
In the bot.js code below, you can see that I have an initial status of "Starting..." and then in ClientReady I set the actual status.

However, seemingly at random, my bot just goes back to the initial "Starting..." status. It operates completely normally though. I assumed it could be that a shard died or something, but why would that kill my interval? The check I tried to do in the Interval sadly doesn't work.

status reset

When I restart my pm2 process for the bot, the status gets correctly set for a while again, but then randomly goes back to "Starting...".


Sharding Manager (app.js) that starts bot.js:

import { ClusterManager } from "discord-hybrid-sharding";
import { config } from "../config/config.js";

const manager = new ClusterManager("./src/bot.js", {
    totalShards: "auto",
    shardsPerClusters: 2,
    token: config.discord.bot_token,
});

manager.on("clusterCreate", shard => console.log(`Launched shard ${shard.id}`));

manager.spawn({ timeout: -1 });

bot.js that sets the status:

import { ClusterClient, getInfo } from "discord-hybrid-sharding";
import DiscordClient from "discord.js";

const client = new DiscordClient({
    presence: {
        status: "dnd",
        activities: [{ name: "Starting...", type: ActivityType.Playing }],
    },
    shards: getInfo().SHARD_LIST,
    shardCount: getInfo().TOTAL_SHARDS,
});

client.cluster = new ClusterClient(client);

client.on(Events.ClientReady, async() => {
    const guildCount = await client.guilds.fetch().then(guilds => guilds.size);

    client.user?.setActivity({ name: `Counting on ${guildCount} servers!`, type: ActivityType.Playing });

    let lastGuildCount = guildCount;
    setInterval(async() => {
        const newGuildCount = await client.guilds.fetch().then(guilds => guilds.size);
        const statusHasReset = client.user?.presence.activities[0].name === "Starting...";

        if (newGuildCount !== lastGuildCount || statusHasReset){
            lastGuildCount = newGuildCount;
            client.user?.setActivity({ name: `Counting on ${newGuildCount} servers!`, type: ActivityType.Playing });
        }
    }, 45 * 60 * 1000);

    client.user?.setStatus("online");
});

(unrelated parts of the code have been omitted. Full code, if required, is at https://github.com/NullDev/Arithmetica-Bot)

Why is this happening and how can I fix it?


Solution

  • Someone on the Discord.js Discord helped me:

    Moving my setInterval logic to the shardReady event did the trick.
    This event is called once the bot starts, and also every time a shard restarts.
    Unlike ClientReady which is only called a single time on bot start.

    const setStatus = async function(client, count){
        client.user?.setActivity({ name: `Counting on ${count} servers!`, type: ActivityType.Playing });
        client.user?.setStatus("online");
    };
    
    client.on(Events.ClientReady, async() => {
        const guildCount = await client.guilds.fetch().then(guilds => guilds.size);
        await setStatus(client, guildCount);
    });
    
    client.on(Events.ShardReady, async shard => {
        const guildCount = await client.guilds.fetch().then(guilds => guilds.size);
        await setStatus(client, guildCount);
    
        let lastGuildCount = guildCount;
        setInterval(async() => {
            const newGuildCount = await client.guilds.fetch().then(guilds => guilds.size);
    
            if (newGuildCount !== lastGuildCount){
                lastGuildCount = newGuildCount;
                await setStatus(client, newGuildCount);
                Log.info("Guild count changed to " + newGuildCount + ". Updated activity.");
            }
        }, 10 * 60 * 1000);
    });