diff --git a/src/gateway/Server.ts b/src/gateway/Server.ts
index f1ef7a27..81e4b7f4 100644
--- a/src/gateway/Server.ts
+++ b/src/gateway/Server.ts
@@ -56,7 +56,6 @@ export class Server {
}
this.server.on("upgrade", (request, socket, head) => {
- // @ts-ignore
this.ws.handleUpgrade(request, socket, head, (socket) => {
this.ws.emit("connection", socket, request);
});
diff --git a/src/gateway/events/Close.ts b/src/gateway/events/Close.ts
index 6b069d0b..296ab5ee 100644
--- a/src/gateway/events/Close.ts
+++ b/src/gateway/events/Close.ts
@@ -26,7 +26,7 @@ import {
User,
} from "@fosscord/util";
-export async function Close(this: WebSocket, code: number, reason: string) {
+export async function Close(this: WebSocket, code: number, reason: Buffer) {
console.log("[WebSocket] closed", code, reason.toString());
if (this.heartbeatTimeout) clearTimeout(this.heartbeatTimeout);
if (this.readyTimeout) clearTimeout(this.readyTimeout);
diff --git a/src/gateway/events/Connection.ts b/src/gateway/events/Connection.ts
index 85ffb1ed..82081266 100644
--- a/src/gateway/events/Connection.ts
+++ b/src/gateway/events/Connection.ts
@@ -16,6 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
+/* eslint-disable @typescript-eslint/ban-ts-comment */
import WS from "ws";
import { genSessionId, WebSocket } from "@fosscord/gateway";
import { Send } from "../util/Send";
@@ -27,10 +28,12 @@ import { Message } from "./Message";
import { Deflate, Inflate } from "fast-zlib";
import { URL } from "url";
import { Config } from "@fosscord/util";
-var erlpack: any;
+let erlpack: unknown;
try {
erlpack = require("@yukikaze-bot/erlpack");
-} catch (error) {}
+} catch (error) {
+ /* empty */
+}
// TODO: check rate limit
// TODO: specify rate limit in config
diff --git a/src/gateway/events/Message.ts b/src/gateway/events/Message.ts
index 57899a23..b949f273 100644
--- a/src/gateway/events/Message.ts
+++ b/src/gateway/events/Message.ts
@@ -27,14 +27,16 @@ import path from "path";
import fs from "fs/promises";
const bigIntJson = BigIntJson({ storeAsString: true });
-var erlpack: any;
+let erlpack: { unpack: (buffer: Buffer) => Payload };
try {
erlpack = require("@yukikaze-bot/erlpack");
-} catch (error) {}
+} catch (error) {
+ /* empty */
+}
export async function Message(this: WebSocket, buffer: WS.Data) {
// TODO: compression
- var data: Payload;
+ let data: Payload;
if (
(buffer instanceof Buffer && buffer[0] === 123) || // ASCII 123 = `{`. Bad check for JSON
@@ -44,9 +46,9 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
} else if (this.encoding === "json" && buffer instanceof Buffer) {
if (this.inflate) {
try {
- buffer = this.inflate.process(buffer) as any;
+ buffer = this.inflate.process(buffer);
} catch {
- buffer = buffer.toString() as any;
+ buffer = buffer.toString();
}
}
data = bigIntJson.parse(buffer as string);
@@ -78,7 +80,6 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
check.call(this, PayloadSchema, data);
- // @ts-ignore
const OPCodeHandler = OPCodeHandlers[data.op];
if (!OPCodeHandler) {
console.error("[Gateway] Unkown opcode " + data.op);
@@ -100,7 +101,7 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
: undefined;
try {
- var ret = await OPCodeHandler.call(this, data);
+ const ret = await OPCodeHandler.call(this, data);
Sentry.withScope((scope) => {
scope.setSpan(transaction);
scope.setUser({ id: this.user_id });
diff --git a/src/gateway/listener/listener.ts b/src/gateway/listener/listener.ts
index 9bdee86a..824341f9 100644
--- a/src/gateway/listener/listener.ts
+++ b/src/gateway/listener/listener.ts
@@ -79,7 +79,10 @@ export async function setupListener(this: WebSocket) {
const guilds = members.map((x) => x.guild);
const dm_channels = recipients.map((x) => x.channel);
- const opts: { acknowledge: boolean; channel?: AMQChannel } = {
+ const opts: {
+ acknowledge: boolean;
+ channel?: AMQChannel & { queues?: unknown };
+ } = {
acknowledge: true,
};
this.listen_options = opts;
@@ -87,7 +90,6 @@ export async function setupListener(this: WebSocket) {
if (RabbitMQ.connection) {
opts.channel = await RabbitMQ.connection.createChannel();
- // @ts-ignore
opts.channel.queues = {};
}
@@ -113,7 +115,7 @@ export async function setupListener(this: WebSocket) {
guild.channels.forEach(async (channel) => {
if (
permission
- .overwriteChannel(channel.permission_overwrites!)
+ .overwriteChannel(channel.permission_overwrites ?? [])
.has("VIEW_CHANNEL")
) {
this.events[channel.id] = await listenEvent(
@@ -128,7 +130,7 @@ export async function setupListener(this: WebSocket) {
this.once("close", () => {
if (opts.channel) opts.channel.close();
else {
- Object.values(this.events).forEach((x) => x());
+ Object.values(this.events).forEach((x) => x?.());
Object.values(this.member_events).forEach((x) => x());
}
});
@@ -137,7 +139,7 @@ export async function setupListener(this: WebSocket) {
// TODO: only subscribe for events that are in the connection intents
async function consume(this: WebSocket, opts: EventOpts) {
const { data, event } = opts;
- let id = data.id as string;
+ const id = data.id as string;
const permission = this.permissions[id] || new Permissions("ADMINISTRATOR"); // default permission for dm
const consumer = consume.bind(this);
@@ -150,6 +152,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
case "GUILD_MEMBER_REMOVE":
this.member_events[data.user.id]?.();
delete this.member_events[data.user.id];
+ break;
case "GUILD_MEMBER_ADD":
if (this.member_events[data.user.id]) break; // already subscribed
this.member_events[data.user.id] = await listenEvent(
@@ -158,7 +161,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
this.listen_options,
);
break;
- case "GUILD_MEMBER_REMOVE":
+ case "GUILD_MEMBER_UPDATE":
if (!this.member_events[data.user.id]) break;
this.member_events[data.user.id]();
break;
@@ -188,9 +191,8 @@ async function consume(this: WebSocket, opts: EventOpts) {
case "GUILD_CREATE":
this.events[id] = await listenEvent(id, consumer, listenOpts);
break;
- case "CHANNEL_UPDATE":
+ case "CHANNEL_UPDATE": {
const exists = this.events[id];
- // @ts-ignore
if (
permission
.overwriteChannel(data.permission_overwrites)
@@ -204,6 +206,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
delete this.events[id];
}
break;
+ }
}
// permission checking
@@ -218,8 +221,7 @@ async function consume(this: WebSocket, opts: EventOpts) {
break;
case "GUILD_MEMBER_ADD":
case "GUILD_MEMBER_REMOVE":
- case "GUILD_MEMBER_UPDATE":
- // only send them, if the user subscribed for this part of the member list, or is a bot
+ case "GUILD_MEMBER_UPDATE": // only send them, if the user subscribed for this part of the member list, or is a bot
case "PRESENCE_UPDATE": // exception if user is friend
break;
case "GUILD_BAN_ADD":
diff --git a/src/gateway/opcodes/Heartbeat.ts b/src/gateway/opcodes/Heartbeat.ts
index b7f21a56..77c8671f 100644
--- a/src/gateway/opcodes/Heartbeat.ts
+++ b/src/gateway/opcodes/Heartbeat.ts
@@ -16,11 +16,11 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Payload, WebSocket } from "@fosscord/gateway";
+import { WebSocket } from "@fosscord/gateway";
import { setHeartbeat } from "../util/Heartbeat";
import { Send } from "../util/Send";
-export async function onHeartbeat(this: WebSocket, data: Payload) {
+export async function onHeartbeat(this: WebSocket) {
// TODO: validate payload
setHeartbeat(this);
diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts
index 8d762967..030ca66e 100644
--- a/src/gateway/opcodes/Identify.ts
+++ b/src/gateway/opcodes/Identify.ts
@@ -42,13 +42,13 @@ import {
UserGuildSettings,
ReadyGuildDTO,
Guild,
+ UserTokenData,
} from "@fosscord/util";
import { Send } from "../util/Send";
import { CLOSECODES, OPCODES } from "../util/Constants";
-import { genSessionId } from "../util/SessionUtils";
import { setupListener } from "../listener/listener";
// import experiments from "./experiments.json";
-const experiments: any = [];
+const experiments: unknown[] = [];
import { check } from "./instanceOf";
import { Recipient } from "@fosscord/util";
@@ -56,6 +56,8 @@ import { Recipient } from "@fosscord/util";
// TODO: check privileged intents, if defined in the config
// TODO: check if already identified
+// TODO: Refactor identify ( and lazyrequest, tbh )
+
export async function onIdentify(this: WebSocket, data: Payload) {
clearTimeout(this.readyTimeout);
// TODO: is this needed now that we use `json-bigint`?
@@ -65,15 +67,16 @@ export async function onIdentify(this: WebSocket, data: Payload) {
const identify: IdentifySchema = data.d;
+ let decoded: UserTokenData["decoded"];
try {
const { jwtSecret } = Config.get().security;
- var { decoded } = await checkToken(identify.token, jwtSecret); // will throw an error if invalid
+ decoded = (await checkToken(identify.token, jwtSecret)).decoded; // will throw an error if invalid
} catch (error) {
console.error("invalid token", error);
return this.close(CLOSECODES.Authentication_failed);
}
this.user_id = decoded.id;
- let session_id = this.session_id;
+ const session_id = this.session_id;
const [user, read_states, members, recipients, session, application] =
await Promise.all([
@@ -144,7 +147,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
return this.close(CLOSECODES.Invalid_shard);
}
}
- var users: PublicUser[] = [];
+ let users: PublicUser[] = [];
const merged_members = members.map((x: Member) => {
return [
@@ -156,18 +159,18 @@ export async function onIdentify(this: WebSocket, data: Payload) {
},
];
}) as PublicMember[][];
- let guilds = members.map((x) => ({ ...x.guild, joined_at: x.joined_at }));
+ // TODO: This type is bad.
+ let guilds: Partial<Guild>[] = members.map((x) => ({
+ ...x.guild,
+ joined_at: x.joined_at,
+ }));
const pending_guilds: typeof guilds = [];
- // @ts-ignore
- guilds = guilds.map((guild) => {
- if (user.bot) {
+ if (user.bot)
+ guilds = guilds.map((guild) => {
pending_guilds.push(guild);
return { id: guild.id, unavailable: true };
- }
-
- return guild;
- });
+ });
// TODO: Rewrite this. Perhaps a DTO?
const user_guild_settings_entries = members.map((x) => ({
@@ -180,24 +183,25 @@ export async function onIdentify(this: WebSocket, data: Payload) {
...y[1],
channel_id: y[0],
})),
- })) as any as UserGuildSettings[];
+ })) as unknown as UserGuildSettings[];
const channels = recipients.map((x) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
- x.channel.recipients = x.channel.recipients?.map((x) =>
+ x.channel.recipients = x.channel.recipients.map((x) =>
x.user.toPublicUser(),
);
//TODO is this needed? check if users in group dm that are not friends are sent in the READY event
users = users.concat(x.channel.recipients as unknown as User[]);
if (x.channel.isDm()) {
- x.channel.recipients = x.channel.recipients!.filter(
+ x.channel.recipients = x.channel.recipients?.filter(
(x) => x.id !== this.user_id,
);
}
return x.channel;
});
- for (let relation of user.relationships) {
+ for (const relation of user.relationships) {
const related_user = relation.to;
const public_related_user = {
username: related_user.username,
@@ -236,7 +240,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
} as PresenceUpdateEvent);
});
- read_states.forEach((s: any) => {
+ read_states.forEach((s: Partial<ReadState>) => {
s.id = s.channel_id;
delete s.user_id;
delete s.channel_id;
@@ -275,10 +279,11 @@ export async function onIdentify(this: WebSocket, data: Payload) {
}, //TODO: check this code!
user: privateUser,
user_settings: user.settings,
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
- guilds: guilds.map((x) => {
+ guilds: guilds.map((x: Guild & { joined_at: Date }) => {
return {
- ...new ReadyGuildDTO(x as Guild & { joined_at: Date }).toJSON(),
+ ...new ReadyGuildDTO(x).toJSON(),
guild_hashes: {},
joined_at: x.joined_at,
};
@@ -307,6 +312,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
},
country_code: user.settings.locale,
friend_suggestion_count: 0, // TODO
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
experiments: experiments, // TODO
guild_join_requests: [], // TODO what is this?
diff --git a/src/gateway/opcodes/LazyRequest.ts b/src/gateway/opcodes/LazyRequest.ts
index d4b612b8..93524058 100644
--- a/src/gateway/opcodes/LazyRequest.ts
+++ b/src/gateway/opcodes/LazyRequest.ts
@@ -46,24 +46,25 @@ async function getMembers(guild_id: string, range: [number, number]) {
let members: Member[] = [];
try {
- members = await getDatabase()!
- .getRepository(Member)
- .createQueryBuilder("member")
- .where("member.guild_id = :guild_id", { guild_id })
- .leftJoinAndSelect("member.roles", "role")
- .leftJoinAndSelect("member.user", "user")
- .leftJoinAndSelect("user.sessions", "session")
- .addSelect("user.settings")
- .addSelect(
- "CASE WHEN session.status = 'offline' THEN 0 ELSE 1 END",
- "_status",
- )
- .orderBy("role.position", "DESC")
- .addOrderBy("_status", "DESC")
- .addOrderBy("user.username", "ASC")
- .offset(Number(range[0]) || 0)
- .limit(Number(range[1]) || 100)
- .getMany();
+ members =
+ (await getDatabase()
+ ?.getRepository(Member)
+ .createQueryBuilder("member")
+ .where("member.guild_id = :guild_id", { guild_id })
+ .leftJoinAndSelect("member.roles", "role")
+ .leftJoinAndSelect("member.user", "user")
+ .leftJoinAndSelect("user.sessions", "session")
+ .addSelect("user.settings")
+ .addSelect(
+ "CASE WHEN session.status = 'offline' THEN 0 ELSE 1 END",
+ "_status",
+ )
+ .orderBy("role.position", "DESC")
+ .addOrderBy("_status", "DESC")
+ .addOrderBy("user.username", "ASC")
+ .offset(Number(range[0]) || 0)
+ .limit(Number(range[1]) || 100)
+ .getMany()) ?? [];
} catch (e) {
console.error(`LazyRequest`, e);
}
@@ -77,7 +78,7 @@ async function getMembers(guild_id: string, range: [number, number]) {
};
}
- const groups = [] as any[];
+ const groups = [];
const items = [];
const member_roles = members
.map((m) => m.roles)
@@ -93,10 +94,9 @@ async function getMembers(guild_id: string, range: [number, number]) {
const offlineItems = [];
for (const role of member_roles) {
- // @ts-ignore
- const [role_members, other_members]: Member[][] = partition(
+ const [role_members, other_members] = partition(
members,
- (m: Member) => m.roles.find((r) => r.id === role.id),
+ (m: Member) => !!m.roles.find((r) => r.id === role.id),
);
const group = {
count: role_members.length,
@@ -126,7 +126,7 @@ async function getMembers(guild_id: string, range: [number, number]) {
(a.activities.length - b.activities.length) * 2
);
});
- var session: Session | undefined = sessions.first();
+ const session: Session | undefined = sessions.first();
if (session?.status == "offline") {
session.status = member?.user?.settings?.status || "online";
@@ -189,7 +189,9 @@ async function getMembers(guild_id: string, range: [number, number]) {
export async function onLazyRequest(this: WebSocket, { d }: Payload) {
// TODO: check data
check.call(this, LazyRequestSchema, d);
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { guild_id, typing, channels, activities } = d as LazyRequestSchema;
+ if (!channels) throw new Error("Must provide channel ranges");
const channel_id = Object.keys(channels || {}).first();
if (!channel_id) return;
@@ -197,7 +199,7 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
const permissions = await getPermission(this.user_id, guild_id, channel_id);
permissions.hasThrow("VIEW_CHANNEL");
- const ranges = channels![channel_id];
+ const ranges = channels[channel_id];
if (!Array.isArray(ranges)) throw new Error("Not a valid Array");
const member_count = await Member.count({ where: { guild_id } });
@@ -244,15 +246,10 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
});
}
-function partition<T>(array: T[], isValid: Function) {
- // @ts-ignore
- return array.reduce(
- // @ts-ignore
- ([pass, fail], elem) => {
- return isValid(elem)
- ? [[...pass, elem], fail]
- : [pass, [...fail, elem]];
- },
- [[], []],
- );
+/* https://stackoverflow.com/a/50636286 */
+function partition<T>(array: T[], filter: (elem: T) => boolean) {
+ const pass: T[] = [],
+ fail: T[] = [];
+ array.forEach((e) => (filter(e) ? pass : fail).push(e));
+ return [pass, fail];
}
diff --git a/src/gateway/opcodes/RequestGuildMembers.ts b/src/gateway/opcodes/RequestGuildMembers.ts
index d669b30e..7822813b 100644
--- a/src/gateway/opcodes/RequestGuildMembers.ts
+++ b/src/gateway/opcodes/RequestGuildMembers.ts
@@ -16,8 +16,8 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Payload, WebSocket } from "@fosscord/gateway";
+import { WebSocket } from "@fosscord/gateway";
-export function onRequestGuildMembers(this: WebSocket, data: Payload) {
+export function onRequestGuildMembers(this: WebSocket) {
// return this.close(CLOSECODES.Unknown_error);
}
diff --git a/src/gateway/opcodes/Resume.ts b/src/gateway/opcodes/Resume.ts
index d4bd5320..a8650cc4 100644
--- a/src/gateway/opcodes/Resume.ts
+++ b/src/gateway/opcodes/Resume.ts
@@ -16,10 +16,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { WebSocket, Payload } from "@fosscord/gateway";
+import { WebSocket } from "@fosscord/gateway";
import { Send } from "../util/Send";
-export async function onResume(this: WebSocket, data: Payload) {
+export async function onResume(this: WebSocket) {
console.log("Got Resume -> cancel not implemented");
await Send(this, {
op: 9,
diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts
index 5ee02e82..d300d7b7 100644
--- a/src/gateway/opcodes/VoiceStateUpdate.ts
+++ b/src/gateway/opcodes/VoiceStateUpdate.ts
@@ -99,6 +99,7 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) {
voiceState.token = genVoiceToken();
voiceState.session_id = this.session_id;
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
const { id, ...newObj } = voiceState;
await Promise.all([
diff --git a/src/gateway/opcodes/index.ts b/src/gateway/opcodes/index.ts
index 05e8964b..1e32f1e6 100644
--- a/src/gateway/opcodes/index.ts
+++ b/src/gateway/opcodes/index.ts
@@ -25,7 +25,7 @@ import { onRequestGuildMembers } from "./RequestGuildMembers";
import { onResume } from "./Resume";
import { onVoiceStateUpdate } from "./VoiceStateUpdate";
-export type OPCodeHandler = (this: WebSocket, data: Payload) => any;
+export type OPCodeHandler = (this: WebSocket, data: Payload) => unknown;
export default {
1: onHeartbeat,
@@ -40,4 +40,4 @@ export default {
// 10: Hello
// 13: Dm_update
14: onLazyRequest,
-};
+} as { [key: number]: OPCodeHandler };
diff --git a/src/gateway/opcodes/instanceOf.ts b/src/gateway/opcodes/instanceOf.ts
index 17de0a67..6c23cb08 100644
--- a/src/gateway/opcodes/instanceOf.ts
+++ b/src/gateway/opcodes/instanceOf.ts
@@ -20,7 +20,7 @@ import { instanceOf } from "lambert-server";
import { WebSocket } from "@fosscord/gateway";
import { CLOSECODES } from "../util/Constants";
-export function check(this: WebSocket, schema: any, data: any) {
+export function check(this: WebSocket, schema: unknown, data: unknown) {
try {
const error = instanceOf(schema, data, { path: "body" });
if (error !== true) {
diff --git a/src/gateway/start.ts b/src/gateway/start.ts
index b86c3eca..79448f91 100644
--- a/src/gateway/start.ts
+++ b/src/gateway/start.ts
@@ -24,7 +24,7 @@ import { Server } from "./Server";
import { config } from "dotenv";
config();
-var port = Number(process.env.PORT);
+let port = Number(process.env.PORT);
if (isNaN(port)) port = 3002;
const server = new Server({
diff --git a/src/gateway/util/Constants.ts b/src/gateway/util/Constants.ts
index cc67ed0f..cb60005c 100644
--- a/src/gateway/util/Constants.ts
+++ b/src/gateway/util/Constants.ts
@@ -64,6 +64,7 @@ export enum CLOSECODES {
export interface Payload {
op: OPCODES /* | VoiceOPCodes */;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
d?: any;
s?: number;
t?: string;
diff --git a/src/gateway/util/Send.ts b/src/gateway/util/Send.ts
index 1ca143b6..a89d92d7 100644
--- a/src/gateway/util/Send.ts
+++ b/src/gateway/util/Send.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-var erlpack: any;
+let erlpack: { pack: (data: Payload) => Buffer };
try {
erlpack = require("@yukikaze-bot/erlpack");
} catch (error) {
@@ -63,7 +63,7 @@ export function Send(socket: WebSocket, data: Payload) {
return;
}
- socket.send(buffer, (err: any) => {
+ socket.send(buffer, (err) => {
if (err) return rej(err);
return res(null);
});
diff --git a/src/gateway/util/WebSocket.ts b/src/gateway/util/WebSocket.ts
index d4a4b8b3..14917f21 100644
--- a/src/gateway/util/WebSocket.ts
+++ b/src/gateway/util/WebSocket.ts
@@ -16,7 +16,7 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Intents, Permissions } from "@fosscord/util";
+import { Intents, ListenEventOpts, Permissions } from "@fosscord/util";
import WS from "ws";
import { Deflate, Inflate } from "fast-zlib";
// import { Client } from "@fosscord/webrtc";
@@ -37,8 +37,8 @@ export interface WebSocket extends WS {
intents: Intents;
sequence: number;
permissions: Record<string, Permissions>;
- events: Record<string, Function>;
- member_events: Record<string, Function>;
- listen_options: any;
+ events: Record<string, undefined | (() => unknown)>;
+ member_events: Record<string, () => unknown>;
+ listen_options: ListenEventOpts;
// client?: Client;
}
|