✨ Event dispatching
This commit is contained in:
parent
3f8c652d68
commit
f5269ef39e
10
package-lock.json
generated
10
package-lock.json
generated
@ -540,12 +540,13 @@
|
||||
},
|
||||
"node_modules/fosscord-server-util": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "git+ssh://git@github.com/fosscord/fosscord-server-util.git#b2e3df59d3829d8a149b0bd0c0679ec967b76e8d",
|
||||
"resolved": "git+ssh://git@github.com/fosscord/fosscord-server-util.git#7363f243ad9936466b97266592037ee0a5290c54",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"lambert-db": "^1.1.7",
|
||||
"missing-native-js-functions": "^1.2.2"
|
||||
"missing-native-js-functions": "^1.2.2",
|
||||
"mongodb": "^3.6.4"
|
||||
}
|
||||
},
|
||||
"node_modules/fresh": {
|
||||
@ -2201,12 +2202,13 @@
|
||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
|
||||
},
|
||||
"fosscord-server-util": {
|
||||
"version": "git+ssh://git@github.com/fosscord/fosscord-server-util.git#b2e3df59d3829d8a149b0bd0c0679ec967b76e8d",
|
||||
"version": "git+ssh://git@github.com/fosscord/fosscord-server-util.git#7363f243ad9936466b97266592037ee0a5290c54",
|
||||
"from": "fosscord-server-util@github:fosscord/fosscord-server-util",
|
||||
"requires": {
|
||||
"jsonwebtoken": "^8.5.1",
|
||||
"lambert-db": "^1.1.7",
|
||||
"missing-native-js-functions": "^1.2.2"
|
||||
"missing-native-js-functions": "^1.2.2",
|
||||
"mongodb": "^3.6.4"
|
||||
}
|
||||
},
|
||||
"fresh": {
|
||||
|
@ -1,23 +1,164 @@
|
||||
import { db, User, Event } from "fosscord-server-util";
|
||||
import { MongodbProviderCache } from "lambert-db/dist/Mongodb";
|
||||
import { db, Event, MongooseCache, UserModel, getPermission, Permissions } from "fosscord-server-util";
|
||||
import WebSocket from "../util/WebSocket";
|
||||
|
||||
export async function setupListener(this: WebSocket) {
|
||||
// TODO: bot sharding
|
||||
// TODO: close connection on Invalidated Token
|
||||
// TODO: check intent
|
||||
// TODO: Guild Member Update is sent for current-user updates regardless of whether the GUILD_MEMBERS intent is set.
|
||||
// ? How to resubscribe MongooseCache for new dm channel events? Maybe directly send them to the user_id regardless of the channel_id? -> max overhead of creating 10 events in database for dm user group. Or a new field in event -> recipient_ids?
|
||||
|
||||
const user: User = await db.data.users({ id: this.userid }).get();
|
||||
export async function setupListener(this: WebSocket) {
|
||||
const user = await UserModel.findOne({ id: this.userid }).exec();
|
||||
|
||||
// * MongoDB specific $in query to get all guilds of the user
|
||||
const eventStream: MongodbProviderCache = await db.data
|
||||
.guilds({ $or: [{ guild_id: { $in: user.guilds } }, { user_id: this.userid }] })
|
||||
.cache({ onlyEvents: true })
|
||||
.init();
|
||||
|
||||
eventStream.on("insert", (document: Event) => {
|
||||
console.log("event", document);
|
||||
this.emit(document.event, document.data);
|
||||
});
|
||||
const eventStream = new MongooseCache(
|
||||
db.collection("events"),
|
||||
[{ $match: { $or: [{ guild_id: { $in: user.guilds } }, { user_id: this.userid }] } }],
|
||||
{ onlyEvents: true }
|
||||
);
|
||||
await eventStream.init();
|
||||
eventStream.on("insert", dispatch.bind(this));
|
||||
|
||||
this.once("close", () => eventStream.destroy());
|
||||
}
|
||||
|
||||
export async function dispatch(this: WebSocket, document: Event) {
|
||||
var permission = new Permissions("ADMINISTRATOR"); // default permission for dms
|
||||
|
||||
if (document.guild_id) {
|
||||
if (!this.intents.has("GUILDS")) return;
|
||||
const channel_id = document.channel_id || document.data?.channel_id;
|
||||
permission = new Permissions(await getPermission(this.userid, document.guild_id, channel_id));
|
||||
}
|
||||
|
||||
console.log("event", document);
|
||||
|
||||
// check intents: https://discord.com/developers/docs/topics/gateway#gateway-intents
|
||||
switch (document.event) {
|
||||
case "GUILD_CREATE":
|
||||
case "GUILD_DELETE":
|
||||
case "GUILD_UPDATE":
|
||||
case "GUILD_ROLE_CREATE":
|
||||
case "GUILD_ROLE_UPDATE":
|
||||
case "GUILD_ROLE_DELETE":
|
||||
case "CHANNEL_CREATE":
|
||||
case "CHANNEL_DELETE":
|
||||
case "CHANNEL_UPDATE":
|
||||
// gets sent if GUILDS intent is set (already checked in if document.guild_id)
|
||||
break;
|
||||
case "GUILD_INTEGRATIONS_UPDATE":
|
||||
if (!this.intents.has("GUILD_INTEGRATIONS")) return;
|
||||
break;
|
||||
case "WEBHOOKS_UPDATE":
|
||||
if (!this.intents.has("GUILD_WEBHOOKS")) return;
|
||||
break;
|
||||
case "GUILD_EMOJI_UPDATE":
|
||||
if (!this.intents.has("GUILD_EMOJIS")) return;
|
||||
break;
|
||||
// only send them, if the user subscribed for this part of the member list, or is a bot
|
||||
case "GUILD_MEMBER_ADD":
|
||||
case "GUILD_MEMBER_REMOVE":
|
||||
case "GUILD_MEMBER_UPDATE":
|
||||
if (!this.intents.has("GUILD_MEMBERS")) return;
|
||||
break;
|
||||
case "VOICE_STATE_UPDATE":
|
||||
if (!this.intents.has("GUILD_VOICE_STATES")) return;
|
||||
break;
|
||||
case "GUILD_BAN_ADD":
|
||||
case "GUILD_BAN_REMOVE":
|
||||
if (!this.intents.has("GUILD_BANS")) return;
|
||||
break;
|
||||
case "INVITE_CREATE":
|
||||
case "INVITE_DELETE":
|
||||
if (!this.intents.has("GUILD_INVITES")) return;
|
||||
case "PRESENCE_UPDATE":
|
||||
if (!this.intents.has("GUILD_PRESENCES")) return;
|
||||
break;
|
||||
case "MESSAGE_CREATE":
|
||||
case "MESSAGE_DELETE":
|
||||
case "MESSAGE_DELETE_BULK":
|
||||
case "MESSAGE_UPDATE":
|
||||
case "CHANNEL_PINS_UPDATE":
|
||||
if (!this.intents.has("GUILD_MESSAGES") && document.guild_id) return;
|
||||
if (!this.intents.has("DIRECT_MESSAGES") && !document.guild_id) return;
|
||||
break;
|
||||
case "MESSAGE_REACTION_ADD":
|
||||
case "MESSAGE_REACTION_REMOVE":
|
||||
case "MESSAGE_REACTION_REMOVE_ALL":
|
||||
case "MESSAGE_REACTION_REMOVE_EMOJI":
|
||||
if (!this.intents.has("GUILD_MESSAGE_REACTIONS") && document.guild_id) return;
|
||||
if (!this.intents.has("DIRECT_MESSAGE_REACTIONS") && !document.guild_id) return;
|
||||
break;
|
||||
|
||||
case "TYPING_START":
|
||||
if (!this.intents.has("GUILD_MESSAGE_TYPING") && document.guild_id) return;
|
||||
if (!this.intents.has("DIRECT_MESSAGE_TYPING") && !document.guild_id) return;
|
||||
break;
|
||||
case "READY":
|
||||
case "USER_UPDATE":
|
||||
case "APPLICATION_COMMAND_CREATE":
|
||||
case "APPLICATION_COMMAND_DELETE":
|
||||
case "APPLICATION_COMMAND_UPDATE":
|
||||
default:
|
||||
// Any events not defined in an intent are considered "passthrough" and will always be sent to you.
|
||||
break;
|
||||
}
|
||||
|
||||
// check permissions
|
||||
switch (document.event) {
|
||||
case "GUILD_INTEGRATIONS_UPDATE":
|
||||
if (!permission.has("MANAGE_GUILD")) return;
|
||||
break;
|
||||
case "WEBHOOKS_UPDATE":
|
||||
if (!permission.has("MANAGE_WEBHOOKS")) return;
|
||||
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
|
||||
break;
|
||||
case "GUILD_BAN_ADD":
|
||||
case "GUILD_BAN_REMOVE":
|
||||
if (!permission.has("BAN_MEMBERS")) break;
|
||||
break;
|
||||
case "INVITE_CREATE":
|
||||
case "INVITE_DELETE":
|
||||
if (!permission.has("MANAGE_GUILD")) break;
|
||||
case "PRESENCE_UPDATE":
|
||||
break;
|
||||
case "VOICE_STATE_UPDATE":
|
||||
case "MESSAGE_CREATE":
|
||||
case "MESSAGE_DELETE":
|
||||
case "MESSAGE_DELETE_BULK":
|
||||
case "MESSAGE_UPDATE":
|
||||
case "CHANNEL_PINS_UPDATE":
|
||||
case "MESSAGE_REACTION_ADD":
|
||||
case "MESSAGE_REACTION_REMOVE":
|
||||
case "MESSAGE_REACTION_REMOVE_ALL":
|
||||
case "MESSAGE_REACTION_REMOVE_EMOJI":
|
||||
case "TYPING_START":
|
||||
// only gets send if the user is alowed to view the current channel
|
||||
if (!permission.has("VIEW_CHANNEL")) return;
|
||||
break;
|
||||
case "GUILD_CREATE":
|
||||
case "GUILD_DELETE":
|
||||
case "GUILD_UPDATE":
|
||||
case "GUILD_ROLE_CREATE":
|
||||
case "GUILD_ROLE_UPDATE":
|
||||
case "GUILD_ROLE_DELETE":
|
||||
case "CHANNEL_CREATE":
|
||||
case "CHANNEL_DELETE":
|
||||
case "CHANNEL_UPDATE":
|
||||
case "GUILD_EMOJI_UPDATE":
|
||||
case "READY":
|
||||
case "USER_UPDATE":
|
||||
case "APPLICATION_COMMAND_CREATE":
|
||||
case "APPLICATION_COMMAND_DELETE":
|
||||
case "APPLICATION_COMMAND_UPDATE":
|
||||
default:
|
||||
// always gets sent
|
||||
// Any events not defined in an intent are considered "passthrough" and will always be sent
|
||||
break;
|
||||
}
|
||||
|
||||
return this.emit(document.event, document.data);
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
import { CLOSECODES, Payload } from "../util/Constants";
|
||||
import WebSocket from "../util/WebSocket";
|
||||
import { checkToken } from "fosscord-server-util";
|
||||
import { checkToken, Intents } from "fosscord-server-util";
|
||||
import { setupListener } from "../listener/listener";
|
||||
import { instanceOf } from "lambert-server";
|
||||
import { IdentifySchema } from "../schema/Identify";
|
||||
// TODO: check priviliged intents
|
||||
|
||||
export async function onIdentify(this: WebSocket, data: Payload) {
|
||||
try {
|
||||
@ -14,6 +15,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
||||
|
||||
var decoded = await checkToken(identify.token);
|
||||
this.userid = decoded.id;
|
||||
this.intents = new Intents(identify.intents);
|
||||
|
||||
await setupListener.call(this);
|
||||
} catch (error) {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Intents } from "fosscord-server-util";
|
||||
import WS, { Server, Data } from "ws";
|
||||
|
||||
interface WebSocket extends WS {
|
||||
@ -7,6 +8,7 @@ interface WebSocket extends WS {
|
||||
compress?: "zlib-stream";
|
||||
heartbeatTimeout: NodeJS.Timeout;
|
||||
readyTimeout: NodeJS.Timeout;
|
||||
intents: Intents;
|
||||
}
|
||||
|
||||
export default WebSocket;
|
||||
|
Loading…
x
Reference in New Issue
Block a user