-
Notifications
You must be signed in to change notification settings - Fork 145
/
Role.lua
383 lines (337 loc) · 8.92 KB
/
Role.lua
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
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
--[=[
@c Role x Snowflake
@d Represents a Discord guild role, which is used to assign priority, permissions,
and a color to guild members.
]=]
local json = require('json')
local Snowflake = require('containers/abstract/Snowflake')
local Color = require('utils/Color')
local Permissions = require('utils/Permissions')
local Resolver = require('client/Resolver')
local FilteredIterable = require('iterables/FilteredIterable')
local format = string.format
local insert, sort = table.insert, table.sort
local min, max, floor = math.min, math.max, math.floor
local huge = math.huge
local Role, get = require('class')('Role', Snowflake)
function Role:__init(data, parent)
Snowflake.__init(self, data, parent)
self.client._role_map[self._id] = parent
end
function Role:_modify(payload)
local data, err = self.client._api:modifyGuildRole(self._parent._id, self._id, payload)
if data then
self:_load(data)
return true
else
return false, err
end
end
--[=[
@m delete
@t http
@r boolean
@d Permanently deletes the role. This cannot be undone!
]=]
function Role:delete()
local data, err = self.client._api:deleteGuildRole(self._parent._id, self._id)
if data then
local cache = self._parent._roles
if cache then
cache:_delete(self._id)
end
return true
else
return false, err
end
end
local function sorter(a, b)
if a.position == b.position then
return tonumber(a.id) < tonumber(b.id)
else
return a.position < b.position
end
end
local function getSortedRoles(self)
local guild = self._parent
local id = self._parent._id
local ret = {}
for role in guild.roles:iter() do
if role._id ~= id then
insert(ret, {id = role._id, position = role._position})
end
end
sort(ret, sorter)
return ret
end
local function setSortedRoles(self, roles)
local id = self._parent._id
insert(roles, {id = id, position = 0})
local data, err = self.client._api:modifyGuildRolePositions(id, roles)
if data then
return true
else
return false, err
end
end
--[=[
@m moveDown
@t http
@p n number
@r boolean
@d Moves a role down its list. The parameter `n` indicates how many spaces the
role should be moved, clamped to the lowest position, with a default of 1 if
it is omitted. This will also normalize the positions of all roles. Note that
the default everyone role cannot be moved.
]=]
function Role:moveDown(n) -- TODO: fix attempt to move roles that cannot be moved
n = tonumber(n) or 1
if n < 0 then
return self:moveDown(-n)
end
local roles = getSortedRoles(self)
local new = huge
for i = #roles, 1, -1 do
local v = roles[i]
if v.id == self._id then
new = max(1, i - floor(n))
v.position = new
elseif i >= new then
v.position = i + 1
else
v.position = i
end
end
return setSortedRoles(self, roles)
end
--[=[
@m moveUp
@t http
@p n number
@r boolean
@d Moves a role up its list. The parameter `n` indicates how many spaces the
role should be moved, clamped to the highest position, with a default of 1 if
it is omitted. This will also normalize the positions of all roles. Note that
the default everyone role cannot be moved.
]=]
function Role:moveUp(n) -- TODO: fix attempt to move roles that cannot be moved
n = tonumber(n) or 1
if n < 0 then
return self:moveUp(-n)
end
local roles = getSortedRoles(self)
local new = -huge
for i = 1, #roles do
local v = roles[i]
if v.id == self._id then
new = min(i + floor(n), #roles)
v.position = new
elseif i <= new then
v.position = i - 1
else
v.position = i
end
end
return setSortedRoles(self, roles)
end
--[=[
@m setName
@t http
@p name string
@r boolean
@d Sets the role's name. The name must be between 1 and 100 characters in length.
]=]
function Role:setName(name)
return self:_modify({name = name or json.null})
end
--[=[
@m setColor
@t http
@p color Color-Resolvable
@r boolean
@d Sets the role's display color.
]=]
function Role:setColor(color)
color = color and Resolver.color(color)
return self:_modify({color = color or json.null})
end
--[=[
@m setPermissions
@t http
@p permissions Permissions-Resolvable
@r boolean
@d Sets the permissions that this role explicitly allows.
]=]
function Role:setPermissions(permissions)
permissions = permissions and Resolver.permissions(permissions)
return self:_modify({permissions = permissions or json.null})
end
--[=[
@m hoist
@t http
@r boolean
@d Causes members with this role to display above unhoisted roles in the member
list.
]=]
function Role:hoist()
return self:_modify({hoist = true})
end
--[=[
@m unhoist
@t http
@r boolean
@d Causes member with this role to display amongst other unhoisted members.
]=]
function Role:unhoist()
return self:_modify({hoist = false})
end
--[=[
@m enableMentioning
@t http
@r boolean
@d Allows anyone to mention this role in text messages.
]=]
function Role:enableMentioning()
return self:_modify({mentionable = true})
end
--[=[
@m disableMentioning
@t http
@r boolean
@d Disallows anyone to mention this role in text messages.
]=]
function Role:disableMentioning()
return self:_modify({mentionable = false})
end
--[=[
@m enablePermissions
@t http
@p ... Permission-Resolvables
@r boolean
@d Enables individual permissions for this role. This does not necessarily fully
allow the permissions.
]=]
function Role:enablePermissions(...)
local permissions = self:getPermissions()
permissions:enable(...)
return self:setPermissions(permissions)
end
--[=[
@m disablePermissions
@t http
@p ... Permission-Resolvables
@r boolean
@d Disables individual permissions for this role. This does not necessarily fully
disallow the permissions.
]=]
function Role:disablePermissions(...)
local permissions = self:getPermissions()
permissions:disable(...)
return self:setPermissions(permissions)
end
--[=[
@m enableAllPermissions
@t http
@r boolean
@d Enables all permissions for this role. This does not necessarily fully
allow the permissions.
]=]
function Role:enableAllPermissions()
local permissions = self:getPermissions()
permissions:enableAll()
return self:setPermissions(permissions)
end
--[=[
@m disableAllPermissions
@t http
@r boolean
@d Disables all permissions for this role. This does not necessarily fully
disallow the permissions.
]=]
function Role:disableAllPermissions()
local permissions = self:getPermissions()
permissions:disableAll()
return self:setPermissions(permissions)
end
--[=[
@m getColor
@t mem
@r Color
@d Returns a color object that represents the role's display color.
]=]
function Role:getColor()
return Color(self._color)
end
--[=[
@m getPermissions
@t mem
@r Permissions
@d Returns a permissions object that represents the permissions that this role
has enabled.
]=]
function Role:getPermissions()
return Permissions(self._permissions_new or self._permissions)
end
--[=[@p hoisted boolean Whether members with this role should be shown separated from other members
in the guild member list.]=]
function get.hoisted(self)
return self._hoist
end
--[=[@p mentionable boolean Whether this role can be mentioned in a text channel message.]=]
function get.mentionable(self)
return self._mentionable
end
--[=[@p managed boolean Whether this role is managed by some integration or bot inclusion.]=]
function get.managed(self)
return self._managed
end
--[=[@p name string The name of the role. This should be between 1 and 100 characters in length.]=]
function get.name(self)
return self._name
end
--[=[@p position number The position of the role, where 0 is the lowest.]=]
function get.position(self)
return self._position
end
--[=[@p color number Represents the display color of the role as a decimal value.]=]
function get.color(self)
return self._color
end
--[=[@p permissions number Represents the total permissions of the role as a decimal value.]=]
function get.permissions(self)
return tonumber(self._permissions_new) or tonumber(self._permissions)
end
--[=[@p mentionString string A string that, when included in a message content, may resolve as a role
notification in the official Discord client.]=]
function get.mentionString(self)
return format('<@&%s>', self._id)
end
--[=[@p guild Guild The guild in which this role exists.]=]
function get.guild(self)
return self._parent
end
--[=[@p members FilteredIterable A filtered iterable of guild members that have
this role. If you want to check whether a specific member has this role, it would
be better to get the member object elsewhere and use `Member:hasRole` rather
than check whether the member exists here.]=]
function get.members(self)
if not self._members then
self._members = FilteredIterable(self._parent._members, function(m)
return m:hasRole(self)
end)
end
return self._members
end
--[=[@p emojis FilteredIterable A filtered iterable of guild emojis that have
this role. If you want to check whether a specific emoji has this role, it would
be better to get the emoji object elsewhere and use `Emoji:hasRole` rather
than check whether the emoji exists here.]=]
function get.emojis(self)
if not self._emojis then
self._emojis = FilteredIterable(self._parent._emojis, function(e)
return e:hasRole(self)
end)
end
return self._emojis
end
return Role