mirror of
https://github.com/spacebarchat/server.git
synced 2024-11-22 10:22:39 +01:00
attempt to implement requestguildmembers
This commit is contained in:
parent
c4701a3299
commit
8313367fdb
4226
assets/schemas.json
4226
assets/schemas.json
File diff suppressed because it is too large
Load Diff
@ -82,6 +82,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
|
|||||||
const identify: IdentifySchema = data.d;
|
const identify: IdentifySchema = data.d;
|
||||||
|
|
||||||
this.capabilities = new Capabilities(identify.capabilities || 0);
|
this.capabilities = new Capabilities(identify.capabilities || 0);
|
||||||
|
this.large_threshold = identify.large_threshold || 250;
|
||||||
|
|
||||||
const user = await tryGetUserFromToken(identify.token, {
|
const user = await tryGetUserFromToken(identify.token, {
|
||||||
relations: ["relationships", "relationships.to", "settings"],
|
relations: ["relationships", "relationships.to", "settings"],
|
||||||
|
@ -16,8 +16,128 @@
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { WebSocket } from "@spacebar/gateway";
|
import { OPCODES, Payload, Send, WebSocket } from "@spacebar/gateway";
|
||||||
|
import { Member, RequestGuildMembersSchema, getDatabase } from "@spacebar/util";
|
||||||
|
import { check } from "./instanceOf";
|
||||||
|
|
||||||
export function onRequestGuildMembers(this: WebSocket) {
|
function partition(members: Member[], size: number) {
|
||||||
// return this.close(CLOSECODES.Unknown_error);
|
const chunks = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < members.length; i += size) {
|
||||||
|
chunks.push(members.slice(i, i + size));
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function onRequestGuildMembers(this: WebSocket, { d }: Payload) {
|
||||||
|
check.call(this, RequestGuildMembersSchema, d);
|
||||||
|
|
||||||
|
const { guild_id, query, limit, presences, user_ids, nonce } =
|
||||||
|
d as RequestGuildMembersSchema;
|
||||||
|
|
||||||
|
if (query && user_ids) {
|
||||||
|
throw new Error("Cannot query and provide user ids");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (query && !limit) {
|
||||||
|
throw new Error("Must provide limit when querying");
|
||||||
|
}
|
||||||
|
|
||||||
|
const takeLimit =
|
||||||
|
(query && query !== "") || user_ids
|
||||||
|
? limit && limit !== 0 && limit <= 1000
|
||||||
|
? limit
|
||||||
|
: 100
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const member_count = await Member.count({
|
||||||
|
where: {
|
||||||
|
guild_id,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: if member count is >75k, only return members in voice plus the connecting users member object
|
||||||
|
// TODO: if member count is >large_threshold, send members who are online, have a role, have a nickname, or are in a voice channel
|
||||||
|
// TODO: if member count is <large_threshold, send all members
|
||||||
|
|
||||||
|
let members: Member[] = [];
|
||||||
|
|
||||||
|
if (member_count > 75000) {
|
||||||
|
// since we dont have voice channels yet, just return the connecting users member object
|
||||||
|
members = await Member.find({
|
||||||
|
where: {
|
||||||
|
guild_id,
|
||||||
|
user: {
|
||||||
|
id: this.user_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
relations: ["user", "roles"],
|
||||||
|
});
|
||||||
|
} else if (member_count > this.large_threshold) {
|
||||||
|
try {
|
||||||
|
// find all members who are online, have a role, have a nickname, or are in a voice channel, as well as respecting the query and user_ids
|
||||||
|
const db = getDatabase();
|
||||||
|
if (!db) throw new Error("Database not initialized");
|
||||||
|
const repo = db.getRepository(Member);
|
||||||
|
const q = repo
|
||||||
|
.createQueryBuilder("member")
|
||||||
|
.where("member.guild_id = :guild_id", { guild_id })
|
||||||
|
.leftJoinAndSelect("member.roles", "role")
|
||||||
|
.leftJoinAndSelect("member.user", "user")
|
||||||
|
.leftJoinAndSelect("user.sessions", "session")
|
||||||
|
.andWhere(
|
||||||
|
`',' || member.roles || ',' NOT LIKE :everyoneRoleIdList`,
|
||||||
|
{ everyoneRoleIdList: `%,${guild_id},%` },
|
||||||
|
)
|
||||||
|
.andWhere("session.status != 'offline'")
|
||||||
|
.addOrderBy("user.username", "ASC")
|
||||||
|
.limit(takeLimit);
|
||||||
|
|
||||||
|
if (query && query !== "") {
|
||||||
|
q.andWhere(`user.username ILIKE :query`, {
|
||||||
|
query: `${query}%`,
|
||||||
|
});
|
||||||
|
} else if (user_ids) {
|
||||||
|
q.andWhere(`user.id IN (:...user_ids)`, { user_ids });
|
||||||
|
}
|
||||||
|
|
||||||
|
members = await q.getMany();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(`request guild members`, e);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
members = await Member.find({
|
||||||
|
where: {
|
||||||
|
guild_id,
|
||||||
|
...(user_ids && { user_id: user_ids }),
|
||||||
|
...(query && { username: { startsWith: query } }),
|
||||||
|
},
|
||||||
|
take: takeLimit,
|
||||||
|
relations: ["user", "roles"],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const chunks = partition(members, 1000);
|
||||||
|
|
||||||
|
for (const [i, chunk] of chunks.entries()) {
|
||||||
|
await Send(this, {
|
||||||
|
op: OPCODES.Dispatch,
|
||||||
|
s: this.sequence++,
|
||||||
|
t: "GUILD_MEMBERS_CHUNK",
|
||||||
|
d: {
|
||||||
|
guild_id,
|
||||||
|
members: chunk.map((member) => ({
|
||||||
|
...member,
|
||||||
|
roles: member.roles.map((role) => role.id),
|
||||||
|
user: member.user.toPublicUser(),
|
||||||
|
})),
|
||||||
|
chunk_index: i + 1,
|
||||||
|
chunk_count: chunks.length,
|
||||||
|
// not_found: []
|
||||||
|
// presences: []
|
||||||
|
nonce,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Intents, ListenEventOpts, Permissions } from "@spacebar/util";
|
import { Intents, ListenEventOpts, Permissions } from "@spacebar/util";
|
||||||
import WS from "ws";
|
|
||||||
import { Deflate, Inflate } from "fast-zlib";
|
import { Deflate, Inflate } from "fast-zlib";
|
||||||
|
import WS from "ws";
|
||||||
import { Capabilities } from "./Capabilities";
|
import { Capabilities } from "./Capabilities";
|
||||||
// import { Client } from "@spacebar/webrtc";
|
// import { Client } from "@spacebar/webrtc";
|
||||||
|
|
||||||
@ -43,4 +43,5 @@ export interface WebSocket extends WS {
|
|||||||
listen_options: ListenEventOpts;
|
listen_options: ListenEventOpts;
|
||||||
capabilities?: Capabilities;
|
capabilities?: Capabilities;
|
||||||
// client?: Client;
|
// client?: Client;
|
||||||
|
large_threshold: number;
|
||||||
}
|
}
|
||||||
|
35
src/util/schemas/RequestGuildMembersSchema.ts
Normal file
35
src/util/schemas/RequestGuildMembersSchema.ts
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
Spacebar: A FOSS re-implementation and extension of the Discord.com backend.
|
||||||
|
Copyright (C) 2023 Spacebar and Spacebar Contributors
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published
|
||||||
|
by the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface RequestGuildMembersSchema {
|
||||||
|
guild_id: string;
|
||||||
|
query?: string;
|
||||||
|
limit?: number;
|
||||||
|
presences?: boolean;
|
||||||
|
user_ids?: string[];
|
||||||
|
nonce?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RequestGuildMembersSchema = {
|
||||||
|
guild_id: String,
|
||||||
|
$query: String,
|
||||||
|
$limit: Number,
|
||||||
|
$presences: Boolean,
|
||||||
|
$user_ids: [] as string[],
|
||||||
|
$nonce: String,
|
||||||
|
};
|
@ -58,6 +58,7 @@ export * from "./PurgeSchema";
|
|||||||
export * from "./RegisterSchema";
|
export * from "./RegisterSchema";
|
||||||
export * from "./RelationshipPostSchema";
|
export * from "./RelationshipPostSchema";
|
||||||
export * from "./RelationshipPutSchema";
|
export * from "./RelationshipPutSchema";
|
||||||
|
export * from "./RequestGuildMembersSchema";
|
||||||
export * from "./RoleModifySchema";
|
export * from "./RoleModifySchema";
|
||||||
export * from "./RolePositionUpdateSchema";
|
export * from "./RolePositionUpdateSchema";
|
||||||
export * from "./SelectProtocolSchema";
|
export * from "./SelectProtocolSchema";
|
||||||
|
Loading…
Reference in New Issue
Block a user