✨ 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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Flam3rboy
						Flam3rboy