16
16
17
17
package net .dv8tion .jda .core .managers ;
18
18
19
+ import gnu .trove .map .hash .TLongObjectHashMap ;
20
+ import gnu .trove .set .TLongSet ;
21
+ import gnu .trove .set .hash .TLongHashSet ;
19
22
import net .dv8tion .jda .core .Permission ;
20
- import net .dv8tion .jda .core .entities .Category ;
21
- import net .dv8tion .jda .core .entities .Channel ;
22
- import net .dv8tion .jda .core .entities .ChannelType ;
23
- import net .dv8tion .jda .core .entities .Guild ;
23
+ import net .dv8tion .jda .core .entities .*;
24
+ import net .dv8tion .jda .core .entities .impl .AbstractChannelImpl ;
24
25
import net .dv8tion .jda .core .exceptions .InsufficientPermissionException ;
25
26
import net .dv8tion .jda .core .managers .impl .ManagerBase ;
26
27
import net .dv8tion .jda .core .requests .Route ;
28
+ import net .dv8tion .jda .core .requests .restaction .PermOverrideData ;
27
29
import net .dv8tion .jda .core .utils .Checks ;
28
30
import okhttp3 .RequestBody ;
29
31
import org .json .JSONObject ;
30
32
31
33
import javax .annotation .CheckReturnValue ;
34
+ import java .util .Collection ;
32
35
33
36
/**
34
37
* Manager providing functionality to update one or more fields for a {@link net.dv8tion.jda.core.entities.Channel Guild Channel}.
@@ -64,6 +67,8 @@ public class ChannelManager extends ManagerBase
64
67
public static final long USERLIMIT = 0x20 ;
65
68
/** Used to reset the bitrate field */
66
69
public static final long BITRATE = 0x40 ;
70
+ /** Used to reset the permission field */
71
+ public static final long PERMISSION = 0x80 ;
67
72
68
73
protected final Channel channel ;
69
74
@@ -75,6 +80,10 @@ public class ChannelManager extends ManagerBase
75
80
protected int userlimit ;
76
81
protected int bitrate ;
77
82
83
+ protected final Object lock = new Object ();
84
+ protected final TLongObjectHashMap <PermOverrideData > overridesAdd ;
85
+ protected final TLongSet overridesRem ;
86
+
78
87
/**
79
88
* Creates a new ChannelManager instance
80
89
*
@@ -89,8 +98,15 @@ public ChannelManager(Channel channel)
89
98
this .channel = channel ;
90
99
if (isPermissionChecksEnabled ())
91
100
checkPermissions ();
101
+ this .overridesAdd = new TLongObjectHashMap <>();
102
+ this .overridesRem = new TLongHashSet ();
92
103
}
93
104
105
+ /**
106
+ * The {@link net.dv8tion.jda.core.entities.ChannelType ChannelType}
107
+ *
108
+ * @return The ChannelType
109
+ */
94
110
public ChannelType getType ()
95
111
{
96
112
return channel .getType ();
@@ -133,6 +149,7 @@ public Guild getGuild()
133
149
* <li>{@link #NSFW}</li>
134
150
* <li>{@link #USERLIMIT}</li>
135
151
* <li>{@link #BITRATE}</li>
152
+ * <li>{@link #PERMISSION}</li>
136
153
* </ul>
137
154
*
138
155
* @param fields
@@ -151,6 +168,14 @@ public ChannelManager reset(long fields)
151
168
this .parent = null ;
152
169
if ((fields & TOPIC ) == TOPIC )
153
170
this .topic = null ;
171
+ if ((fields & PERMISSION ) == PERMISSION )
172
+ {
173
+ withLock (lock , (lock ) ->
174
+ {
175
+ this .overridesRem .clear ();
176
+ this .overridesAdd .clear ();
177
+ });
178
+ }
154
179
return this ;
155
180
}
156
181
@@ -167,6 +192,7 @@ public ChannelManager reset(long fields)
167
192
* <li>{@link #NSFW}</li>
168
193
* <li>{@link #USERLIMIT}</li>
169
194
* <li>{@link #BITRATE}</li>
195
+ * <li>{@link #PERMISSION}</li>
170
196
* </ul>
171
197
*
172
198
* @param fields
@@ -195,6 +221,149 @@ public ChannelManager reset()
195
221
this .name = null ;
196
222
this .parent = null ;
197
223
this .topic = null ;
224
+ withLock (lock , (lock ) ->
225
+ {
226
+ this .overridesRem .clear ();
227
+ this .overridesAdd .clear ();
228
+ });
229
+ return this ;
230
+ }
231
+
232
+ /**
233
+ * Clears the overrides added via {@link #putPermissionOverride(IPermissionHolder, Collection, Collection)}.
234
+ *
235
+ * @return ChannelManager for chaining convenience
236
+ */
237
+ public ChannelManager clearOverridesAdded ()
238
+ {
239
+ withLock (lock , (lock ) ->
240
+ {
241
+ this .overridesAdd .clear ();
242
+ if (this .overridesRem .isEmpty ())
243
+ set &= ~PERMISSION ;
244
+ });
245
+ return this ;
246
+ }
247
+
248
+ /**
249
+ * Clears the overrides removed via {@link #removePermissionOverride(IPermissionHolder)}.
250
+ *
251
+ * @return ChannelManager for chaining convenience
252
+ */
253
+ public ChannelManager clearOverridesRemoved ()
254
+ {
255
+ withLock (lock , (lock ) ->
256
+ {
257
+ this .overridesRem .clear ();
258
+ if (this .overridesAdd .isEmpty ())
259
+ set &= ~PERMISSION ;
260
+ });
261
+ return this ;
262
+ }
263
+
264
+ /**
265
+ * Adds an override for the specified {@link net.dv8tion.jda.core.entities.IPermissionHolder IPermissionHolder}
266
+ * with the provided raw bitmasks as allowed and denied permissions. If the permission holder already
267
+ * had an override on this channel it will be updated instead.
268
+ *
269
+ * @param permHolder
270
+ * The permission holder
271
+ * @param allow
272
+ * The bitmask to grant
273
+ * @param deny
274
+ * The bitmask to deny
275
+ *
276
+ * @throws java.lang.IllegalArgumentException
277
+ * If the provided permission holder is {@code null}
278
+ * @throws net.dv8tion.jda.core.exceptions.InsufficientPermissionException
279
+ * If the currently logged in account does not have {@link net.dv8tion.jda.core.Permission#MANAGE_PERMISSIONS Permission.MANAGE_PERMISSIONS}
280
+ * in this channel
281
+ *
282
+ * @return ChannelManager for chaining convenience
283
+ *
284
+ * @see #putPermissionOverride(IPermissionHolder, Collection, Collection)
285
+ * @see net.dv8tion.jda.core.Permission#getRaw(Permission...) Permission.getRaw(Permission...)
286
+ */
287
+ @ CheckReturnValue
288
+ public ChannelManager putPermissionOverride (IPermissionHolder permHolder , long allow , long deny )
289
+ {
290
+ Checks .notNull (permHolder , "PermissionHolder" );
291
+ Checks .check (permHolder .getGuild ().equals (getGuild ()), "PermissionHolder is not from the same Guild!" );
292
+ if (isPermissionChecksEnabled () && !getGuild ().getSelfMember ().hasPermission (channel , Permission .MANAGE_PERMISSIONS ))
293
+ throw new InsufficientPermissionException (Permission .MANAGE_PERMISSIONS );
294
+ final long id = getId (permHolder );
295
+ final int type = permHolder instanceof Role ? PermOverrideData .ROLE_TYPE : PermOverrideData .MEMBER_TYPE ;
296
+ withLock (lock , (lock ) ->
297
+ {
298
+ this .overridesRem .remove (id );
299
+ this .overridesAdd .put (id , new PermOverrideData (type , id , allow , deny ));
300
+ set |= PERMISSION ;
301
+ });
302
+ return this ;
303
+ }
304
+
305
+ /**
306
+ * Adds an override for the specified {@link net.dv8tion.jda.core.entities.IPermissionHolder IPermissionHolder}
307
+ * with the provided permission sets as allowed and denied permissions. If the permission holder already
308
+ * had an override on this channel it will be updated instead.
309
+ * <br>Example: {@code putPermissionOverride(guild.getSelfMember(), EnumSet.of(Permission.MESSAGE_WRITE, Permission.MESSAGE_READ), null)}
310
+ *
311
+ * @param permHolder
312
+ * The permission holder
313
+ * @param allow
314
+ * The permissions to grant, or null
315
+ * @param deny
316
+ * The permissions to deny, or null
317
+ *
318
+ * @throws java.lang.IllegalArgumentException
319
+ * If the provided permission holder is {@code null}
320
+ * @throws net.dv8tion.jda.core.exceptions.InsufficientPermissionException
321
+ * If the currently logged in account does not have {@link net.dv8tion.jda.core.Permission#MANAGE_PERMISSIONS Permission.MANAGE_PERMISSIONS}
322
+ * in this channel
323
+ *
324
+ * @return ChannelManager for chaining convenience
325
+ *
326
+ * @see #putPermissionOverride(IPermissionHolder, long, long)
327
+ * @see java.util.EnumSet EnumSet
328
+ */
329
+ @ CheckReturnValue
330
+ public ChannelManager putPermissionOverride (IPermissionHolder permHolder , Collection <Permission > allow , Collection <Permission > deny )
331
+ {
332
+ long allowRaw = allow == null ? 0 : Permission .getRaw (allow );
333
+ long denyRaw = deny == null ? 0 : Permission .getRaw (deny );
334
+ return putPermissionOverride (permHolder , allowRaw , denyRaw );
335
+ }
336
+
337
+ /**
338
+ * Removes the {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} for the specified
339
+ * {@link net.dv8tion.jda.core.entities.IPermissionHolder IPermissionHolder}. If no override existed for this member
340
+ * this does nothing.
341
+ *
342
+ * @param permHolder
343
+ * The permission holder
344
+ *
345
+ * @throws java.lang.IllegalArgumentException
346
+ * If the provided permission holder is {@code null}
347
+ * @throws net.dv8tion.jda.core.exceptions.InsufficientPermissionException
348
+ * If the currently logged in account does not have {@link net.dv8tion.jda.core.Permission#MANAGE_PERMISSIONS Permission.MANAGE_PERMISSIONS}
349
+ * in this channel
350
+ *
351
+ * @return ChannelManager for chaining convenience
352
+ */
353
+ @ CheckReturnValue
354
+ public ChannelManager removePermissionOverride (IPermissionHolder permHolder )
355
+ {
356
+ Checks .notNull (permHolder , "PermissionHolder" );
357
+ Checks .check (permHolder .getGuild ().equals (getGuild ()), "PermissionHolder is not from the same Guild!" );
358
+ if (isPermissionChecksEnabled () && !getGuild ().getSelfMember ().hasPermission (channel , Permission .MANAGE_PERMISSIONS ))
359
+ throw new InsufficientPermissionException (Permission .MANAGE_PERMISSIONS );
360
+ final long id = getId (permHolder );
361
+ withLock (lock , (lock ) ->
362
+ {
363
+ this .overridesRem .add (id );
364
+ this .overridesAdd .remove (id );
365
+ set |= PERMISSION ;
366
+ });
198
367
return this ;
199
368
}
200
369
@@ -409,6 +578,11 @@ protected RequestBody finalizeData()
409
578
frame .put ("bitrate" , bitrate );
410
579
if (shouldUpdate (PARENT ))
411
580
frame .put ("parent_id" , opt (parent ));
581
+ withLock (lock , (lock ) ->
582
+ {
583
+ if (shouldUpdate (PERMISSION ))
584
+ frame .put ("permission_overwrites" , getOverrides ());
585
+ });
412
586
413
587
reset ();
414
588
return getRequestBody (frame );
@@ -417,8 +591,34 @@ protected RequestBody finalizeData()
417
591
@ Override
418
592
protected boolean checkPermissions ()
419
593
{
420
- if (!getGuild ().getSelfMember ().hasPermission (channel , Permission .MANAGE_CHANNEL ))
594
+ final Member selfMember = getGuild ().getSelfMember ();
595
+ if (!selfMember .hasPermission (channel , Permission .MANAGE_CHANNEL ))
421
596
throw new InsufficientPermissionException (Permission .MANAGE_CHANNEL );
422
597
return super .checkPermissions ();
423
598
}
599
+
600
+ protected Collection <PermOverrideData > getOverrides ()
601
+ {
602
+ //note: overridesAdd and overridesRem are mutually disjoint
603
+ TLongObjectHashMap <PermOverrideData > data = new TLongObjectHashMap <>(this .overridesAdd );
604
+
605
+ AbstractChannelImpl <?> impl = (AbstractChannelImpl <?>) channel ;
606
+ impl .getOverrideMap ().forEachEntry ((id , override ) ->
607
+ {
608
+ //removed by not adding them here, this data set overrides the existing one
609
+ //we can use remove because it will be reset afterwards either way
610
+ if (!overridesRem .remove (id ) && !data .containsKey (id ))
611
+ data .put (id , new PermOverrideData (override ));
612
+ return true ;
613
+ });
614
+ return data .valueCollection ();
615
+ }
616
+
617
+ protected long getId (IPermissionHolder holder )
618
+ {
619
+ if (holder instanceof Role )
620
+ return ((Role ) holder ).getIdLong ();
621
+ else
622
+ return ((Member ) holder ).getUser ().getIdLong ();
623
+ }
424
624
}
0 commit comments