diff --git a/gateway/src/events/Close.ts b/gateway/src/events/Close.ts
index d68fc751..b4fed316 100644
--- a/gateway/src/events/Close.ts
+++ b/gateway/src/events/Close.ts
@@ -3,6 +3,7 @@ import { Message } from "./Message";
import { Session } from "@fosscord/util";
export async function Close(this: WebSocket, code: number, reason: string) {
+ console.log("[WebSocket] closed", code, reason);
await Session.delete({ session_id: this.session_id });
// @ts-ignore
this.off("message", Message);
diff --git a/gateway/src/listener/listener.ts b/gateway/src/listener/listener.ts
index 67837e8d..0b6fa50c 100644
--- a/gateway/src/listener/listener.ts
+++ b/gateway/src/listener/listener.ts
@@ -26,15 +26,20 @@ import { Recipient } from "../../../util/dist/entities/Recipient";
// TODO: use already queried guilds/channels of Identify and don't fetch them again
export async function setupListener(this: WebSocket) {
- const members = await Member.find({ user_id: this.user_id });
+ const members = await Member.find({ id: this.user_id });
const guild_ids = members.map((x) => x.guild_id);
const user = await User.findOneOrFail({ id: this.user_id });
- const recipients = await Recipient.find({ where: { id: this.user_id }, relations: ["channel"] });
+ const recipients = await Recipient.find({
+ where: { user_id: this.user_id },
+ relations: ["channel"],
+ });
const channels = await Channel.find({ guild_id: In(guild_ids) });
const dm_channels = recipients.map((x) => x.channel);
const guild_channels = channels.filter((x) => x.guild_id);
- const opts: { acknowledge: boolean; channel?: AMQChannel } = { acknowledge: true };
+ const opts: { acknowledge: boolean; channel?: AMQChannel } = {
+ acknowledge: true,
+ };
const consumer = consume.bind(this);
if (RabbitMQ.connection) {
@@ -58,13 +63,25 @@ export async function setupListener(this: WebSocket) {
this.listeners;
this.events[guild] = await listenEvent(guild, consumer, opts);
- for (const channel of guild_channels.filter((c) => c.guild_id === guild)) {
- if (x.overwriteChannel(channel.permission_overwrites).has("VIEW_CHANNEL")) {
- this.events[channel.id] = await listenEvent(channel.id, consumer, opts);
+ for (const channel of guild_channels.filter(
+ (c) => c.guild_id === guild
+ )) {
+ if (
+ x
+ .overwriteChannel(channel.permission_overwrites)
+ .has("VIEW_CHANNEL")
+ ) {
+ this.events[channel.id] = await listenEvent(
+ channel.id,
+ consumer,
+ opts
+ );
}
}
})
- .catch((e) => console.log("couldn't get permission for guild " + guild, e));
+ .catch((e) =>
+ console.log("couldn't get permission for guild " + guild, e)
+ );
}
this.once("close", () => {
@@ -91,7 +108,12 @@ async function consume(this: WebSocket, opts: EventOpts) {
opts.cancel();
break;
case "CHANNEL_CREATE":
- if (!permission.overwriteChannel(data.permission_overwrites).has("VIEW_CHANNEL")) return;
+ if (
+ !permission
+ .overwriteChannel(data.permission_overwrites)
+ .has("VIEW_CHANNEL")
+ )
+ return;
// TODO: check if user has permission to channel
case "GUILD_CREATE":
this.events[id] = await listenEvent(id, consumer, listenOpts);
@@ -99,7 +121,11 @@ async function consume(this: WebSocket, opts: EventOpts) {
case "CHANNEL_UPDATE":
const exists = this.events[id];
// @ts-ignore
- if (permission.overwriteChannel(data.permission_overwrites).has("VIEW_CHANNEL")) {
+ if (
+ permission
+ .overwriteChannel(data.permission_overwrites)
+ .has("VIEW_CHANNEL")
+ ) {
if (exists) break;
this.events[id] = await listenEvent(id, consumer, listenOpts);
} else {
diff --git a/gateway/src/opcodes/Identify.ts b/gateway/src/opcodes/Identify.ts
index 73c9a29e..2b2c31c5 100644
--- a/gateway/src/opcodes/Identify.ts
+++ b/gateway/src/opcodes/Identify.ts
@@ -57,8 +57,16 @@ export async function onIdentify(this: WebSocket, data: Payload) {
}
const members = await Member.find({
- where: { user_id: this.user_id },
- relations: ["guild", "guild.channels", "guild.emojis", "guild.roles", "guild.stickers", "user", "roles"],
+ where: { id: this.user_id },
+ relations: [
+ "guild",
+ "guild.channels",
+ "guild.emojis",
+ "guild.roles",
+ "guild.stickers",
+ "user",
+ "roles",
+ ],
});
const merged_members = members.map((x: any) => {
return [x];
@@ -67,7 +75,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
const user_guild_settings_entries = members.map((x) => x.settings);
const recipients = await Recipient.find({
- where: { id: this.user_id },
+ where: { user_id: this.user_id },
relations: ["channel", "channel.recipients"],
});
const channels = recipients.map((x) => x.channel);
diff --git a/gateway/src/opcodes/LazyRequest.ts b/gateway/src/opcodes/LazyRequest.ts
index 146175b5..e035e6bb 100644
--- a/gateway/src/opcodes/LazyRequest.ts
+++ b/gateway/src/opcodes/LazyRequest.ts
@@ -1,13 +1,19 @@
-// @ts-nocheck WIP
-import { db, getPermission, PublicUserProjection, toObject } from "@fosscord/util";
+import {
+ getPermission,
+ Member,
+ PublicMemberProjection,
+ PublicUserProjection,
+ Role,
+} from "@fosscord/util";
import { LazyRequest } from "../schema/LazyRequest";
import { OPCODES, Payload } from "../util/Constants";
import { Send } from "../util/Send";
import WebSocket from "../util/WebSocket";
import { check } from "./instanceOf";
+import "missing-native-js-functions";
// TODO: check permission and only show roles/members that have access to this channel
-// TODO: config: if want to list all members (even those who are offline) sorted by role, or just those who are online
+// TODO: config: to list all members (even those who are offline) sorted by role, or just those who are online
// TODO: rewrite typeorm
export async function onLazyRequest(this: WebSocket, { d }: Payload) {
@@ -18,60 +24,43 @@ export async function onLazyRequest(this: WebSocket, { d }: Payload) {
const permissions = await getPermission(this.user_id, guild_id);
permissions.hasThrow("VIEW_CHANNEL");
- // MongoDB query to retrieve all hoisted roles and join them with the members and users collection
- const roles = await db
- .collection("roles")
- .aggregate([
- {
- $match: {
- guild_id,
- // hoist: true // TODO: also match @everyone role
- },
- },
- { $sort: { position: 1 } },
- {
- $lookup: {
- from: "members",
- let: { id: "$id" },
- pipeline: [
- { $match: { $expr: { $in: ["$$id", "$roles"] } } },
- { $limit: 100 },
- {
- $lookup: {
- from: "users",
- let: { user_id: "$id" },
- pipeline: [
- { $match: { $expr: { $eq: ["$id", "$$user_id"] } } },
- { $project: PublicUserProjection },
- ],
- as: "user",
- },
- },
- {
- $unwind: "$user",
- },
- ],
- as: "members",
- },
- },
- ])
- .toArray();
+ var members = await Member.find({
+ where: { guild_id: guild_id },
+ relations: ["roles", "user"],
+ select: PublicMemberProjection,
+ });
+
+ const roles = await Role.find({
+ where: { guild_id: guild_id },
+ order: {
+ position: "ASC",
+ },
+ });
- 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 groups = [] as any[];
+ var member_count = 0;
const items = [];
for (const role of roles) {
- items.push({
- group: {
- count: role.members.length,
- id: role.id === guild_id ? "online" : role.name,
- },
- });
- for (const member of role.members) {
- member.roles.remove(guild_id);
- items.push({ member });
+ const [role_members, other_members] = members.partition((m) =>
+ m.roles.find((r) => r.id === role.id)
+ );
+ const group = {
+ count: role_members.length,
+ id: role.id === guild_id ? "online" : role.name,
+ };
+
+ items.push({ group });
+ groups.push(group);
+
+ for (const member of role_members) {
+ member.roles = member.roles.filter((x) => x.id !== guild_id);
+ items.push({
+ member: { ...member, roles: member.roles.map((x) => x.id) },
+ });
}
+ members = other_members;
+ member_count += role_members.length;
}
return Send(this, {
|