diff --git a/package.json b/package.json index 85cf4148..f3fd3362 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "lambert-db": "^1.1.8", "lambert-server": "^1.1.7", "missing-native-js-functions": "^1.2.3", + "mongoose-autopopulate": "^0.12.3", "node-fetch": "^2.6.1", "typescript": "^4.2.3", "uuid": "^8.3.2", @@ -27,6 +28,7 @@ }, "devDependencies": { "@types/jsonwebtoken": "^8.5.0", + "@types/mongoose-autopopulate": "^0.10.1", "@types/uuid": "^8.3.0", "@types/ws": "^7.4.0" } diff --git a/src/listener/listener.ts b/src/listener/listener.ts index 988a791a..f0f9d3e3 100644 --- a/src/listener/listener.ts +++ b/src/listener/listener.ts @@ -2,6 +2,7 @@ import { db, Event, MongooseCache, UserModel, getPermission, Permissions } from import { OPCODES } from "../util/Constants"; import { Send } from "../util/Send"; import WebSocket from "../util/WebSocket"; +import "missing-native-js-functions"; // TODO: close connection on Invalidated Token // TODO: check intent @@ -11,34 +12,40 @@ import WebSocket from "../util/WebSocket"; // Sharding: calculate if the current shard id matches the formula: shard_id = (guild_id >> 22) % num_shards // https://discord.com/developers/docs/topics/gateway#sharding +export interface DispatchOpts { + eventStream: MongooseCache; + guilds: Array; +} + +function getPipeline(this: WebSocket, guilds: string[]) { + if (this.shard_count) { + guilds = guilds.filter((x) => (BigInt(x) >> 22n) % this.shard_count === this.shard_id); + } + + return [ + { + $match: { + $or: [{ "fullDocument.guild_id": { $in: guilds } }, { "fullDocument.user_id": this.user_id }], + }, + }, + ]; +} + export async function setupListener(this: WebSocket) { const user = await UserModel.findOne({ id: this.user_id }).lean().exec(); var guilds = user.guilds; - const shard_count = 10n; - const shard_id = 0n; - if (shard_count) { - guilds = user.guilds.filter((x) => (BigInt(x) >> 22n) % shard_count === shard_id); - } + const eventStream = new MongooseCache(db.collection("events"), getPipeline.call(this, guilds), { + onlyEvents: true, + }); - const eventStream = new MongooseCache( - db.collection("events"), - [ - { - $match: { - $or: [{ "fullDocument.guild_id": { $in: guilds } }, { "fullDocument.user_id": this.user_id }], - }, - }, - ], - { onlyEvents: true } - ); await eventStream.init(); - eventStream.on("insert", dispatch.bind(this)); + eventStream.on("insert", (document: Event) => dispatch.call(this, document, { eventStream, guilds })); this.once("close", () => eventStream.destroy()); } -export async function dispatch(this: WebSocket, document: Event) { +export async function dispatch(this: WebSocket, document: Event, { eventStream, guilds }: DispatchOpts) { var permission = new Permissions("ADMINISTRATOR"); // default permission for dms console.log("event", document); @@ -48,6 +55,14 @@ export async function dispatch(this: WebSocket, document: Event) { permission = await getPermission(this.user_id, document.guild_id, channel_id); } + if (document.event === "GUILD_CREATE") { + guilds.push(document.guild_id); + eventStream.changeStream(getPipeline.call(this, guilds)); + } else if (document.event === "GUILD_DELETE") { + guilds.remove(document.guild); + eventStream.changeStream(getPipeline.call(this, guilds)); + } + // check intents: https://discord.com/developers/docs/topics/gateway#gateway-intents switch (document.event) { case "GUILD_CREATE":