summary refs log tree commit diff
path: root/src/opcodes/LazyRequest.ts
blob: bf7e7f8ea0f67f803fbc5bfcae8fa8f19b4bf7ab (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
// @ts-nocheck WIP
import { db, getPermission, MemberModel, MongooseCache, PublicUserProjection, RoleModel, toObject } from "@fosscord/server-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";

// 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

export async function onLazyRequest(this: WebSocket, { d }: Payload) {
    // TODO: check data
    check.call(this, LazyRequest, d);
    const { guild_id, typing, channels, activities } = d as LazyRequest;

    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
    const roles = toObject(
        await db
            .collection("roles")
            .aggregate([
                {
                    $match: {
                        guild_id
                        // id: { $ne: 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()
    );

    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 === guild_id ? "online" : role.name
            }
        });
        for (const member of role.members) {
            member.roles.remove(guild_id);
            items.push({ member });
        }
    }

    return Send(this, {
        op: OPCODES.Dispatch,
        s: this.sequence++,
        t: "GUILD_MEMBER_LIST_UPDATE",
        d: {
            ops: [
                {
                    range: [0, 99],
                    op: "SYNC",
                    items
                }
            ],
            online_count: member_count, // TODO count online count
            member_count,
            id: "everyone",
            guild_id,
            groups
        }
    });
}