ready and channel events overridable

This commit is contained in:
Skillz
2020-09-12 11:32:15 -04:00
parent 469fc25c38
commit d3d7bdacfa
6 changed files with 103 additions and 54 deletions

View File

@@ -2,41 +2,37 @@ import { cache } from "../utils/cache.ts";
import { ChannelCreatePayload, ChannelTypes } from "../types/channel.ts";
import { eventHandlers } from "../module/client.ts";
import { structures } from "../structures/mod.ts";
import { DiscordPayload } from "../types/discord.ts";
export const handleInternalChannelCreate = (data: ChannelCreatePayload) => {
const channel = structures.createChannel(data);
export function handleInternalChannelCreate(data: DiscordPayload) {
if (data.t !== "CHANNEL_CREATE") return;
const payload = data.d as ChannelCreatePayload;
const channel = structures.createChannel(payload);
cache.channels.set(channel.id, channel);
if (channel.guildID) {
const guild = cache.guilds.get(channel.guildID);
guild?.channels.set(channel.id, channel);
}
eventHandlers.channelCreate?.(channel);
};
}
export const handleInternalChannelUpdate = (data: ChannelCreatePayload) => {
const cachedChannel = cache.channels.get(data.id);
const channel = structures.createChannel(data);
cache.channels.set(channel.id, channel);
export function handleInternalChannelDelete(data: DiscordPayload) {
if (data.t !== "CHANNEL_DELETE") return;
const payload = data.d as ChannelCreatePayload;
const cachedChannel = cache.channels.get(payload.id);
if (!cachedChannel) return;
if (channel.guildID) {
const guild = cache.guilds.get(channel.guildID);
guild?.channels.set(channel.id, channel);
}
eventHandlers.channelUpdate?.(channel, cachedChannel);
};
export const handleInternalChannelDelete = (data: ChannelCreatePayload) => {
const cachedChannel = cache.channels.get(data.id);
if (!cachedChannel) return;
if (cachedChannel.type === ChannelTypes.GUILD_VOICE && data.guild_id) {
const guild = cache.guilds.get(data.guild_id);
if (cachedChannel.type === ChannelTypes.GUILD_VOICE && payload.guild_id) {
const guild = cache.guilds.get(payload.guild_id);
if (guild) {
guild.voiceStates.forEach((vs, key) => {
if (vs.channelID !== data.id) return;
if (vs.channelID !== payload.id) return;
// Since this channel was deleted all voice states for this channel should be deleted
guild.voiceStates.delete(key);
@@ -48,12 +44,29 @@ export const handleInternalChannelDelete = (data: ChannelCreatePayload) => {
});
}
guild?.channels.delete(data.id);
guild?.channels.delete(payload.id);
}
cache.channels.delete(data.id);
cache.channels.delete(payload.id);
cache.messages.forEach((message) => {
if (message.channelID === data.id) cache.messages.delete(message.id);
if (message.channelID === payload.id) cache.messages.delete(message.id);
});
eventHandlers.channelDelete?.(cachedChannel);
};
}
export function handleInternalChannelUpdate(data: DiscordPayload) {
if (data.t !== "CHANNEL_UPDATE") return;
const payload = data.d as ChannelCreatePayload;
const cachedChannel = cache.channels.get(payload.id);
const channel = structures.createChannel(payload);
cache.channels.set(channel.id, channel);
if (!cachedChannel) return;
if (channel.guildID) {
const guild = cache.guilds.get(channel.guildID);
guild?.channels.set(channel.id, channel);
}
eventHandlers.channelUpdate?.(channel, cachedChannel);
}

25
src/controllers/misc.ts Normal file
View File

@@ -0,0 +1,25 @@
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
import { eventHandlers, setBotID } from "../module/client.ts";
import { allowNextShard } from "../module/shardingManager.ts";
import { DiscordPayload, ReadyPayload } from "../types/discord.ts";
import { cache } from "../utils/cache.ts";
export async function handleInternalReady(data: DiscordPayload, shardID: number) {
if (data.t !== "READY") return;
const payload = data.d as ReadyPayload;
setBotID(payload.user.id);
// Triggered on each shard
eventHandlers.shardReady?.(shardID);
if (payload.shard && shardID === payload.shard[1] - 1) {
// Wait 10 seconds to allow all guild create events to be processed
await delay(10000);
cache.isReady = true;
eventHandlers.ready?.();
}
// Wait 5 seconds to spawn next shard
await delay(5000);
allowNextShard()
}

21
src/controllers/mod.ts Normal file
View File

@@ -0,0 +1,21 @@
import {
handleInternalChannelCreate,
handleInternalChannelDelete,
handleInternalChannelUpdate,
} from "./channels.ts";
import {
handleInternalGuildCreate,
handleInternalGuildDelete,
handleInternalGuildUpdate,
} from "./guilds.ts";
import { handleInternalReady } from "./misc.ts";
export let controllers = {
READY: handleInternalReady,
CHANNEL_CREATE: handleInternalChannelCreate,
CHANNEL_DELETE: handleInternalChannelDelete,
CHANNEL_UPDATE: handleInternalChannelUpdate,
GUILD_CREATE: handleInternalGuildCreate,
GUILD_DELETE: handleInternalGuildDelete,
GUILD_UPDATE: handleInternalGuildUpdate,
};

View File

@@ -61,5 +61,5 @@ export function updateEventHandlers(newEventHandlers: EventHandlers) {
}
export function setBotID(id: string) {
botID = id;
if (botID !== id) botID = id;
}

View File

@@ -59,6 +59,7 @@ import {
} from "./basicShard.ts";
import { BotStatusRequest } from "../utils/utils.ts";
import { structures } from "../structures/mod.ts";
import { controllers } from "../controllers/mod.ts";
let shardCounter = 0;
let basicSharding = false;
@@ -76,6 +77,11 @@ const fetchAllMembersProcessingRequests = new Map<
const shards: Worker[] = [];
let createNextShard = true;
/** This function is meant to be used on the ready event to alert the library to start the next shard. */
export function allowNextShard(enabled = true) {
createNextShard = enabled;
}
export function createShardWorker(shardID?: number) {
const path = new URL("./shard.ts", import.meta.url).toString();
const shard = new Worker(path, { type: "module", deno: true });
@@ -140,32 +146,9 @@ export async function handleDiscordPayload(
// Incase the user wants to listen to heartbeat responses
return eventHandlers.heartbeat?.();
case GatewayOpcode.Dispatch:
if (data.t === "READY") {
const payload = data.d as ReadyPayload;
setBotID(payload.user.id);
// Triggered on each shard
eventHandlers.shardReady?.(shardID);
if (payload.shard && shardID === payload.shard[1] - 1) {
// Wait 10 seconds to allow all guild create events to be processed
await delay(10000);
cache.isReady = true;
eventHandlers.ready?.();
}
// Wait 5 seconds to spawn next shard
await delay(5000);
createNextShard = true;
}
if (data.t === "CHANNEL_CREATE") {
return handleInternalChannelCreate(data.d as ChannelCreatePayload);
}
if (data.t === "CHANNEL_UPDATE") {
return handleInternalChannelUpdate(data.d as ChannelCreatePayload);
}
if (data.t === "CHANNEL_DELETE") {
return handleInternalChannelDelete(data.d as ChannelCreatePayload);
}
if (!data.t) return;
// Run the appropriate controller for this event.
controllers[data.t]?.(data, shardID);
if (data.t === "GUILD_CREATE") {
const options = data.d as CreateGuildPayload;

View File

@@ -11,7 +11,14 @@ export interface DiscordPayload {
/** The sequence number, used for resuming sessions and heartbeats. ONLY for OPCode 0 */
s?: number;
/** The event name for this payload. ONLY for OPCode 0 */
t?: string;
t?:
| "READY"
| "CHANNEL_CREATE"
| "CHANNEL_UPDATE"
| "CHANNEL_DELETE"
| "GUILD_CREATE"
| "GUILD_DELETE"
| "GUILD_UPDATE";
}
export interface DiscordBotGatewayData {