1
0
mirror of https://github.com/spacebarchat/server.git synced 2024-09-22 02:31:36 +02:00

Member List

This commit is contained in:
Flam3rboy 2021-05-21 22:16:48 +02:00
parent 671091a13f
commit e434334a21
8 changed files with 112 additions and 63 deletions

14
package-lock.json generated
View File

@ -9,7 +9,7 @@
"version": "1.0.0", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@fosscord/server-util": "^1.0.7", "@fosscord/server-util": "^1.2.1",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"lambert-server": "^1.1.7", "lambert-server": "^1.1.7",
@ -30,9 +30,9 @@
} }
}, },
"node_modules/@fosscord/server-util": { "node_modules/@fosscord/server-util": {
"version": "1.0.7", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.0.7.tgz", "resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.2.1.tgz",
"integrity": "sha512-3vBPCt+lwMS7wk+iRvv+V8qBSnEdNifpPxX97Lfjje/TSWI17Kg29y3BmcGJRC5TwIHTLFtgpNLmZmruhv7ziQ==", "integrity": "sha512-NAAmwDizkjR52O6ZUds+XOH8ydjo///T2EH0scuFF3HtAMjD8Yphgo7+GIKrNt5FfkTR3ma0ycrZLZe0TBE+1A==",
"dependencies": { "dependencies": {
"@types/jsonwebtoken": "^8.5.0", "@types/jsonwebtoken": "^8.5.0",
"@types/mongoose-autopopulate": "^0.10.1", "@types/mongoose-autopopulate": "^0.10.1",
@ -2134,9 +2134,9 @@
}, },
"dependencies": { "dependencies": {
"@fosscord/server-util": { "@fosscord/server-util": {
"version": "1.0.7", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.0.7.tgz", "resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.2.1.tgz",
"integrity": "sha512-3vBPCt+lwMS7wk+iRvv+V8qBSnEdNifpPxX97Lfjje/TSWI17Kg29y3BmcGJRC5TwIHTLFtgpNLmZmruhv7ziQ==", "integrity": "sha512-NAAmwDizkjR52O6ZUds+XOH8ydjo///T2EH0scuFF3HtAMjD8Yphgo7+GIKrNt5FfkTR3ma0ycrZLZe0TBE+1A==",
"requires": { "requires": {
"@types/jsonwebtoken": "^8.5.0", "@types/jsonwebtoken": "^8.5.0",
"@types/mongoose-autopopulate": "^0.10.1", "@types/mongoose-autopopulate": "^0.10.1",

View File

@ -5,16 +5,15 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"start": "npm run build:util && npm run build && node dist/", "start": "npm run build && node dist/",
"build": "npx tsc -b .", "build": "npx tsc -b .",
"build:util": "npx tsc -b ./node_modules/@fosscord/server-util/",
"dev": "tsnd --respawn src/index.ts" "dev": "tsnd --respawn src/index.ts"
}, },
"keywords": [], "keywords": [],
"author": "Fosscord", "author": "Fosscord",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@fosscord/server-util": "^1.0.7", "@fosscord/server-util": "^1.2.1",
"dotenv": "^8.2.0", "dotenv": "^8.2.0",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"lambert-server": "^1.1.7", "lambert-server": "^1.1.7",

View File

@ -6,6 +6,9 @@ import { Server as WebSocketServer } from "ws";
import { Connection } from "./events/Connection"; import { Connection } from "./events/Connection";
import Config from "./util/Config"; import Config from "./util/Config";
// TODO: only listen/start the server if everything got initalized
// https://www.npmjs.com/package/ws use "External HTTP/S server" and listen manually at the end of listen()
var port = Number(process.env.PORT); var port = Number(process.env.PORT);
if (isNaN(port)) port = 3002; if (isNaN(port)) port = 3002;
@ -14,6 +17,7 @@ export class Server {
constructor() { constructor() {
this.ws = new WebSocketServer({ this.ws = new WebSocketServer({
port, port,
maxPayload: 4096, maxPayload: 4096,
// perMessageDeflate: { // perMessageDeflate: {
// zlibDeflateOptions: { // zlibDeflateOptions: {

View File

@ -17,7 +17,7 @@ export interface DispatchOpts {
guilds: Array<string>; guilds: Array<string>;
} }
function getPipeline(this: WebSocket, guilds: string[], channels: string[]) { function getPipeline(this: WebSocket, guilds: string[], channels: string[] = []) {
if (this.shard_count) { if (this.shard_count) {
guilds = guilds.filter((x) => (BigInt(x) >> 22n) % this.shard_count === this.shard_id); guilds = guilds.filter((x) => (BigInt(x) >> 22n) % this.shard_count === this.shard_id);
} }
@ -54,12 +54,7 @@ export async function setupListener(this: WebSocket) {
export async function dispatch(this: WebSocket, document: Event, { eventStream, guilds }: DispatchOpts) { export async function dispatch(this: WebSocket, document: Event, { eventStream, guilds }: DispatchOpts) {
var permission = new Permissions("ADMINISTRATOR"); // default permission for dms var permission = new Permissions("ADMINISTRATOR"); // default permission for dms
console.log("event", document); console.log("event", document);
var channel_id = document.channel_id || document.data?.channel_id;
if (document.guild_id) {
if (!this.intents.has("GUILDS")) return;
const channel_id = document.channel_id || document.data?.channel_id;
permission = await getPermission(this.user_id, document.guild_id, channel_id);
}
if (document.event === "GUILD_CREATE") { if (document.event === "GUILD_CREATE") {
guilds.push(document.data.id); guilds.push(document.data.id);
@ -67,12 +62,19 @@ export async function dispatch(this: WebSocket, document: Event, { eventStream,
} else if (document.event === "GUILD_DELETE") { } else if (document.event === "GUILD_DELETE") {
guilds.remove(document.guild_id); guilds.remove(document.guild_id);
eventStream.changeStream(getPipeline.call(this, guilds)); eventStream.changeStream(getPipeline.call(this, guilds));
} else if (document.event === "CHANNEL_DELETE") channel_id = null;
if (document.guild_id && !this.intents.has("GUILDS")) return;
try {
permission = await getPermission(this.user_id, document.guild_id, channel_id);
} catch (e) {
permission = new Permissions();
} }
// check intents: https://discord.com/developers/docs/topics/gateway#gateway-intents // check intents: https://discord.com/developers/docs/topics/gateway#gateway-intents
switch (document.event) { switch (document.event) {
case "GUILD_CREATE":
case "GUILD_DELETE": case "GUILD_DELETE":
case "GUILD_CREATE":
case "GUILD_UPDATE": case "GUILD_UPDATE":
case "GUILD_ROLE_CREATE": case "GUILD_ROLE_CREATE":
case "GUILD_ROLE_UPDATE": case "GUILD_ROLE_UPDATE":

View File

@ -1,5 +1,13 @@
// @ts-nocheck WIP // @ts-nocheck WIP
import { db, getPermission, MemberModel, MongooseCache, PublicUserProjection, RoleModel } from "@fosscord/server-util"; import {
db,
getPermission,
MemberModel,
MongooseCache,
PublicUserProjection,
RoleModel,
toObject,
} from "@fosscord/server-util";
import { LazyRequest } from "../schema/LazyRequest"; import { LazyRequest } from "../schema/LazyRequest";
import { OPCODES, Payload } from "../util/Constants"; import { OPCODES, Payload } from "../util/Constants";
import { Send } from "../util/Send"; import { Send } from "../util/Send";
@ -9,7 +17,6 @@ import { check } from "./instanceOf";
// TODO: config: if want to list all members (even those who are offline) sorted by role, or just those who are online // TODO: config: if want to list all members (even those who are offline) sorted by role, or just those who are online
export async function onLazyRequest(this: WebSocket, { d }: Payload) { export async function onLazyRequest(this: WebSocket, { d }: Payload) {
return; // WIP
// TODO: check data // TODO: check data
check.call(this, LazyRequest, d); check.call(this, LazyRequest, d);
const { guild_id, typing, channels, activities } = d as LazyRequest; const { guild_id, typing, channels, activities } = d as LazyRequest;
@ -17,37 +24,63 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
const permissions = await getPermission(this.user_id, guild_id); const permissions = await getPermission(this.user_id, guild_id);
// MongoDB query to retrieve all hoisted roles and join them with the members and users collection // MongoDB query to retrieve all hoisted roles and join them with the members and users collection
const roles = await db const roles = toObject(
.collection("roles") await db
.aggregate([ .collection("roles")
{ $match: { guild_id, hoist: true } }, .aggregate([
{ $sort: { position: 1 } }, {
{ $match: {
$lookup: { guild_id,
from: "members", // hoist: true // TODO: also match @everyone role
let: { id: "$id" }, },
pipeline: [
{ $match: { $expr: { $in: ["$$id", "$roles"] } } },
{ $limit: 1 },
{
$lookup: {
from: "users",
let: { user_id: "$id" },
pipeline: [
{ $match: { $expr: { $eq: ["$id", "$$user_id"] } } },
{ $project: PublicUserProjection },
],
as: "user",
},
},
],
as: "members",
}, },
}, { $sort: { position: 1 } },
]) {
.toArray(); $lookup: {
from: "members",
let: { id: "$id" },
pipeline: [
{ $match: { $expr: { $in: ["$$id", "$roles"] } } },
{ $limit: 1 },
{
$lookup: {
from: "users",
let: { user_id: "$id" },
pipeline: [
{ $match: { $expr: { $eq: ["$id", "$$user_id"] } } },
{ $project: PublicUserProjection },
],
as: "user",
},
},
{
$unwind: "$user",
},
],
as: "members",
},
},
])
.toArray()
);
Send(this, { const groups = roles.map((x) => ({ id: x.id === guild_id ? "online" : x.id, count: x.members.length }));
const member_count = roles.reduce((a, b) => b.members.length + a, 0);
const items = [];
for (const role of roles) {
items.push({
group: {
count: role.members.length,
id: role.id,
},
});
for (const member of role.members) {
items.push({ member });
}
}
return Send(this, {
op: OPCODES.Dispatch, op: OPCODES.Dispatch,
s: this.sequence++, s: this.sequence++,
t: "GUILD_MEMBER_LIST_UPDATE", t: "GUILD_MEMBER_LIST_UPDATE",
@ -56,14 +89,14 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
{ {
range: [0, 99], range: [0, 99],
op: "SYNC", op: "SYNC",
items: [{ group: { id: "online", count: 0 } }], items: items,
}, },
], ],
online_count: 1, online_count: member_count, // TODO count online count
member_count: 1, member_count,
id: "everyone", id: "everyone",
guild_id, guild_id,
groups: [{ id: "online", count: 1 }], groups,
}, },
}); });
} }

View File

@ -1,7 +1,14 @@
import { CLOSECODES, Payload } from "../util/Constants"; import { CLOSECODES, Payload } from "../util/Constants";
import { Send } from "../util/Send";
import WebSocket from "../util/WebSocket"; import WebSocket from "../util/WebSocket";
export function onResume(this: WebSocket, data: Payload) { export async function onResume(this: WebSocket, data: Payload) {
return this.close(CLOSECODES.Invalid_session); console.log("Got Resume -> cancel not implemented");
await Send(this, {
op: 9,
d: false,
});
// return this.close(CLOSECODES.Invalid_session);
} }

View File

@ -1,15 +1,17 @@
export interface LazyRequest { export interface LazyRequest {
activities: boolean;
channels: Record<string, [number, number]>;
guild_id: string; guild_id: string;
threads: boolean; channels?: Record<string, [number, number]>;
typing: true; activities?: boolean;
threads?: boolean;
typing?: true;
members?: any[];
} }
export const LazyRequest = { export const LazyRequest = {
activities: Boolean,
channels: Object,
guild_id: String, guild_id: String,
threads: Boolean, $activities: Boolean,
typing: Boolean, $channels: Object,
$typing: Boolean,
$threads: Boolean,
$members: [] as any[],
}; };

View File

@ -3,6 +3,7 @@ export const VoiceStateUpdateSchema = {
channel_id: String, channel_id: String,
self_mute: Boolean, self_mute: Boolean,
self_deaf: Boolean, self_deaf: Boolean,
self_video: Boolean,
}; };
export interface VoiceStateUpdateSchema { export interface VoiceStateUpdateSchema {
@ -10,4 +11,5 @@ export interface VoiceStateUpdateSchema {
channel_id: string; channel_id: string;
self_mute: boolean; self_mute: boolean;
self_deaf: boolean; self_deaf: boolean;
self_video: boolean;
} }