mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-16 03:18:17 +00:00
102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
import {
|
|
eventHandlers,
|
|
lastShardId,
|
|
setApplicationId,
|
|
setBotId,
|
|
} from "../../bot.ts";
|
|
import { cache, cacheHandlers } from "../../cache.ts";
|
|
import { initialMemberLoadQueue } from "../../structures/guild.ts";
|
|
import { structures } from "../../structures/mod.ts";
|
|
import { delay } from "../../util/utils.ts";
|
|
import { allowNextShard, basicShards } from "../../ws/mod.ts";
|
|
|
|
export async function handleReady(
|
|
data: DiscordGatewayPayload,
|
|
shardId: number,
|
|
) {
|
|
// The bot has already started, the last shard is resumed, however.
|
|
if (cache.isReady) return;
|
|
|
|
const payload = data.d as DiscordReady;
|
|
setBotId(payload.user.id);
|
|
setApplicationId(payload.application.id);
|
|
|
|
// Triggered on each shard
|
|
eventHandlers.shardReady?.(shardId);
|
|
// Save when the READY event was received to prevent infinite load loops
|
|
const now = Date.now();
|
|
|
|
const shard = basicShards.get(shardId);
|
|
if (!shard) return;
|
|
|
|
// Set ready to false just to go sure
|
|
shard.ready = false;
|
|
// All guilds are unavailable at first
|
|
shard.unavailableGuildIds = new Set(payload.guilds.map((g) => g.id));
|
|
|
|
// Start ready check in 2 seconds
|
|
setTimeout(() => checkReady(payload, shardId, now), 2000);
|
|
|
|
// Wait 5 seconds to spawn next shard
|
|
await delay(5000);
|
|
allowNextShard();
|
|
}
|
|
|
|
// Don't pass the shard itself because unavailableGuilds won't be updated by the GUILD_CREATE event
|
|
/** This function checks if the shard is fully loaded */
|
|
function checkReady(payload: DiscordReady, shardId: number, now: number) {
|
|
const shard = basicShards.get(shardId);
|
|
if (!shard) return;
|
|
|
|
// Check if all guilds were loaded
|
|
if (shard.unavailableGuildIds.size) {
|
|
if (Date.now() - now > 10000) {
|
|
eventHandlers.shardFailedToLoad?.(shardId, shard.unavailableGuildIds);
|
|
// Force execute the loaded function to prevent infinite loop
|
|
loaded(shardId);
|
|
} else {
|
|
// Not all guilds were loaded but 10 seconds haven't passed so check again
|
|
setTimeout(() => checkReady(payload, shardId, now), 2000);
|
|
}
|
|
} else {
|
|
// All guilds were loaded
|
|
loaded(shardId);
|
|
}
|
|
}
|
|
|
|
async function loaded(shardId: number) {
|
|
const shard = basicShards.get(shardId);
|
|
if (!shard) return;
|
|
|
|
shard.ready = true;
|
|
|
|
// If it is the last shard we can go full ready
|
|
if (shardId === lastShardId - 1) {
|
|
// Still some shards are loading so wait another 2 seconds for them
|
|
if (basicShards.some((shard) => !shard.ready)) {
|
|
setTimeout(() => loaded(shardId), 2000);
|
|
} else {
|
|
cache.isReady = true;
|
|
eventHandlers.ready?.();
|
|
|
|
// All the members that came in on guild creates should now be processed 1 by 1
|
|
for (const [guildId, members] of initialMemberLoadQueue.entries()) {
|
|
await Promise.allSettled(
|
|
members.map(async (member) => {
|
|
const memberStruct = await structures.createMemberStruct(
|
|
member,
|
|
guildId,
|
|
);
|
|
|
|
return cacheHandlers.set(
|
|
"members",
|
|
memberStruct.id,
|
|
memberStruct,
|
|
);
|
|
}),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|