finish transformers and setup gateway stuff

This commit is contained in:
Skillz4Killz
2021-10-12 13:23:24 +00:00
committed by GitHub
parent 3919f84dd1
commit 6b0d8d4921
3 changed files with 181 additions and 71 deletions

View File

@@ -17,6 +17,25 @@ import { Collection } from "./util/collection.ts";
import { DiscordenoUser, transformMember, transformUser } from "./transformers/member.ts";
import { SnakeCasedPropertiesDeep } from "./types/util.ts";
import { Channel } from "./types/channels/channel.ts";
import { DiscordenoChannel, transformChannel } from "./transformers/channel.ts";
import { transformVoiceState } from "./transformers/voice_state.ts";
import { transformRole } from "./transformers/role.ts";
import { transformMessage } from "./transformers/message.ts";
import { transformGuild } from "./transformers/guild.ts";
import { DiscordenoShard } from "./ws/ws.ts";
import { startGateway } from "./ws/start_gateway.ts";
import { spawnShards } from "./ws/spawn_shards.ts";
import { createShard } from "./ws/create_shard.ts";
import { identify } from "./ws/identify.ts";
import { heartbeat } from "./ws/heartbeat.ts";
import { resharder } from "./ws/resharder.ts";
import { tellClusterToIdentify } from "./ws/tell_cluster_to_identify.ts";
import { handleDiscordPayload } from "./ws/handle_discord_payload.ts";
import { log } from "./ws/events.ts";
import { handleOnMessage } from "./ws/handle_on_message.ts";
import { closeWS } from "./ws/close_ws.ts";
import { sendShardMessage } from "./ws/send_shard_message.ts";
import { resume } from "./ws/resume.ts";
export async function createBot(options: CreateBotOptions) {
return {
@@ -102,17 +121,55 @@ export async function startBot(bot: Bot) {
bot.rest = createRestManager({ token: bot.token });
// START WS
bot.gateway = createGatewayManager();
bot.gateway = createGatewayManager({});
}
export interface CreateGatewayManagerOptions {
transformers: Partial<Transformers>;
}
export function createGatewayManager(options: CreateGatewayManagerOptions) {
export function createGatewayManager(options: Partial<GatewayManager>): GatewayManager {
return {
secretKey: options.secretKey ?? "",
url: options.url ?? "",
reshard: options.reshard ?? true,
reshardPercentage: options.reshardPercentage ?? 80,
spawnShardDelay: options.spawnShardDelay ?? 2600,
maxShards: options.maxShards ?? 0,
useOptimalLargeBotSharding: options.useOptimalLargeBotSharding ?? true,
shardsPerCluster: options.shardsPerCluster ?? 25,
maxClusters: options.maxClusters ?? 4,
firstShardId: options.firstShardId ?? 0,
lastShardId: options.lastShardId ?? 1,
token: options.token ?? "",
compress: options.compress ?? false,
$os: options.$os ?? "linux",
$browser: options.$browser ?? "Discordeno",
$device: options.$device ?? "Discordeno",
intents: options.intents ?? 0,
shard: options.shard ?? [0, 0],
urlWSS: options.urlWSS ?? "wss://gateway.discord.gg/?v=9&encoding=json",
shardsRecommended: options.shardsRecommended ?? 1,
sessionStartLimitTotal: options.sessionStartLimitTotal ?? 1000,
sessionStartLimitRemaining: options.sessionStartLimitRemaining ?? 1000,
sessionStartLimitResetAfter: options.sessionStartLimitResetAfter ?? 0,
maxConcurrency: options.maxConcurrency ?? 1,
shards: options.shards ?? new Collection(),
loadingShards: options.loadingShards ?? new Collection(),
buckets: new Collection(),
utf8decoder: new TextDecoder(),
startGateway,
spawnShards,
createShard,
identify,
heartbeat,
handleDiscordPayload,
tellClusterToIdentify,
log,
resharder,
handleOnMessage,
processQueue,
closeWS,
sendShardMessage,
resume,
};
}
export function stopBot(bot: Bot) {
@@ -124,7 +181,7 @@ export interface CreateBotOptions {
token: string;
botId: bigint;
applicationId?: bigint;
events: EventHandlers;
events: Partial<EventHandlers>;
intents: (keyof typeof DiscordGatewayIntents)[];
botGatewayData?: GetGatewayBot;
rest?: Omit<CreateRestManagerOptions, "token">;
@@ -145,22 +202,128 @@ export type Bot = CreatedBot & {
export interface Transformers {
snowflake: typeof snowflakeToBigint;
channel: typeof transformChannel;
guild: typeof transformGuild;
user: typeof transformUser;
member: typeof transformMember;
channel: typeof transformChannel;
message: typeof transformMessage;
role: typeof transformRole;
voiceState: typeof transformVoiceState;
}
export function createTransformers(options: Partial<Transformers>) {
return {
snowflake: options.snowflake || snowflakeToBigint,
channel: options.channel || transformChannel,
guild: options.guild || transformGuild,
user: options.user || transformUser,
member: options.member || transformMember,
message: options.message || transformMessage,
role: options.role || transformRole,
voiceState: options.voiceState || transformVoiceState,
};
}
export type RestManager = ReturnType<typeof createRestManager>;
export interface GatewayManager {}
export interface GatewayManager {
/** The secret key authorization header the bot will expect when sending payloads. */
secretKey: string;
/** The url that all discord payloads for the dispatch type should be sent to. */
url: string;
/** Whether or not to automatically reshard. */
reshard: boolean;
/** The percentage at which resharding should occur. */
reshardPercentage: number;
/** The delay in milliseconds to wait before spawning next shard. OPTIMAL IS ABOVE 2500. YOU DON"T WANT TO HIT THE RATE LIMIT!!! */
spawnShardDelay: number;
/** The maximum shard Id number. Useful for zero-downtime updates or resharding. */
maxShards: number;
/** Whether or not the resharder should automatically switch to LARGE BOT SHARDING when you are above 100K servers. */
useOptimalLargeBotSharding: boolean;
/** The amount of shards to load per cluster. */
shardsPerCluster: number;
/** The maximum amount of clusters to use for your bot. */
maxClusters: number;
/** The first shard Id to start spawning. */
firstShardId: number;
/** The last shard Id for this cluster. */
lastShardId: number;
token: "";
compress: false;
$os: "linux";
$browser: "Discordeno";
$device: "Discordeno";
intents: 0;
shard: [0, 0];
/** The WSS URL that can be used for connecting to the gateway. */
urlWSS: "wss://gateway.discord.gg/?v=9&encoding=json";
/** The recommended number of shards to use when connecting. */
shardsRecommended: 1;
/** The total number of session starts the current user is allowed. */
sessionStartLimitTotal: 1000;
/** The remaining number of session starts the current user is allowed. */
sessionStartLimitRemaining: 1000;
/** Milliseconds left until limit is reset. */
sessionStartLimitResetAfter: 0;
/** The number of identify requests allowed per 5 seconds.
* So, if you had a max concurrency of 16, and 16 shards for example, you could start them all up at the same time.
* Whereas if you had 32 shards, if you tried to start up shard 0 and 16 at the same time for example, it would not work. You can start shards 0-15 concurrently, then 16-31...
*/
maxConcurrency: 1;
shards: Collection<number, DiscordenoShard>;
loadingShards: Collection<
number,
{
shardId: number;
resolve: (value: unknown) => void;
startedAt: number;
}
>;
/** Stored as bucketId: { clusters: [clusterId, [ShardIds]], createNextShard: boolean } */
buckets: Collection<
number,
{
clusters: number[][];
createNextShard: (() => unknown)[];
}
>;
utf8decoder: TextDecoder;
// METHODS
/** The handler function that starts the gateway. */
startGateway: typeof startGateway;
/** The handler for spawning ALL the shards. */
spawnShards: typeof spawnShards;
/** Create the websocket and adds the proper handlers to the websocket. */
createShard: typeof createShard;
/** Begins identification of the shard to discord. */
identify: typeof identify;
/** Begins heartbeating of the shard to keep it alive. */
heartbeat: typeof heartbeat;
/** Sends the discord payload to another server. */
handleDiscordPayload: typeof handleDiscordPayload;
/** Tell the cluster/worker to begin identifying this shard */
tellClusterToIdentify: typeof tellClusterToIdentify;
/** Handle the different logs. Used for debugging. */
log: typeof log;
/** Handles resharding the bot when necessary. */
resharder: typeof resharder;
/** Handles the message events from websocket. */
handleOnMessage: typeof handleOnMessage;
/** Handles processing queue of requests send to this shard. */
processQueue: typeof processQueue;
/** Closes shard WebSocket connection properly. */
closeWS: typeof closeWS;
/** Properly adds a message to the shards queue. */
sendShardMessage: typeof sendShardMessage;
/** Properly resume an old shards session. */
resume: typeof resume;
}
export interface EventHandlers {
debug: (text: string) => unknown;
channelCreate: (bot: Bot, channel: DiscordenoChannel);
channelCreate: (bot: Bot, channel: DiscordenoChannel) => unknown;
}

View File

@@ -1,13 +0,0 @@
import { eventHandlers, replaceEventHandlers } from "../bot.ts";
import type { EventHandlers } from "../types/discordeno/event_handlers.ts";
import type { EventEmitter } from "https://deno.land/std@0.97.0/node/events.ts";
export function proxyEvent(emitter: EventEmitter) {
replaceEventHandlers(
new Proxy(eventHandlers, {
get(target, prop: keyof EventHandlers) {
return target[prop] !== undefined ? target[prop] : (...args: unknown[]) => emitter.emit(prop, ...args);
},
})
);
}

View File

@@ -1,46 +1,6 @@
import { createDiscordenoChannel } from "./channel.ts";
import { createDiscordenoGuild } from "./guild.ts";
import { createDiscordenoMember } from "./member.ts";
import { createDiscordenoMessage } from "./message.ts";
import { createDiscordenoRole } from "./role.ts";
import { createDiscordenoVoiceState } from "./voice_state.ts";
import type { DiscordenoChannel } from "./channel.ts";
import type { DiscordenoGuild } from "./guild.ts";
import type { DiscordenoMember } from "./member.ts";
import type { DiscordenoMessage } from "./message.ts";
import type { DiscordenoRole } from "./role.ts";
import type { DiscordenoVoiceState } from "./voice_state.ts";
/** This is the placeholder where the structure creation functions are kept. */
export let structures = {
createDiscordenoChannel,
createDiscordenoGuild,
createDiscordenoMember,
createDiscordenoMessage,
createDiscordenoRole,
createDiscordenoVoiceState,
};
export type {
DiscordenoChannel,
DiscordenoGuild,
DiscordenoMember,
DiscordenoMessage,
DiscordenoRole,
DiscordenoVoiceState,
};
export type Structures = typeof structures;
/** This function is used to update/reload/customize the internal structures of Discordeno.
*
* ⚠️ **ADVANCED USE ONLY: If you customize this incorrectly, you could potentially create many new errors/bugs.
* Please take caution when using this.**
*/
export function updateStructures(newStructures: Structures) {
structures = {
...structures,
...newStructures,
};
}
export * from "./channel.ts";
export * from "./guild.ts";
export * from "./member.ts";
export * from "./message.ts";
export * from "./role.ts";
export * from "./voice_state.ts";