diff --git a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java
index 848a42eb88..e4e6831ed6 100644
--- a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java
+++ b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java
@@ -321,13 +321,13 @@ public enum AuditLogKey
*/
CHANNEL_ID("channel_id"),
-// /**
-// * The {@link ForumChannel#getDefaultSortOrder()} value.
-// *
Only for {@link ChannelType#FORUM}.
-// *
-// *
Expected type: Integer
-// */
-// CHANNEL_DEFAULT_SORT_ORDER("default_sort_order"),
+ /**
+ * The {@link ForumChannel#getDefaultSortOrder()} value.
+ *
Only for {@link ChannelType#FORUM} and {@link ChannelType#MEDIA}.
+ *
+ *
Expected type: Integer
+ */
+ CHANNEL_DEFAULT_SORT_ORDER("default_sort_order"),
/**
* The {@link ForumChannel#getDefaultLayout()} value.
diff --git a/src/main/java/net/dv8tion/jda/api/entities/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java
index 1775542b6e..10af96368b 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java
@@ -4539,6 +4539,70 @@ default ChannelAction createForumChannel(@Nonnull String name)
@CheckReturnValue
ChannelAction createForumChannel(@Nonnull String name, @Nullable Category parent);
+ /**
+ * Creates a new {@link MediaChannel} in this Guild.
+ * For this to be successful, the logged in account has to have the {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL MANAGE_CHANNEL} Permission.
+ *
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} caused by
+ * the returned {@link RestAction RestAction} include the following:
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
+ *
The channel could not be created due to a permission discrepancy
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MAX_CHANNELS MAX_CHANNELS}
+ *
The maximum number of channels were exceeded
+ *
+ *
+ * @param name
+ * The name of the MediaChannel to create (up to {@value Channel#MAX_NAME_LENGTH} characters)
+ *
+ * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
+ * If the logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL} permission
+ * @throws IllegalArgumentException
+ * If the provided name is {@code null}, blank, or longer than {@value Channel#MAX_NAME_LENGTH} characters
+ *
+ * @return A specific {@link ChannelAction ChannelAction}
+ *
This action allows to set fields for the new MediaChannel before creating it
+ */
+ @Nonnull
+ @CheckReturnValue
+ default ChannelAction createMediaChannel(@Nonnull String name)
+ {
+ return createMediaChannel(name, null);
+ }
+
+ /**
+ * Creates a new {@link MediaChannel} in this Guild.
+ * For this to be successful, the logged in account has to have the {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL MANAGE_CHANNEL} Permission.
+ *
+ * Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} caused by
+ * the returned {@link RestAction RestAction} include the following:
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
+ *
The channel could not be created due to a permission discrepancy
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MAX_CHANNELS MAX_CHANNELS}
+ *
The maximum number of channels were exceeded
+ *
+ *
+ * @param name
+ * The name of the MediaChannel to create (up to {@value Channel#MAX_NAME_LENGTH} characters)
+ * @param parent
+ * The optional parent category for this channel, or null
+ *
+ * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
+ * If the logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL} permission
+ * @throws IllegalArgumentException
+ * If the provided name is {@code null}, blank, or longer than {@value Channel#MAX_NAME_LENGTH} characters;
+ * or the provided parent is not in the same guild.
+ *
+ * @return A specific {@link ChannelAction ChannelAction}
+ *
This action allows to set fields for the new MediaChannel before creating it
+ */
+ @Nonnull
+ @CheckReturnValue
+ ChannelAction createMediaChannel(@Nonnull String name, @Nullable Category parent);
+
/**
* Creates a new {@link Category Category} in this Guild.
* For this to be successful, the logged in account has to have the {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL MANAGE_CHANNEL} Permission.
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelField.java b/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelField.java
index 73ad561ebc..9b9ee49afa 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelField.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelField.java
@@ -255,14 +255,14 @@ public enum ChannelField
*/
DEFAULT_FORUM_LAYOUT("default_forum_layout", AuditLogKey.DEFAULT_FORUM_LAYOUT),
-// /**
-// * The default sort order of a forum channel.
-// *
-// * Limited to {@link ForumChannel Forum Channels}.
-// *
-// * @see ForumChannel#getDefaultSortOrder()
-// */
-// DEFAULT_SORT_ORDER("default_sort_order", AuditLogKey.CHANNEL_DEFAULT_SORT_ORDER)
+ /**
+ * The default sort order of a forum channel.
+ *
+ *
Limited to {@link ForumChannel Forum Channels} and {@link MediaChannel Media Channels}.
+ *
+ * @see ForumChannel#getDefaultSortOrder()
+ */
+ DEFAULT_SORT_ORDER("default_sort_order", AuditLogKey.CHANNEL_DEFAULT_SORT_ORDER)
;
private final String fieldName;
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelFlag.java b/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelFlag.java
index a807d7174e..e889205b93 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelFlag.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelFlag.java
@@ -36,7 +36,12 @@ public enum ChannelFlag
/**
* This is a {@link ForumChannel} which requires all new post threads to have at least one applied tag.
*/
- REQUIRE_TAG(1 << 4);
+ REQUIRE_TAG(1 << 4),
+
+ /**
+ * This is a {@link net.dv8tion.jda.api.entities.channel.concrete.MediaChannel MediaChannel} which hides the copy embed option.
+ */
+ HIDE_MEDIA_DOWNLOAD_OPTIONS(1 << 15);
private final int value;
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelType.java b/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelType.java
index 56d01dbaa8..8e3c5d76fe 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelType.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelType.java
@@ -63,6 +63,11 @@ public enum ChannelType
*/
FORUM(15, 0, true),
+ /**
+ * A {@link MediaChannel}, Guild-Only.
+ */
+ MEDIA(16, 0, true),
+
/**
* Unknown Discord channel type. Should never happen and would only possibly happen if Discord implemented a new
* channel type and JDA had yet to implement support for it.
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IGuildChannelContainer.java b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IGuildChannelContainer.java
index fed544b0f0..ec5a15e0c8 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IGuildChannelContainer.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IGuildChannelContainer.java
@@ -178,6 +178,8 @@ default GuildChannel getGuildChannelById(long id)
channel = getThreadChannelById(id);
if (channel == null)
channel = getForumChannelById(id);
+ if (channel == null)
+ channel = getMediaChannelById(id);
return channel;
}
@@ -273,6 +275,8 @@ default GuildChannel getGuildChannelById(@Nonnull ChannelType type, long id)
return getCategoryById(id);
case FORUM:
return getForumChannelById(id);
+ case MEDIA:
+ return getMediaChannelById(id);
}
if (type.isThread())
@@ -1101,4 +1105,118 @@ default List getForumChannels()
{
return getForumChannelCache().asList();
}
+
+
+ // MediaChannels
+
+
+ /**
+ * {@link SnowflakeCacheView SnowflakeCacheView} of {@link MediaChannel}.
+ *
+ * This getter exists on any instance of {@link IGuildChannelContainer} and only checks the caches with the relevant scoping.
+ * For {@link Guild}, {@link JDA}, or {@link ShardManager},
+ * this returns the relevant channel with respect to the cache within each of those objects.
+ * For a guild, this would mean it only returns channels within the same guild.
+ *
If this is called on {@link JDA} or {@link ShardManager}, this may return null immediately after building, because the cache isn't initialized yet.
+ * To make sure the cache is initialized after building your {@link JDA} instance, you can use {@link JDA#awaitReady()}.
+ *
+ * @return {@link SnowflakeCacheView SnowflakeCacheView}
+ */
+ @Nonnull
+ SnowflakeCacheView getMediaChannelCache();
+
+ /**
+ * Gets a list of all {@link MediaChannel MediaChannels}
+ * in this Guild that have the same name as the one provided.
+ *
If there are no channels with the provided name, then this returns an empty list.
+ *
+ * This getter exists on any instance of {@link IGuildChannelContainer} and only checks the caches with the relevant scoping.
+ * For {@link Guild}, {@link JDA}, or {@link ShardManager},
+ * this returns the relevant channel with respect to the cache within each of those objects.
+ * For a guild, this would mean it only returns channels within the same guild.
+ *
If this is called on {@link JDA} or {@link ShardManager}, this may return null immediately after building, because the cache isn't initialized yet.
+ * To make sure the cache is initialized after building your {@link JDA} instance, you can use {@link JDA#awaitReady()}.
+ *
+ * @param name
+ * The name used to filter the returned {@link MediaChannel MediaChannels}.
+ * @param ignoreCase
+ * Determines if the comparison ignores case when comparing. True - case insensitive.
+ *
+ * @return Possibly-empty immutable list of all ForumChannel names that match the provided name.
+ */
+ @Nonnull
+ default List getMediaChannelsByName(@Nonnull String name, boolean ignoreCase)
+ {
+ return getMediaChannelCache().getElementsByName(name, ignoreCase);
+ }
+
+ /**
+ * Gets a {@link MediaChannel} that has the same id as the one provided.
+ *
If there is no channel with an id that matches the provided one, then this returns {@code null}.
+ *
+ * This getter exists on any instance of {@link IGuildChannelContainer} and only checks the caches with the relevant scoping.
+ * For {@link Guild}, {@link JDA}, or {@link ShardManager},
+ * this returns the relevant channel with respect to the cache within each of those objects.
+ * For a guild, this would mean it only returns channels within the same guild.
+ *
If this is called on {@link JDA} or {@link ShardManager}, this may return null immediately after building, because the cache isn't initialized yet.
+ * To make sure the cache is initialized after building your {@link JDA} instance, you can use {@link JDA#awaitReady()}.
+ *
+ * @param id
+ * The id of the {@link MediaChannel}.
+ *
+ * @throws java.lang.NumberFormatException
+ * If the provided {@code id} cannot be parsed by {@link Long#parseLong(String)}
+ *
+ * @return Possibly-null {@link MediaChannel} with matching id.
+ */
+ @Nullable
+ default MediaChannel getMediaChannelById(@Nonnull String id)
+ {
+ return getMediaChannelCache().getElementById(id);
+ }
+
+ /**
+ * Gets a {@link MediaChannel} that has the same id as the one provided.
+ *
If there is no channel with an id that matches the provided one, then this returns {@code null}.
+ *
+ *
This getter exists on any instance of {@link IGuildChannelContainer} and only checks the caches with the relevant scoping.
+ * For {@link Guild}, {@link JDA}, or {@link ShardManager},
+ * this returns the relevant channel with respect to the cache within each of those objects.
+ * For a guild, this would mean it only returns channels within the same guild.
+ *
If this is called on {@link JDA} or {@link ShardManager}, this may return null immediately after building, because the cache isn't initialized yet.
+ * To make sure the cache is initialized after building your {@link JDA} instance, you can use {@link JDA#awaitReady()}.
+ *
+ * @param id
+ * The id of the {@link MediaChannel}.
+ *
+ * @return Possibly-null {@link MediaChannel} with matching id.
+ */
+ @Nullable
+ default MediaChannel getMediaChannelById(long id)
+ {
+ return getMediaChannelCache().getElementById(id);
+ }
+
+ /**
+ * Gets all {@link MediaChannel} in the cache.
+ *
+ *
This copies the backing store into a list. This means every call
+ * creates a new list with O(n) complexity. It is recommended to store this into
+ * a local variable or use {@link #getForumChannelCache()} and use its more efficient
+ * versions of handling these values.
+ *
+ *
This getter exists on any instance of {@link IGuildChannelContainer} and only checks the caches with the relevant scoping.
+ * For {@link Guild}, {@link JDA}, or {@link ShardManager},
+ * this returns the relevant channel with respect to the cache within each of those objects.
+ * For a guild, this would mean it only returns channels within the same guild.
+ *
If this is called on {@link JDA} or {@link ShardManager}, this may return null immediately after building, because the cache isn't initialized yet.
+ * To make sure the cache is initialized after building your {@link JDA} instance, you can use {@link JDA#awaitReady()}.
+ *
+ * @return An immutable List of {@link MediaChannel}.
+ */
+ @Nonnull
+ default List getMediaChannels()
+ {
+ return getMediaChannelCache().asList();
+ }
}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IPostContainer.java b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IPostContainer.java
new file mode 100644
index 0000000000..6cacb9c2d5
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IPostContainer.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.api.entities.channel.attribute;
+
+import net.dv8tion.jda.annotations.Incubating;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.channel.Channel;
+import net.dv8tion.jda.api.entities.channel.ChannelFlag;
+import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.concrete.MediaChannel;
+import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
+import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
+import net.dv8tion.jda.api.entities.emoji.EmojiUnion;
+import net.dv8tion.jda.api.managers.channel.attribute.IPostContainerManager;
+import net.dv8tion.jda.api.requests.restaction.ForumPostAction;
+import net.dv8tion.jda.api.utils.cache.SortedSnowflakeCacheView;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * A channel which contains {@link #createForumPost(String, MessageCreateData) Forum Posts}.
+ *
Forum posts are simply {@link ThreadChannel ThreadChannels} of type {@link ChannelType#GUILD_PUBLIC_THREAD}.
+ *
+ * The {@code CREATE POSTS} permission that is shown in the official Discord Client, is an alias for {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}.
+ * {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS} is ignored for creating forum posts.
+ *
+ * @see ForumChannel
+ * @see MediaChannel
+ * @see #createForumPost(String, MessageCreateData)
+ */
+public interface IPostContainer extends IThreadContainer
+{
+ /**
+ * The maximum length of a forum / media channel topic ({@value})
+ */
+ int MAX_POST_CONTAINER_TOPIC_LENGTH = 4096;
+ /**
+ * The maximum number of {@link ForumPostAction#setTags(Collection) tags} that can be applied to a forum post. ({@value})
+ */
+ int MAX_POST_TAGS = 5;
+
+ @Nonnull
+ @Override
+ IPostContainerManager, ?> getManager();
+
+ /**
+ * The available {@link ForumTag ForumTags} for this forum channel.
+ *
Tags are sorted by their {@link ForumTag#getPosition() position} ascending.
+ *
+ *
This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
+ *
+ * @return {@link SortedSnowflakeCacheView} of {@link ForumTag}
+ */
+ @Nonnull
+ SortedSnowflakeCacheView getAvailableTagCache();
+
+ /**
+ * The available {@link ForumTag ForumTags} for this channel.
+ *
Tags are sorted by their {@link ForumTag#getPosition() position} ascending.
+ *
+ * This is a shortcut for {@link #getAvailableTagCache() getAvailableTagCache().asList()}.
+ * This method will copy the underlying cache into the list, running in {@code O(n)} time.
+ *
+ *
This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
+ *
+ * @return Immutable {@link List} of {@link ForumTag}
+ */
+ @Nonnull
+ default List getAvailableTags()
+ {
+ return getAvailableTagCache().asList();
+ }
+
+ /**
+ * The available {@link ForumTag ForumTags} for this channel.
+ *
Tags are sorted by their {@link ForumTag#getPosition() position} ascending.
+ *
+ * This is a shortcut for {@link #getAvailableTagCache() getAvailableTagCache().getElementsByName(name, ignoreCase)}.
+ * This method will copy the underlying cache into the list, running in {@code O(n)} time.
+ *
+ *
This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
+ *
+ * @param name
+ * The name of the tag
+ * @param ignoreCase
+ * Whether to use {@link String#equalsIgnoreCase(String)}
+ *
+ * @throws IllegalArgumentException
+ * If the name is {@code null}
+ *
+ * @return Immutable {@link List} of {@link ForumTag} with the given name
+ */
+ @Nonnull
+ default List getAvailableTagsByName(@Nonnull String name, boolean ignoreCase)
+ {
+ return getAvailableTagCache().getElementsByName(name, ignoreCase);
+ }
+
+ /**
+ * Retrieves the tag for the provided id.
+ *
+ * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
+ *
+ * @param id
+ * The tag id
+ *
+ * @return The tag for the provided id, or {@code null} if no tag with that id exists
+ *
+ * @see net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake#fromId(long)
+ */
+ @Nullable
+ default ForumTag getAvailableTagById(long id)
+ {
+ return getAvailableTagCache().getElementById(id);
+ }
+
+ /**
+ * Retrieves the tag for the provided id.
+ *
+ *
This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
+ *
+ * @param id
+ * The tag id
+ *
+ * @throws IllegalArgumentException
+ * If the provided id is null
+ * @throws NumberFormatException
+ * If the provided id is not a valid snowflake
+ *
+ * @return The tag for the provided id, or {@code null} if no tag with that id exists
+ *
+ * @see net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake#fromId(String)
+ */
+ @Nullable
+ default ForumTag getAvailableTagById(@Nonnull String id)
+ {
+ return getAvailableTagCache().getElementById(id);
+ }
+
+ /**
+ * The topic set for this channel, this is referred to as Guidelines in the official Discord client.
+ *
If no topic has been set, this returns null.
+ *
+ * @return Possibly-null String containing the topic of this channel.
+ */
+ @Nullable
+ String getTopic();
+
+ /**
+ * Whether all new forum posts must have a tag.
+ *
+ * @return True, if all new posts must have a tag.
+ */
+ default boolean isTagRequired()
+ {
+ return getFlags().contains(ChannelFlag.REQUIRE_TAG);
+ }
+
+ /**
+ * The emoji which will show up on new forum posts as default reaction.
+ *
+ * @return The default reaction for new forum posts.
+ */
+ @Nullable
+ EmojiUnion getDefaultReaction();
+
+ /**
+ * The default order used to show threads.
+ *
+ * @return The default order used to show threads.
+ */
+ @Nonnull
+ SortOrder getDefaultSortOrder();
+
+ /**
+ * Creates a new forum/media post (thread) in this channel.
+ *
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
+ *
If the channel was deleted
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MESSAGE_BLOCKED_BY_AUTOMOD MESSAGE_BLOCKED_BY_AUTOMOD}
+ *
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MESSAGE_BLOCKED_BY_HARMFUL_LINK_FILTER MESSAGE_BLOCKED_BY_HARMFUL_LINK_FILTER}
+ *
If this message was blocked by the harmful link filter
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
+ *
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#TITLE_BLOCKED_BY_AUTOMOD TITLE_BLOCKED_BY_AUTOMOD}
+ *
If the forum post name was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
+ *
+ *
+ * @param name
+ * The name of the post (up to {@value Channel#MAX_NAME_LENGTH} characters)
+ * @param message
+ * The starting message of the post (see {@link net.dv8tion.jda.api.utils.messages.MessageCreateBuilder MessageCreateBuilder})
+ *
+ * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
+ * If the bot does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in the channel
+ * @throws IllegalArgumentException
+ *
+ * - If null is provided
+ * - If the name is empty or longer than {@value Channel#MAX_NAME_LENGTH} characters
+ *
+ *
+ * @return {@link ForumPostAction}
+ */
+ @Nonnull
+ @Incubating
+ @CheckReturnValue
+ ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message);
+
+ /**
+ * The order used to sort forum posts.
+ */
+ enum SortOrder
+ {
+ /**
+ * Sort by recent activity, including unarchive, message, reaction, and thread creation.
+ */
+ RECENT_ACTIVITY(0),
+ /**
+ * Sort by the time the post was originally created.
+ */
+ CREATION_TIME(1),
+ /**
+ * Placeholder for possible future order modes.
+ */
+ UNKNOWN(-1),
+ ;
+
+ private final int order;
+
+ SortOrder(int order)
+ {
+ this.order = order;
+ }
+
+ /**
+ * The underlying value as used by Discord.
+ *
+ * @return The raw order key
+ */
+ public int getKey()
+ {
+ return order;
+ }
+
+ /**
+ * The {@link SortOrder} for the provided key.
+ *
+ * @param key
+ * The key to get the {@link SortOrder} for
+ *
+ * @return The {@link SortOrder} for the provided key, or {@link #UNKNOWN} if the key is not known
+ */
+ @Nonnull
+ public static SortOrder fromKey(int key)
+ {
+ for (SortOrder order : values())
+ {
+ if (order.order == key)
+ return order;
+ }
+
+ return UNKNOWN;
+ }
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IThreadContainer.java b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IThreadContainer.java
index 3f0eccc224..ff9db5180d 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IThreadContainer.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/IThreadContainer.java
@@ -56,6 +56,7 @@ public interface IThreadContainer extends GuildChannel, IPermissionContainer
*
* @return Immutable list of all ThreadChannel children.
*/
+ @Nonnull
default List getThreadChannels()
{
return Collections.unmodifiableList(
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/Category.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/Category.java
index 1a9e78ce21..5ff2369865 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/Category.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/Category.java
@@ -72,6 +72,7 @@ default List getChannels()
channels.addAll(getStageChannels());
channels.addAll(getNewsChannels());
channels.addAll(getForumChannels());
+ channels.addAll(getMediaChannels());
Collections.sort(channels);
return Collections.unmodifiableList(channels);
@@ -124,6 +125,21 @@ default List getForumChannels()
));
}
+ /**
+ * All {@link net.dv8tion.jda.api.entities.channel.concrete.MediaChannel MediaChannels} listed for this Category
+ *
+ * @return Immutable list of all child ForumChannels
+ */
+ @Nonnull
+ default List getMediaChannels()
+ {
+ return Collections.unmodifiableList(getGuild().getMediaChannelCache().applyStream(stream ->
+ stream.filter(channel -> equals(channel.getParentCategory()))
+ .sorted()
+ .collect(Collectors.toList())
+ ));
+ }
+
/**
* All {@link VoiceChannel VoiceChannels}
* listed for this Category
@@ -341,6 +357,43 @@ default List getStageChannels()
@CheckReturnValue
ChannelAction createForumChannel(@Nonnull String name);
+ /**
+ * Creates a new {@link MediaChannel} with this Category as parent.
+ * For this to be successful, the logged in account has to have the
+ * {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL MANAGE_CHANNEL} Permission in this Category.
+ *
+ * This will copy all {@link net.dv8tion.jda.api.entities.PermissionOverride PermissionOverrides} of this Category!
+ * Unless the bot is unable to sync it with this category due to permission escalation.
+ * See {@link IPermissionHolder#canSync(IPermissionContainer, IPermissionContainer)} for details.
+ *
+ *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} caused by
+ * the returned {@link net.dv8tion.jda.api.requests.RestAction RestAction} include the following:
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS MISSING_PERMISSIONS}
+ *
The channel could not be created due to a permission discrepancy
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_ACCESS MISSING_ACCESS}
+ *
The {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL VIEW_CHANNEL} permission was removed
+ *
+ * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MAX_CHANNELS MAX_CHANNELS}
+ *
The maximum number of channels were exceeded
+ *
+ *
+ * @param name
+ * The name of the MediaChannel to create (up to {@value Channel#MAX_NAME_LENGTH} characters)
+ *
+ * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
+ * If the logged in account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL} permission
+ * @throws IllegalArgumentException
+ * If the provided name is {@code null}, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters
+ *
+ * @return A specific {@link ChannelAction ChannelAction}
+ *
This action allows to set fields for the new MediaChannel before creating it
+ */
+ @Nonnull
+ @CheckReturnValue
+ ChannelAction createMediaChannel(@Nonnull String name);
+
/**
* Modifies the positional order of this Category's nested {@link #getTextChannels() TextChannels} and {@link #getNewsChannels() NewsChannels}.
*
This uses an extension of {@link ChannelOrderAction ChannelOrderAction}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ForumChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ForumChannel.java
index 3d151591e4..bf860d3672 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ForumChannel.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ForumChannel.java
@@ -16,29 +16,20 @@
package net.dv8tion.jda.api.entities.channel.concrete;
-import net.dv8tion.jda.annotations.Incubating;
import net.dv8tion.jda.api.entities.Guild;
-import net.dv8tion.jda.api.entities.channel.Channel;
-import net.dv8tion.jda.api.entities.channel.ChannelFlag;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel;
-import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
import net.dv8tion.jda.api.entities.channel.attribute.IWebhookContainer;
-import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildChannel;
-import net.dv8tion.jda.api.entities.emoji.EmojiUnion;
import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager;
import net.dv8tion.jda.api.requests.restaction.ChannelAction;
import net.dv8tion.jda.api.requests.restaction.ForumPostAction;
-import net.dv8tion.jda.api.utils.cache.SortedSnowflakeCacheView;
import net.dv8tion.jda.api.utils.messages.MessageCreateData;
-import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import java.util.Collection;
-import java.util.List;
/**
* A Forum Channel which contains {@link #createForumPost(String, MessageCreateData) Forum Posts}.
@@ -50,16 +41,16 @@
* @see Guild#createForumChannel(String, Category)
* @see #createForumPost(String, MessageCreateData)
*/
-public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IWebhookContainer, IAgeRestrictedChannel, ISlowmodeChannel
+public interface ForumChannel extends StandardGuildChannel, IPostContainer, IWebhookContainer, IAgeRestrictedChannel, ISlowmodeChannel
{
/**
* The maximum length of a forum topic ({@value #MAX_FORUM_TOPIC_LENGTH})
*/
- int MAX_FORUM_TOPIC_LENGTH = 4096;
+ int MAX_FORUM_TOPIC_LENGTH = IPostContainer.MAX_POST_CONTAINER_TOPIC_LENGTH;
/**
* The maximum number of {@link ForumPostAction#setTags(Collection) tags} that can be applied to a forum post. ({@value #MAX_POST_TAGS})
*/
- int MAX_POST_TAGS = 5;
+ int MAX_POST_TAGS = IPostContainer.MAX_POST_TAGS;
@Nonnull
@Override
@@ -83,135 +74,6 @@ default ChannelAction createCopy()
return createCopy(getGuild());
}
- /**
- * The available {@link ForumTag ForumTags} for this forum channel.
- *
Tags are sorted by their {@link ForumTag#getPosition() position} ascending.
- *
- * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
- *
- * @return {@link SortedSnowflakeCacheView} of {@link ForumTag}
- */
- @Nonnull
- SortedSnowflakeCacheView getAvailableTagCache();
-
- /**
- * The available {@link ForumTag ForumTags} for this forum channel.
- *
Tags are sorted by their {@link ForumTag#getPosition() position} ascending.
- *
- * This is a shortcut for {@link #getAvailableTagCache() getAvailableTagCache().asList()}.
- * This method will copy the underlying cache into the list, running in {@code O(n)} time.
- *
- *
This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
- *
- * @return Immutable {@link List} of {@link ForumTag}
- */
- @Nonnull
- default List getAvailableTags()
- {
- return getAvailableTagCache().asList();
- }
-
- /**
- * The available {@link ForumTag ForumTags} for this forum channel.
- *
Tags are sorted by their {@link ForumTag#getPosition() position} ascending.
- *
- * This is a shortcut for {@link #getAvailableTagCache() getAvailableTagCache().getElementsByName(name, ignoreCase)}.
- * This method will copy the underlying cache into the list, running in {@code O(n)} time.
- *
- *
This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
- *
- * @param name
- * The name of the tag
- * @param ignoreCase
- * Whether to use {@link String#equalsIgnoreCase(String)}
- *
- * @throws IllegalArgumentException
- * If the name is {@code null}
- *
- * @return Immutable {@link List} of {@link ForumTag} with the given name
- */
- @Nonnull
- default List getAvailableTagsByName(@Nonnull String name, boolean ignoreCase)
- {
- return getAvailableTagCache().getElementsByName(name, ignoreCase);
- }
-
- /**
- * Retrieves the tag for the provided id.
- *
- * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
- *
- * @param id
- * The tag id
- *
- * @return The tag for the provided id, or {@code null} if no tag with that id exists
- *
- * @see net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake#fromId(long)
- */
- @Nullable
- default ForumTag getAvailableTagById(long id)
- {
- return getAvailableTagCache().getElementById(id);
- }
-
- /**
- * Retrieves the tag for the provided id.
- *
- *
This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled.
- *
- * @param id
- * The tag id
- *
- * @throws IllegalArgumentException
- * If the provided id is null
- * @throws NumberFormatException
- * If the provided id is not a valid snowflake
- *
- * @return The tag for the provided id, or {@code null} if no tag with that id exists
- *
- * @see net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake#fromId(String)
- */
- @Nullable
- default ForumTag getAvailableTagById(@Nonnull String id)
- {
- return getAvailableTagCache().getElementById(id);
- }
-
- /**
- * The topic set for this channel, this is referred to as Guidelines in the official Discord client.
- *
If no topic has been set, this returns null.
- *
- * @return Possibly-null String containing the topic of this channel.
- */
- @Nullable
- String getTopic();
-
- /**
- * Whether all new forum posts must have a tag.
- *
- * @return True, if all new posts must have a tag.
- */
- default boolean isTagRequired()
- {
- return getFlags().contains(ChannelFlag.REQUIRE_TAG);
- }
-
- /**
- * The emoji which will show up on new forum posts as default reaction.
- *
- * @return The default reaction for new forum posts.
- */
- @Nullable
- EmojiUnion getDefaultReaction();
-
-// /**
-// * The default order used to show threads.
-// *
-// * @return The default order used to show threads.
-// */
-// @Nonnull
-// SortOrder getDefaultSortOrder();
-
/**
* The default layout used to show threads.
*
@@ -220,47 +82,6 @@ default boolean isTagRequired()
@Nonnull
Layout getDefaultLayout();
- /**
- * Creates a new forum post (thread) in this forum.
- *
- *
Possible {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} include:
- *
- * - {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL}
- *
If the forum channel was deleted
- *
- * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MESSAGE_BLOCKED_BY_AUTOMOD MESSAGE_BLOCKED_BY_AUTOMOD}
- *
If this message was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
- *
- * - {@link net.dv8tion.jda.api.requests.ErrorResponse#MESSAGE_BLOCKED_BY_HARMFUL_LINK_FILTER MESSAGE_BLOCKED_BY_HARMFUL_LINK_FILTER}
- *
If this message was blocked by the harmful link filter
- *
- * - {@link net.dv8tion.jda.api.requests.ErrorResponse#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE}
- *
If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
- *
- * - {@link net.dv8tion.jda.api.requests.ErrorResponse#TITLE_BLOCKED_BY_AUTOMOD TITLE_BLOCKED_BY_AUTOMOD}
- *
If the forum post name was blocked by an {@link net.dv8tion.jda.api.entities.automod.AutoModRule AutoModRule}
- *
- *
- * @param name
- * The name of the post (up to {@value Channel#MAX_NAME_LENGTH} characters)
- * @param message
- * The starting message of the post (see {@link net.dv8tion.jda.api.utils.messages.MessageCreateBuilder MessageCreateBuilder})
- *
- * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException
- * If the bot does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND} in the channel
- * @throws IllegalArgumentException
- *
- * - If null is provided
- * - If the name is empty or longer than {@value Channel#MAX_NAME_LENGTH} characters
- *
- *
- * @return {@link ForumPostAction}
- */
- @Nonnull
- @Incubating
- @CheckReturnValue
- ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message);
-
/**
* The layout used to sort forum posts.
*/
@@ -321,61 +142,4 @@ public static Layout fromKey(int key)
return UNKNOWN;
}
}
-
-// /**
-// * The order used to sort forum posts.
-// */
-// enum SortOrder
-// {
-// /**
-// * Sort by recent activity, including unarchive, message, reaction, and thread creation.
-// */
-// RECENT_ACTIVITY(0),
-// /**
-// * Sort by the time the post was originally created.
-// */
-// CREATION_TIME(1),
-// /**
-// * Placeholder for possible future order modes.
-// */
-// UNKNOWN(-1),
-// ;
-//
-// private final int order;
-//
-// SortOrder(int order)
-// {
-// this.order = order;
-// }
-//
-// /**
-// * The underlying value as used by Discord.
-// *
-// * @return The raw order key
-// */
-// public int getKey()
-// {
-// return order;
-// }
-//
-// /**
-// * The {@link SortOrder} for the provided key.
-// *
-// * @param key
-// * The key to get the {@link SortOrder} for
-// *
-// * @return The {@link SortOrder} for the provided key, or {@link #UNKNOWN} if the key is not known
-// */
-// @Nonnull
-// public static SortOrder fromKey(int key)
-// {
-// for (SortOrder order : values())
-// {
-// if (order.order == key)
-// return order;
-// }
-//
-// return UNKNOWN;
-// }
-// }
}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/MediaChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/MediaChannel.java
new file mode 100644
index 0000000000..3b7ba72e3f
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/MediaChannel.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.api.entities.channel.concrete;
+
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.channel.ChannelFlag;
+import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
+import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IWebhookContainer;
+import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildChannel;
+import net.dv8tion.jda.api.managers.channel.concrete.MediaChannelManager;
+import net.dv8tion.jda.api.requests.restaction.ChannelAction;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+
+import javax.annotation.Nonnull;
+
+/**
+ * A Media Channel which contains {@link #createForumPost(String, MessageCreateData) Forum Posts}.
+ *
Forum posts are simply {@link ThreadChannel ThreadChannels} of type {@link ChannelType#GUILD_PUBLIC_THREAD}.
+ *
+ * The {@code CREATE POSTS} permission that is shown in the official Discord Client, is an alias for {@link net.dv8tion.jda.api.Permission#MESSAGE_SEND Permission.MESSAGE_SEND}.
+ * {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS} is ignored for creating forum posts.
+ *
+ * @see Guild#createMediaChannel(String, Category)
+ * @see #createForumPost(String, MessageCreateData)
+ */
+public interface MediaChannel extends StandardGuildChannel, IPostContainer, IWebhookContainer, IAgeRestrictedChannel, ISlowmodeChannel
+{
+ @Nonnull
+ @Override
+ MediaChannelManager getManager();
+
+ @Nonnull
+ @Override
+ ChannelAction createCopy(@Nonnull Guild guild);
+
+ @Nonnull
+ @Override
+ default ChannelAction createCopy()
+ {
+ return createCopy(getGuild());
+ }
+
+ @Nonnull
+ @Override
+ default ChannelType getType()
+ {
+ return ChannelType.MEDIA;
+ }
+
+ /**
+ * Whether this media channel hides the download option for embeds.
+ *
+ * @return True, if download option is hidden
+ */
+ default boolean isMediaDownloadHidden()
+ {
+ return getFlags().contains(ChannelFlag.HIDE_MEDIA_DOWNLOAD_OPTIONS);
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/ChannelUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/ChannelUnion.java
index 7fb7089a3f..9bb7ba1821 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/ChannelUnion.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/ChannelUnion.java
@@ -38,6 +38,7 @@
* {@link VoiceChannel}
* {@link StageChannel}
* {@link ForumChannel}
+ * {@link MediaChannel}
* {@link Category}
*
*/
@@ -198,6 +199,28 @@ public interface ChannelUnion extends Channel
@Nonnull
ForumChannel asForumChannel();
+ /**
+ * Casts this union to a {@link MediaChannel}.
+ * This method exists for developer discoverability.
+ *
+ * Note: This is effectively equivalent to using the cast operator:
+ *
+ * //These are the same!
+ * MediaChannel channel = union.asMediaChannel();
+ * MediaChannel channel2 = (MediaChannel) union;
+ *
+ *
+ * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#MEDIA} to validate
+ * whether you can call this method in addition to normal instanceof checks: channel instanceof MediaChannel
+ *
+ * @throws IllegalStateException
+ * If the channel represented by this union is not actually a {@link MediaChannel}.
+ *
+ * @return The channel as a {@link MediaChannel}
+ */
+ @Nonnull
+ MediaChannel asMediaChannel();
+
/**
* Casts this union to a {@link Category}.
* This method exists for developer discoverability.
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/DefaultGuildChannelUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/DefaultGuildChannelUnion.java
index 6d52184c92..34ab88534b 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/DefaultGuildChannelUnion.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/DefaultGuildChannelUnion.java
@@ -110,6 +110,7 @@ public interface DefaultGuildChannelUnion extends StandardGuildChannel
*
* @return The channel as a {@link net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer}
*/
+ @Nonnull
IThreadContainer asThreadContainer();
/**
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildChannelUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildChannelUnion.java
index 4278af799a..4f52569650 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildChannelUnion.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildChannelUnion.java
@@ -36,6 +36,7 @@
* {@link VoiceChannel}
* {@link StageChannel}
* {@link ForumChannel}
+ * {@link MediaChannel}
* {@link Category}
*
*/
@@ -195,6 +196,28 @@ public interface GuildChannelUnion extends GuildChannel
@Nonnull
ForumChannel asForumChannel();
+ /**
+ * Casts this union to a {@link MediaChannel}.
+ * This method exists for developer discoverability.
+ *
+ * Note: This is effectively equivalent to using the cast operator:
+ *
+ * //These are the same!
+ * MediaChannel channel = union.asMediaChannel();
+ * MediaChannel channel2 = (MediaChannel) union;
+ *
+ *
+ * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#MEDIA} to validate
+ * whether you can call this method in addition to normal instanceof checks: channel instanceof MediaChannel
+ *
+ * @throws IllegalStateException
+ * If the channel represented by this union is not actually a {@link MediaChannel}.
+ *
+ * @return The channel as a {@link MediaChannel}
+ */
+ @Nonnull
+ MediaChannel asMediaChannel();
+
/**
* Casts this union to a {@link GuildMessageChannel}.
* This method exists for developer discoverability.
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IThreadContainerUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IThreadContainerUnion.java
index 1f23ab3f67..0b76e80cd0 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IThreadContainerUnion.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IThreadContainerUnion.java
@@ -19,6 +19,7 @@
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.concrete.MediaChannel;
import net.dv8tion.jda.api.entities.channel.concrete.NewsChannel;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
@@ -37,6 +38,7 @@
* {@link TextChannel}
* {@link NewsChannel}
* {@link ForumChannel}
+ * {@link MediaChannel}
*
*/
public interface IThreadContainerUnion extends IThreadContainer
@@ -107,6 +109,28 @@ public interface IThreadContainerUnion extends IThreadContainer
@Nonnull
ForumChannel asForumChannel();
+ /**
+ * Casts this union to a {@link MediaChannel}.
+ * This method exists for developer discoverability.
+ *
+ * Note: This is effectively equivalent to using the cast operator:
+ *
+ * //These are the same!
+ * MediaChannel channel = union.asMediaChannel();
+ * MediaChannel channel2 = (MediaChannel) union;
+ *
+ *
+ * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#MEDIA} to validate
+ * whether you can call this method in addition to normal instanceof checks: channel instanceof MediaChannel
+ *
+ * @throws IllegalStateException
+ * If the channel represented by this union is not actually a {@link MediaChannel}.
+ *
+ * @return The channel as a {@link MediaChannel}
+ */
+ @Nonnull
+ MediaChannel asMediaChannel();
+
/**
* Casts this union to a {@link GuildMessageChannel}.
*
This works for the following channel types represented by this union:
diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IWebhookContainerUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IWebhookContainerUnion.java
index 8a4d23c1a9..fca9e8c1d3 100644
--- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IWebhookContainerUnion.java
+++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IWebhookContainerUnion.java
@@ -39,6 +39,7 @@
* {@link VoiceChannel}
* {@link StageChannel}
* {@link ForumChannel}
+ * {@link MediaChannel}
*
*/
public interface IWebhookContainerUnion extends IWebhookContainer
@@ -109,6 +110,28 @@ public interface IWebhookContainerUnion extends IWebhookContainer
@Nonnull
ForumChannel asForumChannel();
+ /**
+ * Casts this union to a {@link MediaChannel}.
+ * This method exists for developer discoverability.
+ *
+ * Note: This is effectively equivalent to using the cast operator:
+ *
+ * //These are the same!
+ * MediaChannel channel = union.asMediaChannel();
+ * MediaChannel channel2 = (MediaChannel) union;
+ *
+ *
+ * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#MEDIA} to validate
+ * whether you can call this method in addition to normal instanceof checks: channel instanceof MediaChannel
+ *
+ * @throws IllegalStateException
+ * If the channel represented by this union is not actually a {@link MediaChannel}.
+ *
+ * @return The channel as a {@link MediaChannel}
+ */
+ @Nonnull
+ MediaChannel asMediaChannel();
+
/**
* Casts this union to a {@link net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer}.
* This method exists for developer discoverability.
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagAddEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagAddEvent.java
index 9f1129304d..25c2a51ffc 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagAddEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagAddEvent.java
@@ -17,14 +17,14 @@
package net.dv8tion.jda.api.events.channel.forum;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
import javax.annotation.Nonnull;
import java.util.Collection;
/**
- * Indicates that a new {@link ForumTag} was added to a {@link ForumChannel}.
+ * Indicates that a new {@link ForumTag} was added to a {@link IPostContainer}.
*
* Use {@link net.dv8tion.jda.api.events.channel.update.ChannelUpdateAppliedTagsEvent ChannelUpdateAppliedTagsEvent}
* to detect when a tag is added to a forum post instead.
@@ -35,7 +35,7 @@
*/
public class ForumTagAddEvent extends GenericForumTagEvent
{
- public ForumTagAddEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag)
+ public ForumTagAddEvent(@Nonnull JDA api, long responseNumber, @Nonnull IPostContainer channel, @Nonnull ForumTag tag)
{
super(api, responseNumber, channel, tag);
}
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagRemoveEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagRemoveEvent.java
index 8237153aa1..3b4ee3103e 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagRemoveEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagRemoveEvent.java
@@ -17,14 +17,14 @@
package net.dv8tion.jda.api.events.channel.forum;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
import javax.annotation.Nonnull;
import java.util.Collection;
/**
- * Indicates that a {@link ForumTag} was removed from a {@link ForumChannel}.
+ * Indicates that a {@link ForumTag} was removed from a {@link IPostContainer}.
*
*
Use {@link net.dv8tion.jda.api.events.channel.update.ChannelUpdateAppliedTagsEvent ChannelUpdateAppliedTagsEvent}
* to detect when a tag is removed from a forum post instead.
@@ -35,7 +35,7 @@
*/
public class ForumTagRemoveEvent extends GenericForumTagEvent
{
- public ForumTagRemoveEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag)
+ public ForumTagRemoveEvent(@Nonnull JDA api, long responseNumber, @Nonnull IPostContainer channel, @Nonnull ForumTag tag)
{
super(api, responseNumber, channel, tag);
}
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/GenericForumTagEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/GenericForumTagEvent.java
index 64f3ff4cba..95226446d5 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/forum/GenericForumTagEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/GenericForumTagEvent.java
@@ -17,7 +17,7 @@
package net.dv8tion.jda.api.events.channel.forum;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
import net.dv8tion.jda.api.events.Event;
@@ -34,10 +34,10 @@
*/
public abstract class GenericForumTagEvent extends Event
{
- protected final ForumChannel channel;
+ protected final IPostContainer channel;
protected final ForumTag tag;
- public GenericForumTagEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag)
+ public GenericForumTagEvent(@Nonnull JDA api, long responseNumber, @Nonnull IPostContainer channel, @Nonnull ForumTag tag)
{
super(api, responseNumber);
this.channel = channel;
@@ -45,12 +45,12 @@ public GenericForumTagEvent(@Nonnull JDA api, long responseNumber, @Nonnull Foru
}
/**
- * The {@link ForumChannel} which has been updated.
+ * The {@link IPostContainer} which has been updated.
*
- * @return The {@link ForumChannel}
+ * @return The {@link IPostContainer}
*/
@Nonnull
- public ForumChannel getChannel()
+ public IPostContainer getChannel()
{
return channel;
}
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateEmojiEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateEmojiEvent.java
index 26b77296cf..22ec23c96d 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateEmojiEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateEmojiEvent.java
@@ -17,7 +17,7 @@
package net.dv8tion.jda.api.events.channel.forum.update;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
import net.dv8tion.jda.api.entities.emoji.EmojiUnion;
@@ -38,7 +38,7 @@ public class ForumTagUpdateEmojiEvent extends GenericForumTagUpdateEvent
{
public static final String IDENTIFIER = "name";
- public ForumTagUpdateNameEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag, @Nonnull String previous)
+ public ForumTagUpdateNameEvent(@Nonnull JDA api, long responseNumber, @Nonnull IPostContainer channel, @Nonnull ForumTag tag, @Nonnull String previous)
{
super(api, responseNumber, channel, tag, previous, tag.getName(), IDENTIFIER);
}
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/GenericForumTagUpdateEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/GenericForumTagUpdateEvent.java
index 0791789050..4c44aabb39 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/GenericForumTagUpdateEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/GenericForumTagUpdateEvent.java
@@ -17,7 +17,7 @@
package net.dv8tion.jda.api.events.channel.forum.update;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
import net.dv8tion.jda.api.events.UpdateEvent;
import net.dv8tion.jda.api.events.channel.forum.GenericForumTagEvent;
@@ -41,7 +41,7 @@ public abstract class GenericForumTagUpdateEvent extends GenericForumTagEvent
private final T next;
private final String identifier;
- public GenericForumTagUpdateEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag,
+ public GenericForumTagUpdateEvent(@Nonnull JDA api, long responseNumber, @Nonnull IPostContainer channel, @Nonnull ForumTag tag,
T previous, T next, @Nonnull String identifier)
{
super(api, responseNumber, channel, tag);
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateAppliedTagsEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateAppliedTagsEvent.java
index 86baf100c4..7d5efe47b2 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateAppliedTagsEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateAppliedTagsEvent.java
@@ -39,7 +39,6 @@
*/
public class ChannelUpdateAppliedTagsEvent extends GenericChannelUpdateEvent>
{
-
public static final ChannelField FIELD = ChannelField.APPLIED_TAGS;
public static final String IDENTIFIER = FIELD.getFieldName();
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultLayoutEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultLayoutEvent.java
index b471987e02..9d043c530a 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultLayoutEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultLayoutEvent.java
@@ -33,6 +33,9 @@
@SuppressWarnings("ConstantConditions")
public class ChannelUpdateDefaultLayoutEvent extends GenericChannelUpdateEvent
{
+ public static final ChannelField FIELD = ChannelField.DEFAULT_FORUM_LAYOUT;
+ public static final String IDENTIFIER = FIELD.getFieldName();
+
public ChannelUpdateDefaultLayoutEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nonnull ForumChannel.Layout oldValue, @Nonnull ForumChannel.Layout newValue)
{
super(api, responseNumber, channel, ChannelField.DEFAULT_FORUM_LAYOUT, oldValue, newValue);
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultReactionEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultReactionEvent.java
index caf25d4c1a..0a035ee172 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultReactionEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultReactionEvent.java
@@ -17,8 +17,8 @@
package net.dv8tion.jda.api.events.channel.update;
import net.dv8tion.jda.api.JDA;
-import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.ChannelField;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
import net.dv8tion.jda.api.entities.emoji.EmojiUnion;
@@ -26,7 +26,7 @@
import javax.annotation.Nullable;
/**
- * Indicates that the {@link ForumChannel#getDefaultReaction() default reaction emoji} of a {@link ForumChannel} changed.
+ * Indicates that the {@link ForumChannel#getDefaultReaction() default reaction emoji} of a {@link IPostContainer} changed.
*
* Can be used to retrieve the old default reaction and the new one.
*
@@ -34,11 +34,10 @@
*/
public class ChannelUpdateDefaultReactionEvent extends GenericChannelUpdateEvent
{
-
public static final ChannelField FIELD = ChannelField.DEFAULT_REACTION_EMOJI;
public static final String IDENTIFIER = FIELD.getFieldName();
- public ChannelUpdateDefaultReactionEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nullable EmojiUnion oldValue, @Nullable EmojiUnion newValue)
+ public ChannelUpdateDefaultReactionEvent(@Nonnull JDA api, long responseNumber, @Nonnull IPostContainer channel, @Nullable EmojiUnion oldValue, @Nullable EmojiUnion newValue)
{
super(api, responseNumber, channel, FIELD, oldValue, newValue);
}
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultSortOrderEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultSortOrderEvent.java
new file mode 100644
index 0000000000..cd9e0e512c
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultSortOrderEvent.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.api.events.channel.update;
+
+import net.dv8tion.jda.api.JDA;
+import net.dv8tion.jda.api.entities.channel.ChannelField;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
+
+import javax.annotation.Nonnull;
+
+/**
+ * Indicates that the {@link IPostContainer#getDefaultSortOrder() default sort order} of a {@link IPostContainer} changed.
+ *
+ * Can be used to retrieve the old default sort order and the new one.
+ *
+ * @see ChannelField#DEFAULT_SORT_ORDER
+ */
+@SuppressWarnings("ConstantConditions")
+public class ChannelUpdateDefaultSortOrderEvent extends GenericChannelUpdateEvent
+{
+ public static final ChannelField FIELD = ChannelField.DEFAULT_SORT_ORDER;
+ public static final String IDENTIFIER = FIELD.getFieldName();
+
+ public ChannelUpdateDefaultSortOrderEvent(@Nonnull JDA api, long responseNumber, IPostContainer channel, IPostContainer.SortOrder oldValue)
+ {
+ super(api, responseNumber, channel, ChannelField.DEFAULT_SORT_ORDER, oldValue, channel.getDefaultSortOrder());
+ }
+
+ @Nonnull
+ @Override
+ public IPostContainer.SortOrder getOldValue()
+ {
+ return super.getOldValue();
+ }
+
+ @Nonnull
+ @Override
+ public IPostContainer.SortOrder getNewValue()
+ {
+ return super.getNewValue();
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultThreadSlowmodeEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultThreadSlowmodeEvent.java
index 04856f45e2..793301d671 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultThreadSlowmodeEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultThreadSlowmodeEvent.java
@@ -32,7 +32,6 @@
*/
public class ChannelUpdateDefaultThreadSlowmodeEvent extends GenericChannelUpdateEvent
{
-
public static final ChannelField FIELD = ChannelField.DEFAULT_THREAD_SLOWMODE;
public static final String IDENTIFIER = FIELD.getFieldName();
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateFlagsEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateFlagsEvent.java
index b3630e396e..f07d1a8474 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateFlagsEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateFlagsEvent.java
@@ -33,7 +33,6 @@
*/
public class ChannelUpdateFlagsEvent extends GenericChannelUpdateEvent>
{
-
public static final ChannelField FIELD = ChannelField.FLAGS;
public static final String IDENTIFIER = FIELD.getFieldName();
diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateTypeEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateTypeEvent.java
index 96b6bd064d..51a5775e0f 100644
--- a/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateTypeEvent.java
+++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateTypeEvent.java
@@ -32,6 +32,7 @@
*
* - of type {@link ChannelType#TEXT} is converted to type {@link ChannelType#NEWS}
* - of type {@link ChannelType#NEWS} is converted to type {@link ChannelType#TEXT}
+ * - of type {@link ChannelType#FORUM} is converted to type {@link ChannelType#MEDIA}
*
*
* @see Channel#getType()
diff --git a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java
index 2362720ba2..4da8931a5c 100644
--- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java
+++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java
@@ -214,7 +214,7 @@ public void onChannelUpdateRegion(@Nonnull ChannelUpdateRegionEvent event) {}
public void onChannelUpdateSlowmode(@Nonnull ChannelUpdateSlowmodeEvent event) {}
public void onChannelUpdateDefaultThreadSlowmode(@Nonnull ChannelUpdateDefaultThreadSlowmodeEvent event) {}
public void onChannelUpdateDefaultReaction(@Nonnull ChannelUpdateDefaultReactionEvent event) {}
-// public void onChannelUpdateDefaultSortOrder(@Nonnull ChannelUpdateDefaultSortOrderEvent event) {}
+ public void onChannelUpdateDefaultSortOrder(@Nonnull ChannelUpdateDefaultSortOrderEvent event) {}
public void onChannelUpdateDefaultLayout(@Nonnull ChannelUpdateDefaultLayoutEvent event) {}
public void onChannelUpdateTopic(@Nonnull ChannelUpdateTopicEvent event) {}
public void onChannelUpdateType(@Nonnull ChannelUpdateTypeEvent event) {}
diff --git a/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java b/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java
index 75750e7f2e..336d58b9f7 100644
--- a/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java
+++ b/src/main/java/net/dv8tion/jda/api/interactions/Interaction.java
@@ -29,7 +29,7 @@
import net.dv8tion.jda.api.interactions.commands.Command;
import net.dv8tion.jda.api.interactions.modals.Modal;
import net.dv8tion.jda.api.interactions.modals.ModalInteraction;
-import net.dv8tion.jda.internal.utils.Helpers;
+import net.dv8tion.jda.internal.utils.ChannelUtil;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -168,7 +168,7 @@ default ChannelType getChannelType()
@Nonnull
default GuildChannel getGuildChannel()
{
- return Helpers.safeChannelCast(getChannel(), GuildChannel.class);
+ return ChannelUtil.safeChannelCast(getChannel(), GuildChannel.class);
}
/**
@@ -183,7 +183,7 @@ default GuildChannel getGuildChannel()
@Nonnull
default MessageChannel getMessageChannel()
{
- return Helpers.safeChannelCast(getChannel(), MessageChannel.class);
+ return ChannelUtil.safeChannelCast(getChannel(), MessageChannel.class);
}
/**
diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/ChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/ChannelManager.java
index 5436d69669..7010b09f20 100644
--- a/src/main/java/net/dv8tion/jda/api/managers/channel/ChannelManager.java
+++ b/src/main/java/net/dv8tion/jda/api/managers/channel/ChannelManager.java
@@ -42,7 +42,6 @@
*
* @see GuildChannel#getManager()
*/
-//TODO-v5: Revisit all usages of IllegalStateException in the setX methods in this class to see if they should be UnsupportedOperationException like in ChannelAction
public interface ChannelManager> extends Manager
{
/** Used to reset the name field */
@@ -79,18 +78,20 @@ public interface ChannelManager{@link #REQUIRE_TAG}
* {@link #DEFAULT_REACTION}
* {@link #DEFAULT_LAYOUT}
+ * {@link #DEFAULT_SORT_ORDER}
+ * {@link #HIDE_MEDIA_DOWNLOAD_OPTIONS}
+ * {@link #DEFAULT_THREAD_SLOWMODE}
*
*
* @param fields
@@ -157,6 +161,9 @@ public interface ChannelManager{@link #REQUIRE_TAG}
* {@link #DEFAULT_REACTION}
* {@link #DEFAULT_LAYOUT}
+ * {@link #DEFAULT_SORT_ORDER}
+ * {@link #HIDE_MEDIA_DOWNLOAD_OPTIONS}
+ * {@link #DEFAULT_THREAD_SLOWMODE}
*
*
* @param fields
diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/IPostContainerManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/IPostContainerManager.java
new file mode 100644
index 0000000000..f9c1004973
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/IPostContainerManager.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.api.managers.channel.attribute;
+
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer.SortOrder;
+import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag;
+import net.dv8tion.jda.api.entities.channel.forums.ForumTagData;
+import net.dv8tion.jda.api.entities.emoji.Emoji;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.List;
+
+/**
+ * Manager abstraction to configure settings related to forum post containers, such as {@link ForumChannel}.
+ *
+ * @param The channel type
+ * @param The manager type
+ */
+public interface IPostContainerManager> extends IThreadContainerManager, IPermissionContainerManager
+{
+ /**
+ * Sets the tag requirement state of this {@link IPostContainer}.
+ *
If true, all new posts must have at least one tag.
+ *
+ * @param requireTag
+ * The new tag requirement state for the selected {@link IPostContainer}
+ *
+ * @return ChannelManager for chaining convenience.
+ *
+ * @see IPostContainer#isTagRequired()
+ */
+ @Nonnull
+ @CheckReturnValue
+ M setTagRequired(boolean requireTag);
+
+ /**
+ * Sets the available tags of the selected {@link IPostContainer}.
+ *
Tags will be ordered based on the provided list order.
+ *
+ * This is a full replacement of the tags list, all missing tags will be removed.
+ * You can use {@link ForumTagData} to create new tags or update existing ones.
+ *
+ *
Example
+ *
{@code
+ * List tags = new ArrayList<>(channel.getAvailableTags());
+ * tags.add(new ForumTagData("question").setModerated(true)); // add a new tag
+ * tags.set(0, ForumTagData.from(tags.get(0)).setName("bug report")); // update an existing tag
+ * // Update the tag list
+ * channel.getManager().setAvailableTags(tags).queue();
+ * }
+ *
+ * @param tags
+ * The new available tags in the desired order.
+ *
+ * @throws IllegalArgumentException
+ * If the provided list is null or contains null elements
+ *
+ * @return ChannelManager for chaining convenience
+ *
+ * @see IPostContainer#getAvailableTags()
+ */
+ @Nonnull
+ @CheckReturnValue
+ M setAvailableTags(@Nonnull List extends BaseForumTag> tags);
+
+ /**
+ * Sets the default reaction emoji of the selected {@link IPostContainer}.
+ *
This does not support custom emoji from other guilds.
+ *
+ * @param emoji
+ * The new default reaction emoji, or null to unset.
+ *
+ * @return ChannelManager for chaining convenience
+ *
+ * @see IPostContainer#getDefaultReaction()
+ */
+ @Nonnull
+ @CheckReturnValue
+ M setDefaultReaction(@Nullable Emoji emoji);
+
+ /**
+ * Sets the default sort order of the selected {@link IPostContainer}.
+ *
+ * @param sortOrder
+ * The new {@link SortOrder}
+ *
+ * @throws IllegalArgumentException
+ * If null or {@link SortOrder#UNKNOWN} is provided
+ *
+ * @return ChannelManager for chaining convenience
+ *
+ * @see IPostContainer#getDefaultSortOrder()
+ */
+ @Nonnull
+ @CheckReturnValue
+ M setDefaultSortOrder(@Nonnull SortOrder sortOrder);
+}
diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/IThreadContainerManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/IThreadContainerManager.java
new file mode 100644
index 0000000000..c8bae1a70b
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/IThreadContainerManager.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.api.managers.channel.attribute;
+
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
+import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.managers.channel.ChannelManager;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nonnull;
+
+/**
+ * Manager abstraction to configure settings related to thread channel containers, such as {@link ForumChannel}.
+ *
+ * @param The channel type
+ * @param The manager type
+ */
+public interface IThreadContainerManager> extends ChannelManager
+{
+ /**
+ * Sets the default thread slowmode of the selected channel.
+ * This is applied to newly created threads by default.
+ *
Provide {@code 0} to disable slowmode.
+ *
+ * A channel default thread slowmode must not be negative nor greater than {@link ISlowmodeChannel#MAX_SLOWMODE}!
+ *
+ *
Note: Bots are unaffected by this.
+ *
Having {@link Permission#MESSAGE_MANAGE MESSAGE_MANAGE} or
+ * {@link Permission#MANAGE_CHANNEL MANAGE_CHANNEL} permission also
+ * grants immunity to slowmode.
+ *
+ * @param slowmode
+ * The new default thread slowmode (in seconds)
+ *
+ * @throws IllegalArgumentException
+ * If the provided slowmode is negative or greater than {@value ISlowmodeChannel#MAX_SLOWMODE}
+ *
+ * @return ChannelManager for chaining convenience
+ *
+ * @see IThreadContainer#getDefaultThreadSlowmode()
+ */
+ @Nonnull
+ @CheckReturnValue
+ M setDefaultThreadSlowmode(int slowmode);
+}
diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ForumChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ForumChannelManager.java
index 0434a7a125..b19e489a5c 100644
--- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ForumChannelManager.java
+++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ForumChannelManager.java
@@ -17,17 +17,13 @@
package net.dv8tion.jda.api.managers.channel.concrete;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
-import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag;
-import net.dv8tion.jda.api.entities.channel.forums.ForumTagData;
-import net.dv8tion.jda.api.entities.emoji.Emoji;
import net.dv8tion.jda.api.managers.channel.attribute.IAgeRestrictedChannelManager;
+import net.dv8tion.jda.api.managers.channel.attribute.IPostContainerManager;
import net.dv8tion.jda.api.managers.channel.attribute.ISlowmodeChannelManager;
import net.dv8tion.jda.api.managers.channel.middleman.StandardGuildChannelManager;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
-import java.util.List;
/**
* Manager providing functionality to modify a {@link ForumChannel ForumChannel}.
@@ -46,69 +42,10 @@
*/
public interface ForumChannelManager extends
StandardGuildChannelManager,
+ IPostContainerManager,
IAgeRestrictedChannelManager,
ISlowmodeChannelManager
{
- /**
- * Sets the tag requirement state of this {@link ForumChannel}.
- *
If true, all new posts must have at least one tag.
- *
- * @param requireTag
- * The new tag requirement state for the selected {@link ForumChannel}
- *
- * @return ChannelManager for chaining convenience.
- *
- * @see ForumChannel#isTagRequired()
- */
- @Nonnull
- @CheckReturnValue
- ForumChannelManager setTagRequired(boolean requireTag);
-
- /**
- * Sets the available tags of the selected {@link ForumChannel}.
- *
Tags will be ordered based on the provided list order.
- *
- * This is a full replacement of the tags list, all missing tags will be removed.
- * You can use {@link ForumTagData} to create new tags or update existing ones.
- *
- *
Example
- *
{@code
- * List tags = new ArrayList<>(channel.getAvailableTags());
- * tags.add(new ForumTagData("question").setModerated(true)); // add a new tag
- * tags.set(0, ForumTagData.from(tags.get(0)).setName("bug report")); // update an existing tag
- * // Update the tag list
- * channel.getManager().setAvailableTags(tags).queue();
- * }
- *
- * @param tags
- * The new available tags in the desired order.
- *
- * @throws IllegalArgumentException
- * If the provided list is null or contains null elements
- *
- * @return ChannelManager for chaining convenience
- *
- * @see ForumChannel#getAvailableTags()
- */
- @Nonnull
- @CheckReturnValue
- ForumChannelManager setAvailableTags(@Nonnull List extends BaseForumTag> tags);
-
- /**
- * Sets the default reaction emoji of the selected {@link ForumChannel}.
- *
This does not support custom emoji from other guilds.
- *
- * @param emoji
- * The new default reaction emoji, or null to unset.
- *
- * @return ChannelManager for chaining convenience
- *
- * @see ForumChannel#getDefaultReaction()
- */
- @Nonnull
- @CheckReturnValue
- ForumChannelManager setDefaultReaction(@Nullable Emoji emoji);
-
/**
* Sets the default layout of the selected {@link ForumChannel}.
*
diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/MediaChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/MediaChannelManager.java
new file mode 100644
index 0000000000..b215cd306a
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/MediaChannelManager.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.api.managers.channel.concrete;
+
+import net.dv8tion.jda.api.entities.channel.concrete.MediaChannel;
+import net.dv8tion.jda.api.managers.channel.attribute.IAgeRestrictedChannelManager;
+import net.dv8tion.jda.api.managers.channel.attribute.IPostContainerManager;
+import net.dv8tion.jda.api.managers.channel.attribute.ISlowmodeChannelManager;
+import net.dv8tion.jda.api.managers.channel.middleman.StandardGuildChannelManager;
+
+import javax.annotation.CheckReturnValue;
+import javax.annotation.Nonnull;
+
+/**
+ * Manager providing functionality to modify a {@link MediaChannel}.
+ *
+ * Example
+ *
{@code
+ * manager.setName("Art Showcase")
+ * .setSlowmode(10)
+ * .setTopic("Showcase your art creations here.")
+ * .queue();
+ * manager.reset(ChannelManager.NSFW | ChannelManager.NAME)
+ * .setName("NSFW Art Showcase")
+ * .setNSFW(true)
+ * .queue();
+ * }
+ */
+public interface MediaChannelManager extends
+ StandardGuildChannelManager,
+ IPostContainerManager,
+ IAgeRestrictedChannelManager,
+ ISlowmodeChannelManager
+{
+ /**
+ * Sets whether to hide the download media option on this channel.
+ *
+ * @param hideOption
+ * Whether to hide the download option
+ *
+ * @return ChannelManager for chaining convenience.
+ *
+ * @see MediaChannel#isMediaDownloadHidden()
+ */
+ @Nonnull
+ @CheckReturnValue
+ MediaChannelManager setHideMediaDownloadOption(boolean hideOption);
+}
diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/middleman/StandardGuildMessageChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/middleman/StandardGuildMessageChannelManager.java
index 4c283e357a..1fdd865a7b 100644
--- a/src/main/java/net/dv8tion/jda/api/managers/channel/middleman/StandardGuildMessageChannelManager.java
+++ b/src/main/java/net/dv8tion/jda/api/managers/channel/middleman/StandardGuildMessageChannelManager.java
@@ -18,6 +18,7 @@
import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel;
import net.dv8tion.jda.api.managers.channel.attribute.IAgeRestrictedChannelManager;
+import net.dv8tion.jda.api.managers.channel.attribute.IThreadContainerManager;
import javax.annotation.CheckReturnValue;
import javax.annotation.Nonnull;
@@ -40,7 +41,7 @@
* @see StandardGuildMessageChannel#getManager()
*/
public interface StandardGuildMessageChannelManager>
- extends StandardGuildChannelManager, IAgeRestrictedChannelManager
+ extends StandardGuildChannelManager, IAgeRestrictedChannelManager, IThreadContainerManager
{
/**
* Sets the topic of the selected {@link StandardGuildMessageChannel channel}.
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/ChannelAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/ChannelAction.java
index 86d7504aa5..5c94ecc372 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/ChannelAction.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/ChannelAction.java
@@ -24,7 +24,9 @@
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
import net.dv8tion.jda.api.entities.channel.concrete.Category;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
import net.dv8tion.jda.api.entities.channel.concrete.StageChannel;
@@ -142,7 +144,7 @@ public interface ChannelAction extends FluentAuditableRe
ChannelAction setPosition(@Nullable Integer position);
/**
- * Sets the topic for the new TextChannel
+ * Sets the topic for the channel
*
* @param topic
* The topic for the new GuildChannel
@@ -151,8 +153,8 @@ public interface ChannelAction extends FluentAuditableRe
* If this ChannelAction is not for a TextChannel
* @throws IllegalArgumentException
* If the provided topic is greater than {@value StandardGuildMessageChannel#MAX_TOPIC_LENGTH} in length.
- * For {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels},
- * this limit is {@value net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#MAX_FORUM_TOPIC_LENGTH} instead.
+ * For {@link IPostContainer IPostContainers},
+ * this limit is {@value IPostContainer#MAX_POST_CONTAINER_TOPIC_LENGTH} instead.
*
* @return The current ChannelAction, for chaining convenience
*/
@@ -161,7 +163,7 @@ public interface ChannelAction extends FluentAuditableRe
ChannelAction setTopic(@Nullable String topic);
/**
- * Sets the NSFW flag for the new TextChannel
+ * Sets the NSFW flag for the channel
*
* @param nsfw
* The NSFW flag for the new GuildChannel
@@ -199,7 +201,31 @@ public interface ChannelAction extends FluentAuditableRe
ChannelAction setSlowmode(int slowmode);
/**
- * Sets the default reaction emoji of the new {@link ForumChannel}.
+ * Sets the slowmode value, which limits the amount of time that individual users must wait
+ * between sending messages in the new channel. This is measured in seconds.
+ *
This is applied to newly created threads by default.
+ *
+ * Note: Bots are unaffected by this.
+ *
Having {@link net.dv8tion.jda.api.Permission#MESSAGE_MANAGE MESSAGE_MANAGE} or
+ * {@link net.dv8tion.jda.api.Permission#MANAGE_CHANNEL MANAGE_CHANNEL} permission also
+ * grants immunity to slowmode.
+ *
+ * @param slowmode
+ * The number of seconds required to wait between sending messages in the channel.
+ *
+ * @throws UnsupportedOperationException
+ * If this ChannelAction is not for a {@link IThreadContainer}
+ * @throws IllegalArgumentException
+ * If the {@code slowmode} is greater than {@link ISlowmodeChannel#MAX_SLOWMODE ISlowmodeChannel.MAX_SLOWMODE}, or less than 0
+ *
+ * @return The current ChannelAction, for chaining convenience
+ */
+ @Nonnull
+ @CheckReturnValue
+ ChannelAction setDefaultThreadSlowmode(int slowmode);
+
+ /**
+ * Sets the default reaction emoji of the channel.
*
This does not support custom emoji from other guilds.
*
* @param emoji
@@ -207,7 +233,7 @@ public interface ChannelAction extends FluentAuditableRe
*
* @return The current ChannelAction, for chaining convenience
*
- * @see ForumChannel#getDefaultReaction()
+ * @see IPostContainer#getDefaultReaction()
*/
@Nonnull
@CheckReturnValue
@@ -219,6 +245,9 @@ public interface ChannelAction extends FluentAuditableRe
* @param layout
* The new default layout.
*
+ * @throws IllegalArgumentException
+ * If null or {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel.Layout#UNKNOWN UNKNOWN} is provided
+ *
* @return The current ChannelAction, for chaining convenience
*
* @see ForumChannel#getDefaultLayout()
@@ -228,7 +257,24 @@ public interface ChannelAction extends FluentAuditableRe
ChannelAction setDefaultLayout(@Nonnull ForumChannel.Layout layout);
/**
- * Sets the available tags of the new {@link ForumChannel}.
+ * Sets the default sort order of the channel.
+ *
+ * @param sortOrder
+ * The new default sort order.
+ *
+ * @throws IllegalArgumentException
+ * If null or {@link net.dv8tion.jda.api.entities.channel.attribute.IPostContainer.SortOrder#UNKNOWN UNKNOWN} is provided
+ *
+ * @return The current ChannelAction, for chaining convenience
+ *
+ * @see IPostContainer#getDefaultSortOrder()
+ */
+ @Nonnull
+ @CheckReturnValue
+ ChannelAction setDefaultSortOrder(@Nonnull IPostContainer.SortOrder sortOrder);
+
+ /**
+ * Sets the available tags of the channel.
*
Tags will be ordered based on the provided list order.
*
* You can use {@link ForumTagData} to create new tags.
@@ -241,7 +287,7 @@ public interface ChannelAction extends FluentAuditableRe
*
* @return The current ChannelAction, for chaining convenience
*
- * @see ForumChannel#getAvailableTags()
+ * @see IPostContainer#getAvailableTags()
*/
@Nonnull
@CheckReturnValue
diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/ForumPostAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/ForumPostAction.java
index e381812d36..3f7ee64ec6 100644
--- a/src/main/java/net/dv8tion/jda/api/requests/restaction/ForumPostAction.java
+++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/ForumPostAction.java
@@ -16,6 +16,7 @@
package net.dv8tion.jda.api.requests.restaction;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
import net.dv8tion.jda.api.entities.channel.forums.ForumPost;
import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake;
@@ -35,17 +36,17 @@
* On success, this provides a {@link ForumPost} object with the {@link ForumPost#getMessage() starter message}
* and the {@link ForumPost#getThreadChannel() thread channel} of the post.
*
- * @see net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, MessageCreateData)
+ * @see IPostContainer#createForumPost(String, MessageCreateData)
*/
public interface ForumPostAction extends AbstractThreadCreateAction, MessageCreateRequest, FluentRestAction
{
/**
- * The {@link ForumChannel} to create the post in
+ * The {@link IPostContainer} to create the post in
*
- * @return The {@link ForumChannel}
+ * @return The {@link IPostContainer}
*/
@Nonnull
- ForumChannel getChannel();
+ IPostContainer getChannel();
/**
* Configures that tags which should be applied to the new post.
diff --git a/src/main/java/net/dv8tion/jda/api/sharding/ShardManager.java b/src/main/java/net/dv8tion/jda/api/sharding/ShardManager.java
index 1d8151a102..a611589ac0 100644
--- a/src/main/java/net/dv8tion/jda/api/sharding/ShardManager.java
+++ b/src/main/java/net/dv8tion/jda/api/sharding/ShardManager.java
@@ -812,6 +812,13 @@ default SnowflakeCacheView getForumChannelCache()
return CacheView.allSnowflakes(() -> this.getShardCache().stream().map(JDA::getForumChannelCache));
}
+ @Nonnull
+ @Override
+ default SnowflakeCacheView getMediaChannelCache()
+ {
+ return CacheView.allSnowflakes(() -> this.getShardCache().stream().map(JDA::getMediaChannelCache));
+ }
+
/**
* This returns the {@link net.dv8tion.jda.api.JDA JDA} instance which has the same id as the one provided.
*
If there is no shard with an id that matches the provided one, this will return {@code null}.
diff --git a/src/main/java/net/dv8tion/jda/api/utils/cache/CacheFlag.java b/src/main/java/net/dv8tion/jda/api/utils/cache/CacheFlag.java
index daaa6f3c80..d00955ad78 100644
--- a/src/main/java/net/dv8tion/jda/api/utils/cache/CacheFlag.java
+++ b/src/main/java/net/dv8tion/jda/api/utils/cache/CacheFlag.java
@@ -19,7 +19,7 @@
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Role;
-import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.requests.GatewayIntent;
@@ -73,7 +73,7 @@ public enum CacheFlag
*/
ROLE_TAGS,
/**
- * Enables cache for {@link ForumChannel#getAvailableTagCache()} and {@link ThreadChannel#getAppliedTags()}
+ * Enables cache for {@link IPostContainer#getAvailableTagCache()} and {@link ThreadChannel#getAppliedTags()}
*/
FORUM_TAGS,
/**
diff --git a/src/main/java/net/dv8tion/jda/internal/JDAImpl.java b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java
index 4db04cdfdd..cdab669427 100644
--- a/src/main/java/net/dv8tion/jda/internal/JDAImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java
@@ -108,6 +108,7 @@ public class JDAImpl implements JDA
protected final SnowflakeCacheViewImpl stageChannelCache = new SnowflakeCacheViewImpl<>(StageChannel.class, Channel::getName);
protected final SnowflakeCacheViewImpl threadChannelsCache = new SnowflakeCacheViewImpl<>(ThreadChannel.class, Channel::getName);
protected final SnowflakeCacheViewImpl forumChannelsCache = new SnowflakeCacheViewImpl<>(ForumChannel.class, Channel::getName);
+ protected final SnowflakeCacheViewImpl mediaChannelsCache = new SnowflakeCacheViewImpl<>(MediaChannel.class, Channel::getName);
protected final SnowflakeCacheViewImpl privateChannelCache = new SnowflakeCacheViewImpl<>(PrivateChannel.class, Channel::getName);
protected final LinkedList privateChannelLRU = new LinkedList<>();
@@ -775,6 +776,13 @@ public SnowflakeCacheView getForumChannelCache()
return forumChannelsCache;
}
+ @Nonnull
+ @Override
+ public SnowflakeCacheView getMediaChannelCache()
+ {
+ return mediaChannelsCache;
+ }
+
@Nonnull
@Override
public SnowflakeCacheView getPrivateChannelCache()
@@ -1278,6 +1286,11 @@ public SnowflakeCacheViewImpl getForumChannelsView()
return forumChannelsCache;
}
+ public SnowflakeCacheViewImpl getMediaChannelsView()
+ {
+ return mediaChannelsCache;
+ }
+
public SnowflakeCacheViewImpl getPrivateChannelsView()
{
return privateChannelCache;
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java
index 903cf4f006..a3514369c7 100644
--- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java
+++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java
@@ -59,6 +59,7 @@
import net.dv8tion.jda.internal.JDAImpl;
import net.dv8tion.jda.internal.entities.channel.concrete.*;
import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IPermissionContainerMixin;
+import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IPostContainerMixin;
import net.dv8tion.jda.internal.entities.channel.mixin.middleman.AudioChannelMixin;
import net.dv8tion.jda.internal.entities.emoji.CustomEmojiImpl;
import net.dv8tion.jda.internal.entities.emoji.RichCustomEmojiImpl;
@@ -398,31 +399,28 @@ public GuildImpl createGuild(long guildId, DataObject guildJson, TLongObjectMap<
return guildObj;
}
- private void createGuildChannel(GuildImpl guildObj, DataObject channelData)
+ public GuildChannel createGuildChannel(GuildImpl guildObj, DataObject channelData)
{
final ChannelType channelType = ChannelType.fromId(channelData.getInt("type"));
switch (channelType)
{
case TEXT:
- createTextChannel(guildObj, channelData, guildObj.getIdLong());
- break;
+ return createTextChannel(guildObj, channelData, guildObj.getIdLong());
case NEWS:
- createNewsChannel(guildObj, channelData, guildObj.getIdLong());
- break;
+ return createNewsChannel(guildObj, channelData, guildObj.getIdLong());
case STAGE:
- createStageChannel(guildObj, channelData, guildObj.getIdLong());
- break;
+ return createStageChannel(guildObj, channelData, guildObj.getIdLong());
case VOICE:
- createVoiceChannel(guildObj, channelData, guildObj.getIdLong());
- break;
+ return createVoiceChannel(guildObj, channelData, guildObj.getIdLong());
case CATEGORY:
- createCategory(guildObj, channelData, guildObj.getIdLong());
- break;
+ return createCategory(guildObj, channelData, guildObj.getIdLong());
case FORUM:
- createForumChannel(guildObj, channelData, guildObj.getIdLong());
- break;
+ return createForumChannel(guildObj, channelData, guildObj.getIdLong());
+ case MEDIA:
+ return createMediaChannel(guildObj, channelData, guildObj.getIdLong());
default:
LOG.debug("Cannot create channel for type " + channelData.getInt("type"));
+ return null;
}
}
@@ -1412,7 +1410,7 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu
.setParentCategory(json.getLong("parent_id", 0))
.setFlags(json.getInt("flags", 0))
.setDefaultReaction(json.optObject("default_reaction_emoji").orElse(null))
-// .setDefaultSortOrder(json.getInt("default_sort_order", -1))
+ .setDefaultSortOrder(json.getInt("default_sort_order", -1))
.setDefaultLayout(json.getInt("default_forum_layout", -1))
.setName(json.getString("name"))
.setTopic(json.getString("topic", null))
@@ -1427,7 +1425,59 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu
return channel;
}
- public ForumTagImpl createForumTag(ForumChannelImpl channel, DataObject json, int index)
+ public MediaChannel createMediaChannel(DataObject json, long guildId)
+ {
+ return createMediaChannel(null, json, guildId);
+ }
+
+ public MediaChannel createMediaChannel(GuildImpl guild, DataObject json, long guildId)
+ {
+ boolean playbackCache = false;
+ final long id = json.getLong("id");
+ MediaChannelImpl channel = (MediaChannelImpl) getJDA().getMediaChannelsView().get(id);
+ if (channel == null)
+ {
+ if (guild == null)
+ guild = (GuildImpl) getJDA().getGuildsView().get(guildId);
+ SnowflakeCacheViewImpl
+ guildView = guild.getMediaChannelsView(),
+ globalView = getJDA().getMediaChannelsView();
+ try (
+ UnlockHook vlock = guildView.writeLock();
+ UnlockHook jlock = globalView.writeLock())
+ {
+ channel = new MediaChannelImpl(id, guild);
+ guildView.getMap().put(id, channel);
+ playbackCache = globalView.getMap().put(id, channel) == null;
+ }
+ }
+
+ if (api.isCacheFlagSet(CacheFlag.FORUM_TAGS))
+ {
+ DataArray tags = json.getArray("available_tags");
+ for (int i = 0; i < tags.length(); i++)
+ createForumTag(channel, tags.getObject(i), i);
+ }
+
+ channel
+ .setParentCategory(json.getLong("parent_id", 0))
+ .setFlags(json.getInt("flags", 0))
+ .setDefaultReaction(json.optObject("default_reaction_emoji").orElse(null))
+ .setDefaultSortOrder(json.getInt("default_sort_order", -1))
+ .setName(json.getString("name"))
+ .setTopic(json.getString("topic", null))
+ .setPosition(json.getInt("position"))
+ .setDefaultThreadSlowmode(json.getInt("default_thread_rate_limit_per_user", 0))
+ .setSlowmode(json.getInt("rate_limit_per_user", 0))
+ .setNSFW(json.getBoolean("nsfw"));
+
+ createOverridesPass(channel, json.getArray("permission_overwrites"));
+ if (playbackCache)
+ getJDA().getEventCache().playbackCache(EventCache.Type.CHANNEL, id);
+ return channel;
+ }
+
+ public ForumTagImpl createForumTag(IPostContainerMixin> channel, DataObject json, int index)
{
final long id = json.getUnsignedLong("id");
SortedSnowflakeCacheViewImpl cache = channel.getAvailableTagCache();
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java
index 82eb8c051b..d0e706a273 100644
--- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java
@@ -27,6 +27,7 @@
import net.dv8tion.jda.api.entities.automod.build.AutoModRuleData;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
import net.dv8tion.jda.api.entities.channel.concrete.*;
import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
@@ -110,6 +111,7 @@ public class GuildImpl implements Guild
private final SortedSnowflakeCacheViewImpl stageChannelCache = new SortedSnowflakeCacheViewImpl<>(StageChannel.class, Channel::getName, Comparator.naturalOrder());
private final SortedSnowflakeCacheViewImpl threadChannelCache = new SortedSnowflakeCacheViewImpl<>(ThreadChannel.class, Channel::getName, Comparator.naturalOrder());
private final SortedSnowflakeCacheViewImpl forumChannelCache = new SortedSnowflakeCacheViewImpl<>(ForumChannel.class, Channel::getName, Comparator.naturalOrder());
+ private final SortedSnowflakeCacheViewImpl mediaChannelCache = new SortedSnowflakeCacheViewImpl<>(MediaChannel.class, Channel::getName, Comparator.naturalOrder());
private final SortedSnowflakeCacheViewImpl roleCache = new SortedSnowflakeCacheViewImpl<>(Role.class, Role::getName, Comparator.reverseOrder());
private final SnowflakeCacheViewImpl emojicache = new SnowflakeCacheViewImpl<>(RichCustomEmoji.class, RichCustomEmoji::getName);
private final SnowflakeCacheViewImpl stickerCache = new SnowflakeCacheViewImpl<>(GuildSticker.class, GuildSticker::getName);
@@ -163,6 +165,7 @@ public void invalidate()
SnowflakeCacheViewImpl threadView = getJDA().getThreadChannelsView();
SnowflakeCacheViewImpl newsView = getJDA().getNewsChannelView();
SnowflakeCacheViewImpl forumView = getJDA().getForumChannelsView();
+ SnowflakeCacheViewImpl mediaView = getJDA().getMediaChannelsView();
SnowflakeCacheViewImpl voiceView = getJDA().getVoiceChannelsView();
SnowflakeCacheViewImpl categoryView = getJDA().getCategoriesView();
@@ -191,7 +194,12 @@ public void invalidate()
try (UnlockHook hook = forumView.writeLock())
{
getForumChannelCache()
- .forEachUnordered(chan -> forumView.getMap().remove(chan.getIdLong()));
+ .forEachUnordered(chan -> forumView.getMap().remove(chan.getIdLong()));
+ }
+ try (UnlockHook hook = mediaView.writeLock())
+ {
+ getMediaChannelsView()
+ .forEachUnordered(chan -> mediaView.getMap().remove(chan.getIdLong()));
}
try (UnlockHook hook = voiceView.writeLock())
{
@@ -234,6 +242,76 @@ public void invalidate()
}
}
+ public void uncacheChannel(GuildChannel channel, boolean keepThreads)
+ {
+ long id = channel.getIdLong();
+ switch (channel.getType())
+ {
+ case TEXT:
+ api.getTextChannelsView().remove(id);
+ this.getTextChannelsView().remove(id);
+ break;
+ case NEWS:
+ api.getNewsChannelView().remove(id);
+ this.getNewsChannelView().remove(id);
+ break;
+ case MEDIA:
+ api.getMediaChannelsView().remove(id);
+ this.getMediaChannelsView().remove(id);
+ break;
+ case FORUM:
+ api.getForumChannelsView().remove(id);
+ this.getForumChannelsView().remove(id);
+ break;
+ case VOICE:
+ api.getVoiceChannelsView().remove(id);
+ this.getVoiceChannelsView().remove(id);
+ break;
+ case STAGE:
+ api.getStageChannelView().remove(id);
+ this.getStageChannelsView().remove(id);
+ break;
+ case CATEGORY:
+ api.getCategoriesView().remove(id);
+ this.getCategoriesView().remove(id);
+ break;
+ case GUILD_NEWS_THREAD:
+ case GUILD_PUBLIC_THREAD:
+ case GUILD_PRIVATE_THREAD:
+ api.getThreadChannelsView().remove(id);
+ this.getThreadChannelsView().remove(id);
+ break;
+ }
+
+ if (!keepThreads && channel instanceof IThreadContainer)
+ {
+ // Remove dangling threads
+ SortedSnowflakeCacheViewImpl localView = this.getThreadChannelsView();
+ SnowflakeCacheViewImpl globalView = api.getThreadChannelsView();
+ Predicate predicate = thread -> channel.equals(thread.getParentChannel());
+
+ try (UnlockHook hook1 = localView.writeLock(); UnlockHook hook2 = globalView.writeLock())
+ {
+ localView.getMap().valueCollection().removeIf(predicate);
+ globalView.getMap().valueCollection().removeIf(predicate);
+ }
+ }
+
+ // This might be too presumptuous, Channel#getParent still returns null regardless if the category is uncached
+// if (channel instanceof Category)
+// {
+// for (Channel chan : guild.getChannels())
+// {
+// if (!(chan instanceof ICategorizableChannelMixin>))
+// continue;
+//
+// ICategorizableChannelMixin> categoizable = (ICategorizableChannelMixin>) chan;
+// if (categoizable.getParentCategoryIdLong() == id)
+// categoizable.setParentCategory(0L);
+// }
+// }
+ }
+
@Nonnull
@Override
public RestAction> retrieveCommands(boolean withLocalizations)
@@ -772,6 +850,13 @@ public SortedSnowflakeCacheView getForumChannelCache()
return forumChannelCache;
}
+ @Nonnull
+ @Override
+ public SnowflakeCacheView getMediaChannelCache()
+ {
+ return mediaChannelCache;
+ }
+
@Nonnull
@Override
public SortedSnowflakeCacheView getStageChannelCache()
@@ -820,14 +905,16 @@ public List getChannels(boolean includeHidden)
SnowflakeCacheViewImpl text = getTextChannelsView();
SnowflakeCacheViewImpl news = getNewsChannelView();
SnowflakeCacheViewImpl forum = getForumChannelsView();
+ SnowflakeCacheViewImpl media = getMediaChannelsView();
- List channels = new ArrayList<>((int) (categories.size() + voice.size() + stage.size() + text.size() + news.size() + forum.size()));
+ List channels = new ArrayList<>((int) (categories.size() + voice.size() + stage.size() + text.size() + news.size() + forum.size() + media.size()));
voice.acceptStream(stream -> stream.filter(filterHidden).forEach(channels::add));
stage.acceptStream(stream -> stream.filter(filterHidden).forEach(channels::add));
text.acceptStream(stream -> stream.filter(filterHidden).forEach(channels::add));
news.acceptStream(stream -> stream.filter(filterHidden).forEach(channels::add));
forum.acceptStream(stream -> stream.filter(filterHidden).forEach(channels::add));
+ media.acceptStream(stream -> stream.filter(filterHidden).forEach(channels::add));
categories.forEach(category ->
{
@@ -1776,6 +1863,13 @@ public ChannelAction createForumChannel(@Nonnull String name, Cate
return createChannel(ChannelType.FORUM, ForumChannel.class, name, parent);
}
+ @Nonnull
+ @Override
+ public ChannelAction createMediaChannel(@Nonnull String name, @Nullable Category parent)
+ {
+ return createChannel(ChannelType.MEDIA, MediaChannel.class, name, parent);
+ }
+
@Nonnull
@Override
public ChannelAction createCategory(@Nonnull String name)
@@ -2250,6 +2344,11 @@ public SortedSnowflakeCacheViewImpl getForumChannelsView()
return forumChannelCache;
}
+ public SortedSnowflakeCacheViewImpl getMediaChannelsView()
+ {
+ return mediaChannelCache;
+ }
+
public SortedSnowflakeCacheViewImpl getRolesView()
{
return roleCache;
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/channel/AbstractChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/channel/AbstractChannelImpl.java
index 6ee0c87800..6a97f8e0b0 100644
--- a/src/main/java/net/dv8tion/jda/internal/entities/channel/AbstractChannelImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/entities/channel/AbstractChannelImpl.java
@@ -22,8 +22,8 @@
import net.dv8tion.jda.api.entities.channel.middleman.*;
import net.dv8tion.jda.internal.JDAImpl;
import net.dv8tion.jda.internal.entities.channel.mixin.ChannelMixin;
+import net.dv8tion.jda.internal.utils.ChannelUtil;
import net.dv8tion.jda.internal.utils.EntityString;
-import net.dv8tion.jda.internal.utils.Helpers;
import javax.annotation.Nonnull;
@@ -73,92 +73,99 @@ public T setName(String name)
@Nonnull
public PrivateChannel asPrivateChannel()
{
- return Helpers.safeChannelCast(this, PrivateChannel.class);
+ return ChannelUtil.safeChannelCast(this, PrivateChannel.class);
}
@Nonnull
public TextChannel asTextChannel()
{
- return Helpers.safeChannelCast(this, TextChannel.class);
+ return ChannelUtil.safeChannelCast(this, TextChannel.class);
}
@Nonnull
public NewsChannel asNewsChannel()
{
- return Helpers.safeChannelCast(this, NewsChannel.class);
+ return ChannelUtil.safeChannelCast(this, NewsChannel.class);
}
@Nonnull
public VoiceChannel asVoiceChannel()
{
- return Helpers.safeChannelCast(this, VoiceChannel.class);
+ return ChannelUtil.safeChannelCast(this, VoiceChannel.class);
}
@Nonnull
public StageChannel asStageChannel()
{
- return Helpers.safeChannelCast(this, StageChannel.class);
+ return ChannelUtil.safeChannelCast(this, StageChannel.class);
}
@Nonnull
public ThreadChannel asThreadChannel()
{
- return Helpers.safeChannelCast(this, ThreadChannel.class);
+ return ChannelUtil.safeChannelCast(this, ThreadChannel.class);
}
@Nonnull
public Category asCategory()
{
- return Helpers.safeChannelCast(this, Category.class);
+ return ChannelUtil.safeChannelCast(this, Category.class);
}
@Nonnull
@Override
public ForumChannel asForumChannel()
{
- return Helpers.safeChannelCast(this, ForumChannel.class);
+ return ChannelUtil.safeChannelCast(this, ForumChannel.class);
+ }
+
+ @Nonnull
+ @Override
+ public MediaChannel asMediaChannel()
+ {
+ return ChannelUtil.safeChannelCast(this, MediaChannel.class);
}
@Nonnull
public MessageChannel asMessageChannel()
{
- return Helpers.safeChannelCast(this, MessageChannel.class);
+ return ChannelUtil.safeChannelCast(this, MessageChannel.class);
}
@Nonnull
public AudioChannel asAudioChannel()
{
- return Helpers.safeChannelCast(this, AudioChannel.class);
+ return ChannelUtil.safeChannelCast(this, AudioChannel.class);
}
@Nonnull
public IThreadContainer asThreadContainer()
{
- return Helpers.safeChannelCast(this, IThreadContainer.class);
+ return ChannelUtil.safeChannelCast(this, IThreadContainer.class);
}
@Nonnull
public GuildChannel asGuildChannel()
{
- return Helpers.safeChannelCast(this, GuildChannel.class);
+ return ChannelUtil.safeChannelCast(this, GuildChannel.class);
}
@Nonnull
public GuildMessageChannel asGuildMessageChannel()
{
- return Helpers.safeChannelCast(this, GuildMessageChannel.class);
+ return ChannelUtil.safeChannelCast(this, GuildMessageChannel.class);
}
@Nonnull
public StandardGuildChannel asStandardGuildChannel()
{
- return Helpers.safeChannelCast(this, StandardGuildChannel.class);
+ return ChannelUtil.safeChannelCast(this, StandardGuildChannel.class);
}
@Nonnull
public StandardGuildMessageChannel asStandardGuildMessageChannel()
{
- return Helpers.safeChannelCast(this, StandardGuildMessageChannel.class);
+ return ChannelUtil.safeChannelCast(this, StandardGuildMessageChannel.class);
}
@Override
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/CategoryImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/CategoryImpl.java
index 7018f18bb0..9dcbd3a5a4 100644
--- a/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/CategoryImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/CategoryImpl.java
@@ -104,6 +104,14 @@ public ChannelAction createForumChannel(@Nonnull String name)
return trySync(action);
}
+ @Nonnull
+ @Override
+ public ChannelAction createMediaChannel(@Nonnull String name)
+ {
+ ChannelAction action = getGuild().createMediaChannel(name, this);
+ return trySync(action);
+ }
+
@Nonnull
@Override
public CategoryOrderAction modifyTextChannelPositions()
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/ForumChannelImpl.java
similarity index 79%
rename from src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java
rename to src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/ForumChannelImpl.java
index 2000d654ac..42b46f53ec 100644
--- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/ForumChannelImpl.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package net.dv8tion.jda.internal.entities;
+package net.dv8tion.jda.internal.entities.channel.concrete;
import gnu.trove.map.TLongObjectMap;
import net.dv8tion.jda.api.Permission;
@@ -31,22 +31,14 @@
import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji;
import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager;
import net.dv8tion.jda.api.requests.restaction.ChannelAction;
-import net.dv8tion.jda.api.requests.restaction.ForumPostAction;
-import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
import net.dv8tion.jda.api.utils.MiscUtil;
import net.dv8tion.jda.api.utils.data.DataObject;
-import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
-import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+import net.dv8tion.jda.internal.entities.GuildImpl;
import net.dv8tion.jda.internal.entities.channel.middleman.AbstractGuildChannelImpl;
-import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IAgeRestrictedChannelMixin;
-import net.dv8tion.jda.internal.entities.channel.mixin.attribute.ISlowmodeChannelMixin;
-import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IWebhookContainerMixin;
-import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IThreadContainerMixin;
-import net.dv8tion.jda.internal.entities.channel.mixin.attribute.ITopicChannelMixin;
+import net.dv8tion.jda.internal.entities.channel.mixin.attribute.*;
import net.dv8tion.jda.internal.entities.channel.mixin.middleman.StandardGuildChannelMixin;
import net.dv8tion.jda.internal.entities.emoji.CustomEmojiImpl;
import net.dv8tion.jda.internal.managers.channel.concrete.ForumChannelManagerImpl;
-import net.dv8tion.jda.internal.requests.restaction.ForumPostActionImpl;
import net.dv8tion.jda.internal.utils.Checks;
import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl;
@@ -64,7 +56,7 @@ public class ForumChannelImpl extends AbstractGuildChannelImpl
IAgeRestrictedChannelMixin,
ISlowmodeChannelMixin,
IWebhookContainerMixin,
- IThreadContainerMixin,
+ IPostContainerMixin,
ITopicChannelMixin
{
private final TLongObjectMap overrides = MiscUtil.newLongMap();
@@ -77,7 +69,7 @@ public class ForumChannelImpl extends AbstractGuildChannelImpl
private int position;
private int flags;
private int slowmode;
-// private int defaultSortOrder;
+ private int defaultSortOrder;
private int defaultLayout;
protected int defaultThreadSlowmode;
@@ -114,6 +106,8 @@ public ChannelAction createCopy(@Nonnull Guild guild)
.setSlowmode(slowmode)
.setAvailableTags(getAvailableTags())
.setDefaultLayout(Layout.fromKey(defaultLayout));
+ if (defaultSortOrder != -1)
+ action.setDefaultSortOrder(SortOrder.fromKey(defaultSortOrder));
if (defaultReaction instanceof UnicodeEmoji)
action.setDefaultReaction(defaultReaction);
if (guild.equals(getGuild()))
@@ -195,40 +189,18 @@ public int getDefaultThreadSlowmode()
return defaultThreadSlowmode;
}
-// @Nonnull
-// @Override
-// public SortOrder getDefaultSortOrder()
-// {
-// return SortOrder.fromKey(defaultSortOrder);
-// }
-
- @Nonnull
- @Override
- public Layout getDefaultLayout()
- {
- return Layout.fromKey(defaultLayout);
- }
-
@Nonnull
@Override
- public ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message)
+ public SortOrder getDefaultSortOrder()
{
- checkPermission(Permission.MESSAGE_SEND);
- return new ForumPostActionImpl(this, name, new MessageCreateBuilder().applyData(message));
+ return SortOrder.fromKey(defaultSortOrder);
}
@Nonnull
@Override
- public ThreadChannelAction createThreadChannel(@Nonnull String name)
- {
- throw new UnsupportedOperationException("You cannot create threads without a message payload in forum channels! Use createForumPost(...) instead.");
- }
-
- @Nonnull
- @Override
- public ThreadChannelAction createThreadChannel(@Nonnull String name, @Nonnull String messageId)
+ public Layout getDefaultLayout()
{
- throw new UnsupportedOperationException("You cannot create threads without a message payload in forum channels! Use createForumPost(...) instead.");
+ return Layout.fromKey(defaultLayout);
}
public int getRawFlags()
@@ -236,10 +208,10 @@ public int getRawFlags()
return flags;
}
-// public int getRawSortOrder()
-// {
-// return defaultSortOrder;
-// }
+ public int getRawSortOrder()
+ {
+ return defaultSortOrder;
+ }
public int getRawLayout()
{
@@ -287,12 +259,14 @@ public ForumChannelImpl setTopic(String topic)
return this;
}
+ @Override
public ForumChannelImpl setFlags(int flags)
{
this.flags = flags;
return this;
}
+ @Override
public ForumChannelImpl setDefaultReaction(DataObject emoji)
{
if (emoji != null && !emoji.isNull("emoji_id"))
@@ -304,11 +278,12 @@ else if (emoji != null && !emoji.isNull("emoji_name"))
return this;
}
-// public ForumChannelImpl setDefaultSortOrder(int defaultSortOrder)
-// {
-// this.defaultSortOrder = defaultSortOrder;
-// return this;
-// }
+ @Override
+ public ForumChannelImpl setDefaultSortOrder(int defaultSortOrder)
+ {
+ this.defaultSortOrder = defaultSortOrder;
+ return this;
+ }
public ForumChannelImpl setDefaultLayout(int layout)
{
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/MediaChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/MediaChannelImpl.java
new file mode 100644
index 0000000000..62bdb2dc37
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/MediaChannelImpl.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.internal.entities.channel.concrete;
+
+import gnu.trove.map.TLongObjectMap;
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.Member;
+import net.dv8tion.jda.api.entities.PermissionOverride;
+import net.dv8tion.jda.api.entities.channel.ChannelFlag;
+import net.dv8tion.jda.api.entities.channel.concrete.Category;
+import net.dv8tion.jda.api.entities.channel.concrete.MediaChannel;
+import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
+import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion;
+import net.dv8tion.jda.api.entities.emoji.Emoji;
+import net.dv8tion.jda.api.entities.emoji.EmojiUnion;
+import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji;
+import net.dv8tion.jda.api.managers.channel.concrete.MediaChannelManager;
+import net.dv8tion.jda.api.requests.restaction.ChannelAction;
+import net.dv8tion.jda.api.utils.MiscUtil;
+import net.dv8tion.jda.api.utils.data.DataObject;
+import net.dv8tion.jda.internal.entities.GuildImpl;
+import net.dv8tion.jda.internal.entities.channel.middleman.AbstractGuildChannelImpl;
+import net.dv8tion.jda.internal.entities.channel.mixin.attribute.*;
+import net.dv8tion.jda.internal.entities.channel.mixin.middleman.StandardGuildChannelMixin;
+import net.dv8tion.jda.internal.entities.emoji.CustomEmojiImpl;
+import net.dv8tion.jda.internal.managers.channel.concrete.MediaChannelManagerImpl;
+import net.dv8tion.jda.internal.utils.Checks;
+import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl;
+
+import javax.annotation.Nonnull;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class MediaChannelImpl extends AbstractGuildChannelImpl
+ implements MediaChannel,
+ GuildChannelUnion,
+ StandardGuildChannelMixin,
+ IAgeRestrictedChannelMixin,
+ ISlowmodeChannelMixin,
+ IWebhookContainerMixin,
+ IPostContainerMixin,
+ ITopicChannelMixin
+{
+ private final TLongObjectMap overrides = MiscUtil.newLongMap();
+ private final SortedSnowflakeCacheViewImpl tagCache = new SortedSnowflakeCacheViewImpl<>(ForumTag.class, ForumTag::getName, Comparator.naturalOrder());
+
+ private Emoji defaultReaction;
+ private String topic;
+ private long parentCategoryId;
+ private boolean nsfw = false;
+ private int position;
+ private int flags;
+ private int slowmode;
+ private int defaultSortOrder;
+ protected int defaultThreadSlowmode;
+
+ public MediaChannelImpl(long id, GuildImpl guild)
+ {
+ super(id, guild);
+ }
+
+ @Nonnull
+ @Override
+ public MediaChannelManager getManager()
+ {
+ return new MediaChannelManagerImpl(this);
+ }
+
+ @Nonnull
+ @Override
+ public List getMembers()
+ {
+ return Collections.unmodifiableList(getGuild().getMembers()
+ .stream()
+ .filter(m -> m.hasPermission(this, Permission.VIEW_CHANNEL))
+ .collect(Collectors.toList()));
+ }
+
+ @Nonnull
+ @Override
+ public ChannelAction createCopy(@Nonnull Guild guild)
+ {
+ Checks.notNull(guild, "Guild");
+ ChannelAction action = guild.createMediaChannel(name)
+ .setNSFW(nsfw)
+ .setTopic(topic)
+ .setSlowmode(slowmode)
+ .setAvailableTags(getAvailableTags());
+ if (defaultSortOrder != -1)
+ action.setDefaultSortOrder(SortOrder.fromKey(defaultSortOrder));
+ if (defaultReaction instanceof UnicodeEmoji)
+ action.setDefaultReaction(defaultReaction);
+ if (guild.equals(getGuild()))
+ {
+ Category parent = getParentCategory();
+ action.setDefaultReaction(defaultReaction);
+ if (parent != null)
+ action.setParent(parent);
+ for (PermissionOverride o : overrides.valueCollection())
+ {
+ if (o.isMemberOverride())
+ action.addMemberPermissionOverride(o.getIdLong(), o.getAllowedRaw(), o.getDeniedRaw());
+ else
+ action.addRolePermissionOverride(o.getIdLong(), o.getAllowedRaw(), o.getDeniedRaw());
+ }
+ }
+ return action;
+ }
+
+ @Nonnull
+ @Override
+ public EnumSet getFlags()
+ {
+ return ChannelFlag.fromRaw(flags);
+ }
+
+ @Nonnull
+ @Override
+ public SortedSnowflakeCacheViewImpl getAvailableTagCache()
+ {
+ return tagCache;
+ }
+
+ @Override
+ public TLongObjectMap getPermissionOverrideMap()
+ {
+ return overrides;
+ }
+
+ @Override
+ public boolean isNSFW()
+ {
+ return nsfw;
+ }
+
+ @Override
+ public int getPositionRaw()
+ {
+ return position;
+ }
+
+ @Override
+ public long getParentCategoryIdLong()
+ {
+ return parentCategoryId;
+ }
+
+ @Override
+ public int getSlowmode()
+ {
+ return slowmode;
+ }
+
+ @Override
+ public String getTopic()
+ {
+ return topic;
+ }
+
+ @Override
+ public EmojiUnion getDefaultReaction()
+ {
+ return (EmojiUnion) defaultReaction;
+ }
+
+ @Override
+ public int getDefaultThreadSlowmode()
+ {
+ return defaultThreadSlowmode;
+ }
+
+ @Nonnull
+ @Override
+ public SortOrder getDefaultSortOrder()
+ {
+ return SortOrder.fromKey(defaultSortOrder);
+ }
+
+ public int getRawFlags()
+ {
+ return flags;
+ }
+
+ public int getRawSortOrder()
+ {
+ return defaultSortOrder;
+ }
+
+ // Setters
+
+ @Override
+ public MediaChannelImpl setParentCategory(long parentCategoryId)
+ {
+ this.parentCategoryId = parentCategoryId;
+ return this;
+ }
+
+ @Override
+ public MediaChannelImpl setPosition(int position)
+ {
+ this.position = position;
+ return this;
+ }
+
+ @Override
+ public MediaChannelImpl setDefaultThreadSlowmode(int defaultThreadSlowmode)
+ {
+ this.defaultThreadSlowmode = defaultThreadSlowmode;
+ return this;
+ }
+
+ @Override
+ public MediaChannelImpl setNSFW(boolean nsfw)
+ {
+ this.nsfw = nsfw;
+ return this;
+ }
+
+ @Override
+ public MediaChannelImpl setSlowmode(int slowmode)
+ {
+ this.slowmode = slowmode;
+ return this;
+ }
+
+ @Override
+ public MediaChannelImpl setTopic(String topic)
+ {
+ this.topic = topic;
+ return this;
+ }
+
+ public MediaChannelImpl setFlags(int flags)
+ {
+ this.flags = flags;
+ return this;
+ }
+
+ public MediaChannelImpl setDefaultReaction(DataObject emoji)
+ {
+ if (emoji != null && !emoji.isNull("emoji_id"))
+ this.defaultReaction = new CustomEmojiImpl("", emoji.getUnsignedLong("emoji_id"), false);
+ else if (emoji != null && !emoji.isNull("emoji_name"))
+ this.defaultReaction = Emoji.fromUnicode(emoji.getString("emoji_name"));
+ else
+ this.defaultReaction = null;
+ return this;
+ }
+
+ public MediaChannelImpl setDefaultSortOrder(int defaultSortOrder)
+ {
+ this.defaultSortOrder = defaultSortOrder;
+ return this;
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/ThreadChannelImpl.java
index ce4e5fd45f..f01c5485c4 100644
--- a/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/ThreadChannelImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/entities/channel/concrete/ThreadChannelImpl.java
@@ -149,6 +149,9 @@ public List getMembers()
@Override
public IThreadContainerUnion getParentChannel()
{
+ IThreadContainer realChannel = getGuild().getChannelById(IThreadContainer.class, parentChannel.getIdLong());
+ if (realChannel != null)
+ parentChannel = (IThreadContainerUnion) realChannel;
return parentChannel;
}
diff --git a/src/main/java/net/dv8tion/jda/internal/entities/channel/mixin/attribute/IPostContainerMixin.java b/src/main/java/net/dv8tion/jda/internal/entities/channel/mixin/attribute/IPostContainerMixin.java
new file mode 100644
index 0000000000..114e1e770e
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/internal/entities/channel/mixin/attribute/IPostContainerMixin.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.internal.entities.channel.mixin.attribute;
+
+import net.dv8tion.jda.api.Permission;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
+import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
+import net.dv8tion.jda.api.requests.restaction.ForumPostAction;
+import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction;
+import net.dv8tion.jda.api.utils.data.DataObject;
+import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
+import net.dv8tion.jda.api.utils.messages.MessageCreateData;
+import net.dv8tion.jda.internal.requests.restaction.ForumPostActionImpl;
+import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl;
+
+import javax.annotation.Nonnull;
+
+public interface IPostContainerMixin> extends IPostContainer, IThreadContainerMixin
+{
+ @Nonnull
+ @Override
+ SortedSnowflakeCacheViewImpl getAvailableTagCache();
+
+ @Nonnull
+ @Override
+ default ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message)
+ {
+ checkPermission(Permission.MESSAGE_SEND);
+ return new ForumPostActionImpl(this, name, new MessageCreateBuilder().applyData(message));
+ }
+
+ @Nonnull
+ @Override
+ default ThreadChannelAction createThreadChannel(@Nonnull String name)
+ {
+ throw new UnsupportedOperationException("You cannot create threads without a message payload in forum/media channels! Use createForumPost(...) instead.");
+ }
+
+ @Nonnull
+ @Override
+ default ThreadChannelAction createThreadChannel(@Nonnull String name, @Nonnull String messageId)
+ {
+ throw new UnsupportedOperationException("You cannot create threads without a message payload in forum/media channels! Use createForumPost(...) instead.");
+ }
+
+ T setDefaultReaction(DataObject emoji);
+ T setDefaultSortOrder(int defaultSortOrder);
+ T setFlags(int flags);
+
+ int getRawSortOrder();
+ int getRawFlags();
+}
diff --git a/src/main/java/net/dv8tion/jda/internal/handle/ChannelCreateHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/ChannelCreateHandler.java
index 5454dad81c..c153eb8d83 100644
--- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelCreateHandler.java
+++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelCreateHandler.java
@@ -68,6 +68,7 @@ private Channel buildChannel(ChannelType type, DataObject content, long guildId)
case STAGE: return builder.createStageChannel(content, guildId);
case CATEGORY: return builder.createCategory(content, guildId);
case FORUM: return builder.createForumChannel(content, guildId);
+ case MEDIA: return builder.createMediaChannel(content, guildId);
default:
return null;
diff --git a/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java
index 2ef2ccdc6f..a37aa145ca 100644
--- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java
+++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java
@@ -16,7 +16,6 @@
package net.dv8tion.jda.internal.handle;
-import net.dv8tion.jda.api.entities.ScheduledEvent;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.concrete.*;
import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent;
@@ -156,6 +155,22 @@ protected Long handleInternally(DataObject content)
channel));
break;
}
+ case MEDIA:
+ {
+ MediaChannel channel = getJDA().getMediaChannelsView().remove(channelId);
+ if (channel == null || guild == null)
+ {
+ WebSocketClient.LOG.debug("CHANNEL_DELETE attempted to delete a media channel that is not yet cached. JSON: {}", content);
+ return null;
+ }
+
+ guild.getMediaChannelsView().remove(channel.getIdLong());
+ getJDA().handleEvent(
+ new ChannelDeleteEvent(
+ getJDA(), responseNumber,
+ channel));
+ break;
+ }
case PRIVATE:
{
SnowflakeCacheViewImpl privateView = getJDA().getPrivateChannelsView();
diff --git a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java
index 842cc20218..e36ba17698 100644
--- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java
+++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java
@@ -25,11 +25,16 @@
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.IPermissionHolder;
import net.dv8tion.jda.api.entities.PermissionOverride;
+import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.ChannelFlag;
import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
-import net.dv8tion.jda.api.entities.channel.concrete.*;
+import net.dv8tion.jda.api.entities.channel.concrete.Category;
+import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
+import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.entities.channel.forums.ForumTag;
+import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
import net.dv8tion.jda.api.entities.emoji.EmojiUnion;
import net.dv8tion.jda.api.events.channel.forum.ForumTagAddEvent;
import net.dv8tion.jda.api.events.channel.forum.ForumTagRemoveEvent;
@@ -45,18 +50,22 @@
import net.dv8tion.jda.api.utils.data.DataArray;
import net.dv8tion.jda.api.utils.data.DataObject;
import net.dv8tion.jda.internal.JDAImpl;
-import net.dv8tion.jda.internal.entities.*;
-import net.dv8tion.jda.internal.entities.channel.concrete.NewsChannelImpl;
-import net.dv8tion.jda.internal.entities.channel.concrete.TextChannelImpl;
+import net.dv8tion.jda.internal.entities.EntityBuilder;
+import net.dv8tion.jda.internal.entities.ForumTagImpl;
+import net.dv8tion.jda.internal.entities.GuildImpl;
+import net.dv8tion.jda.internal.entities.PermissionOverrideImpl;
+import net.dv8tion.jda.internal.entities.channel.concrete.ForumChannelImpl;
import net.dv8tion.jda.internal.entities.channel.middleman.AbstractGuildChannelImpl;
import net.dv8tion.jda.internal.entities.channel.mixin.attribute.*;
import net.dv8tion.jda.internal.entities.channel.mixin.middleman.AudioChannelMixin;
+import net.dv8tion.jda.internal.entities.channel.mixin.middleman.MessageChannelMixin;
import net.dv8tion.jda.internal.requests.WebSocketClient;
import net.dv8tion.jda.internal.utils.UnlockHook;
import net.dv8tion.jda.internal.utils.cache.SnowflakeCacheViewImpl;
import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl;
import java.util.ArrayList;
+import java.util.EnumSet;
import java.util.List;
import java.util.Objects;
@@ -97,6 +106,8 @@ protected Long handleInternally(DataObject content)
//Detect if we changed the channel type at all and reconstruct the channel entity if needed
channel = handleChannelTypeChange(channel, content, type);
+ if (channel == null)
+ return null;
//Handle shared properties
@@ -132,6 +143,9 @@ protected Long handleInternally(DataObject content)
if (channel instanceof AudioChannelMixin>)
handleAudioChannel((AudioChannelMixin>) channel, content);
+ if (channel instanceof IPostContainerMixin>)
+ handlePostContainer((IPostContainerMixin>) channel, content);
+
//Handle concrete type specific properties
switch (type)
@@ -139,38 +153,9 @@ protected Long handleInternally(DataObject content)
case FORUM:
ForumChannelImpl forumChannel = (ForumChannelImpl) channel;
- int flags = content.getInt("flags", 0);
-// int sortOrder = content.getInt("default_sort_order", ((ForumChannelImpl) channel).getRawSortOrder());
int layout = content.getInt("default_forum_layout", ((ForumChannelImpl) channel).getRawLayout());
- EmojiUnion defaultReaction = content.optObject("default_reaction_emoji")
- .map(json -> EntityBuilder.createEmoji(json, "emoji_name", "emoji_id"))
- .orElse(null);
-
- int oldFlags = forumChannel.getRawFlags();
-// int oldSortOrder = forumChannel.getRawSortOrder();
int oldLayout = forumChannel.getRawLayout();
- EmojiUnion oldDefaultReaction = forumChannel.getDefaultReaction();
- content.optArray("available_tags").ifPresent(
- array -> handleTagsUpdate(forumChannel, array)
- );
-
- if (oldFlags != flags)
- {
- forumChannel.setFlags(flags);
- getJDA().handleEvent(
- new ChannelUpdateFlagsEvent(
- getJDA(), responseNumber,
- forumChannel, ChannelFlag.fromRaw(oldFlags), ChannelFlag.fromRaw(flags)));
- }
-// if (oldSortOrder != sortOrder)
-// {
-// forumChannel.setDefaultSortOrder(sortOrder);
-// getJDA().handleEvent(
-// new ChannelUpdateDefaultSortOrderEvent(
-// getJDA(), responseNumber,
-// forumChannel, ForumChannel.SortOrder.fromKey(oldSortOrder), ForumChannel.SortOrder.fromKey(sortOrder)));
-// }
if (oldLayout != layout)
{
forumChannel.setDefaultLayout(layout);
@@ -179,14 +164,6 @@ protected Long handleInternally(DataObject content)
getJDA(), responseNumber,
forumChannel, ForumChannel.Layout.fromKey(oldLayout), ForumChannel.Layout.fromKey(layout)));
}
- if (!Objects.equals(oldDefaultReaction, defaultReaction))
- {
- forumChannel.setDefaultReaction(content.optObject("default_reaction_emoji").orElse(null));
- getJDA().handleEvent(
- new ChannelUpdateDefaultReactionEvent(
- getJDA(), responseNumber,
- forumChannel, oldDefaultReaction, defaultReaction));
- }
break;
case VOICE:
case TEXT:
@@ -216,46 +193,52 @@ private AbstractGuildChannelImpl> handleChannelTypeChange(AbstractGuildChannel
EntityBuilder builder = getJDA().getEntityBuilder();
GuildImpl guild = channel.getGuild();
- if (newChannelType == ChannelType.TEXT)
- {
- //This assumes that if we're moving to a TextChannel that we're transitioning from a NewsChannel
- NewsChannel newsChannel = (NewsChannel) channel;
- getJDA().getNewsChannelView().remove(newsChannel.getIdLong());
- guild.getNewsChannelView().remove(newsChannel.getIdLong());
+ ChannelType oldType = channel.getType();
- TextChannelImpl textChannel = (TextChannelImpl) builder.createTextChannel(guild, content, guild.getIdLong());
+ EnumSet expectedTypes = EnumSet.complementOf(EnumSet.of(
+ ChannelType.PRIVATE,
+ ChannelType.GROUP,
+ ChannelType.GUILD_NEWS_THREAD,
+ ChannelType.GUILD_PRIVATE_THREAD,
+ ChannelType.GUILD_PUBLIC_THREAD,
+ ChannelType.UNKNOWN
+ ));
- //CHANNEL_UPDATE doesn't track last_message_id, so make sure to copy it over.
- textChannel.setLatestMessageIdLong(newsChannel.getLatestMessageIdLong());
+ if (!expectedTypes.contains(oldType) || !expectedTypes.contains(newChannelType))
+ {
+ WebSocketClient.LOG.warn("Unexpected channel type change {}->{}, discarding from cache.", channel.getType().getId(), content.getInt("type"));
+ guild.uncacheChannel(channel, false);
+ return null;
+ }
- getJDA().handleEvent(
- new ChannelUpdateTypeEvent(
- getJDA(), responseNumber,
- textChannel, ChannelType.NEWS, ChannelType.TEXT));
+ guild.uncacheChannel(channel, true);
+ Channel newChannel = builder.createGuildChannel(guild, content);
- return textChannel;
+ if (channel instanceof IThreadContainer)
+ {
+ if (newChannel instanceof IThreadContainer)
+ {
+ // Refresh thread parents to avoid keeping strong references to parent channel
+ guild.getThreadChannelCache().forEachUnordered(ThreadChannel::getParentChannel);
+ }
+ else
+ {
+ // Change introduced dangling thread channels (with no parent)
+ WebSocketClient.LOG.error("ThreadContainer channel transitioned into type that is not ThreadContainer? {} -> {}", channel.getType(), newChannel.getType());
+ }
}
- if (newChannelType == ChannelType.NEWS)
+ if (newChannel instanceof MessageChannelMixin> && channel instanceof MessageChannel)
{
- //This assumes that if we're moving to a NewsChannel that we're transitioning from a TextChannel
- TextChannel textChannel = (TextChannel) channel;
- getJDA().getTextChannelsView().remove(textChannel.getIdLong());
- guild.getTextChannelsView().remove(textChannel.getIdLong());
-
- NewsChannelImpl newsChannel = (NewsChannelImpl) builder.createNewsChannel(guild, content, guild.getIdLong());
-
- //CHANNEL_UPDATE doesn't track last_message_id, so make sure to copy it over.
- newsChannel.setLatestMessageIdLong(textChannel.getLatestMessageIdLong());
-
- getJDA().handleEvent(
- new ChannelUpdateTypeEvent(
- getJDA(), responseNumber,
- newsChannel, ChannelType.TEXT, ChannelType.NEWS));
-
- return newsChannel;
+ long latestMessageIdLong = ((MessageChannel) channel).getLatestMessageIdLong();
+ ((MessageChannelMixin>) channel).setLatestMessageIdLong(latestMessageIdLong);
}
+ getJDA().handleEvent(
+ new ChannelUpdateTypeEvent(
+ getJDA(), responseNumber,
+ newChannel, oldType, newChannelType));
+
return channel;
}
@@ -388,7 +371,7 @@ private void handleHideChildThreads(IThreadContainer channel)
}
}
- private void handleTagsUpdate(ForumChannelImpl channel, DataArray tags)
+ private void handleTagsUpdate(IPostContainerMixin> channel, DataArray tags)
{
if (!api.isCacheFlagSet(CacheFlag.FORUM_TAGS))
return;
@@ -572,4 +555,50 @@ private void handleAudioChannel(AudioChannelMixin> channel, DataObject content
channel, Region.fromKey(oldRegion), Region.fromKey(regionRaw)));
}
}
+
+ private void handlePostContainer(IPostContainerMixin> channel, DataObject content)
+ {
+ content.optArray("available_tags").ifPresent(
+ array -> handleTagsUpdate(channel, array)
+ );
+
+ EmojiUnion defaultReaction = content.optObject("default_reaction_emoji")
+ .map(json -> EntityBuilder.createEmoji(json, "emoji_name", "emoji_id"))
+ .orElse(null);
+ EmojiUnion oldDefaultReaction = channel.getDefaultReaction();
+
+ if (!Objects.equals(oldDefaultReaction, defaultReaction))
+ {
+ channel.setDefaultReaction(content.optObject("default_reaction_emoji").orElse(null));
+ getJDA().handleEvent(
+ new ChannelUpdateDefaultReactionEvent(
+ getJDA(), responseNumber,
+ channel, oldDefaultReaction, defaultReaction));
+ }
+
+
+ int sortOrder = content.getInt("default_sort_order", channel.getRawSortOrder());
+ int oldSortOrder = channel.getRawSortOrder();
+
+ if (oldSortOrder != sortOrder)
+ {
+ channel.setDefaultSortOrder(sortOrder);
+ getJDA().handleEvent(
+ new ChannelUpdateDefaultSortOrderEvent(
+ getJDA(), responseNumber,
+ channel, IPostContainer.SortOrder.fromKey(oldSortOrder)));
+ }
+
+ int newFlags = content.getInt("flags", 0);
+ int oldFlags = channel.getRawFlags();
+
+ if (oldFlags != newFlags)
+ {
+ channel.setFlags(newFlags);
+ getJDA().handleEvent(
+ new ChannelUpdateFlagsEvent(
+ getJDA(), responseNumber,
+ channel, ChannelFlag.fromRaw(oldFlags), ChannelFlag.fromRaw(newFlags)));
+ }
+ }
}
diff --git a/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java
index fb25f5e74c..b0efe4071d 100644
--- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java
+++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java
@@ -57,6 +57,10 @@ protected Long handleInternally(DataObject content)
//Refer to the documentation for more info: https://discord.com/developers/docs/topics/threads#unarchiving-a-thread
if (thread == null)
{
+ // This seems to never be true but its better to check
+ if (content.getObject("thread_metadata").getBoolean("archived"))
+ return null;
+
//Technically, when the ThreadChannel is unarchived the archive_timestamp (getTimeArchiveInfoLastModified) changes
// as well, but we don't have the original value because we didn't have the thread in memory, so we can't
// provide an entirely accurate ChannelUpdateArchiveTimestampEvent. Not sure how much that'll matter.
diff --git a/src/main/java/net/dv8tion/jda/internal/managers/channel/ChannelManagerImpl.java b/src/main/java/net/dv8tion/jda/internal/managers/channel/ChannelManagerImpl.java
index e915f2b820..9db8a80eb9 100644
--- a/src/main/java/net/dv8tion/jda/internal/managers/channel/ChannelManagerImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/managers/channel/ChannelManagerImpl.java
@@ -26,7 +26,9 @@
import net.dv8tion.jda.api.entities.channel.ChannelFlag;
import net.dv8tion.jda.api.entities.channel.ChannelType;
import net.dv8tion.jda.api.entities.channel.attribute.IPermissionContainer;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel;
+import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer;
import net.dv8tion.jda.api.entities.channel.concrete.*;
import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag;
import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake;
@@ -45,6 +47,7 @@
import net.dv8tion.jda.internal.entities.channel.mixin.middleman.GuildChannelMixin;
import net.dv8tion.jda.internal.managers.ManagerBase;
import net.dv8tion.jda.internal.requests.restaction.PermOverrideData;
+import net.dv8tion.jda.internal.utils.ChannelUtil;
import net.dv8tion.jda.internal.utils.Checks;
import net.dv8tion.jda.internal.utils.PermissionUtil;
import okhttp3.RequestBody;
@@ -60,12 +63,6 @@
@SuppressWarnings("unchecked") //We do a lot of (M) and (T) casting that we know is correct but the compiler warns about.
public class ChannelManagerImpl> extends ManagerBase implements ChannelManager
{
- private static final EnumSet SLOWMODE_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM,
- ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_NEWS_THREAD, ChannelType.GUILD_PRIVATE_THREAD,
- ChannelType.STAGE, ChannelType.VOICE);
- private static final EnumSet NSFW_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM, ChannelType.NEWS, ChannelType.STAGE);
- private static final EnumSet TOPIC_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, ChannelType.NEWS);
-
protected T channel;
protected final EnumSet flags;
@@ -74,6 +71,7 @@ public class ChannelManagerImpl appliedTags;
protected Emoji defaultReactionEmoji;
protected int defaultLayout;
+ protected int defaultSortOrder;
protected ChannelType type;
protected String name;
protected String parent;
@@ -85,6 +83,7 @@ public class ChannelManagerImpl= 0, "Slowmode per user must be between 0 and %d (seconds)!", ISlowmodeChannel.MAX_SLOWMODE);
this.slowmode = slowmode;
set |= SLOWMODE;
return (M) this;
}
+ @Nonnull
+ @CheckReturnValue
+ public M setDefaultThreadSlowmode(int slowmode)
+ {
+ Checks.check(channel instanceof IThreadContainer, "Cannot set default thread slowmode on channels of type %s!", channel.getType());
+ Checks.check(slowmode <= ISlowmodeChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode per user must be between 0 and %d (seconds)!", ISlowmodeChannel.MAX_SLOWMODE);
+ this.defaultThreadSlowmode = slowmode;
+ set |= DEFAULT_THREAD_SLOWMODE;
+ return (M) this;
+ }
+
@Nonnull
@CheckReturnValue
public M setUserLimit(int userLimit)
@@ -579,6 +597,8 @@ public M setInvitable(boolean invitable)
public M setPinned(boolean pinned)
{
+ if (!type.isThread())
+ throw new IllegalStateException("Can only pin threads.");
if (pinned)
flags.add(ChannelFlag.PINNED);
else
@@ -589,6 +609,8 @@ public M setPinned(boolean pinned)
public M setTagRequired(boolean requireTag)
{
+ if (!(channel instanceof IPostContainer))
+ throw new IllegalStateException("Can only set tag required flag on forum/media channels.");
if (requireTag)
flags.add(ChannelFlag.REQUIRE_TAG);
else
@@ -597,10 +619,22 @@ public M setTagRequired(boolean requireTag)
return (M) this;
}
+ public M setHideMediaDownloadOption(boolean hideOption)
+ {
+ if (!(channel instanceof MediaChannel))
+ throw new IllegalStateException("Can only set hide media download flag on media channels.");
+ if (hideOption)
+ flags.add(ChannelFlag.HIDE_MEDIA_DOWNLOAD_OPTIONS);
+ else
+ flags.remove(ChannelFlag.HIDE_MEDIA_DOWNLOAD_OPTIONS);
+ set |= HIDE_MEDIA_DOWNLOAD_OPTIONS;
+ return (M) this;
+ }
+
public M setAvailableTags(List extends BaseForumTag> tags)
{
- if (type != ChannelType.FORUM)
- throw new IllegalStateException("Can only set available tags on forum channels.");
+ if (!(channel instanceof IPostContainer))
+ throw new IllegalStateException("Can only set available tags on forum/media channels.");
Checks.noneNull(tags, "Available Tags");
this.availableTags = new ArrayList<>(tags);
set |= AVAILABLE_TAGS;
@@ -612,13 +646,13 @@ public M setAppliedTags(Collection extends ForumTagSnowflake> tags)
if (type != ChannelType.GUILD_PUBLIC_THREAD)
throw new IllegalStateException("Can only set applied tags on forum post thread channels.");
Checks.noneNull(tags, "Applied Tags");
- Checks.check(tags.size() <= ForumChannel.MAX_POST_TAGS, "Cannot apply more than %d tags to a post thread!", ForumChannel.MAX_POST_TAGS);
+ Checks.check(tags.size() <= IPostContainer.MAX_POST_TAGS, "Cannot apply more than %d tags to a post thread!", ForumChannel.MAX_POST_TAGS);
ThreadChannel thread = (ThreadChannel) getChannel();
IThreadContainerUnion parentChannel = thread.getParentChannel();
- if (!(parentChannel instanceof ForumChannel))
- throw new IllegalStateException("Cannot apply tags to threads outside of forum channels.");
+ if (!(parentChannel instanceof IPostContainer))
+ throw new IllegalStateException("Cannot apply tags to threads outside of forum/media channels.");
if (tags.isEmpty() && parentChannel.asForumChannel().isTagRequired())
- throw new IllegalArgumentException("Cannot remove all tags from a forum post which requires at least one tag! See ForumChannel#isRequireTag()");
+ throw new IllegalArgumentException("Cannot remove all tags from a forum post which requires at least one tag! See IPostContainer#isRequireTag()");
this.appliedTags = tags.stream().map(ISnowflake::getId).collect(Collectors.toList());
set |= APPLIED_TAGS;
return (M) this;
@@ -626,8 +660,8 @@ public M setAppliedTags(Collection extends ForumTagSnowflake> tags)
public M setDefaultReaction(Emoji emoji)
{
- if (type != ChannelType.FORUM)
- throw new IllegalStateException("Can only set default reaction on forum channels.");
+ if (!(channel instanceof IPostContainer))
+ throw new IllegalStateException("Can only set default reaction on forum/media channels.");
this.defaultReactionEmoji = emoji;
set |= DEFAULT_REACTION;
return (M) this;
@@ -645,6 +679,18 @@ public M setDefaultLayout(ForumChannel.Layout layout)
return (M) this;
}
+ public M setDefaultSortOrder(IPostContainer.SortOrder sortOrder)
+ {
+ if (!(channel instanceof IPostContainer))
+ throw new IllegalStateException("Can only set default layout on forum/media channels.");
+ Checks.notNull(sortOrder, "SortOrder");
+ if (sortOrder == IPostContainer.SortOrder.UNKNOWN)
+ throw new IllegalStateException("SortOrder type cannot be UNKNOWN.");
+ this.defaultSortOrder = sortOrder.getKey();
+ set |= DEFAULT_SORT_ORDER;
+ return (M) this;
+ }
+
@Override
protected RequestBody finalizeData()
{
@@ -661,6 +707,8 @@ protected RequestBody finalizeData()
frame.put("nsfw", nsfw);
if (shouldUpdate(SLOWMODE))
frame.put("rate_limit_per_user", slowmode);
+ if (shouldUpdate(DEFAULT_THREAD_SLOWMODE))
+ frame.put("default_thread_rate_limit_per_user", defaultThreadSlowmode);
if (shouldUpdate(USERLIMIT))
frame.put("user_limit", userlimit);
if (shouldUpdate(BITRATE))
@@ -681,7 +729,7 @@ protected RequestBody finalizeData()
frame.put("available_tags", DataArray.fromCollection(availableTags));
if (shouldUpdate(APPLIED_TAGS))
frame.put("applied_tags", DataArray.fromCollection(appliedTags));
- if (shouldUpdate(PINNED | REQUIRE_TAG))
+ if (shouldUpdate(PINNED | REQUIRE_TAG | HIDE_MEDIA_DOWNLOAD_OPTIONS))
frame.put("flags", ChannelFlag.getRaw(flags));
if (shouldUpdate(DEFAULT_REACTION))
{
@@ -694,6 +742,8 @@ else if (defaultReactionEmoji instanceof UnicodeEmoji)
}
if (shouldUpdate(DEFAULT_LAYOUT))
frame.put("default_forum_layout", defaultLayout);
+ if (shouldUpdate(DEFAULT_SORT_ORDER))
+ frame.put("default_sort_order", defaultSortOrder);
withLock(lock, (lock) ->
{
diff --git a/src/main/java/net/dv8tion/jda/internal/managers/channel/concrete/MediaChannelManagerImpl.java b/src/main/java/net/dv8tion/jda/internal/managers/channel/concrete/MediaChannelManagerImpl.java
new file mode 100644
index 0000000000..527478b71c
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/internal/managers/channel/concrete/MediaChannelManagerImpl.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.internal.managers.channel.concrete;
+
+import net.dv8tion.jda.api.entities.channel.concrete.MediaChannel;
+import net.dv8tion.jda.api.managers.channel.concrete.MediaChannelManager;
+import net.dv8tion.jda.internal.managers.channel.ChannelManagerImpl;
+
+public class MediaChannelManagerImpl extends ChannelManagerImpl implements MediaChannelManager
+{
+ public MediaChannelManagerImpl(MediaChannel channel)
+ {
+ super(channel);
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/internal/requests/WebSocketClient.java b/src/main/java/net/dv8tion/jda/internal/requests/WebSocketClient.java
index 1467d81cba..7f96b98eb9 100644
--- a/src/main/java/net/dv8tion/jda/internal/requests/WebSocketClient.java
+++ b/src/main/java/net/dv8tion/jda/internal/requests/WebSocketClient.java
@@ -809,6 +809,7 @@ protected void invalidate()
api.getStageChannelView().clear();
api.getThreadChannelsView().clear();
api.getForumChannelsView().clear();
+ api.getMediaChannelsView().clear();
api.getGuildsView().clear();
api.getUsersView().clear();
diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ChannelActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ChannelActionImpl.java
index 722da24290..d5a245fbbd 100644
--- a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ChannelActionImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ChannelActionImpl.java
@@ -24,6 +24,7 @@
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel;
import net.dv8tion.jda.api.entities.channel.concrete.Category;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
@@ -43,8 +44,8 @@
import net.dv8tion.jda.api.utils.data.DataArray;
import net.dv8tion.jda.api.utils.data.DataObject;
import net.dv8tion.jda.internal.entities.EntityBuilder;
-import net.dv8tion.jda.internal.requests.restaction.AuditableRestActionImpl;
-import net.dv8tion.jda.internal.requests.restaction.PermOverrideData;
+import net.dv8tion.jda.internal.entities.GuildImpl;
+import net.dv8tion.jda.internal.utils.ChannelUtil;
import net.dv8tion.jda.internal.utils.Checks;
import net.dv8tion.jda.internal.utils.PermissionUtil;
import okhttp3.RequestBody;
@@ -60,12 +61,6 @@
public class ChannelActionImpl extends AuditableRestActionImpl implements ChannelAction
{
- private static final EnumSet SLOWMODE_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM,
- ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_NEWS_THREAD, ChannelType.GUILD_PRIVATE_THREAD,
- ChannelType.STAGE, ChannelType.VOICE);
- private static final EnumSet NSFW_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM, ChannelType.NEWS, ChannelType.STAGE);
- private static final EnumSet TOPIC_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, ChannelType.NEWS);
-
protected final TLongObjectMap overrides = new TLongObjectHashMap<>();
protected final Guild guild;
protected final Class clazz;
@@ -82,6 +77,7 @@ public class ChannelActionImpl extends AuditableRestActi
// --text/forum/voice only--
protected Integer slowmode = null;
+ protected Integer defaultThreadSlowmode = null;
// --text/forum/voice/news--
protected String topic = null;
@@ -96,6 +92,7 @@ public class ChannelActionImpl extends AuditableRestActi
// --forum only--
protected Integer defaultLayout = null;
+ protected Integer defaultSortOrder = null;
public ChannelActionImpl(Class clazz, String name, Guild guild, ChannelType type)
{
@@ -190,11 +187,11 @@ public ChannelActionImpl setPosition(Integer position)
@CheckReturnValue
public ChannelActionImpl setTopic(String topic)
{
- Checks.checkSupportedChannelTypes(TOPIC_SUPPORTED, type, "Topic");
+ Checks.checkSupportedChannelTypes(ChannelUtil.TOPIC_SUPPORTED, type, "Topic");
if (topic != null)
{
- if (type == ChannelType.FORUM)
- Checks.notLonger(topic, ForumChannel.MAX_FORUM_TOPIC_LENGTH, "Topic");
+ if (ChannelUtil.POST_CONTAINERS.contains(type))
+ Checks.notLonger(topic, IPostContainer.MAX_POST_CONTAINER_TOPIC_LENGTH, "Topic");
else
Checks.notLonger(topic, StandardGuildMessageChannel.MAX_TOPIC_LENGTH, "Topic");
}
@@ -207,7 +204,7 @@ public ChannelActionImpl setTopic(String topic)
@CheckReturnValue
public ChannelActionImpl setNSFW(boolean nsfw)
{
- Checks.checkSupportedChannelTypes(NSFW_SUPPORTED, type, "NSFW (age-restricted)");
+ Checks.checkSupportedChannelTypes(ChannelUtil.NSFW_SUPPORTED, type, "NSFW (age-restricted)");
this.nsfw = nsfw;
return this;
}
@@ -217,18 +214,27 @@ public ChannelActionImpl setNSFW(boolean nsfw)
@CheckReturnValue
public ChannelActionImpl setSlowmode(int slowmode)
{
- Checks.checkSupportedChannelTypes(SLOWMODE_SUPPORTED, type, "Slowmode");
+ Checks.checkSupportedChannelTypes(ChannelUtil.SLOWMODE_SUPPORTED, type, "Slowmode");
Checks.check(slowmode <= ISlowmodeChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode must be between 0 and %d (seconds)!", ISlowmodeChannel.MAX_SLOWMODE);
this.slowmode = slowmode;
return this;
}
+ @Nonnull
+ @Override
+ public ChannelAction setDefaultThreadSlowmode(int slowmode)
+ {
+ Checks.checkSupportedChannelTypes(ChannelUtil.THREAD_CONTAINERS, type, "Default Thread Slowmode");
+ Checks.check(slowmode <= ISlowmodeChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode must be between 0 and %d (seconds)!", ISlowmodeChannel.MAX_SLOWMODE);
+ this.defaultThreadSlowmode = slowmode;
+ return this;
+ }
+
@Nonnull
@Override
public ChannelAction setDefaultReaction(@Nullable Emoji emoji)
{
- if (type != ChannelType.FORUM)
- throw new UnsupportedOperationException("Can only set default reaction emoji on a ForumChannel!");
+ Checks.checkSupportedChannelTypes(ChannelUtil.POST_CONTAINERS, type, "Default Reaction");
this.defaultReactionEmoji = emoji;
return this;
}
@@ -239,18 +245,27 @@ public ChannelAction setDefaultLayout(@Nonnull ForumChannel.Layout layout)
{
Checks.checkSupportedChannelTypes(EnumSet.of(ChannelType.FORUM), type, "Default Layout");
Checks.notNull(layout, "layout");
- if (layout == ForumChannel.Layout.UNKNOWN)
- throw new IllegalStateException("Layout type cannot be UNKNOWN.");
+ Checks.check(layout != ForumChannel.Layout.UNKNOWN, "Layout type cannot be UNKNOWN.");
this.defaultLayout = layout.getKey();
return this;
}
+ @Nonnull
+ @Override
+ public ChannelAction setDefaultSortOrder(@Nonnull IPostContainer.SortOrder sortOrder)
+ {
+ Checks.checkSupportedChannelTypes(ChannelUtil.POST_CONTAINERS, type, "Default Sort Order");
+ Checks.notNull(sortOrder, "SortOrder");
+ Checks.check(sortOrder != IPostContainer.SortOrder.UNKNOWN, "Sort Order cannot be UNKNOWN.");
+ this.defaultSortOrder = sortOrder.getKey();
+ return this;
+ }
+
@Nonnull
@Override
public ChannelAction setAvailableTags(@Nonnull List extends BaseForumTag> tags)
{
- if (type != ChannelType.FORUM)
- throw new UnsupportedOperationException("Can only set available tags on a ForumChannel!");
+ Checks.checkSupportedChannelTypes(ChannelUtil.POST_CONTAINERS, type, "Available Tags");
Checks.noneNull(tags, "Tags");
this.availableTags = new ArrayList<>(tags);
return this;
@@ -417,6 +432,8 @@ protected RequestBody finalizeData()
//Text and Forum
if (slowmode != null)
object.put("rate_limit_per_user", slowmode);
+ if (defaultThreadSlowmode != null)
+ object.put("default_thread_rate_limit_per_user", defaultThreadSlowmode);
//Text, Forum, and News
if (topic != null && !topic.isEmpty())
@@ -424,13 +441,17 @@ protected RequestBody finalizeData()
if (nsfw != null)
object.put("nsfw", nsfw);
- //Forum only
+ //Forum/Media only
if (defaultReactionEmoji instanceof CustomEmoji)
object.put("default_reaction_emoji", DataObject.empty().put("emoji_id", ((CustomEmoji) defaultReactionEmoji).getId()));
else if (defaultReactionEmoji instanceof UnicodeEmoji)
object.put("default_reaction_emoji", DataObject.empty().put("emoji_name", defaultReactionEmoji.getName()));
if (availableTags != null)
object.put("available_tags", DataArray.fromCollection(availableTags));
+ if (defaultSortOrder != null)
+ object.put("default_sort_order", defaultSortOrder);
+
+ //Forum only
if (defaultLayout != null)
object.put("default_forum_layout", defaultLayout);
@@ -451,31 +472,10 @@ else if (defaultReactionEmoji instanceof UnicodeEmoji)
protected void handleSuccess(Response response, Request request)
{
EntityBuilder builder = api.getEntityBuilder();
- GuildChannel channel;
- switch (type)
- {
- case TEXT:
- channel = builder.createTextChannel(response.getObject(), guild.getIdLong());
- break;
- case NEWS:
- channel = builder.createNewsChannel(response.getObject(), guild.getIdLong());
- break;
- case VOICE:
- channel = builder.createVoiceChannel(response.getObject(), guild.getIdLong());
- break;
- case STAGE:
- channel = builder.createStageChannel(response.getObject(), guild.getIdLong());
- break;
- case CATEGORY:
- channel = builder.createCategory(response.getObject(), guild.getIdLong());
- break;
- case FORUM:
- channel = builder.createForumChannel(response.getObject(), guild.getIdLong());
- break;
- default:
- request.onFailure(new IllegalStateException("Created channel of unknown type!"));
- return;
- }
- request.onSuccess(clazz.cast(channel));
+ GuildChannel channel = builder.createGuildChannel((GuildImpl) guild, response.getObject());
+ if (channel == null)
+ request.onFailure(new IllegalStateException("Created channel of unknown type!"));
+ else
+ request.onSuccess(clazz.cast(channel));
}
}
diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ForumPostActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ForumPostActionImpl.java
index 07285efa32..e40c0cff0b 100644
--- a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ForumPostActionImpl.java
+++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ForumPostActionImpl.java
@@ -22,6 +22,7 @@
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.attribute.IPostContainer;
import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel;
import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel;
import net.dv8tion.jda.api.entities.channel.forums.ForumPost;
@@ -46,12 +47,12 @@
public class ForumPostActionImpl extends RestActionImpl implements ForumPostAction, MessageCreateBuilderMixin
{
private final MessageCreateBuilder builder;
- private final ForumChannel channel;
+ private final IPostContainer channel;
private final TLongSet appliedTags = new TLongHashSet();
private String name;
private ThreadChannel.AutoArchiveDuration autoArchiveDuration;
- public ForumPostActionImpl(ForumChannel channel, String name, MessageCreateBuilder builder)
+ public ForumPostActionImpl(IPostContainer channel, String name, MessageCreateBuilder builder)
{
super(channel.getJDA(), Route.Channels.CREATE_THREAD.compile(channel.getId()));
this.builder = builder;
@@ -89,7 +90,7 @@ public Guild getGuild()
@Nonnull
@Override
- public ForumChannel getChannel()
+ public IPostContainer getChannel()
{
return channel;
}
diff --git a/src/main/java/net/dv8tion/jda/internal/utils/ChannelUtil.java b/src/main/java/net/dv8tion/jda/internal/utils/ChannelUtil.java
new file mode 100644
index 0000000000..1f70447799
--- /dev/null
+++ b/src/main/java/net/dv8tion/jda/internal/utils/ChannelUtil.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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.internal.utils;
+
+import net.dv8tion.jda.api.entities.channel.Channel;
+import net.dv8tion.jda.api.entities.channel.ChannelType;
+
+import java.util.EnumSet;
+
+public class ChannelUtil
+{
+ public static final EnumSet SLOWMODE_SUPPORTED = EnumSet.of(
+ ChannelType.TEXT, ChannelType.FORUM, ChannelType.MEDIA,
+ ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_NEWS_THREAD, ChannelType.GUILD_PRIVATE_THREAD,
+ ChannelType.STAGE, ChannelType.VOICE
+ );
+
+ public static final EnumSet NSFW_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM, ChannelType.MEDIA, ChannelType.NEWS, ChannelType.STAGE);
+
+ public static final EnumSet TOPIC_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, ChannelType.MEDIA, ChannelType.NEWS);
+
+ public static final EnumSet POST_CONTAINERS = EnumSet.of(ChannelType.FORUM, ChannelType.MEDIA);
+
+ public static final EnumSet THREAD_CONTAINERS = EnumSet.of(ChannelType.TEXT, ChannelType.NEWS, ChannelType.FORUM, ChannelType.MEDIA);
+
+ public static T safeChannelCast(Object instance, Class toObjectClass)
+ {
+ if (toObjectClass.isInstance(instance))
+ return toObjectClass.cast(instance);
+
+ String cleanedClassName = instance.getClass().getSimpleName().replace("Impl", "");
+ throw new IllegalStateException(Helpers.format("Cannot convert channel of type %s to %s!", cleanedClassName, toObjectClass.getSimpleName()));
+ }
+}
diff --git a/src/main/java/net/dv8tion/jda/internal/utils/Helpers.java b/src/main/java/net/dv8tion/jda/internal/utils/Helpers.java
index 84fa4ab311..1c9ca0a0f6 100644
--- a/src/main/java/net/dv8tion/jda/internal/utils/Helpers.java
+++ b/src/main/java/net/dv8tion/jda/internal/utils/Helpers.java
@@ -18,7 +18,6 @@
import gnu.trove.map.TLongObjectMap;
import gnu.trove.map.hash.TLongObjectHashMap;
-import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.utils.data.DataArray;
import net.dv8tion.jda.api.utils.data.DataObject;
@@ -49,15 +48,6 @@ public static Consumer emptyConsumer()
return (Consumer) EMPTY_CONSUMER;
}
- public static T safeChannelCast(Object instance, Class toObjectClass)
- {
- if (toObjectClass.isInstance(instance))
- return toObjectClass.cast(instance);
-
- String cleanedClassName = instance.getClass().getSimpleName().replace("Impl", "");
- throw new IllegalStateException(Helpers.format("Cannot convert channel of type %s to %s!", cleanedClassName, toObjectClass.getSimpleName()));
- }
-
public static OffsetDateTime toOffset(long instant)
{
return OffsetDateTime.ofInstant(Instant.ofEpochMilli(instant), OFFSET);
diff --git a/src/test/java/net/dv8tion/jda/ChannelConsistencyTest.java b/src/test/java/net/dv8tion/jda/ChannelConsistencyTest.java
new file mode 100644
index 0000000000..da07ad56bb
--- /dev/null
+++ b/src/test/java/net/dv8tion/jda/ChannelConsistencyTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2015 Austin Keener, Michael Ritter, Florian Spieß, and the JDA contributors
+ *
+ * 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;
+
+import net.dv8tion.jda.api.entities.Guild;
+import net.dv8tion.jda.api.entities.channel.ChannelType;
+import net.dv8tion.jda.api.entities.channel.attribute.IGuildChannelContainer;
+import net.dv8tion.jda.api.entities.channel.concrete.Category;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Locale;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class ChannelConsistencyTest
+{
+ private static Set getMethodNames(Class> clazz)
+ {
+ return Arrays.stream(clazz.getDeclaredMethods()).map(Method::getName).collect(Collectors.toSet());
+ }
+
+ private static String getChannelName(ChannelType type)
+ {
+ return type.name().substring(0, 1) + type.name().substring(1).toLowerCase(Locale.ROOT);
+ }
+
+ @Test
+ public void checkCreateChannelMethods()
+ {
+ Set guildMethods = getMethodNames(Guild.class);
+
+ EnumSet creatable = EnumSet.complementOf(EnumSet.of(
+ ChannelType.UNKNOWN, ChannelType.PRIVATE, ChannelType.GROUP, ChannelType.CATEGORY,
+ ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_PRIVATE_THREAD, ChannelType.GUILD_NEWS_THREAD
+ ));
+
+ for (ChannelType type : creatable)
+ {
+ String channelName = getChannelName(type);
+ String methodName = "create" + channelName + "Channel";
+ Assertions.assertTrue(guildMethods.contains(methodName), "Missing method Guild#" + methodName);
+ }
+
+ Set categoryMethods = getMethodNames(Category.class);
+
+ for (ChannelType type : creatable)
+ {
+ String channelName = getChannelName(type);
+ String methodName = "create" + channelName + "Channel";
+ Assertions.assertTrue(categoryMethods.contains(methodName), "Missing method Category#" + methodName);
+ }
+ }
+
+ @Test
+ public void checkCacheAccessMethods()
+ {
+ Set jdaMethods = getMethodNames(IGuildChannelContainer.class);
+ Set categoryMethods = getMethodNames(Category.class);
+
+ EnumSet cacheable = EnumSet.complementOf(EnumSet.of(
+ ChannelType.UNKNOWN, ChannelType.PRIVATE, ChannelType.GROUP, ChannelType.CATEGORY,
+ ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_PRIVATE_THREAD, ChannelType.GUILD_NEWS_THREAD
+ ));
+
+ for (ChannelType type : cacheable)
+ {
+ String channelName = getChannelName(type);
+
+ String methodName = "get" + channelName + "ChannelCache";
+ Assertions.assertTrue(jdaMethods.contains(methodName), "Missing method IGuildChannelContainer#" + methodName);
+
+ methodName = "get" + channelName + "ChannelsByName";
+ Assertions.assertTrue(jdaMethods.contains(methodName), "Missing method IGuildChannelContainer#" + methodName);
+
+ methodName = "get" + channelName + "ChannelById";
+ Assertions.assertTrue(jdaMethods.contains(methodName), "Missing method IGuildChannelContainer#" + methodName);
+
+ methodName = "get" + channelName + "Channels";
+ Assertions.assertTrue(jdaMethods.contains(methodName), "Missing method IGuildChannelContainer#" + methodName);
+ Assertions.assertTrue(categoryMethods.contains(methodName), "Missing method Category#" + methodName);
+ }
+ }
+
+ @Test
+ public void checkManagerExists()
+ {
+ EnumSet editable = EnumSet.complementOf(EnumSet.of(
+ ChannelType.UNKNOWN, ChannelType.PRIVATE, ChannelType.GROUP, ChannelType.CATEGORY,
+ ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_PRIVATE_THREAD, ChannelType.GUILD_NEWS_THREAD
+ ));
+
+ for (ChannelType type : editable)
+ {
+ String channelName = getChannelName(type);
+
+ Assertions.assertDoesNotThrow(() -> {
+ Class.forName("net.dv8tion.jda.api.managers.channel.concrete." + channelName + "ChannelManager");
+ }, "Missing manager interface for ChannelType." + type);
+ }
+ }
+}