forked from stoatchat/javascript-client-sdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathServerMember.ts
More file actions
248 lines (220 loc) · 5.72 KB
/
Copy pathServerMember.ts
File metadata and controls
248 lines (220 loc) · 5.72 KB
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
import type {
DataBanCreate,
DataMemberEdit,
MemberCompositeKey,
Role,
} from "stoat-api";
import type { ServerMemberCollection } from "../collections/ServerMemberCollection.js";
import {
bitwiseAndEq,
calculatePermission,
} from "../permissions/calculator.js";
import { Permission } from "../permissions/definitions.js";
import type { Channel } from "./Channel.js";
import type { File } from "./File.js";
import type { Server } from "./Server.js";
import type { User } from "./User.js";
/**
* Deterministic conversion of member composite key to string ID
* @param key Key
* @returns String key
*/
function key(key: MemberCompositeKey): string {
return key.server + key.user;
}
/**
* Server Member Class
*/
export class ServerMember {
readonly #collection: ServerMemberCollection;
readonly id: MemberCompositeKey;
/**
* Construct Server Member
* @param collection Collection
* @param id Id
*/
constructor(collection: ServerMemberCollection, id: MemberCompositeKey) {
this.#collection = collection;
this.id = id;
}
/**
* Convert to string
* @returns String
*/
toString(): string {
return `<@${this.id.user}>`;
}
/**
* Whether this object exists
*/
get $exists(): boolean {
return !this.#collection.getUnderlyingObject(key(this.id)).id;
}
/**
* Server this member belongs to
*/
get server(): Server | undefined {
return this.#collection.client.servers.get(this.id.server);
}
/**
* User corresponding to this member
*/
get user(): User | undefined {
return this.#collection.client.users.get(this.id.user);
}
/**
* When this user joined the server
*/
get joinedAt(): Date {
return this.#collection.getUnderlyingObject(key(this.id)).joinedAt;
}
/**
* Nickname
*/
get nickname(): string | undefined {
return this.#collection.getUnderlyingObject(key(this.id)).nickname;
}
/**
* Avatar
*/
get avatar(): File | undefined {
return this.#collection.getUnderlyingObject(key(this.id)).avatar;
}
/**
* List of role IDs
*/
get roles(): string[] {
return this.#collection.getUnderlyingObject(key(this.id)).roles;
}
/**
* Time at which timeout expires
*/
get timeout(): Date | undefined {
return this.#collection.getUnderlyingObject(key(this.id)).timeout;
}
/**
* Ordered list of roles for this member, from lowest to highest priority.
*/
get orderedRoles(): (Partial<Omit<Role, 'permissions'> & { permissions: { a: bigint, d: bigint } }> & { id: string })[] {
const server = this.server!;
return (
this.roles
?.map((id) => ({
id,
...server.roles?.get(id),
}))
.sort((a, b) => b.rank! - a.rank!) ?? []
);
}
/**
* Member's currently hoisted role.
*/
get hoistedRole(): Partial<Omit<Role, 'permissions'> & { permissions: { a: bigint, d: bigint } }> | null {
const roles = this.orderedRoles.filter((x) => x.hoist);
if (roles.length > 0) {
return roles[roles.length - 1];
} else {
return null;
}
}
/**
* Member's current role colour.
*/
get roleColour(): string | null | undefined {
const roles = this.orderedRoles.filter((x) => x.colour);
if (roles.length > 0) {
return roles[roles.length - 1].colour;
} else {
return null;
}
}
/**
* Member's ranking
* Smaller values are ranked as higher priority
*/
get ranking(): number {
if (this.id.user === this.server?.ownerId) {
return -Infinity;
}
const roles = this.orderedRoles;
if (roles.length > 0) {
return roles[roles.length - 1].rank!;
} else {
return Infinity;
}
}
/**
* Get the permissions that this member has against a certain object
* @param target Target object to check permissions against
* @returns Permissions that this member has
*/
getPermissions(target: Server | Channel): bigint {
return calculatePermission(this.#collection.client, target, {
member: this,
});
}
/**
* Check whether a member has a certain permission against a certain object
* @param target Target object to check permissions against
* @param permission Permission names to check for
* @returns Whether the member has this permission
*/
hasPermission(
target: Server | Channel,
...permission: (keyof typeof Permission)[]
): boolean {
return bitwiseAndEq(
this.getPermissions(target),
...permission.map((x) => Permission[x]),
);
}
/**
* Checks whether the target member has a higher rank than this member.
* @param target The member to compare against
* @returns Whether this member is inferior to the target
*/
inferiorTo(target: ServerMember): boolean {
return target.ranking < this.ranking;
}
/**
* Display name
*/
get displayName(): string | undefined {
return this.nickname ?? this.user?.displayName;
}
/**
* URL to the member's avatar
*/
get avatarURL(): string | undefined {
return this.avatar?.createFileURL() ?? this.user?.avatarURL;
}
/**
* URL to the member's animated avatar
*/
get animatedAvatarURL(): string | undefined {
return this.avatar?.createFileURL(true) ?? this.user?.animatedAvatarURL;
}
/**
* Edit a member
* @param data Changes
*/
async edit(data: DataMemberEdit): Promise<void> {
await this.#collection.client.api.patch(
`/servers/${this.id.server as ""}/members/${this.id.user as ""}`,
data,
);
}
/**
* Ban this member from the server
* @param options Ban options
*/
async ban(options: DataBanCreate): Promise<void> {
this.server?.banUser(this, options);
}
/**
* Kick this member from the server
*/
async kick(): Promise<void> {
this.server?.kickUser(this);
}
}