diff --git a/managers/ShardingManager.ts b/managers/ShardingManager.ts index 1f2128397..e82c74479 100644 --- a/managers/ShardingManager.ts +++ b/managers/ShardingManager.ts @@ -1,5 +1,4 @@ class ShardingManager extends Map { - constructor(class) } -export default ShardingManager \ No newline at end of file +export default ShardingManager diff --git a/module/Client.ts b/module/Client.ts index 8208bfc68..1511cd5da 100644 --- a/module/Client.ts +++ b/module/Client.ts @@ -1,22 +1,76 @@ -import { endpoints } from "../constants/discord.ts" -import RequestHandler from "../services/RequestHandler.ts" +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 +} 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 { blue, green, red, yellow } from "https://deno.land/std/fmt/colors.ts" +import { keepDiscordWebsocketAlive } from "./websocket"; 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. */ - RequestHandler: RequestHandler + /** 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.RequestHandler = new RequestHandler(this, this.token) - } + constructor(token: string) { + this.token = `Bot ${token}`; + this.RequestManager = new RequestManager(this, this.token); + this.ShardingManager = new ShardingManager(); + } - async connect() { - // const data = await fetch(endpoints.GATEWAY_BOT).then(res => res.json()) - // console.log(data) - console.log(await this.RequestHandler.get(endpoints.GATEWAY_BOT)) - } + /** 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) + console.log(green("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) + } catch { + console.log(red(`Invalid JSON String send by discord: ${msg}`)) + } + console.log(yellow("< " + msg)); + } else if (isWebSocketPingEvent(msg)) { + console.log(blue("< ping")); + } else if (isWebSocketPongEvent(msg)) { + console.log(blue("< pong")); + } else if (isWebSocketCloseEvent(msg)) { + console.log(red(`closed: code=${msg.code}, reason=${msg.reason}`)); + } + } + + // Begin spawning all necessary shards + this.spawnShards(data.shards); + } + + handleDiscordPayload(data: DiscordPayload) { + switch (data.op) { + case 10: // Initial Heartbeat + keepDiscordWebsocketAlive((data.d as DiscordHeartbeatPayload).heartbeat_interval, data.s) + } + } + + spawnShards(total: number, id = 1) { + // this.ShardingManager.spawnShard(id); + if (id < total) this.spawnShards(total, id + 1); + } } -export default Client \ No newline at end of file +export default Client; diff --git a/module/websocket.ts b/module/websocket.ts new file mode 100644 index 000000000..8c9428352 --- /dev/null +++ b/module/websocket.ts @@ -0,0 +1,7 @@ +export const keepDiscordWebsocketAlive = (millesecondsInterval: number, payload: number | null = null) => { + let previousSequenceNumber = payload + + setInterval(() => { + + }, millesecondsInterval) +} diff --git a/types/discord.ts b/types/discord.ts index 2d5f01e7c..a80e58e94 100644 --- a/types/discord.ts +++ b/types/discord.ts @@ -24,3 +24,7 @@ export interface DiscordBotGateway { reset_after: number } } + +export interface DiscordHeartbeatPayload { + heartbeat_interval: number +}