Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add category feature to ChannelOrderAction #2136

Merged
merged 6 commits into from
Sep 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions src/main/java/net/dv8tion/jda/api/entities/Guild.java
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
import net.dv8tion.jda.internal.utils.Helpers;
import net.dv8tion.jda.internal.utils.concurrent.task.GatewayTask;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.Duration;
import java.time.temporal.TemporalAccessor;
import java.util.*;
Expand All @@ -65,10 +68,6 @@
import java.util.function.Consumer;
import java.util.function.Predicate;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
* Represents a Discord {@link net.dv8tion.jda.api.entities.Guild Guild}.
* This should contain all information provided from Discord about a Guild.
Expand Down Expand Up @@ -4559,12 +4558,16 @@ default AuditableRestAction<GuildSticker> createSticker(@Nonnull String name, @N
* {@link net.dv8tion.jda.api.requests.restaction.order.OrderAction#moveUp(int) up}/{@link net.dv8tion.jda.api.requests.restaction.order.OrderAction#moveDown(int) down}
* or {@link net.dv8tion.jda.api.requests.restaction.order.OrderAction#moveTo(int) to} a specific position.
*
* <p>This uses <b>ascending</b> ordering which means the lowest role is first!
* <br>This means the highest role appears at index {@code n - 1} and the lower role at index {@code 0}.
* <p>You can also move roles to a position relative to another role, by using {@link net.dv8tion.jda.api.requests.restaction.order.OrderAction#moveBelow(Object) moveBelow(...)}
* and {@link net.dv8tion.jda.api.requests.restaction.order.OrderAction#moveAbove(Object) moveAbove(...)}.
*
* <p>This uses <b>descending</b> ordering which means the highest role is first!
* <br>This means the lowest role appears at index {@code n - 1} and the highest role at index {@code 0}.
* <br>Providing {@code true} to {@link #modifyRolePositions(boolean)} will result in the ordering being
* in ascending order, with the lower role at index {@code n - 1} and the highest at index {@code 0}.
* in ascending order, with the highest role at index {@code n - 1} and the lowest at index {@code 0}.
*
* <br>As a note: {@link net.dv8tion.jda.api.entities.Member#getRoles() Member.getRoles()}
* and {@link net.dv8tion.jda.api.entities.Guild#getRoles() Guild.getRoles()} are both in descending order.
* and {@link net.dv8tion.jda.api.entities.Guild#getRoles() Guild.getRoles()} are both in descending order, just like this method.
*
* <p>Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
* <ul>
Expand All @@ -4575,13 +4578,13 @@ default AuditableRestAction<GuildSticker> createSticker(@Nonnull String name, @N
* <br>The currently logged in account was removed from the Guild</li>
* </ul>
*
* @return {@link net.dv8tion.jda.api.requests.restaction.order.RoleOrderAction RoleOrderAction}
* @return {@link RoleOrderAction}
*/
@Nonnull
@CheckReturnValue
default RoleOrderAction modifyRolePositions()
{
return modifyRolePositions(true);
return modifyRolePositions(false);
}

/**
Expand All @@ -4607,7 +4610,7 @@ default RoleOrderAction modifyRolePositions()
* <br>As a note: {@link net.dv8tion.jda.api.entities.Member#getRoles() Member.getRoles()}
* and {@link net.dv8tion.jda.api.entities.Guild#getRoles() Guild.getRoles()} are both in descending order.
*
* @return {@link RoleOrderAction RoleOrderAction}
* @return {@link RoleOrderAction}
*/
@Nonnull
@CheckReturnValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

package net.dv8tion.jda.api.requests.restaction.order;

import net.dv8tion.jda.api.entities.Category;
import net.dv8tion.jda.api.entities.ChannelType;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel;

import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.EnumSet;

/**
Expand Down Expand Up @@ -71,4 +74,46 @@ default EnumSet<ChannelType> getChannelTypes()
{
return ChannelType.fromSortBucket(getSortBucket());
}

/**
* Set the parent category for the currently selected channel.
*
* @param category
* The new parent category, or null to not have any category
* @param syncPermissions
* Whether to sync the permissions of the channel to the new category
*
* @throws IllegalStateException
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws IllegalArgumentException
* If the provided category is not in the same guild as the channel
*
* @return The current ChannelOrderAction
*/
@Nonnull
@CheckReturnValue
ChannelOrderAction setCategory(@Nullable Category category, boolean syncPermissions);

/**
* Set the parent category for the currently selected channel.
*
* <p>By default, this will not sync the permissions with the new category.
* You can use {@link #setCategory(Category, boolean)} to sync permissions.
*
* @param category
* The new parent category, or null to not have any category
*
* @throws IllegalStateException
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws IllegalArgumentException
* If the provided category is not in the same guild as the channel
*
* @return The current ChannelOrderAction
*/
@Nonnull
@CheckReturnValue
default ChannelOrderAction setCategory(@Nullable Category category)
{
return setCategory(category, false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ public interface OrderAction<T, M extends OrderAction<T, M>> extends RestAction<
* The entity which is currently at the {@link #getSelectedPosition() selected position}
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* If no entity has been selected yet, use {@link #selectPosition(Object)}
*
* @return The currently selected entity
*/
Expand All @@ -138,7 +138,7 @@ public interface OrderAction<T, M extends OrderAction<T, M>> extends RestAction<
* The amount of positions that should be moved
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws java.lang.IllegalArgumentException
* If the specified amount would cause the entity to go out-of-bounds
*
Expand All @@ -157,7 +157,7 @@ public interface OrderAction<T, M extends OrderAction<T, M>> extends RestAction<
* The amount of positions that should be moved
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws java.lang.IllegalArgumentException
* If the specified amount would cause the entity to go out-of-bounds
*
Expand All @@ -177,18 +177,60 @@ public interface OrderAction<T, M extends OrderAction<T, M>> extends RestAction<
* The new not-negative position for the currently selected entity
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws java.lang.IllegalArgumentException
* If the specified position is out-of-bounds
*
* @return The current OrderAction sub-implementation instance
*
* @see #moveDown(int)
* @see #moveUp(int)
* @see #moveBelow(Object)
* @see #moveAbove(Object)
*/
@Nonnull
M moveTo(int position);

/**
* Moves the currently selected entity below the specified target entity.
*
* @param other
* The reference entity that should end up above the selected entity
*
* @throws IllegalStateException
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws IllegalArgumentException
* If the specified target entity is not managed by this instance or null
*
* @return The current OrderAction sub-implementation instance
*
* @see #moveUp(int)
* @see #moveDown(int)
* @see #moveAbove(Object)
*/
@Nonnull
M moveBelow(@Nonnull T other);

/**
* Moves the currently selected entity above the specified target entity.
*
* @param other
* The reference entity that should end up below the selected entity
*
* @throws IllegalStateException
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws IllegalArgumentException
* If the specified target entity is not managed by this instance or null
*
* @return The current OrderAction sub-implementation instance
*
* @see #moveUp(int)
* @see #moveDown(int)
* @see #moveBelow(Object)
*/
@Nonnull
M moveAbove(@Nonnull T other);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if you use setCategory and then moveAbove and provide a channel that is not inside of the category?

Does it move the selected channel to the top of the category but not outside of it? Does it move the channel back outside of the category and actually above the provided channel?

Should it throw?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The channel position field is independent of the parent_id, so it would only matter for the sorting of channels by their partial ordering through position/id.


/**
* Swaps the currently selected entity with the entity located
* at the specified position. No other entities are affected by this operation.
Expand All @@ -197,7 +239,7 @@ public interface OrderAction<T, M extends OrderAction<T, M>> extends RestAction<
* 0 based index of target position
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws java.lang.IllegalArgumentException
* If the specified position is out-of-bounds
*
Expand All @@ -214,7 +256,7 @@ public interface OrderAction<T, M extends OrderAction<T, M>> extends RestAction<
* Target entity to switch positions with
*
* @throws java.lang.IllegalStateException
* If no entity has been selected yet
* If no entity has been selected yet, use {@link #selectPosition(Object)}
* @throws java.lang.IllegalArgumentException
* If the specified position is out-of-bounds,
* or if the target entity is {@code null} or not
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@

package net.dv8tion.jda.internal.requests.restaction.order;

import gnu.trove.map.TLongLongMap;
import gnu.trove.map.hash.TLongLongHashMap;
import gnu.trove.set.TLongSet;
import gnu.trove.set.hash.TLongHashSet;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.exceptions.InsufficientPermissionException;
import net.dv8tion.jda.api.requests.restaction.order.ChannelOrderAction;
import net.dv8tion.jda.api.utils.data.DataArray;
Expand All @@ -29,6 +31,7 @@
import okhttp3.RequestBody;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.stream.Collectors;

Expand All @@ -38,6 +41,8 @@ public class ChannelOrderActionImpl
{
protected final Guild guild;
protected final int bucket;
protected final TLongSet lockPermissions = new TLongHashSet();
protected final TLongLongMap parent = new TLongLongHashMap();

/**
* Creates a new ChannelOrderAction instance
Expand Down Expand Up @@ -102,6 +107,25 @@ public int getSortBucket()
return bucket;
}

@Nonnull
@Override
public ChannelOrderAction setCategory(@Nullable Category category, boolean syncPermissions)
{
GuildChannel channel = getSelectedEntity();
if (!(channel instanceof ICategorizableChannel) && category != null)
throw new IllegalStateException("Cannot move channel of type " + channel.getType() + " to category!");
if (category != null)
Checks.check(category.getGuild().equals(getGuild()), "Category is not from the same guild!");

long id = channel.getIdLong();
parent.put(id, category == null ? 0 : category.getIdLong());
if (syncPermissions)
lockPermissions.add(id);
else
lockPermissions.remove(id);
return this;
}

@Override
protected RequestBody finalizeData()
{
Expand All @@ -112,9 +136,16 @@ protected RequestBody finalizeData()
for (int i = 0; i < orderList.size(); i++)
{
GuildChannel chan = orderList.get(i);
array.add(DataObject.empty()
DataObject json = DataObject.empty()
.put("id", chan.getId())
.put("position", i));
.put("position", i);
if (parent.containsKey(chan.getIdLong()))
{
long parentId = parent.get(chan.getIdLong());
json.put("parent_id", parentId == 0 ? null : parentId);
json.put("lock_permissions", lockPermissions.contains(chan.getIdLong()));
}
array.add(json);
}

return getRequestBody(array);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,13 @@ public M moveDown(int amount)
if (ascendingOrder)
{
Checks.check(selectedPosition + amount < orderList.size(),
"Amount provided to move down is too large and would be out of bounds." +
"Amount provided to move down is too large and would be out of bounds. " +
"Selected position: " + selectedPosition + " Amount: " + amount + " Largest Position: " + orderList.size());
}
else
{
Checks.check(selectedPosition - amount >= orderList.size(),
"Amount provided to move down is too large and would be out of bounds." +
Checks.check(selectedPosition - amount >= 0,
"Amount provided to move down is too large and would be out of bounds. " +
"Selected position: " + selectedPosition + " Amount: " + amount + " Largest Position: " + orderList.size());
}

Expand All @@ -211,7 +211,34 @@ public M moveTo(int position)

T selectedItem = orderList.remove(selectedPosition);
orderList.add(position, selectedItem);
selectedPosition = position;

return (M) this;
}

@Nonnull
@Override
@SuppressWarnings("unchecked")
public M moveBelow(@Nonnull T other)
{
validateInput(other);
int index = getCurrentOrder().indexOf(other);
moveTo(index);
if (isAscendingOrder())
return moveDown(1);
return (M) this;
}

@Nonnull
@Override
@SuppressWarnings("unchecked")
public M moveAbove(@Nonnull T other)
{
validateInput(other);
int index = getCurrentOrder().indexOf(other);
moveTo(index);
if (!isAscendingOrder())
return moveUp(1);
return (M) this;
}

Expand All @@ -228,6 +255,7 @@ public M swapPosition(int swapPosition)
T swapItem = orderList.get(swapPosition);
orderList.set(swapPosition, selectedItem);
orderList.set(selectedPosition, swapItem);
selectedPosition = swapPosition;

return (M) this;
}
Expand Down