mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-11 13:14:06 +01:00
✨ Member List
This commit is contained in:
parent
671091a13f
commit
e434334a21
14
package-lock.json
generated
14
package-lock.json
generated
@ -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",
|
||||||
|
@ -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",
|
||||||
|
@ -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: {
|
||||||
|
@ -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":
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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[],
|
||||||
};
|
};
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user