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
95
|
import {
getPermission,
Member,
PublicMemberProjection,
Role,
} from "@fosscord/util";
import { LazyRequest } from "../schema/LazyRequest";
import { Send } from "../util/Send";
import { OPCODES } from "../util/Constants";
import { WebSocket, Payload } from "@fosscord/gateway";
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: 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) {
// 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);
permissions.hasThrow("VIEW_CHANNEL");
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: "DESC",
},
});
const groups = [] as any[];
var member_count = 0;
const items = [];
for (const role of roles) {
const [role_members, other_members] = partition(members, (m: Member) =>
m.roles.find((r) => r.id === role.id)
);
const group = {
count: role_members.length,
id: role.id === guild_id ? "online" : role.id,
};
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, {
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,
},
});
}
function partition<T>(array: T[], isValid: Function) {
return array.reduce(
([pass, fail], elem) => {
return isValid(elem)
? [[...pass, elem], fail]
: [pass, [...fail, elem]];
},
[[], []]
);
}
|