summary refs log tree commit diff
path: root/src/gateway/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/gateway/util')
-rw-r--r--src/gateway/util/Constants.ts50
-rw-r--r--src/gateway/util/Heartbeat.ts11
-rw-r--r--src/gateway/util/Send.ts33
-rw-r--r--src/gateway/util/SessionUtils.ts13
-rw-r--r--src/gateway/util/WebSocket.ts22
-rw-r--r--src/gateway/util/index.ts5
6 files changed, 134 insertions, 0 deletions
diff --git a/src/gateway/util/Constants.ts b/src/gateway/util/Constants.ts
new file mode 100644
index 00000000..692f9028
--- /dev/null
+++ b/src/gateway/util/Constants.ts
@@ -0,0 +1,50 @@
+export enum OPCODES {
+	Dispatch = 0,
+	Heartbeat = 1,
+	Identify = 2,
+	Presence_Update = 3,
+	Voice_State_Update = 4,
+	Voice_Server_Ping = 5, // ? What is opcode 5?
+	Resume = 6,
+	Reconnect = 7,
+	Request_Guild_Members = 8,
+	Invalid_Session = 9,
+	Hello = 10,
+	Heartbeat_ACK = 11,
+	Guild_Sync = 12,
+	DM_Update = 13,
+	Lazy_Request = 14,
+	Lobby_Connect = 15,
+	Lobby_Disconnect = 16,
+	Lobby_Voice_States_Update = 17,
+	Stream_Create = 18,
+	Stream_Delete = 19,
+	Stream_Watch = 20,
+	Stream_Ping = 21,
+	Stream_Set_Paused = 22,
+	Request_Application_Commands = 24,
+}
+export enum CLOSECODES {
+	Unknown_error = 4000,
+	Unknown_opcode,
+	Decode_error,
+	Not_authenticated,
+	Authentication_failed,
+	Already_authenticated,
+	Invalid_session,
+	Invalid_seq,
+	Rate_limited,
+	Session_timed_out,
+	Invalid_shard,
+	Sharding_required,
+	Invalid_API_version,
+	Invalid_intent,
+	Disallowed_intent,
+}
+
+export interface Payload {
+	op: OPCODES;
+	d?: any;
+	s?: number;
+	t?: string;
+}
diff --git a/src/gateway/util/Heartbeat.ts b/src/gateway/util/Heartbeat.ts
new file mode 100644
index 00000000..f6871cfe
--- /dev/null
+++ b/src/gateway/util/Heartbeat.ts
@@ -0,0 +1,11 @@
+import { CLOSECODES } from "./Constants";
+import { WebSocket } from "./WebSocket";
+
+// TODO: make heartbeat timeout configurable
+export function setHeartbeat(socket: WebSocket) {
+	if (socket.heartbeatTimeout) clearTimeout(socket.heartbeatTimeout);
+
+	socket.heartbeatTimeout = setTimeout(() => {
+		return socket.close(CLOSECODES.Session_timed_out);
+	}, 1000 * 45);
+}
diff --git a/src/gateway/util/Send.ts b/src/gateway/util/Send.ts
new file mode 100644
index 00000000..2a28d8e0
--- /dev/null
+++ b/src/gateway/util/Send.ts
@@ -0,0 +1,33 @@
+let erlpack: any;
+try {
+	erlpack = require("@yukikaze-bot/erlpack");
+} catch (error) {
+	console.log("Missing @yukikaze-bot/erlpack, electron-based desktop clients designed for discord.com will not be able to connect!");
+}
+import { Payload, WebSocket } from "@fosscord/gateway";
+
+export async function Send(socket: WebSocket, data: Payload) {
+	if(process.env.WS_VERBOSE)
+		console.log(`[Websocket] Outgoing message: ${JSON.stringify(data)}`);
+	let buffer: Buffer | string;
+	if (socket.encoding === "etf") buffer = erlpack.pack(data);
+	// TODO: encode circular object
+	else if (socket.encoding === "json") buffer = JSON.stringify(data);
+	else return;
+	// TODO: compression
+	if (socket.deflate) {
+		socket.deflate.write(buffer);
+		socket.deflate.flush();
+		return;
+	}
+
+	return new Promise((res, rej) => {
+		if (socket.readyState !== 1) {
+			return rej("socket not open");
+		}
+		socket.send(buffer, (err: any) => {
+			if (err) return rej(err);
+			return res(null);
+		});
+	});
+}
diff --git a/src/gateway/util/SessionUtils.ts b/src/gateway/util/SessionUtils.ts
new file mode 100644
index 00000000..bf854042
--- /dev/null
+++ b/src/gateway/util/SessionUtils.ts
@@ -0,0 +1,13 @@
+export function genSessionId() {
+	return genRanHex(32);
+}
+
+export function genVoiceToken() {
+	return genRanHex(16);
+}
+
+function genRanHex(size: number) {
+	return [...Array(size)]
+		.map(() => Math.floor(Math.random() * 16).toString(16))
+		.join("");
+}
diff --git a/src/gateway/util/WebSocket.ts b/src/gateway/util/WebSocket.ts
new file mode 100644
index 00000000..9496da85
--- /dev/null
+++ b/src/gateway/util/WebSocket.ts
@@ -0,0 +1,22 @@
+import { Intents, Permissions } from "@fosscord/util";
+import WS from "ws";
+import { Deflate } from "zlib";
+
+export interface WebSocket extends WS {
+	version: number;
+	user_id: string;
+	session_id: string;
+	encoding: "etf" | "json";
+	compress?: "zlib-stream";
+	shard_count?: number;
+	shard_id?: number;
+	deflate?: Deflate;
+	heartbeatTimeout: NodeJS.Timeout;
+	readyTimeout: NodeJS.Timeout;
+	intents: Intents;
+	sequence: number;
+	permissions: Record<string, Permissions>;
+	events: Record<string, Function>;
+	member_events: Record<string, Function>;
+	listen_options: any;
+}
diff --git a/src/gateway/util/index.ts b/src/gateway/util/index.ts
new file mode 100644
index 00000000..0be5ecee
--- /dev/null
+++ b/src/gateway/util/index.ts
@@ -0,0 +1,5 @@
+export * from "./Constants";
+export * from "./Send";
+export * from "./SessionUtils";
+export * from "./Heartbeat";
+export * from "./WebSocket";