Fetching specific guilds across all shards

Hey there, what's the proper way of finding specific guilds across all shards? I tried following the tutorial on the guide but I don't quite get it. This is how I'm doing it, but I always get ReferenceError: notification is not defined - Are we not allowed to access outside-variables within broadcastEval? Am I even doing this right? Do I even need broadcastEval? Appreciate every hint.
// Loop through all guilds
const notifications = await EpisodeChannelModel.find({});
for (const notification of notifications) {
await client.shard?.broadcastEval(async (client) => {
const guild = await client.guilds.fetch(notification.guildId);
console.log(guild.name);
});
}
// Loop through all guilds
const notifications = await EpisodeChannelModel.find({});
for (const notification of notifications) {
await client.shard?.broadcastEval(async (client) => {
const guild = await client.guilds.fetch(notification.guildId);
console.log(guild.name);
});
}
6 Replies
d.js toolkit
d.js toolkit10mo ago
- What's your exact discord.js npm list discord.js and node node -v version? - Not a discord.js issue? Check out #other-js-ts. - Consider reading #how-to-get-help to improve your question! - Explain what exactly your issue is. - Post the full error stack trace, not just the top part! - Show your code! - Issue solved? Press the button!
Enze
EnzeOP10mo ago
[email protected] & node v20.10.0
d.js docs
d.js docs10mo ago
:method: (static) ShardClientUtil.shardIdForGuildId() Get the shard id for a given guild id. :guide: Sharding: Additional information - Specific shards read more
Enze
EnzeOP10mo ago
Before I try this, let me understand your previous ideas. The following one works but I want to be sure that this is done correctly. Is this good?
// Loop through all guilds
function getGuilds(c: Client, { notif }: { notif: any }) {
const guild: Guild | undefined = c.guilds.cache.get(notif.guildId);
if (guild) console.log(guild.name);
}

const notifications = await EpisodeChannelModel.find({});
for (const notification of notifications) {
await client.shard?.broadcastEval(getGuilds, { context: { notif: notification } });
}
// Loop through all guilds
function getGuilds(c: Client, { notif }: { notif: any }) {
const guild: Guild | undefined = c.guilds.cache.get(notif.guildId);
if (guild) console.log(guild.name);
}

const notifications = await EpisodeChannelModel.find({});
for (const notification of notifications) {
await client.shard?.broadcastEval(getGuilds, { context: { notif: notification } });
}
Or like that?
// Loop through all guilds
function getGuilds(c: Client, { notif }: { notif: any }) {
const guild: Guild | undefined = c.guilds.cache.get(notif.guildId);
if (guild) console.log(guild.name);
}

const notifications = await EpisodeChannelModel.find({});
for (const notification of notifications) {
const shardId = ShardClientUtil.shardIdForGuildId(notification.guildId, client.shard?.count ?? 1);
await client.shard?.broadcastEval(getGuilds, { context: { notif: notification }, shard: shardId });
}
// Loop through all guilds
function getGuilds(c: Client, { notif }: { notif: any }) {
const guild: Guild | undefined = c.guilds.cache.get(notif.guildId);
if (guild) console.log(guild.name);
}

const notifications = await EpisodeChannelModel.find({});
for (const notification of notifications) {
const shardId = ShardClientUtil.shardIdForGuildId(notification.guildId, client.shard?.count ?? 1);
await client.shard?.broadcastEval(getGuilds, { context: { notif: notification }, shard: shardId });
}
So basically I have a scheduled task that checks if a new episode was released and once there is a new one, it will notify all guilds (with one specific channel) that subscribed about it. The task runs every 30 seconds So it's not really guaranteed to be on all shards I guess I call the scheduler on client creation. So not really sure? Would that be shard 0? Sorry, my explanation here was really raw. It‘s more complicated than that so I can‘t really use an announcement channel. Is there a way to run the task one shard and one shard only? Can I check if it‘s the first shard and then run the scheduler or would that not work? So basically a guild can setup a specific channel where either all episodes or only relevant episodes will be posted. The users in that guild can subscribe to specific keywords, so whenever an episode is released it will also look for users with matching keywords for the episode title. If it finds users, it‘ll create a role, add all of the users to it, and ping the role additionally. Relevant episodes meaning that the episode has at least one user subscribed to it Maybe not the best way, but that‘s how it should work Thanks a bunch for your help! One more question: Do you happen to know when to exactly use sharding functions? For example if I want to look for a specific user, do I also use the same logic or can I simply use client.users.fetch(...)? I'm not really sure when to use what For channels, roles, messages, users - is it all the same way? Is it because all guilds are always in the cache or is there another reason? Oh makes sense. Thanks for the warning! Hey I got another question: Can the function I pass to broadcastEval be async? Or does that not work? I see, thanks! Just realized I can't use global variables in these functions too, I really have to pass all of it to the context, right? With global variables I mean like a winston logger and stuff I got a ReferenceError: logger_1 is not defined error and I was using a LOGGER variable in the function which is basically an import of this:
export const LOGGER = createLogger({
levels: logLevels,
transports: [
new LogtailTransport(logtail, { level: 'debug' }),
new transports.Console({ format: consoleFormat, level: 'debug' }),
],
});
export const LOGGER = createLogger({
levels: logLevels,
transports: [
new LogtailTransport(logtail, { level: 'debug' }),
new transports.Console({ format: consoleFormat, level: 'debug' }),
],
});
I'm kinda lost here, do you have a guide that explains how I'm supposed to solve this? I put all the logic that works with that specific guild into the broadcastEval and I'm also using logs in there. Maybe I'm not using the broadcastEval correctly.. should I create another function to handle that logic and just make the broadcastEval get the guild I need? This is what I'm doing in the broadcastEval: https://hastebin.de/sanuyihivu.typescript. I get the Guild instance and do everything I need
Erick
Erick10mo ago
Because these type of channels can take up to 1 hour to send the messages to all channels.
Enze
EnzeOP10mo ago
Thanks. I assume I need to do the same for the mongodb models?
Want results from more Discord servers?
Add your server