Skip to content

Commit

Permalink
Adding ability to change position of Channels and Roles. (#237)
Browse files Browse the repository at this point in the history
* First pass ChannelOrderAction.

* Second pass on OrderAction system. WIP commit.
Abstracted most code to OrderAction.
Created RoleOrderAction however currently does not work due to implementation differences with Channel#getPosition and Role#getPosition.

* Made OrderAction more generic for future use in different ordering situations.
Added abstract hook to OrderAction: verifyInput(T)
Note, position system is still broken for RoleOrderAction.

* Implemented support for different order methodologies into OrderAction
Fixed RoleOrderAction. Now actually works.

* Added reverse, sort, and shuffle functionality to OrderAction.
Added getGuild() to RoleOrderAction and ChannelOrderAction.

* Fixed stuff mentioned in review.

* Added documentation for OrderAction

* added ability to use ascending ordering with RoleOrderAction.

* Added position checking for RoleOrderAction and overall permission checks

* Finished RoleOrderAction permission logic

* Fixed descriptions explaining what descending / ascending meant for role ordering.
  • Loading branch information
DV8FromTheWorld committed Feb 25, 2017
1 parent 3d7916e commit bc4482c
Show file tree
Hide file tree
Showing 5 changed files with 777 additions and 3 deletions.
109 changes: 106 additions & 3 deletions src/main/java/net/dv8tion/jda/core/managers/GuildController.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
import net.dv8tion.jda.core.requests.Response;
import net.dv8tion.jda.core.requests.RestAction;
import net.dv8tion.jda.core.requests.Route;
import net.dv8tion.jda.core.requests.restaction.ChannelAction;
import net.dv8tion.jda.core.requests.restaction.RoleAction;
import net.dv8tion.jda.core.requests.restaction.WebhookAction;
import net.dv8tion.jda.core.requests.restaction.*;
import net.dv8tion.jda.core.utils.PermissionUtil;
import org.apache.http.util.Args;
import org.json.JSONArray;
Expand Down Expand Up @@ -1712,6 +1710,111 @@ protected void handleResponse(Response response, Request request)
};
}

/**
* Modifies the positional order of {@link net.dv8tion.jda.core.entities.Guild#getTextChannels() Guild.getTextChannels()}
* using a specific {@link net.dv8tion.jda.core.requests.RestAction RestAction} extension to allow moving Channels
* {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveUp(int) up}/{@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveDown(int) down}
* or {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveTo(int) to} a specific position.
* <br>This uses <b>ascending</b> order with a 0 based index.
*
* <p>Possible {@link net.dv8tion.jda.core.requests.ErrorResponse ErrorResponses} include:
* <ul>
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#UNKNOWN_CHANNEL UNNKOWN_CHANNEL}
* <br>One of the channels has been deleted before the completion of the task</li>
*
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
* <br>The currently logged in account was removed from the Guild</li>
* </ul>
*
* @return {@link net.dv8tion.jda.core.requests.restaction.ChannelOrderAction ChannelOrderAction} - Type: {@link net.dv8tion.jda.core.entities.TextChannel TextChannel}
*/
public ChannelOrderAction<TextChannel> modifyTextChannelPositions()
{
return new ChannelOrderAction(guild, ChannelType.TEXT);
}

/**
* Modifies the positional order of {@link net.dv8tion.jda.core.entities.Guild#getVoiceChannels() Guild.getVoiceChannels()}
* using a specific {@link net.dv8tion.jda.core.requests.RestAction RestAction} extension to allow moving Channels
* {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveUp(int) up}/{@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveDown(int) down}
* or {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveTo(int) to} a specific position.
* <br>This uses <b>ascending</b> order with a 0 based index.
*
* <p>Possible {@link net.dv8tion.jda.core.requests.ErrorResponse ErrorResponses} include:
* <ul>
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#UNKNOWN_CHANNEL UNNKOWN_CHANNEL}
* <br>One of the channels has been deleted before the completion of the task</li>
*
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
* <br>The currently logged in account was removed from the Guild</li>
* </ul>
*
* @return {@link net.dv8tion.jda.core.requests.restaction.ChannelOrderAction ChannelOrderAction} - Type: {@link net.dv8tion.jda.core.entities.VoiceChannel VoiceChannel}
*/
public ChannelOrderAction<VoiceChannel> modifyVoiceChannelPositions()
{
return new ChannelOrderAction(guild, ChannelType.VOICE);
}

/**
* Modifies the positional order of {@link net.dv8tion.jda.core.entities.Guild#getRoles() Guild.getRoles()}
* using a specific {@link net.dv8tion.jda.core.requests.RestAction RestAction} extension to allow moving Roles
* {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveUp(int) up}/{@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveDown(int) down}
* or {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveTo(int) to} a specific position.
*
* <p>This uses the ordering defined by Discord, which is <b>descending</b>!
* <br>This means the highest role appears at index {@code 0} and the lower role at index {@code n - 1}.
* <br>Providing {@code false} to {@link #modifyRolePositions(boolean)} will result in the ordering being
* in ascending order, with the lower role at index {@code 0} and the highest at index {@code n - 1}.
* <br>As a note: {@link net.dv8tion.jda.core.entities.Member#getRoles() Member.getRoles()}
* and {@link net.dv8tion.jda.core.entities.Guild#getRoles() Guild.getRoles()} are both in descending order.
*
* <p>Possible {@link net.dv8tion.jda.core.requests.ErrorResponse ErrorResponses} include:
* <ul>
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#UNKNOWN_ROLE UNKNOWN_ROLE}
* <br>One of the roles was deleted before the completion of the task</li>
*
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
* <br>The currently logged in account was removed from the Guild</li>
* </ul>
*
* @return {@link net.dv8tion.jda.core.requests.restaction.RoleOrderAction RoleOrderAction}
*/
public RoleOrderAction modifyRolePositions()
{
return modifyRolePositions(true);
}

/**
* Modifies the positional order of {@link net.dv8tion.jda.core.entities.Guild#getRoles() Guild.getRoles()}
* using a specific {@link net.dv8tion.jda.core.requests.RestAction RestAction} extension to allow moving Roles
* {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveUp(int) up}/{@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveDown(int) down}
* or {@link net.dv8tion.jda.core.requests.restaction.OrderAction#moveTo(int) to} a specific position.
*
* <p>Possible {@link net.dv8tion.jda.core.requests.ErrorResponse ErrorResponses} include:
* <ul>
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#UNKNOWN_ROLE UNKNOWN_ROLE}
* <br>One of the roles was deleted before the completion of the task</li>
*
* <li>{@link net.dv8tion.jda.core.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
* <br>The currently logged in account was removed from the Guild</li>
* </ul>
*
* @param useDiscordOrder
* Defines the ordering of the OrderAction. If {@code true}, the OrderAction will be in the ordering
* defined by Discord for roles, which is Descending. This means that the highest role appears at index {@code 0}
* and the lowest role at index {@code n - 1}. Providing {@code false} will result in the ordering being
* in ascending order, with the lower role at index {@code 0} and the highest at index {@code n - 1}.
* <br>As a note: {@link net.dv8tion.jda.core.entities.Member#getRoles() Member.getRoles()}
* and {@link net.dv8tion.jda.core.entities.Guild#getRoles() Guild.getRoles()} are both in descending order.
*
* @return {@link net.dv8tion.jda.core.requests.restaction.RoleOrderAction RoleOrderAction}
*/
public RoleOrderAction modifyRolePositions(boolean useDiscordOrder)
{
return new RoleOrderAction(guild, useDiscordOrder);
}

protected void checkAvailable()
{
if (!guild.isAvailable())
Expand Down
1 change: 1 addition & 0 deletions src/main/java/net/dv8tion/jda/core/requests/Route.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ public static class Guilds
public static final Route CREATE_CHANNEL = new Route(POST, "guilds/{guild_id}/channels", "guild_id");
public static final Route GET_CHANNELS = new Route(GET, "guilds/{guild_id}/channels", "guild_id");
public static final Route MODIFY_CHANNELS = new Route(PATCH, "guilds/{guild_id}/channels", "guild_id");
public static final Route MODIFY_ROLES = new Route(PATCH, "guilds/{guild_id}/roles", "guild_id");
public static final Route GET_BANS = new Route(GET, "guilds/{guild_id}/bans", "guild_id");
public static final Route BAN = new Route(PUT, "guilds/{guild_id}/bans/{user_id}", "guild_id");
public static final Route BAN_WITH_DELETE = new Route(PUT, "guilds/{guild_id}/bans/{user_id}?delete-message-days={}", "guild_id");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2015-2017 Austin Keener & Michael Ritter
*
* 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.requests.restaction;

import net.dv8tion.jda.core.Permission;
import net.dv8tion.jda.core.entities.*;
import net.dv8tion.jda.core.exceptions.PermissionException;
import net.dv8tion.jda.core.requests.Route;
import org.apache.http.util.Args;
import org.json.JSONArray;
import org.json.JSONObject;

import java.util.Collection;

/**
* Implementation of {@link net.dv8tion.jda.core.requests.restaction.OrderAction OrderAction}
* to modify the order of {@link net.dv8tion.jda.core.entities.Channel Channels} for a {@link net.dv8tion.jda.core.entities.Guild Guild}.
* <br>To apply the changes you must finish the {@link net.dv8tion.jda.core.requests.RestAction RestAction}
*
* @param <T>
* The type of {@link net.dv8tion.jda.core.entities.Channel Channel} defining
* which channels to order
*
* @since 3.0
*/
public class ChannelOrderAction<T extends Channel> extends OrderAction<T, ChannelOrderAction>
{
protected final Guild guild;
protected final ChannelType type;

/**
* Creates a new ChannelOrderAction instance
*
* @param guild
* The target {@link net.dv8tion.jda.core.entities.Guild Guild}
* of which to order the channels defined by the specified type
* @param type
* The {@link net.dv8tion.jda.core.entities.ChannelType ChannelType} corresponding
* to the generic type of {@link net.dv8tion.jda.core.entities.Channel Channel} which
* defines the type of channel that will be ordered
*/
public ChannelOrderAction(Guild guild, ChannelType type)
{
super(guild.getJDA(), Route.Guilds.MODIFY_CHANNELS.compile(guild.getId()));
this.guild = guild;
this.type = type;

Collection chans = type == ChannelType.TEXT ? guild.getTextChannels() : guild.getVoiceChannels();
this.orderList.addAll(chans);
}

/**
* The {@link net.dv8tion.jda.core.entities.Guild Guild} which holds
* the channels from {@link #getCurrentOrder()}
*
* @return The corresponding {@link net.dv8tion.jda.core.entities.Guild Guild}
*/
public Guild getGuild()
{
return guild;
}

/**
* The {@link net.dv8tion.jda.core.entities.ChannelType ChannelType} of
* all channels that are ordered by this ChannelOrderAction
*
* @return The corresponding {@link net.dv8tion.jda.core.entities.ChannelType ChannelType}
*/
public ChannelType getChannelType()
{
return type;
}

@Override
protected void finalizeData()
{
final Member self = guild.getSelfMember();
if (!self.hasPermission(Permission.MANAGE_CHANNEL))
throw new PermissionException(Permission.MANAGE_CHANNEL);
JSONArray array = new JSONArray();
for (int i = 0; i < orderList.size(); i++)
{
Channel chan = orderList.get(i);
array.put(new JSONObject()
.put("id", chan.getId())
.put("position", i));
}

this.data = array;
}

@Override
protected void validateInput(T entity)
{
Args.check(entity.getGuild().equals(guild), "Provided channel is not from this Guild!");
Args.check(orderList.contains(entity), "Provided channel is not in the list of orderable channels!");
}
}
Loading

0 comments on commit bc4482c

Please sign in to comment.