Java tutorial
/* * Copyright 2015-2017 Austin Keener & Michael Ritter & Florian Spie * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.dv8tion.jda.core.managers; import net.dv8tion.jda.core.JDA; import net.dv8tion.jda.core.Permission; import net.dv8tion.jda.core.entities.Channel; import net.dv8tion.jda.core.entities.Guild; import net.dv8tion.jda.core.entities.PermissionOverride; import net.dv8tion.jda.core.exceptions.PermissionException; import net.dv8tion.jda.core.requests.Request; import net.dv8tion.jda.core.requests.Response; import net.dv8tion.jda.core.requests.Route; import net.dv8tion.jda.core.requests.restaction.AuditableRestAction; import net.dv8tion.jda.core.utils.Checks; import org.json.JSONObject; import javax.annotation.CheckReturnValue; import java.util.Arrays; import java.util.Collection; /** * An {@link #update() updatable} manager that allows * to modify {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} settings * such as the granted and denied {@link net.dv8tion.jda.core.Permission Permissions}. * * <p>This manager allows to modify multiple fields at once followed by a call of {@link #update()}! * <br>Default is no permissions granted/denied. * * <p>The {@link net.dv8tion.jda.core.managers.PermOverrideManager PermOverrideManager} implementation * simplifies this process by giving simple setters that return the {@link #update() update} {@link net.dv8tion.jda.core.requests.RestAction RestAction} * * <p><b>Note</b>: To {@link #update() update} this manager * the currently logged in account requires the Permission {@link net.dv8tion.jda.core.Permission#MANAGE_PERMISSIONS MANAGE_PERMISSIONS} * in the parent {@link net.dv8tion.jda.core.entities.Channel Channel} */ public class PermOverrideManagerUpdatable { protected final PermissionOverride override; protected Long allow; protected Long deny; protected boolean set; /** * Creates a new PermOverrideManagerUpdatable instance * * @param override * The {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} to manage */ public PermOverrideManagerUpdatable(PermissionOverride override) { this.override = override; } /** * The {@link net.dv8tion.jda.core.JDA JDA} instance of this Manager * * @return the corresponding JDA instance */ public JDA getJDA() { return override.getJDA(); } /** * The {@link net.dv8tion.jda.core.entities.Guild Guild} this Manager's * {@link net.dv8tion.jda.core.entities.Channel Channel} is in. * <br>This is logically the same as calling {@code getPermissionOverride().getGuild()} * * @return The parent {@link net.dv8tion.jda.core.entities.Guild Guild} */ public Guild getGuild() { return override.getGuild(); } /** * The {@link net.dv8tion.jda.core.entities.Channel Channel} this Manager's * {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} is in. * <br>This is logically the same as calling {@code getPermissionOverride().getChannel()} * * @return The parent {@link net.dv8tion.jda.core.entities.Channel Channel} */ public Channel getChannel() { return override.getChannel(); } /** * The target {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} * that will be modified by this Manager * * @return The target {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} */ public PermissionOverride getPermissionOverride() { return override; } /** * Grants the specified permission bits * to the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * * @param permissions * Raw permission bits to grant * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable grant(long permissions) { return grant(Permission.getPermissions(permissions)); } /** * Grants the specified {@link net.dv8tion.jda.core.Permission Permissions} * to the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * * @param permissions * Permissions to grant * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * @throws IllegalArgumentException * If any of the provided permissions is {@code null} * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable grant(Permission... permissions) { return grant(Arrays.asList(permissions)); } /** * Grants the specified {@link net.dv8tion.jda.core.Permission Permissions} * to the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * * @param permissions * Permissions to grant * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * @throws IllegalArgumentException * If any of the provided permissions is {@code null} * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable grant(Collection<Permission> permissions) { Checks.notNull(permissions, "Permission Collection"); permissions.forEach(perm -> { Checks.notNull(perm, "Permission in Permission Collection"); //checkPermission(perm); }); setupValues(); long allowBits = Permission.getRaw(permissions); allow |= allowBits; deny &= ~allowBits; return this; } /** * Denies the specified permission bits * from the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * * @param permissions * Raw permission bits to deny * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable deny(long permissions) { return deny(Permission.getPermissions(permissions)); } /** * Denies the specified {@link net.dv8tion.jda.core.Permission Permissions} * from the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * * @param permissions * Permissions to deny * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * @throws IllegalArgumentException * If any of the provided permissions is {@code null} * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable deny(Permission... permissions) { return deny(Arrays.asList(permissions)); } /** * Denies the specified {@link net.dv8tion.jda.core.Permission Permissions} * from the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * * @param permissions * Permissions to deny * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * @throws IllegalArgumentException * If any of the provided permissions is {@code null} * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable deny(Collection<Permission> permissions) { Checks.notNull(permissions, "Permission Collection"); permissions.forEach(perm -> { Checks.notNull(perm, "Permission in Permission Collection"); //checkPermission(perm); }); setupValues(); long denyBits = Permission.getRaw(permissions); allow &= ~denyBits; deny |= denyBits; return this; } /** * Clears the specified permission bits * from the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * <br>This will make the specified Permissions be inherited * * @param permission * Raw permission bits to clear * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable clear(long permission) { return clear(Permission.getPermissions(permission)); } /** * Clears the specified {@link net.dv8tion.jda.core.Permission Permissions} * from the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * <br>This will make the specified Permissions be inherited * * @param permissions * Permissions to clear * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * @throws IllegalArgumentException * If any of the provided permissions is {@code null} * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable clear(Permission... permissions) { return clear(Arrays.asList(permissions)); } /** * Clears the specified {@link net.dv8tion.jda.core.Permission Permissions} * from the target {@link net.dv8tion.jda.core.entities.PermissionOverride} * <br>This will make the specified Permissions be inherited * * @param permissions * Permissions to clear * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If any of the provided permissions are not accessible * @throws IllegalArgumentException * If any of the provided permissions is {@code null} * * @return The current Manager instance for chaining convenience */ @CheckReturnValue public PermOverrideManagerUpdatable clear(Collection<Permission> permissions) { Checks.notNull(permissions, "Permission Collection"); permissions.forEach(perm -> { Checks.notNull(perm, "Permission in Permission Collection"); //checkPermission(perm); }); setupValues(); long clearBits = Permission.getRaw(permissions); allow &= ~clearBits; deny &= ~clearBits; return this; } /** * The granted {@link net.dv8tion.jda.core.Permission Permissions} * value represented as raw long bits. * <br>Use {@link Permission#getPermissions(long)} to retrieve a list of {@link net.dv8tion.jda.core.Permission Permissions} * from the returned bits. * * <p>This value represents all permissions that should be granted by this {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} * * @return Granted {@link net.dv8tion.jda.core.Permission Permissions} value * or {@code null} if {@link #isSet()} is {@code false} */ public Long getAllowBits() { return allow; } /** * The denied {@link net.dv8tion.jda.core.Permission Permissions} * value represented as raw long bits. * <br>Use {@link Permission#getPermissions(long)} to retrieve a list of {@link net.dv8tion.jda.core.Permission Permissions} * from the returned bits. * * <p>This value represents all permissions that should be denied by this {@link net.dv8tion.jda.core.entities.PermissionOverride PermissionOverride} * * @return Denied {@link net.dv8tion.jda.core.Permission Permissions} value * or {@code null} if {@link #isSet()} is {@code false} */ public Long getDenyBits() { return deny; } /** * The inherited {@link net.dv8tion.jda.core.Permission Permissions} * value represented as raw long bits. * <br>Use {@link Permission#getPermissions(long)} to retrieve a list of {@link net.dv8tion.jda.core.Permission Permissions} * from the returned bits. * * <p>This value represents all permissions that are not granted or denied by the settings of this Manager instance * - thus they represent all permissions that are set to inherit from other overrides. * * @return Inherited {@link net.dv8tion.jda.core.Permission Permissions} value * or {@code null} if {@link #isSet()} is {@code false} */ public Long getInheritBits() { if (!set) return null; long maxPerms = 0; for (Permission perm : Permission.values()) { if (perm.getOffset() > maxPerms) maxPerms = perm.getOffset(); } maxPerms = ~(1 << (maxPerms + 1)); //push 1 to max offset + 1, then flip to get a full-permission bit mask. return (~allow | ~deny) & maxPerms; } /** * Whether anything has been modified yet * * @return Whether anything has been modified */ public boolean isSet() { return set; } /** * Resets all {@link net.dv8tion.jda.core.Permission Permission} values * <br>This is automatically called by {@link #update()} */ public void reset() { set = false; allow = null; deny = null; } /** * Creates a new {@link net.dv8tion.jda.core.requests.RestAction RestAction} instance * that will apply <b>all</b> changes that have been made to this manager instance. * <br>If no changes have been made this will simply return {@link net.dv8tion.jda.core.requests.RestAction.EmptyRestAction EmptyRestAction}. * * <p>Before applying new changes it is recommended to call {@link #reset()} to reset previous changes. * <br>This is automatically called if this method returns successfully. * * <p>Possible {@link net.dv8tion.jda.core.requests.ErrorResponse ErrorResponses} for this * update include the following: * <ul> * <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#UNKNOWN_OVERRIDE UNKNOWN_OVERRIDE} * <br>If the PermissionOverride was deleted before finishing the task</li> * * <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS} * <br>If the currently logged in account was removed from the Guild before finishing the task</li> * * <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS} * <br>If the currently logged in account loses the {@link net.dv8tion.jda.core.Permission#MANAGE_PERMISSIONS MANAGE_PERMISSIONS Permission}</li> * </ul> * * @throws net.dv8tion.jda.core.exceptions.PermissionException * If the currently logged in account does not have the Permission {@link net.dv8tion.jda.core.Permission#MANAGE_PERMISSIONS MANAGE_PERMISSIONS} * in the {@link #getChannel() Channel} * * @return {@link net.dv8tion.jda.core.requests.restaction.AuditableRestAction AuditableRestAction} * <br>Applies all changes that have been made in a single api-call. */ @CheckReturnValue public AuditableRestAction<Void> update() { checkPermission(Permission.MANAGE_PERMISSIONS); if (!shouldUpdate()) return new AuditableRestAction.EmptyRestAction<>(getJDA(), null); String targetId = override.isRoleOverride() ? override.getRole().getId() : override.getMember().getUser().getId(); JSONObject body = new JSONObject().put("id", targetId) .put("type", override.isRoleOverride() ? "role" : "member").put("allow", getAllowBits()) .put("deny", getDenyBits()); reset(); Route.CompiledRoute route = Route.Channels.MODIFY_PERM_OVERRIDE.compile(override.getChannel().getId(), targetId); return new AuditableRestAction<Void>(getJDA(), route, body) { @Override protected void handleResponse(Response response, Request<Void> request) { if (response.isOk()) request.onSuccess(null); else request.onFailure(response); } }; } protected boolean shouldUpdate() { return set && (allow != override.getAllowedRaw() || deny != override.getDeniedRaw()); } protected void setupValues() { if (!set) { set = true; allow = override.getAllowedRaw(); deny = override.getDeniedRaw(); } } protected void checkPermission(Permission perm) { if (!getGuild().getSelfMember().hasPermission(getChannel(), perm)) throw new PermissionException(perm); } }