net.dv8tion.jda.core.managers.RoleManagerUpdatable.java Source code

Java tutorial

Introduction

Here is the source code for net.dv8tion.jda.core.managers.RoleManagerUpdatable.java

Source

/*
 *     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.Guild;
import net.dv8tion.jda.core.entities.Role;
import net.dv8tion.jda.core.exceptions.PermissionException;
import net.dv8tion.jda.core.managers.fields.PermissionField;
import net.dv8tion.jda.core.managers.fields.RoleField;
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.awt.Color;

/**
 * An {@link #update() updatable} manager that allows
 * to modify role settings like the {@link #getNameField() name} or the {@link #getColorField() color}.
 *
 * <p>This manager allows to modify multiple fields at once
 * by getting the {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} for specific
 * properties and setting or resetting their values; followed by a call of {@link #update()}!
 * <br>Default values depend on the inherited properties of the <u>Public Role</u> in the parent Guild.
 *
 * <p>The {@link net.dv8tion.jda.core.managers.RoleManager RoleManager} 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_ROLES MANAGE_ROLES} and
 * must be more powerful according to Discord hierarchy rules (positional strength). [ee {@link Role#canInteract(net.dv8tion.jda.core.entities.Role) Role.canInteract(Role)}]
 */
public class RoleManagerUpdatable {
    protected final Role role;

    protected RoleField<String> name;
    protected RoleField<Color> color;
    protected RoleField<Boolean> hoisted;
    protected RoleField<Boolean> mentionable;
    protected PermissionField permissions;

    /**
     * Creates a new RoleManagerUpdatable instance
     *
     * @param role
     *        The {@link net.dv8tion.jda.core.entities.Role Role} to manage
     */
    public RoleManagerUpdatable(Role role) {
        this.role = role;
        setupFields();
    }

    /**
     * The {@link net.dv8tion.jda.core.JDA JDA} instance of this Manager
     *
     * @return the corresponding JDA instance
     */
    public JDA getJDA() {
        return role.getJDA();
    }

    /**
     * The {@link net.dv8tion.jda.core.entities.Guild Guild} this Manager's
     * {@link net.dv8tion.jda.core.entities.Role Role} is in.
     * <br>This is logically the same as calling {@code getRole().getGuild()}
     *
     * @return The parent {@link net.dv8tion.jda.core.entities.Guild Guild}
     */
    public Guild getGuild() {
        return role.getGuild();
    }

    /**
     * The target {@link net.dv8tion.jda.core.entities.Role Role} for this
     * manager
     *
     * @return The target Role
     */
    public Role getRole() {
        return role;
    }

    /**
     * An {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField}
     * for the <b><u>name</u></b> of the selected {@link net.dv8tion.jda.core.entities.Role Role}.
     *
     * <p>To set the value use {@link net.dv8tion.jda.core.managers.fields.Field#setValue(Object) setValue(String)}
     * on the returned {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} instance.
     *
     * <p>A role name <b>must</b> be between 1-32 characters long!
     * <br>Otherwise {@link net.dv8tion.jda.core.managers.fields.Field#setValue(Object) Field.setValue(...)} will
     * throw an {@link IllegalArgumentException IllegalArgumentException}.
     *
     * @return {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} - Type: {@code String}
     */
    public RoleField<String> getNameField() {
        return name;
    }

    /**
     * An {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField}
     * for the <b><u>color</u></b> of the selected {@link net.dv8tion.jda.core.entities.Role Role}.
     *
     * <p>To set the value use {@link net.dv8tion.jda.core.managers.fields.Field#setValue(Object) setValue(Color)}
     * on the returned {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} instance.
     * <br>Provide {@code null} or {@link Color#BLACK black} to use the default color.
     *
     * @return {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} - Type: {@link java.awt.Color Color}
     */
    public RoleField<Color> getColorField() {
        return color;
    }

    /**
     * An {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField}
     * for the <b><u>hoist state</u></b> of the selected {@link net.dv8tion.jda.core.entities.Role Role}.
     *
     * <p>To set the value use {@link net.dv8tion.jda.core.managers.fields.Field#setValue(Object) setValue(Boolean)}
     * on the returned {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} instance.
     *
     * <p>A role hoist state <b>must not</b> be {@code null}!
     * <br>Otherwise {@link net.dv8tion.jda.core.managers.fields.Field#setValue(Object) Field.setValue(...)} will
     * throw an {@link IllegalArgumentException IllegalArgumentException}.
     *
     * @return {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} - Type: {@code Boolean}
     */
    public RoleField<Boolean> getHoistedField() {
        return hoisted;
    }

    /**
     * An {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField}
     * for the <b><u>mentionable state</u></b> of the selected {@link net.dv8tion.jda.core.entities.Role Role}.
     *
     * <p>To set the value use {@link net.dv8tion.jda.core.managers.fields.Field#setValue(Object) setValue(Boolean)}
     * on the returned {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} instance.
     *
     * <p>A role mentionable state <b>must not</b> be {@code null}!
     * <br>Otherwise {@link net.dv8tion.jda.core.managers.fields.Field#setValue(Object) Field.setValue(...)} will
     * throw an {@link IllegalArgumentException IllegalArgumentException}.
     *
     * @return {@link net.dv8tion.jda.core.managers.fields.RoleField RoleField} - Type: {@code Boolean}
     */
    public RoleField<Boolean> getMentionableField() {
        return mentionable;
    }

    /**
     * An {@link net.dv8tion.jda.core.managers.fields.PermissionField PermissionField}
     * for the {@link net.dv8tion.jda.core.Permission Permissions} of the selected {@link net.dv8tion.jda.core.entities.Role Role}.
     *
     * <p>To set the value use {@link net.dv8tion.jda.core.managers.fields.PermissionField#setPermissions(Permission...) setPermissions(Permission...)}
     * on the returned {@link net.dv8tion.jda.core.managers.fields.PermissionField PermissionField} instance.
     *
     * <p>A role permissions <b>must not</b> be {@code null}!
     * <br>Otherwise the {@link net.dv8tion.jda.core.managers.fields.PermissionField PermissionField} will
     * throw an {@link IllegalArgumentException IllegalArgumentException}.
     *
     * @return {@link net.dv8tion.jda.core.managers.fields.PermissionField PermissionField}
     */
    public PermissionField getPermissionField() {
        return permissions;
    }

    /**
     * Resets all {@link net.dv8tion.jda.core.managers.fields.Field Fields}
     * for this manager instance by calling {@link net.dv8tion.jda.core.managers.fields.Field#reset() Field.reset()} sequentially
     * <br>This is automatically called by {@link #update()}
     */
    public void reset() {
        name.reset();
        color.reset();
        hoisted.reset();
        mentionable.reset();
        permissions.reset();
    }

    /**
     * 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_ROLE UNKNOWN_ROLE}
     *      <br>If the Role 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_ROLES MANAGE_ROLES Permission} or lost
     *          positional power before finishing the task</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_ROLES MANAGE_ROLES}
     *         or does not have the power to {@link Role#canInteract(net.dv8tion.jda.core.entities.Role) interact} with this Role
     *
     * @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_ROLES);
        checkPosition();

        if (!needsUpdate())
            return new AuditableRestAction.EmptyRestAction<>(getJDA(), null);

        //TODO: check if all of this is *actually* needed.
        JSONObject body = new JSONObject().put("name", role.getName());

        if (name.shouldUpdate())
            body.put("name", name.getValue());
        if (color.shouldUpdate())
            body.put("color", color.getValue() == null ? 0 : color.getValue().getRGB() & 0xFFFFFF);
        if (hoisted.shouldUpdate())
            body.put("hoist", hoisted.getValue().booleanValue());
        if (mentionable.shouldUpdate())
            body.put("mentionable", mentionable.getValue().booleanValue());
        if (permissions.shouldUpdate())
            body.put("permissions", permissions.getValue());

        reset();
        Route.CompiledRoute route = Route.Roles.MODIFY_ROLE.compile(getGuild().getId(), role.getId());
        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 needsUpdate() {
        return name.shouldUpdate() || color.shouldUpdate() || hoisted.shouldUpdate() || mentionable.shouldUpdate()
                || permissions.shouldUpdate();
    }

    protected void checkPermission(Permission perm) {
        if (!getGuild().getSelfMember().hasPermission(perm))
            throw new PermissionException(perm);
    }

    protected void checkPosition() {
        if (!getGuild().getSelfMember().canInteract(role))
            throw new PermissionException("Can't modify role >= highest self-role");
    }

    protected void setupFields() {
        this.name = new RoleField<String>(this, role::getName) {
            @Override
            public void checkValue(String value) {
                Checks.notNull(value, "name");
                if (value.isEmpty() || value.length() > 32)
                    throw new IllegalArgumentException("Provided role name must be 1 to 32 characters in length");
            }
        };

        this.color = new RoleField<Color>(this, role::getColor) {
            @Override
            public RoleManagerUpdatable setValue(Color color) {
                if (color != null && color.getRGB() == 0)
                    color = null;

                super.setValue(color);
                return manager;
            }

            @Override
            public void checkValue(Color value) {
            }
        };

        this.hoisted = new RoleField<Boolean>(this, role::isHoisted) {
            @Override
            public void checkValue(Boolean value) {
                Checks.notNull(value, "hoisted Boolean");
            }
        };

        this.mentionable = new RoleField<Boolean>(this, role::isMentionable) {
            @Override
            public void checkValue(Boolean value) {
                Checks.notNull(value, "mentionable Boolean");
            }
        };

        this.permissions = new PermissionField(this, role::getPermissionsRaw);
    }
}