add: guild dispatch

This commit is contained in:
ITOH
2021-05-27 17:17:09 +02:00
parent 6a8b183fbf
commit 7f280bd17b
2 changed files with 117 additions and 1 deletions

View File

@@ -11,7 +11,7 @@ import { Collection } from "./util/collection.ts";
export const cache = {
isReady: false,
/** All of the guild objects the bot has access to, mapped by their Ids */
guilds: new Collection<bigint, DiscordenoGuild>(),
guilds: new Collection<bigint, DiscordenoGuild>([], { sweeper: { filter: guildSweeper, interval: 3600000 } }),
/** All of the channel objects the bot has access to, mapped by their Ids */
channels: new Collection<bigint, DiscordenoChannel>(),
/** All of the message objects the bot has cached since the bot acquired `READY` state, mapped by their Ids */
@@ -32,6 +32,9 @@ export const cache = {
this.guilds.reduce((a, b) => [...a, ...b.emojis.map((e) => [e.id, e])], [] as any[])
);
},
activeGuildIds: new Set<bigint>(),
dispatchedGuildIds: new Set<bigint>(),
dispatchedChannelIds: new Set<bigint>(),
};
function messageSweeper(message: DiscordenoMessage) {
@@ -54,6 +57,26 @@ function memberSweeper(member: DiscordenoMember) {
return true;
}
export function guildSweeper(guild: DiscordenoGuild) {
if (cache.activeGuildIds.has(guild.id)) return false;
// This is inactive guild. Not a single thing has happened for atleast 30 minutes.
// Not a reaction, not a message, not any event!
cache.guilds.delete(guild.id);
cache.dispatchedGuildIds.add(guild.id);
// Remove all channel if they were dispatched
cache.channels.forEach((channel) => {
if (!cache.dispatchedGuildIds.has(channel.guildId)) return;
cache.channels.delete(channel.id);
cache.dispatchedChannelIds.add(channel.id);
});
// Reset activity for next interval
cache.activeGuildIds.clear();
}
export let cacheHandlers = {
/** Deletes all items from the cache */
async clear(table: TableName) {

View File

@@ -0,0 +1,93 @@
import { botId } from "../bot.ts";
import { cache } from "../cache.ts";
import { getChannels } from "../helpers/channels/get_channels.ts";
import { getGuild } from "../helpers/guilds/get_guild.ts";
import { getMember } from "../helpers/members/get_member.ts";
import { structures } from "../structures/mod.ts";
import type { DiscordGatewayPayload } from "../types/gateway/gateway_payload.ts";
import type { Guild } from "../types/guilds/guild.ts";
import { snowflakeToBigint } from "./bigint.ts";
import { delay } from "./utils.ts";
const processing = new Set<bigint>();
export async function dispatchRequirements(data: DiscordGatewayPayload, shardId: number) {
if (!cache.isReady) return;
// DELETE MEANS WE DONT NEED TO FETCH. CREATE SHOULD HAVE DATA TO CACHE
if (data.t && ["GUILD_CREATE", "GUILD_DELETE"].includes(data.t)) return;
const id = snowflakeToBigint(
(data.t && ["GUILD_UPDATE"].includes(data.t)
? // deno-lint-ignore no-explicit-any
(data.d as any)?.id
: // deno-lint-ignore no-explicit-any
(data.d as any)?.guild_id) ?? ""
);
if (!id || cache.activeGuildIds.has(id)) return;
// If this guild is in cache, it has not been swept and we can cancel
if (cache.guilds.has(id)) {
cache.activeGuildIds.add(id);
return;
}
if (processing.has(id)) {
console.info(`[DISPATCH] New Guild ID already being processed: ${id} in ${data.t} event`);
let runs = 0;
do {
await delay(500);
runs++;
} while (processing.has(id) && runs < 40);
if (!processing.has(id)) return;
return console.warn(`[DISPATCH] Already processed guild was not successfully fetched: ${id} in ${data.t} event`);
}
processing.add(id);
// New guild id has appeared, fetch all relevant data
console.info(`[DISPATCH] New Guild ID has appeared: ${id} in ${data.t} event`);
const rawGuild = (await getGuild(id, {
counts: true,
addToCache: false,
}).catch(console.info)) as Guild | undefined;
if (!rawGuild) {
processing.delete(id);
return console.warn(`[DISPATCH] Guild ID ${id} failed to fetch.`);
}
console.info(`[DISPATCH] Guild ID ${id} has been found. ${rawGuild.name}`);
const [channels, botMember] = await Promise.all([
getChannels(id, false),
getMember(id, botId, { force: true }),
]).catch((error) => {
console.warn(error);
return [];
});
if (!botMember || !channels) {
processing.delete(id);
return console.info(`[DISPATCH] Guild ID ${id} Name: ${rawGuild.name} failed. Unable to get botMember or channels`);
}
const guild = await structures.createDiscordenoGuild(rawGuild, shardId);
// Add to cache
cache.guilds.set(id, guild);
cache.dispatchedGuildIds.delete(id);
channels.forEach((channel) => {
cache.dispatchedChannelIds.delete(channel.id);
cache.channels.set(channel.id, channel);
});
processing.delete(id);
console.info(`[DISPATCH] Guild ID ${id} Name: ${guild.name} completely loaded.`);
}