Files
discordeno/module/Client.ts
2020-02-10 15:56:33 -05:00

88 lines
2.9 KiB
TypeScript

import { endpoints } from "../constants/discord.ts";
import RequestManager from "../managers/RequestManager.ts";
import { DiscordBotGateway, DiscordPayload,
DiscordHeartbeatPayload } from "../types/discord.ts";
import ShardingManager from "../managers/ShardingManager.ts";
import {
connectWebSocket,
isWebSocketCloseEvent,
isWebSocketPingEvent,
isWebSocketPongEvent,
WebSocket
} from "https://deno.land/std/ws/mod.ts";
// import { encode } from "https://deno.land/std/strings/mod.ts"
// import { BufReader } from "https://deno.land/std/io/bufio.ts"
// import { TextProtoReader } from "https://deno.land/std/textproto/mod.ts"
import { keepDiscordWebsocketAlive,
updatePreviousSequenceNumber } from "./websocket.ts";
import { logGreen, logRed, logYellow, logBlue } from "../utils/logger.ts";
class Client {
/** The bot's token. This should never be used by end users. It is meant to be used internally to make requests to the Discord API. */
token: string;
/** The Rate limit manager to handle all outgoing requests to discord. Not meant to be used by users. */
RequestManager: RequestManager;
/** Creates and handles all the shards necessary for the bot. */
ShardingManager: ShardingManager;
constructor(token: string) {
this.token = `Bot ${token}`;
this.RequestManager = new RequestManager(this, this.token);
this.ShardingManager = new ShardingManager();
}
/** Begins initial handshake, creates the websocket with Discord and spawns all necessary shards. */
async connect() {
const data = (await this.RequestManager.get(
endpoints.GATEWAY_BOT
)) as DiscordBotGateway;
// Open a WS with the url from discord.
const sock = await connectWebSocket(data.url);
console.log(sock);
logGreen("ws connected! (type 'close' to quit)");
for await (const msg of sock.receive()) {
if (typeof msg === "string") {
try {
const json = JSON.parse(msg);
this.handleDiscordPayload(json, sock);
} catch {
logRed(`Invalid JSON String send by discord: ${msg}`);
}
logYellow("< " + msg);
} else if (isWebSocketPingEvent(msg)) {
logBlue("< ping");
} else if (isWebSocketPongEvent(msg)) {
logBlue("< pong");
} else if (isWebSocketCloseEvent(msg)) {
logRed(`closed: code=${msg.code}, reason=${msg.reason}`);
}
}
// Begin spawning all necessary shards
this.spawnShards(data.shards);
}
handleDiscordPayload(data: DiscordPayload, socket: WebSocket) {
switch (data.op) {
case 10: // Initial Heartbeat
keepDiscordWebsocketAlive(
socket,
(data.d as DiscordHeartbeatPayload).heartbeat_interval,
data.s
);
break;
case 11:
updatePreviousSequenceNumber(data.s);
break;
}
}
spawnShards(total: number, id = 1) {
// this.ShardingManager.spawnShard(id);
if (id < total) this.spawnShards(total, id + 1);
}
}
export default Client;