From b9065eec9e5147c17a913eff891fa6332cde6b2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 19 Jul 2022 15:25:36 +0200 Subject: [PATCH 01/75] Add initial support for forum channels --- .../dv8tion/jda/api/entities/Category.java | 38 ++++ .../dv8tion/jda/api/entities/ChannelType.java | 2 + .../net/dv8tion/jda/api/entities/Guild.java | 76 +++++++- .../channel/IGuildChannelContainer.java | 115 ++++++++++++ .../channel/concrete/ForumChannel.java | 78 ++++++++ .../entities/channel/unions/ChannelUnion.java | 23 +++ .../channel/unions/GuildChannelUnion.java | 23 +++ .../unions/IPermissionContainerUnion.java | 23 +++ .../channel/unions/IThreadContainerUnion.java | 23 ++- .../unions/IWebhookContainerUnion.java | 23 ++- .../channel/concrete/ForumChannelManager.java | 57 ++++++ .../jda/api/sharding/ShardManager.java | 8 + .../net/dv8tion/jda/internal/JDAImpl.java | 14 ++ .../entities/AbstractChannelImpl.java | 8 + .../jda/internal/entities/CategoryImpl.java | 9 + .../jda/internal/entities/EntityBuilder.java | 45 +++++ .../internal/entities/ForumChannelImpl.java | 171 ++++++++++++++++++ .../jda/internal/entities/GuildImpl.java | 44 ++++- .../attribute/IThreadContainerMixin.java | 1 + .../internal/handle/ChannelCreateHandler.java | 4 +- .../internal/handle/ChannelDeleteHandler.java | 16 ++ .../internal/handle/ChannelUpdateHandler.java | 66 +++++++ .../restaction/ChannelActionImpl.java | 3 + 23 files changed, 853 insertions(+), 17 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ForumChannel.java create mode 100644 src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ForumChannelManager.java create mode 100644 src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java diff --git a/src/main/java/net/dv8tion/jda/api/entities/Category.java b/src/main/java/net/dv8tion/jda/api/entities/Category.java index 4f42078bf7..e18e1c44e5 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Category.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Category.java @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.entities; import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.managers.channel.concrete.CategoryManager; import net.dv8tion.jda.api.requests.restaction.ChannelAction; import net.dv8tion.jda.api.requests.restaction.order.CategoryOrderAction; @@ -236,6 +237,43 @@ default List getStageChannels() @CheckReturnValue ChannelAction createStageChannel(@Nonnull String name); + /** + * Creates a new {@link ForumChannel} 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 ForumChannel to create + * + * @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} or empty or greater than 100 characters in length + * + * @return A specific {@link ChannelAction ChannelAction} + *
This action allows to set fields for the new ForumChannel before creating it + */ + @Nonnull + @CheckReturnValue + ChannelAction createForumChannel(@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/ChannelType.java b/src/main/java/net/dv8tion/jda/api/entities/ChannelType.java index 2bcacdfa3f..99c2e0f234 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ChannelType.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ChannelType.java @@ -56,6 +56,8 @@ public enum ChannelType GUILD_PUBLIC_THREAD(11, -1, true), GUILD_PRIVATE_THREAD(12, -1, true), + FORUM(15, 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/Guild.java b/src/main/java/net/dv8tion/jda/api/entities/Guild.java index d94e7fc73c..47cf16038f 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -19,6 +19,7 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.channel.IGuildChannelContainer; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.DefaultGuildChannelUnion; import net.dv8tion.jda.api.entities.emoji.CustomEmoji; import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji; @@ -57,6 +58,9 @@ import net.dv8tion.jda.internal.utils.Helpers; import net.dv8tion.jda.internal.utils.concurrent.task.GatewayTask; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.time.Duration; import java.time.temporal.TemporalAccessor; import java.util.*; @@ -65,10 +69,6 @@ import java.util.function.Consumer; import java.util.function.Predicate; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - /** * Represents a Discord {@link net.dv8tion.jda.api.entities.Guild Guild}. * This should contain all information provided from Discord about a Guild. @@ -1275,6 +1275,10 @@ default List getMembersWithRoles(@Nonnull Collection roles) @Override SortedSnowflakeCacheView getVoiceChannelCache(); + @Nonnull + @Override + SortedSnowflakeCacheView getForumChannelCache(); + /** * Populated list of {@link GuildChannel channels} for this guild. * This includes all types of channels, such as category/voice/text. @@ -4147,6 +4151,70 @@ default ChannelAction createStageChannel(@Nonnull String name) @CheckReturnValue ChannelAction createStageChannel(@Nonnull String name, @Nullable Category parent); + /** + * Creates a new {@link net.dv8tion.jda.api.entities.StageChannel StageChannel} 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 StageChannel to create + * + * @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} or empty or greater than 100 characters in length + * + * @return A specific {@link ChannelAction ChannelAction} + *
This action allows to set fields for the new StageChannel before creating it + */ + @Nonnull + @CheckReturnValue + default ChannelAction createForumChannel(@Nonnull String name) + { + return createForumChannel(name, null); + } + + /** + * Creates a new {@link ForumChannel} 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 ForumChannel to create + * @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} or empty or greater than 100 characters in length; + * 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 ForumChannel before creating it + */ + @Nonnull + @CheckReturnValue + ChannelAction createForumChannel(@Nonnull String name, @Nullable Category parent); + /** * Creates a new {@link net.dv8tion.jda.api.entities.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/IGuildChannelContainer.java b/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java index 13b74c7ac7..ad429d16a9 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java @@ -18,6 +18,7 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.sharding.ShardManager; import net.dv8tion.jda.api.utils.MiscUtil; import net.dv8tion.jda.api.utils.cache.CacheView; @@ -966,4 +967,118 @@ default List getVoiceChannels() { return getVoiceChannelCache().asList(); } + + + // ForumChannels + + + /** + * {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} of {@link ThreadChannel}. + * + *

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 net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} + */ + @Nonnull + SnowflakeCacheView getForumChannelCache(); + + /** + * Gets a list of all {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannels} + * 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 ThreadChannel ThreadChannels}. + * @param ignoreCase + * Determines if the comparison ignores case when comparing. True - case insensitive. + * + * @return Possibly-empty immutable list of all ThreadChannel names that match the provided name. + */ + @Nonnull + default List getForumChannelsByName(@Nonnull String name, boolean ignoreCase) + { + return getForumChannelCache().getElementsByName(name, ignoreCase); + } + + /** + * Gets a {@link ThreadChannel ThreadChannel} 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 ThreadChannel ThreadChannel}. + * + * @throws java.lang.NumberFormatException + * If the provided {@code id} cannot be parsed by {@link Long#parseLong(String)} + * + * @return Possibly-null {@link ThreadChannel ThreadChannel} with matching id. + */ + @Nullable + default ForumChannel getForumChannelById(@Nonnull String id) + { + return getForumChannelCache().getElementById(id); + } + + /** + * Gets a {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} 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 ThreadChannel ThreadChannel}. + * + * @return Possibly-null {@link ThreadChannel ThreadChannel} with matching id. + */ + @Nullable + default ForumChannel getForumChannelById(long id) + { + return getForumChannelCache().getElementById(id); + } + + /** + * Gets all {@link ThreadChannel ThreadChannel} 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 #getThreadChannelCache()} 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 ThreadChannel ThreadChannels}. + */ + @Nonnull + default List getForumChannels() + { + return getForumChannelCache().asList(); + } } 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 new file mode 100644 index 0000000000..dc2d9dafa3 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ForumChannel.java @@ -0,0 +1,78 @@ +/* + * 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.ChannelType; +import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.IThreadContainer; +import net.dv8tion.jda.api.entities.StandardGuildChannel; +import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel; +import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; +import net.dv8tion.jda.api.requests.restaction.ChannelAction; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IAgeRestrictedChannel +{ + @Nonnull + @Override + default ChannelType getType() + { + return ChannelType.FORUM; + } + + @Nonnull + @Override + ForumChannelManager getManager(); + + @Nonnull + @Override + ChannelAction createCopy(@Nonnull Guild guild); + + @Nonnull + @Override + default ChannelAction createCopy() + { + return createCopy(getGuild()); + } + + /** + * The slowmode set for this ForumChannel. + *
If slowmode is set this returns an {@code int} between 1 and {@link net.dv8tion.jda.api.entities.TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}. + *
If not set this returns {@code 0}. + * + *

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. + * + * @return The slowmode for this ForumChannel, between 1 and {@link net.dv8tion.jda.api.entities.TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}, or {@code 0} if no slowmode is set. + */ + int getSlowmode(); + + // TODO: Should this be in StandardGuildChannel? + + /** + * The topic set for this channel. + *
If no topic has been set, this returns null. + * + * @return Possibly-null String containing the topic of this channel. + */ + @Nullable + String getTopic(); +} 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 0826c6a198..724c644cd1 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 @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.entities.channel.unions; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import javax.annotation.Nonnull; @@ -171,6 +172,28 @@ public interface ChannelUnion extends Channel @Nonnull StageChannel asStageChannel(); + /** + * Casts this union to a {@link ForumChannel}. + * This method exists for developer discoverability. + * + * Note: This is effectively equivalent to using the cast operator: + *


+     * //These are the same!
+     * ForumChannel channel = union.asForumChannel();
+     * ForumChannel channel2 = (ForumChannel) union;
+     * 
+ * + * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#FORUM} to validate + * whether you can call this method in addition to normal instanceof checks: channel instanceof ForumChannel + * + * @throws IllegalStateException + * If the channel represented by this union is not actually a {@link ForumChannel}. + * + * @return The channel as a {@link ForumChannel} + */ + @Nonnull + ForumChannel asForumChannel(); + /** * 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/GuildChannelUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildChannelUnion.java index 77977ba6b1..5e7df28965 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 @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.entities.channel.unions; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import javax.annotation.Nonnull; @@ -169,6 +170,28 @@ public interface GuildChannelUnion extends GuildChannel @Nonnull Category asCategory(); + /** + * Casts this union to a {@link ForumChannel}. + * This method exists for developer discoverability. + * + * Note: This is effectively equivalent to using the cast operator: + *

+     * //These are the same!
+     * ForumChannel channel = union.asForumChannel();
+     * ForumChannel channel2 = (ForumChannel) union;
+     * 
+ * + * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#FORUM} to validate + * whether you can call this method in addition to normal instanceof checks: channel instanceof ForumChannel + * + * @throws IllegalStateException + * If the channel represented by this union is not actually a {@link ForumChannel}. + * + * @return The channel as a {@link ForumChannel} + */ + @Nonnull + ForumChannel asForumChannel(); + /** * 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/IPermissionContainerUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IPermissionContainerUnion.java index 9792fc1982..f2062fc5b3 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IPermissionContainerUnion.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IPermissionContainerUnion.java @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.entities.channel.unions; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import javax.annotation.Nonnull; @@ -146,6 +147,28 @@ public interface IPermissionContainerUnion extends IPermissionContainer @Nonnull Category asCategory(); + /** + * Casts this union to a {@link ForumChannel}. + * This method exists for developer discoverability. + * + * Note: This is effectively equivalent to using the cast operator: + *

+     * //These are the same!
+     * ForumChannel channel = union.asForumChannel();
+     * ForumChannel channel2 = (ForumChannel) union;
+     * 
+ * + * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#FORUM} to validate + * whether you can call this method in addition to normal instanceof checks: channel instanceof ForumChannel + * + * @throws IllegalStateException + * If the channel represented by this union is not actually a {@link ForumChannel}. + * + * @return The channel as a {@link ForumChannel} + */ + @Nonnull + ForumChannel asForumChannel(); + /** * 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 c4d55b2bbe..3b7bd01e50 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 @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.entities.channel.unions; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import javax.annotation.Nonnull; @@ -77,7 +78,27 @@ public interface IThreadContainerUnion extends IThreadContainer @Nonnull NewsChannel asNewsChannel(); - //TODO: Add asForumChannel + /** + * Casts this union to a {@link ForumChannel}. + * This method exists for developer discoverability. + * + * Note: This is effectively equivalent to using the cast operator: + *

+     * //These are the same!
+     * ForumChannel channel = union.asForumChannel();
+     * ForumChannel channel2 = (ForumChannel) union;
+     * 
+ * + * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#FORUM} to validate + * whether you can call this method in addition to normal instanceof checks: channel instanceof ForumChannel + * + * @throws IllegalStateException + * If the channel represented by this union is not actually a {@link ForumChannel}. + * + * @return The channel as a {@link ForumChannel} + */ + @Nonnull + ForumChannel asForumChannel(); /** * Casts this union to a {@link GuildMessageChannel}. 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 7a3c2c077b..a282363bc6 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 @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.entities.channel.unions; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import javax.annotation.Nonnull; @@ -77,7 +78,27 @@ public interface IWebhookContainerUnion extends IWebhookContainer @Nonnull NewsChannel asNewsChannel(); - //TODO: Add asForumChannel + /** + * Casts this union to a {@link ForumChannel}. + * This method exists for developer discoverability. + * + * Note: This is effectively equivalent to using the cast operator: + *

+     * //These are the same!
+     * ForumChannel channel = union.asForumChannel();
+     * ForumChannel channel2 = (ForumChannel) union;
+     * 
+ * + * You can use {@link #getType()} to see if the channel is of type {@link ChannelType#FORUM} to validate + * whether you can call this method in addition to normal instanceof checks: channel instanceof ForumChannel + * + * @throws IllegalStateException + * If the channel represented by this union is not actually a {@link ForumChannel}. + * + * @return The channel as a {@link ForumChannel} + */ + @Nonnull + ForumChannel asForumChannel(); /** * Casts this union to a {@link IThreadContainer}. 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 new file mode 100644 index 0000000000..47daecc056 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ForumChannelManager.java @@ -0,0 +1,57 @@ +/* + * 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.Permission; +import net.dv8tion.jda.api.entities.TextChannel; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.managers.channel.attribute.IAgeRestrictedChannelManager; +import net.dv8tion.jda.api.managers.channel.middleman.StandardGuildChannelManager; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; + +// TODO implementation +public interface ForumChannelManager extends + StandardGuildChannelManager, + IAgeRestrictedChannelManager +{ + /** + * Sets the slowmode of the selected {@link ForumChannel}. + *
Provide {@code 0} to reset the slowmode of the {@link ForumChannel} + * + *

A channel slowmode must not be negative nor greater than {@link TextChannel#MAX_SLOWMODE TextChannel.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 slowmode for the selected {@link ForumChannel} + * + * @throws IllegalArgumentException + * If the provided slowmode is negative or greater than {@link TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE} + * + * @return ChannelManager for chaining convenience + * + * @see ForumChannel#getSlowmode() + */ + @Nonnull + @CheckReturnValue + ForumChannelManager setSlowmode(int slowmode); +} 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 cb5a4f63f1..10c693d456 100644 --- a/src/main/java/net/dv8tion/jda/api/sharding/ShardManager.java +++ b/src/main/java/net/dv8tion/jda/api/sharding/ShardManager.java @@ -20,6 +20,7 @@ import net.dv8tion.jda.api.OnlineStatus; import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.IGuildChannelContainer; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji; import net.dv8tion.jda.api.requests.GatewayIntent; import net.dv8tion.jda.api.requests.RestAction; @@ -801,6 +802,13 @@ default SnowflakeCacheView getNewsChannelCache() return CacheView.allSnowflakes(() -> this.getShardCache().stream().map(JDA::getNewsChannelCache)); } + @Nonnull + @Override + default SnowflakeCacheView getForumChannelCache() + { + return CacheView.allSnowflakes(() -> this.getShardCache().stream().map(JDA::getForumChannelCache)); + } + /** * 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/internal/JDAImpl.java b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java index 798dc7a7ed..4e43fef0d1 100644 --- a/src/main/java/net/dv8tion/jda/internal/JDAImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/JDAImpl.java @@ -26,6 +26,7 @@ import net.dv8tion.jda.api.audio.factory.IAudioSendFactory; import net.dv8tion.jda.api.audio.hooks.ConnectionStatus; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji; import net.dv8tion.jda.api.entities.sticker.StickerPack; import net.dv8tion.jda.api.entities.sticker.StickerSnowflake; @@ -108,6 +109,7 @@ public class JDAImpl implements JDA protected final SnowflakeCacheViewImpl voiceChannelCache = new SnowflakeCacheViewImpl<>(VoiceChannel.class, Channel::getName); 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 privateChannelCache = new SnowflakeCacheViewImpl<>(PrivateChannel.class, Channel::getName); protected final LinkedList privateChannelLRU = new LinkedList<>(); @@ -701,6 +703,13 @@ public SnowflakeCacheView getThreadChannelCache() return threadChannelsCache; } + @Nonnull + @Override + public SnowflakeCacheView getForumChannelCache() + { + return forumChannelsCache; + } + @Nonnull @Override public SnowflakeCacheView getPrivateChannelCache() @@ -1158,6 +1167,11 @@ public SnowflakeCacheViewImpl getThreadChannelsView() return threadChannelsCache; } + public SnowflakeCacheViewImpl getForumChannelsView() + { + return forumChannelsCache; + } + public SnowflakeCacheViewImpl getPrivateChannelsView() { return privateChannelCache; diff --git a/src/main/java/net/dv8tion/jda/internal/entities/AbstractChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/AbstractChannelImpl.java index 1debada4ba..4953759923 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/AbstractChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/AbstractChannelImpl.java @@ -18,6 +18,7 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.internal.JDAImpl; import net.dv8tion.jda.internal.entities.mixin.channel.middleman.ChannelMixin; import net.dv8tion.jda.internal.utils.Helpers; @@ -109,6 +110,13 @@ public Category asCategory() return Helpers.safeChannelCast(this, Category.class); } + @Nonnull + @Override + public ForumChannel asForumChannel() + { + return Helpers.safeChannelCast(this, ForumChannel.class); + } + @Nonnull public MessageChannel asMessageChannel() { diff --git a/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java index 125f1f3668..09849d80d5 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java @@ -18,6 +18,7 @@ import gnu.trove.map.TLongObjectMap; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.managers.channel.concrete.CategoryManager; import net.dv8tion.jda.api.requests.restaction.ChannelAction; import net.dv8tion.jda.api.requests.restaction.order.CategoryOrderAction; @@ -81,6 +82,14 @@ public ChannelAction createStageChannel(@Nonnull String name) return trySync(action); } + @Nonnull + @Override + public ChannelAction createForumChannel(@Nonnull String name) + { + ChannelAction action = getGuild().createForumChannel(name, this); + return trySync(action); + } + @Nonnull @Override public CategoryOrderAction modifyTextChannelPositions() 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 c0569e96b6..9c4d394243 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -29,6 +29,7 @@ import net.dv8tion.jda.api.entities.Guild.Timeout; import net.dv8tion.jda.api.entities.Guild.VerificationLevel; import net.dv8tion.jda.api.entities.MessageEmbed.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji; import net.dv8tion.jda.api.entities.sticker.*; @@ -367,6 +368,9 @@ private void createGuildChannel(GuildImpl guildObj, DataObject channelData) case CATEGORY: createCategory(guildObj, channelData, guildObj.getIdLong()); break; + case FORUM: + createForumChannel(guildObj, channelData, guildObj.getIdLong()); + break; default: LOG.debug("Cannot create channel for type " + channelData.getInt("type")); } @@ -1216,6 +1220,47 @@ public ThreadMember createThreadMember(ThreadChannelImpl threadChannel, Member m return threadMember; } + public ForumChannel createForumChannel(DataObject json, long guildId) + { + return createForumChannel(null, json, guildId); + } + + public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long guildId) + { + boolean playbackCache = false; + final long id = json.getLong("id"); + ForumChannelImpl channel = (ForumChannelImpl) getJDA().getForumChannelsView().get(id); + if (channel == null) + { + if (guild == null) + guild = (GuildImpl) getJDA().getGuildsView().get(guildId); + SnowflakeCacheViewImpl + guildView = guild.getForumChannelsView(), + globalView = getJDA().getForumChannelsView(); + try ( + UnlockHook vlock = guildView.writeLock(); + UnlockHook jlock = globalView.writeLock()) + { + channel = new ForumChannelImpl(id, guild); + guildView.getMap().put(id, channel); + playbackCache = globalView.getMap().put(id, channel) == null; + } + } + + channel + .setParentCategory(json.getLong("parent_id", 0)) + .setName(json.getString("name")) + .setTopic(json.getString("topic", null)) + .setPosition(json.getInt("position")) + .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 PrivateChannel createPrivateChannel(DataObject json) { return createPrivateChannel(json, null); diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java new file mode 100644 index 0000000000..e0a431c275 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -0,0 +1,171 @@ +/* + * 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; + +import gnu.trove.map.TLongObjectMap; +import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; +import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; +import net.dv8tion.jda.api.requests.restaction.ChannelAction; +import net.dv8tion.jda.api.utils.MiscUtil; +import net.dv8tion.jda.internal.entities.mixin.channel.attribute.IThreadContainerMixin; +import net.dv8tion.jda.internal.entities.mixin.channel.middleman.StandardGuildChannelMixin; +import net.dv8tion.jda.internal.utils.Checks; + +import javax.annotation.Nonnull; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class ForumChannelImpl extends AbstractGuildChannelImpl + implements ForumChannel, + GuildChannelUnion, + StandardGuildChannelMixin, + IThreadContainerMixin +{ + private final TLongObjectMap overrides = MiscUtil.newLongMap(); + + private String topic; + private long parentCategoryId; + private boolean nsfw = false; + private int position; + private int slowmode; + + public ForumChannelImpl(long id, GuildImpl guild) + { + super(id, guild); + } + + @Nonnull + @Override + public ForumChannelManager getManager() + { + //TODO + throw new UnsupportedOperationException(); + } + + @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.createForumChannel(name).setNSFW(nsfw).setTopic(topic).setSlowmode(slowmode); + if (guild.equals(getGuild())) + { + Category parent = getParentCategory(); + 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 IPermissionContainer getPermissionContainer() + { + return this; + } + + @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; + } + + // Setters + + @Override + public ForumChannelImpl setParentCategory(long parentCategoryId) + { + this.parentCategoryId = parentCategoryId; + return this; + } + + @Override + public ForumChannelImpl setPosition(int position) + { + this.position = position; + return this; + } + + public ForumChannelImpl setNSFW(boolean nsfw) + { + this.nsfw = nsfw; + return this; + } + + public ForumChannelImpl setSlowmode(int slowmode) + { + this.slowmode = slowmode; + return this; + } + + public ForumChannelImpl setTopic(String topic) + { + this.topic = topic; + return this; + } +} 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 a98cc225e7..f98f722b5b 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -16,10 +16,14 @@ package net.dv8tion.jda.internal.entities; +import gnu.trove.map.TLongObjectMap; +import gnu.trove.map.hash.TLongObjectHashMap; +import gnu.trove.set.TLongSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.audio.hooks.ConnectionStatus; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.DefaultGuildChannelUnion; import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji; import net.dv8tion.jda.api.entities.sticker.GuildSticker; @@ -73,7 +77,12 @@ import net.dv8tion.jda.internal.utils.cache.SnowflakeCacheViewImpl; import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl; import net.dv8tion.jda.internal.utils.concurrent.task.GatewayTask; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.time.OffsetDateTime; import java.time.temporal.TemporalAccessor; import java.util.*; @@ -83,16 +92,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.annotation.CheckReturnValue; -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -import gnu.trove.map.TLongObjectMap; -import gnu.trove.map.hash.TLongObjectHashMap; -import gnu.trove.set.TLongSet; -import okhttp3.MediaType; -import okhttp3.MultipartBody; - public class GuildImpl implements Guild { private final long id; @@ -104,6 +103,7 @@ public class GuildImpl implements Guild private final SortedSnowflakeCacheViewImpl newsChannelCache = new SortedSnowflakeCacheViewImpl<>(NewsChannel.class, Channel::getName, Comparator.naturalOrder()); 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 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); @@ -643,6 +643,13 @@ public SortedSnowflakeCacheView getVoiceChannelCache() return voiceChannelCache; } + @Nonnull + @Override + public SortedSnowflakeCacheView getForumChannelCache() + { + return null; + } + @Nonnull @Override public SortedSnowflakeCacheView getStageChannelCache() @@ -1706,6 +1713,18 @@ public ChannelAction createStageChannel(@Nonnull String name, Cate return new ChannelActionImpl<>(StageChannel.class, name, this, ChannelType.STAGE).setParent(parent); } + @Nonnull + @Override + public ChannelAction createForumChannel(@Nonnull String name, Category parent) + { + checkCanCreateChannel(parent); + + Checks.notBlank(name, "Name"); + name = name.trim(); + Checks.notLonger(name, 100, "Name"); + return new ChannelActionImpl<>(ForumChannel.class, name, this, ChannelType.FORUM).setParent(parent); + } + @Nonnull @Override public ChannelAction createCategory(@Nonnull String name) @@ -2132,6 +2151,11 @@ public SortedSnowflakeCacheViewImpl getThreadChannelsView() return threadChannelCache; } + public SortedSnowflakeCacheViewImpl getForumChannelsView() + { + return forumChannelCache; + } + public SortedSnowflakeCacheViewImpl getRolesView() { return roleCache; diff --git a/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java b/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java index 21789b7f3d..9eec35ee54 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java @@ -43,6 +43,7 @@ public interface IThreadContainerMixin> exten default ThreadChannelAction createThreadChannel(String name, boolean isPrivate) { checkPermission(Permission.VIEW_CHANNEL); + // TODO: Update these checks for forums! if (isPrivate) { if (!getGuild().getFeatures().contains("PRIVATE_THREADS")) 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 a34cba92aa..1a2bdfc97e 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelCreateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelCreateHandler.java @@ -46,7 +46,8 @@ protected Long handleInternally(DataObject content) } Channel channel = buildChannel(type, content, guildId); - if (channel == null) { + if (channel == null) + { WebSocketClient.LOG.debug("Discord provided an CREATE_CHANNEL event with an unknown channel type! JSON: {}", content); return null; } @@ -66,6 +67,7 @@ private Channel buildChannel(ChannelType type, DataObject content, long guildId) case VOICE: return builder.createVoiceChannel(content, guildId); case STAGE: return builder.createStageChannel(content, guildId); case CATEGORY: return builder.createCategory(content, guildId); + case FORUM: return builder.createForumChannel(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 5036f3ecab..b2e67a379e 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java @@ -17,6 +17,7 @@ package net.dv8tion.jda.internal.handle; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.JDAImpl; @@ -137,6 +138,21 @@ protected Long handleInternally(DataObject content) category)); break; } + case FORUM: + { + ForumChannel channel = getJDA().getForumChannelsView().remove(channelId); + if (channel == null || guild == null) + { + WebSocketClient.LOG.debug("CHANNEL_DELETE attempted to delete a forum channel that is not yet cached. JSON: {}", content); + return null; + } + + guild.getForumChannelsView().remove(channel.getIdLong()); + getJDA().handleEvent( + new ChannelDeleteEvent( + getJDA(), responseNumber, + channel)); + } 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 e567f25fbd..e9744ae7cf 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -151,6 +151,72 @@ protected Long handleInternally(DataObject content) } break; } + case FORUM: + { + final String topic = content.getString("topic", null); + + ForumChannelImpl forumChannel = (ForumChannelImpl) channel; + + //If any properties changed, update the values and fire the proper events. + final long oldParentId = forumChannel.getParentCategoryIdLong(); + final String oldName = forumChannel.getName(); + final String oldTopic = forumChannel.getTopic(); + final int oldPosition = forumChannel.getPositionRaw(); + final boolean oldNsfw = forumChannel.isNSFW(); + final int oldSlowmode = forumChannel.getSlowmode(); + if (!Objects.equals(oldName, name)) + { + forumChannel.setName(name); + getJDA().handleEvent( + new ChannelUpdateNameEvent( + getJDA(), responseNumber, + forumChannel, oldName, name)); + } + if (oldParentId != parentId) + { + final Category oldParent = forumChannel.getParentCategory(); + forumChannel.setParentCategory(parentId); + getJDA().handleEvent( + new ChannelUpdateParentEvent( + getJDA(), responseNumber, + forumChannel, oldParent, forumChannel.getParentCategory())); + } + if (!Objects.equals(oldTopic, topic)) + { + forumChannel.setTopic(topic); + getJDA().handleEvent( + new ChannelUpdateTopicEvent( + getJDA(), responseNumber, + forumChannel, oldTopic, topic)); + } + if (oldPosition != position) + { + forumChannel.setPosition(position); + getJDA().handleEvent( + new ChannelUpdatePositionEvent( + getJDA(), responseNumber, + forumChannel, oldPosition, position)); + } + + if (oldNsfw != nsfw) + { + forumChannel.setNSFW(nsfw); + getJDA().handleEvent( + new ChannelUpdateNSFWEvent( + getJDA(), responseNumber, + forumChannel, oldNsfw, nsfw)); + } + + if (oldSlowmode != slowmode) + { + forumChannel.setSlowmode(slowmode); + getJDA().handleEvent( + new ChannelUpdateSlowmodeEvent( + getJDA(), responseNumber, + forumChannel, oldSlowmode, slowmode)); + } + break; + } case NEWS: { final String topic = content.getString("topic", null); 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 6e7e9ae1d7..a879d23340 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 @@ -385,6 +385,9 @@ protected void handleSuccess(Response response, Request request) 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; From 56442662bb4b8388197c13538d201a6ed9574110 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 19 Jul 2022 15:29:34 +0200 Subject: [PATCH 02/75] Fix some copy-paste issues --- .../channel/IGuildChannelContainer.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java b/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java index ad429d16a9..cae17ffba7 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java @@ -973,7 +973,7 @@ default List getVoiceChannels() /** - * {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} of {@link ThreadChannel}. + * {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} of {@link ForumChannel}. * *

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}, @@ -988,7 +988,7 @@ default List getVoiceChannels() SnowflakeCacheView getForumChannelCache(); /** - * Gets a list of all {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannels} + * Gets a list of all {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels} * 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. * @@ -1013,7 +1013,7 @@ default List getForumChannelsByName(@Nonnull String name, boolean } /** - * Gets a {@link ThreadChannel ThreadChannel} that has the same id as the one provided. + * Gets a {@link ForumChannel} 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. @@ -1024,12 +1024,12 @@ default List getForumChannelsByName(@Nonnull String name, boolean * 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 ThreadChannel ThreadChannel}. + * The id of the {@link ForumChannel}. * * @throws java.lang.NumberFormatException * If the provided {@code id} cannot be parsed by {@link Long#parseLong(String)} * - * @return Possibly-null {@link ThreadChannel ThreadChannel} with matching id. + * @return Possibly-null {@link ForumChannel} with matching id. */ @Nullable default ForumChannel getForumChannelById(@Nonnull String id) @@ -1038,7 +1038,7 @@ default ForumChannel getForumChannelById(@Nonnull String id) } /** - * Gets a {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} that has the same id as the one provided. + * Gets a {@link ForumChannel} 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. @@ -1049,9 +1049,9 @@ default ForumChannel getForumChannelById(@Nonnull String id) * 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 ThreadChannel ThreadChannel}. + * The id of the {@link ForumChannel}. * - * @return Possibly-null {@link ThreadChannel ThreadChannel} with matching id. + * @return Possibly-null {@link ForumChannel} with matching id. */ @Nullable default ForumChannel getForumChannelById(long id) @@ -1060,11 +1060,11 @@ default ForumChannel getForumChannelById(long id) } /** - * Gets all {@link ThreadChannel ThreadChannel} in the cache. + * Gets all {@link ForumChannel} 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 #getThreadChannelCache()} and use its more efficient + * 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. @@ -1074,7 +1074,7 @@ default ForumChannel getForumChannelById(long id) *
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 ThreadChannel ThreadChannels}. + * @return An immutable List of {@link ForumChannel}. */ @Nonnull default List getForumChannels() From 0cabd2dcee87db2f8bde16a1dc84b6de29ecea34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 19 Jul 2022 15:32:01 +0200 Subject: [PATCH 03/75] Update union type list --- .../dv8tion/jda/api/entities/channel/unions/ChannelUnion.java | 1 + .../jda/api/entities/channel/unions/GuildChannelUnion.java | 1 + .../api/entities/channel/unions/GuildMessageChannelUnion.java | 1 + .../api/entities/channel/unions/IPermissionContainerUnion.java | 1 + .../jda/api/entities/channel/unions/IThreadContainerUnion.java | 1 + .../jda/api/entities/channel/unions/IWebhookContainerUnion.java | 1 + .../jda/api/entities/channel/unions/MessageChannelUnion.java | 1 + 7 files changed, 7 insertions(+) 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 724c644cd1..5752d10eca 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 @@ -34,6 +34,7 @@ *

  • {@link ThreadChannel}
  • *
  • {@link VoiceChannel}
  • *
  • {@link StageChannel}
  • + *
  • {@link ForumChannel}
  • *
  • {@link Category}
  • * */ 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 5e7df28965..aa469b3da8 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 @@ -33,6 +33,7 @@ *
  • {@link ThreadChannel}
  • *
  • {@link VoiceChannel}
  • *
  • {@link StageChannel}
  • + *
  • {@link ForumChannel}
  • *
  • {@link Category}
  • * */ diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildMessageChannelUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildMessageChannelUnion.java index a88f8a7414..0afa63e62b 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildMessageChannelUnion.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/GuildMessageChannelUnion.java @@ -29,6 +29,7 @@ *
      *
    • {@link TextChannel}
    • *
    • {@link NewsChannel}
    • + *
    • {@link VoiceChannel}
    • *
    • {@link ThreadChannel}
    • *
    */ diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IPermissionContainerUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IPermissionContainerUnion.java index f2062fc5b3..f39440dafe 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IPermissionContainerUnion.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/IPermissionContainerUnion.java @@ -32,6 +32,7 @@ *
  • {@link NewsChannel}
  • *
  • {@link VoiceChannel}
  • *
  • {@link StageChannel}
  • + *
  • {@link ForumChannel}
  • *
  • {@link Category}
  • * */ 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 3b7bd01e50..0272dcb4c3 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 @@ -30,6 +30,7 @@ *
      *
    • {@link TextChannel}
    • *
    • {@link NewsChannel}
    • + *
    • {@link ForumChannel}
    • *
    */ public interface IThreadContainerUnion extends IThreadContainer 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 a282363bc6..17acd55c67 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 @@ -30,6 +30,7 @@ *
      *
    • {@link TextChannel}
    • *
    • {@link NewsChannel}
    • + *
    • {@link ForumChannel}
    • *
    */ public interface IWebhookContainerUnion extends IWebhookContainer diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/MessageChannelUnion.java b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/MessageChannelUnion.java index 90005d6cb3..b054f594c7 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/unions/MessageChannelUnion.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/unions/MessageChannelUnion.java @@ -29,6 +29,7 @@ *
      *
    • {@link TextChannel}
    • *
    • {@link NewsChannel}
    • + *
    • {@link VoiceChannel}
    • *
    • {@link ThreadChannel}
    • *
    • {@link PrivateChannel}
    • *
    From a97bc9101754836bc934e63060cf2f9608eeb10d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 19 Jul 2022 17:10:07 +0200 Subject: [PATCH 04/75] Add ForumChannel#createForumPost --- .../channel/concrete/ForumChannel.java | 31 ++++++- .../internal/entities/ForumChannelImpl.java | 85 +++++++++++++++++++ 2 files changed, 112 insertions(+), 4 deletions(-) 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 dc2d9dafa3..5c7d7ef383 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,16 +16,19 @@ package net.dv8tion.jda.api.entities.channel.concrete; -import net.dv8tion.jda.api.entities.ChannelType; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.IThreadContainer; -import net.dv8tion.jda.api.entities.StandardGuildChannel; +import net.dv8tion.jda.annotations.Incubating; +import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; +import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.restaction.ChannelAction; +import net.dv8tion.jda.api.utils.FileUpload; +import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collection; +import java.util.Collections; public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IAgeRestrictedChannel { @@ -75,4 +78,24 @@ default ChannelAction createCopy() */ @Nullable String getTopic(); + +// TODO-message-rework: Specializing by combining message send with thread create into a unified interface +// +// Note: This requires changes coming with the message-rework. Specifically, you need a nice way to create a complete message and pass it to the method. +// In addition, we need a comprehensive abstraction for all the message specific setters, coming with the MessageSend interface in the message rework. +// +// There is a temporary implementation available, which will most definitely be replaced in a future release. + + @Nonnull + @Incubating + @CheckReturnValue + default RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull FileUpload... uploads) + { + return createForumPost(name, message, Collections.emptyList(), uploads); + } + + @Nonnull + @Incubating + @CheckReturnValue + RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull Collection tags, @Nonnull FileUpload... uploads); } diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index e0a431c275..4fa624702f 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -21,14 +21,30 @@ import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; +import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; +import net.dv8tion.jda.api.exceptions.MissingAccessException; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; +import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.restaction.ChannelAction; +import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction; +import net.dv8tion.jda.api.utils.AttachedFile; +import net.dv8tion.jda.api.utils.FileUpload; import net.dv8tion.jda.api.utils.MiscUtil; +import net.dv8tion.jda.api.utils.data.DataArray; +import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.entities.mixin.channel.attribute.IThreadContainerMixin; import net.dv8tion.jda.internal.entities.mixin.channel.middleman.StandardGuildChannelMixin; +import net.dv8tion.jda.internal.requests.Requester; +import net.dv8tion.jda.internal.requests.RestActionImpl; +import net.dv8tion.jda.internal.requests.Route; import net.dv8tion.jda.internal.utils.Checks; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; @@ -135,6 +151,75 @@ public String getTopic() return topic; } + @Nonnull + @Override + public RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull Collection tags, @Nonnull FileUpload... uploads) + { + Checks.notBlank(name, "Name"); + Checks.notNull(message, "Message"); + Checks.notNull(tags, "Tags"); + Checks.noneNull(uploads, "Uploads"); + + Member selfMember = getGuild().getSelfMember(); + if (!selfMember.hasAccess(this)) + throw new MissingAccessException(this, Permission.VIEW_CHANNEL); + if (!selfMember.hasPermission(this, Permission.MESSAGE_SEND)) + throw new InsufficientPermissionException(this, Permission.MESSAGE_SEND); + + DataObject payload = DataObject.empty(); + payload.put("name", name); + + if (!tags.isEmpty()) + payload.put("applied_tags", DataArray.fromCollection(tags)); + + DataObject messageJson; + payload.put("message", messageJson = DataObject.empty()); + + messageJson.put("content", message.getContentRaw()); + messageJson.put("embeds", DataArray.fromCollection(message.getEmbeds())); + + RequestBody body; + + if (uploads.length > 0) + { + MultipartBody.Builder form = AttachedFile.createMultipartBody(Arrays.asList(uploads), null); + + DataArray attachments = DataArray.empty(); + for (int i = 0; i < uploads.length; i++) + attachments.add(uploads[i].toAttachmentData(i)); + + form.addFormDataPart("payload_json", payload.toString()); + body = form.build(); + } + else + { + body = RequestBody.create(payload.toString(), Requester.MEDIA_TYPE_JSON); + } + + Route.CompiledRoute route = Route.Channels.CREATE_THREAD_WITHOUT_MESSAGE.compile(getId()); + route = route.withQueryParams("use_nested_fields", "true"); + + return new RestActionImpl<>(getJDA(), route, body, (response, request) -> { + DataObject json = response.getObject(); + EntityBuilder builder = api.getEntityBuilder(); + return builder.createThreadChannel(getGuild(), json, guild.getIdLong()); + }); + } + + @NotNull + @Override + public ThreadChannelAction createThreadChannel(String name) + { + throw new UnsupportedOperationException("You cannot create threads without a message payload in forum channels! Use createForumPost(...) instead."); + } + + @NotNull + @Override + public ThreadChannelAction createThreadChannel(String name, String messageId) + { + throw new UnsupportedOperationException("You cannot create threads without a message payload in forum channels! Use createForumPost(...) instead."); + } + // Setters @Override From d3d371972f510862c6df1a677f0645c0cec000f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 20 Jul 2022 18:54:00 +0200 Subject: [PATCH 05/75] Implement ForumChannelManagerImpl --- .../jda/api/entities/GuildChannel.java | 2 +- .../internal/entities/ForumChannelImpl.java | 11 ++----- .../internal/entities/ThreadChannelImpl.java | 1 + .../managers/channel/ChannelManagerImpl.java | 31 ++++++++++--------- .../concrete/ForumChannelManagerImpl.java | 29 +++++++++++++++++ 5 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/internal/managers/channel/concrete/ForumChannelManagerImpl.java diff --git a/src/main/java/net/dv8tion/jda/api/entities/GuildChannel.java b/src/main/java/net/dv8tion/jda/api/entities/GuildChannel.java index 015b23b349..d16cf0d7bc 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/GuildChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/GuildChannel.java @@ -43,7 +43,6 @@ public interface GuildChannel extends Channel, Comparable ChannelManager getManager(); /** - * TODO-v5: this override might not be needed anymore if we remove AuditableRestAction and instead place auditable hooks onto RestAction itself. * Deletes this GuildChannel. * *

    Possible ErrorResponses include: @@ -71,5 +70,6 @@ public interface GuildChannel extends Channel, Comparable AuditableRestAction delete(); //TODO-v5: Docs + @Nonnull IPermissionContainer getPermissionContainer(); } diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index 4fa624702f..b0aaabec5c 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -34,6 +34,7 @@ import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.entities.mixin.channel.attribute.IThreadContainerMixin; import net.dv8tion.jda.internal.entities.mixin.channel.middleman.StandardGuildChannelMixin; +import net.dv8tion.jda.internal.managers.channel.concrete.ForumChannelManagerImpl; import net.dv8tion.jda.internal.requests.Requester; import net.dv8tion.jda.internal.requests.RestActionImpl; import net.dv8tion.jda.internal.requests.Route; @@ -72,8 +73,7 @@ public ForumChannelImpl(long id, GuildImpl guild) @Override public ForumChannelManager getManager() { - //TODO - throw new UnsupportedOperationException(); + return new ForumChannelManagerImpl(this); } @Nonnull @@ -108,13 +108,6 @@ public ChannelAction createCopy(@Nonnull Guild guild) return action; } - @Nonnull - @Override - public IPermissionContainer getPermissionContainer() - { - return this; - } - @Override public TLongObjectMap getPermissionOverrideMap() { diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index b5b8576298..e590026502 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -128,6 +128,7 @@ public RestAction retrieveParentMessage() return this.getParentMessageChannel().retrieveMessageById(this.getIdLong()); } + @Nonnull @Override public IPermissionContainer getPermissionContainer() { 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 44ea9f012c..570ebc7f3f 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 @@ -37,10 +37,15 @@ import javax.annotation.Nonnull; import java.util.Collection; import java.util.EnumSet; +import java.util.stream.Collectors; @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.VOICE, ChannelType.FORUM); + private static final EnumSet NSFW_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM, ChannelType.NEWS); + private static final EnumSet TOPIC_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, ChannelType.NEWS); + protected T channel; protected ThreadChannel.AutoArchiveDuration autoArchiveDuration; @@ -62,13 +67,6 @@ public class ChannelManagerImpl overridesAdd; protected final TLongSet overridesRem; - /** - * Creates a new ChannelManager instance - * - * @param channel - * {@link GuildChannel GuildChannel} that should be modified - *
    Either {@link VoiceChannel Voice}- or {@link TextChannel TextChannel} - */ public ChannelManagerImpl(T channel) { super(channel.getJDA(), Route.Channels.MODIFY_CHANNEL.compile(channel.getId())); @@ -177,9 +175,7 @@ public M clearOverridesRemoved() public M putPermissionOverride(@Nonnull IPermissionHolder permHolder, long allow, long deny) { if (!(channel instanceof IPermissionContainer)) - { throw new IllegalStateException("Can only set permissions on Channels that implement IPermissionContainer"); - } Checks.notNull(permHolder, "PermissionHolder"); Checks.check(permHolder.getGuild().equals(getGuild()), "PermissionHolder is not from the same Guild!"); @@ -402,8 +398,8 @@ public M setPosition(int position) @CheckReturnValue public M setTopic(String topic) { - if (type != ChannelType.TEXT && type != ChannelType.NEWS) - throw new IllegalStateException("Can only set topic on text and news channels"); + if (TOPIC_SUPPORTED.contains(type)) + throw new IllegalStateException("Can only set topic on text, forum, and news channels"); if (topic != null) Checks.notLonger(topic, 1024, "Topic"); this.topic = topic; @@ -415,8 +411,7 @@ public M setTopic(String topic) @CheckReturnValue public M setNSFW(boolean nsfw) { - if (type != ChannelType.TEXT && type != ChannelType.NEWS) - throw new IllegalStateException("Can only set nsfw on text and news channels"); + checkTypes(NSFW_SUPPORTED, "NSFW (age-restriction)"); this.nsfw = nsfw; set |= NSFW; return (M) this; @@ -426,8 +421,7 @@ public M setNSFW(boolean nsfw) @CheckReturnValue public M setSlowmode(int slowmode) { - if (type != ChannelType.TEXT && !type.isThread()) - throw new IllegalStateException("Can only set slowmode on text channels and threads"); + checkTypes(SLOWMODE_SUPPORTED, "slowmode"); Checks.check(slowmode <= TextChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode per user must be between 0 and %d (seconds)!", TextChannel.MAX_SLOWMODE); this.slowmode = slowmode; set |= SLOWMODE; @@ -600,4 +594,11 @@ protected Collection getOverrides() }); return data.valueCollection(); } + + protected void checkTypes(EnumSet supported, String what) + { + if (!supported.contains(type)) + throw new IllegalArgumentException("Can only configure " + what + " for channels of types " + + supported.stream().map(ChannelType::name).collect(Collectors.joining(", "))); + } } diff --git a/src/main/java/net/dv8tion/jda/internal/managers/channel/concrete/ForumChannelManagerImpl.java b/src/main/java/net/dv8tion/jda/internal/managers/channel/concrete/ForumChannelManagerImpl.java new file mode 100644 index 0000000000..64f55cc48d --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/managers/channel/concrete/ForumChannelManagerImpl.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.ForumChannel; +import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; +import net.dv8tion.jda.internal.managers.channel.ChannelManagerImpl; + +public class ForumChannelManagerImpl extends ChannelManagerImpl implements ForumChannelManager +{ + public ForumChannelManagerImpl(ForumChannel channel) + { + super(channel); + } +} From 8765433a6c1cc54c72df64b733c18ffd2f667046 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 20 Jul 2022 19:14:55 +0200 Subject: [PATCH 06/75] Improve checks in ChannelActionImpl --- .../restaction/ChannelActionImpl.java | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) 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 a879d23340..231dfbdba3 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 @@ -37,9 +37,14 @@ import java.util.EnumSet; import java.util.concurrent.TimeUnit; import java.util.function.BooleanSupplier; +import java.util.stream.Collectors; public class ChannelActionImpl extends AuditableRestActionImpl implements ChannelAction { + private static final EnumSet SLOWMODE_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM); + private static final EnumSet NSFW_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM, ChannelType.NEWS); + 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; @@ -50,17 +55,17 @@ public class ChannelActionImpl extends AuditableRestActi protected Integer position; protected ChannelType type; - // --text only-- + // --text/forum/voice only-- protected Integer slowmode = null; - // --text and news-- + // --text/forum/voice/news-- protected String topic = null; protected Boolean nsfw = null; // --voice only-- protected Integer userlimit = null; - // --voice and stage-- + // --audio only-- protected Integer bitrate = null; public ChannelActionImpl(Class clazz, String name, Guild guild, ChannelType type) @@ -169,8 +174,7 @@ public ChannelActionImpl setPosition(Integer position) @CheckReturnValue public ChannelActionImpl setTopic(String topic) { - if (type != ChannelType.TEXT && type != ChannelType.NEWS) - throw new UnsupportedOperationException("Can only set the topic for a TextChannel or NewsChannel!"); + checkTypes(TOPIC_SUPPORTED, "Topic"); if (topic != null && topic.length() > 1024) throw new IllegalArgumentException("Channel Topic must not be greater than 1024 in length!"); this.topic = topic; @@ -182,8 +186,7 @@ public ChannelActionImpl setTopic(String topic) @CheckReturnValue public ChannelActionImpl setNSFW(boolean nsfw) { - if (type != ChannelType.TEXT && type != ChannelType.NEWS) - throw new UnsupportedOperationException("Can only set nsfw for a TextChannel or NewsChannel!"); + checkTypes(NSFW_SUPPORTED, "NSFW (age-restricted)"); this.nsfw = nsfw; return this; } @@ -193,8 +196,7 @@ public ChannelActionImpl setNSFW(boolean nsfw) @CheckReturnValue public ChannelActionImpl setSlowmode(int slowmode) { - if (type != ChannelType.TEXT) - throw new UnsupportedOperationException("Can only set slowmode on text channels"); + checkTypes(SLOWMODE_SUPPORTED, "Slowmode"); Checks.check(slowmode <= TextChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode must be between 0 and %d (seconds)!", TextChannel.MAX_SLOWMODE); this.slowmode = slowmode; return this; @@ -294,7 +296,6 @@ private ChannelActionImpl addOverride(long targetId, int type, long allow, lo return this; } - // --voice only-- @Nonnull @Override @CheckReturnValue @@ -394,4 +395,11 @@ protected void handleSuccess(Response response, Request request) } request.onSuccess(clazz.cast(channel)); } + + protected void checkTypes(EnumSet supported, String what) + { + if (!supported.contains(type)) + throw new IllegalArgumentException("Can only configure " + what + " for channels of types " + + supported.stream().map(ChannelType::name).collect(Collectors.joining(", "))); + } } From fd4d312587b2513ee1066136b16a6607c2dac036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 20 Jul 2022 19:15:21 +0200 Subject: [PATCH 07/75] Remove tags --- .../jda/api/entities/ThreadChannel.java | 2 + .../channel/concrete/ForumChannel.java | 59 ++++++++++++++++--- .../internal/entities/ForumChannelImpl.java | 53 ++++++++++------- 3 files changed, 86 insertions(+), 28 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java index 3917ee11f0..d4d98cb67f 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java @@ -38,6 +38,8 @@ public interface ThreadChannel extends GuildMessageChannel, IMemberContainer // - rate_limit_per_user // - last_pin_timestamp (do we even use this for Text/News channels?) + int NAME_MAX_LENGTH = 100; + /** * Whether this thread is public or not. * 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 5c7d7ef383..5366a4e39e 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 @@ -27,8 +27,6 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.Collection; -import java.util.Collections; public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IAgeRestrictedChannel { @@ -54,6 +52,8 @@ default ChannelAction createCopy() return createCopy(getGuild()); } + // TODO: Should this be in StandardGuildMessageChannel? + /** * The slowmode set for this ForumChannel. *
    If slowmode is set this returns an {@code int} between 1 and {@link net.dv8tion.jda.api.entities.TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}. @@ -71,7 +71,7 @@ default ChannelAction createCopy() // TODO: Should this be in StandardGuildChannel? /** - * The topic set for this channel. + * 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. @@ -86,16 +86,59 @@ default ChannelAction createCopy() // // There is a temporary implementation available, which will most definitely be replaced in a future release. + /** + * 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#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE} + *
      If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
    • + *
    + * + * @param name + * The name of the post + * @param upload + * A file attachment to upload as the post content + * @param uploads + * Additional files to attach to the post + * + * @return {@link RestAction} - Type: {@link ThreadChannel} + */ @Nonnull @Incubating @CheckReturnValue - default RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull FileUpload... uploads) - { - return createForumPost(name, message, Collections.emptyList(), uploads); - } + RestAction createForumPost(@Nonnull String name, @Nonnull FileUpload upload, @Nonnull FileUpload... uploads); + /** + * 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#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE} + *
      If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
    • + *
    + * + * @param name + * The name of the post + * @param message + * The post message content + * @param uploads + * Additional files to attach to the post + * + * @throws IllegalArgumentException + *
      + *
    • If null is provided
    • + *
    • If the name is empty or longer than 100 characters
    • + *
    + * + * @return {@link RestAction} - Type: {@link ThreadChannel} + */ @Nonnull @Incubating @CheckReturnValue - RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull Collection tags, @Nonnull FileUpload... uploads); + RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull FileUpload... uploads); } diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index b0aaabec5c..1e6efc258a 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -44,10 +44,7 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.stream.Collectors; public class ForumChannelImpl extends AbstractGuildChannelImpl @@ -146,12 +143,29 @@ public String getTopic() @Nonnull @Override - public RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull Collection tags, @Nonnull FileUpload... uploads) + public RestAction createForumPost(@Nonnull String name, @Nonnull FileUpload upload, @Nonnull FileUpload... uploads) + { + Checks.notNull(upload, "Uploads"); + Checks.notNull(uploads, "Uploads"); + List files = new ArrayList<>(1 + uploads.length); + files.add(upload); + Collections.addAll(files, uploads); + return createForumPost(name, null, files); + } + + @Nonnull + @Override + public RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull FileUpload... uploads) { - Checks.notBlank(name, "Name"); Checks.notNull(message, "Message"); - Checks.notNull(tags, "Tags"); + return createForumPost(name, message, Arrays.asList(uploads)); + } + + private RestAction createForumPost(String name, Message message, Collection uploads) + { + Checks.notBlank(name, "Name"); Checks.noneNull(uploads, "Uploads"); + Checks.notLonger(name, ThreadChannel.NAME_MAX_LENGTH, "Name"); Member selfMember = getGuild().getSelfMember(); if (!selfMember.hasAccess(this)) @@ -162,24 +176,25 @@ public RestAction createForumPost(@Nonnull String name, @Nonnull DataObject payload = DataObject.empty(); payload.put("name", name); - if (!tags.isEmpty()) - payload.put("applied_tags", DataArray.fromCollection(tags)); - - DataObject messageJson; - payload.put("message", messageJson = DataObject.empty()); + if (message != null) + { + DataObject messageJson; + payload.put("message", messageJson = DataObject.empty()); - messageJson.put("content", message.getContentRaw()); - messageJson.put("embeds", DataArray.fromCollection(message.getEmbeds())); + messageJson.put("content", message.getContentRaw()); + messageJson.put("embeds", DataArray.fromCollection(message.getEmbeds())); + } RequestBody body; - if (uploads.length > 0) + if (!uploads.isEmpty()) { - MultipartBody.Builder form = AttachedFile.createMultipartBody(Arrays.asList(uploads), null); + List files = new ArrayList<>(uploads); + MultipartBody.Builder form = AttachedFile.createMultipartBody(files, null); DataArray attachments = DataArray.empty(); - for (int i = 0; i < uploads.length; i++) - attachments.add(uploads[i].toAttachmentData(i)); + for (int i = 0; i < files.size(); i++) + attachments.add(files.get(i).toAttachmentData(i)); form.addFormDataPart("payload_json", payload.toString()); body = form.build(); @@ -190,8 +205,6 @@ public RestAction createForumPost(@Nonnull String name, @Nonnull } Route.CompiledRoute route = Route.Channels.CREATE_THREAD_WITHOUT_MESSAGE.compile(getId()); - route = route.withQueryParams("use_nested_fields", "true"); - return new RestActionImpl<>(getJDA(), route, body, (response, request) -> { DataObject json = response.getObject(); EntityBuilder builder = api.getEntityBuilder(); From 45ae0ca76687cab2f6e4edcc2d0d46663e15e966 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 20 Jul 2022 19:16:39 +0200 Subject: [PATCH 08/75] Add throws docs for other overload --- .../jda/api/entities/channel/concrete/ForumChannel.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 5366a4e39e..2313181942 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 @@ -104,6 +104,12 @@ default ChannelAction createCopy() * @param uploads * Additional files to attach to the post * + * @throws IllegalArgumentException + *
      + *
    • If null is provided
    • + *
    • If the name is empty or longer than 100 characters
    • + *
    + * * @return {@link RestAction} - Type: {@link ThreadChannel} */ @Nonnull From 581f56f4e4d23a238f555b448fa81e5878b11984 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 20 Jul 2022 19:18:43 +0200 Subject: [PATCH 09/75] Add docs for permission checks --- .../jda/api/entities/channel/concrete/ForumChannel.java | 4 ++++ 1 file changed, 4 insertions(+) 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 2313181942..5a55bf5e2a 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 @@ -104,6 +104,8 @@ default ChannelAction createCopy() * @param uploads * Additional files to attach to the post * + * @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
    • @@ -135,6 +137,8 @@ default ChannelAction createCopy() * @param uploads * Additional files to attach to the post * + * @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
      • From 48ba485bad03fed73ab4e6245016f3ceff61d00b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 27 Jul 2022 00:40:01 +0200 Subject: [PATCH 10/75] Add new message count logic --- .../jda/api/entities/ThreadChannel.java | 19 ++++++++++++------- .../jda/internal/entities/EntityBuilder.java | 1 + .../internal/entities/ThreadChannelImpl.java | 15 ++++++++++++++- .../internal/handle/MessageCreateHandler.java | 6 ++---- .../internal/handle/MessageDeleteHandler.java | 9 ++------- 5 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java index d4d98cb67f..1bb4a6c25e 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java @@ -55,19 +55,24 @@ default boolean isPublic() /** * Gets the current number of messages present in this thread. - *
        - * Threads started from seed messages in the {@link IThreadContainer parent channel} will not count that seed message. - *
        - * This will be capped at 50, regardless of actual count. + *
        Threads started from seed messages in the {@link IThreadContainer parent channel} will not count that seed message. + *
        This will be capped at 50 for threads created before July 1, 2022. * - * @return The number of messages sent in this channel, capping at 50. + * @return The number of messages sent in this thread */ int getMessageCount(); + /** + * The total number of messages sent in this thread, including all deleted messages. + *
        This might be inaccurate for threads created before July 1, 2022. + * + * @return The total number of messages ever sent in this thread + */ + int getTotalMessageCount(); + /** * Gets the current number of members that have joined this thread. - *
        - * This is capped at 50, meaning any additional members will not affect this count. + *
        This is capped at 50, meaning any additional members will not affect this count. * * @return The number of members that have joined this thread, capping at 50. */ 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 9c4d394243..149ce89f81 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1176,6 +1176,7 @@ public ThreadChannel createThreadChannel(GuildImpl guild, DataObject json, long .setOwnerId(json.getLong("owner_id")) .setMemberCount(json.getInt("member_count")) .setMessageCount(json.getInt("message_count")) + .setTotalMessageCount(json.getInt("total_message_count", 0)) .setLatestMessageIdLong(json.getLong("last_message_id", 0)) .setSlowmode(json.getInt("rate_limit_per_user", 0)) .setLocked(threadMetadata.getBoolean("locked")) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index e590026502..98c0af1340 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -59,6 +59,7 @@ public class ThreadChannelImpl extends AbstractGuildChannelImpl 0) - { - gThread.setMessageCount(messageCount - 1); - } + gThread.setMessageCount(Math.max(0, gThread.getMessageCount() - 1)); + // Not decrementing total since that should include deleted as well } getJDA().handleEvent(new MessageDeleteEvent(getJDA(), responseNumber, messageId, channel)); From 26d4428ecd5af29d2e7c4610bb0b0e04e8b7bd63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 27 Jul 2022 00:42:12 +0200 Subject: [PATCH 11/75] Fix typo --- .../net/dv8tion/jda/internal/entities/ThreadChannelImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index 98c0af1340..5a626b7283 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -350,13 +350,13 @@ public ThreadChannelImpl setOwnerId(long ownerId) public ThreadChannelImpl setMessageCount(int messageCount) { - this.messageCount = Math.max(messageCount, this.messageCount); // If this is 0 we use the older count + this.messageCount = messageCount; return this; } public ThreadChannelImpl setTotalMessageCount(int messageCount) { - this.totalMessageCount = messageCount; + this.totalMessageCount = Math.max(messageCount, this.messageCount); // If this is 0 we use the older count return this; } From 9768352248cd77a1b0b291f49e77c69b315fbd26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sun, 31 Jul 2022 14:29:16 +0200 Subject: [PATCH 12/75] Add forums to Guild#getChannels --- .../net/dv8tion/jda/api/entities/Guild.java | 28 ++++++++----------- .../jda/internal/entities/GuildImpl.java | 8 +++++- 2 files changed, 19 insertions(+), 17 deletions(-) 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 47cf16038f..dfc0db0de8 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -1281,19 +1281,18 @@ default List getMembersWithRoles(@Nonnull Collection roles) /** * Populated list of {@link GuildChannel channels} for this guild. - * This includes all types of channels, such as category/voice/text. - *
        This includes hidden channels by default. + *
        This includes all types of channels, except for threads. + *
        This includes hidden channels by default, + * you can use {@link #getChannels(boolean) getChannels(false)} to exclude hidden channels. * *

        The returned list is ordered in the same fashion as it would be by the official discord client. *

          - *
        1. TextChannel and NewsChannel without parent
        2. - *
        3. VoiceChannel without parent
        4. - *
        5. StageChannel without parent
        6. + *
        7. TextChannel, ForumChannel, and NewsChannel without parent
        8. + *
        9. VoiceChannel and StageChannel without parent
        10. *
        11. Categories *
            - *
          1. TextChannel and NewsChannel with category as parent
          2. - *
          3. VoiceChannel with category as parent
          4. - *
          5. StageChannel with category as parent
          6. + *
          7. TextChannel, ForumChannel, and NewsChannel with category as parent
          8. + *
          9. VoiceChannel and StageChannel with category as parent
          10. *
          *
        12. *
        @@ -1310,23 +1309,20 @@ default List getChannels() /** * Populated list of {@link GuildChannel channels} for this guild. - * This includes all types of channels, such as category/voice/text. + *
        This includes all types of channels, except for threads. * *

        The returned list is ordered in the same fashion as it would be by the official discord client. *

          - *
        1. TextChannel and NewsChannel without parent
        2. - *
        3. VoiceChannel without parent
        4. - *
        5. StageChannel without parent
        6. + *
        7. TextChannel, ForumChannel, and NewsChannel without parent
        8. + *
        9. VoiceChannel and StageChannel without parent
        10. *
        11. Categories *
            - *
          1. TextChannel and NewsChannel with category as parent
          2. - *
          3. VoiceChannel with category as parent
          4. - *
          5. StageChannel with category as parent
          6. + *
          7. TextChannel, ForumChannel, and NewsChannel with category as parent
          8. + *
          9. VoiceChannel and StageChannel with category as parent
          10. *
          *
        12. *
        * - * * @param includeHidden * Whether to include channels with denied {@link Permission#VIEW_CHANNEL View Channel Permission} * 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 f98f722b5b..445af387c2 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -704,16 +704,19 @@ public List getChannels(boolean includeHidden) SnowflakeCacheViewImpl stageView = getStageChannelsView(); SnowflakeCacheViewImpl textView = getTextChannelsView(); SnowflakeCacheViewImpl newsView = getNewsChannelView(); + SnowflakeCacheViewImpl forumView = getForumChannelsView(); List textChannels; List newsChannels; List voiceChannels; List stageChannels; + List forumChannels; List categories; try (UnlockHook categoryHook = categoryView.readLock(); UnlockHook voiceHook = voiceView.readLock(); UnlockHook textHook = textView.readLock(); UnlockHook newsHook = newsView.readLock(); - UnlockHook stageHook = stageView.readLock()) + UnlockHook stageHook = stageView.readLock(); + UnlockHook forumHook = forumView.readLock()) { if (includeHidden) { @@ -721,6 +724,7 @@ public List getChannels(boolean includeHidden) newsChannels = newsView.asList(); voiceChannels = voiceView.asList(); stageChannels = stageView.asList(); + forumChannels = forumView.asList(); } else { @@ -728,6 +732,7 @@ public List getChannels(boolean includeHidden) newsChannels = newsView.stream().filter(filterHidden).collect(Collectors.toList()); voiceChannels = voiceView.stream().filter(filterHidden).collect(Collectors.toList()); stageChannels = stageView.stream().filter(filterHidden).collect(Collectors.toList()); + forumChannels = forumView.stream().filter(filterHidden).collect(Collectors.toList()); } categories = categoryView.asList(); // we filter categories out when they are empty (no visible channels inside) channels = new ArrayList<>((int) categoryView.size() + voiceChannels.size() + textChannels.size() + newsChannels.size() + stageChannels.size()); @@ -737,6 +742,7 @@ public List getChannels(boolean includeHidden) newsChannels.stream().filter(it -> it.getParentCategory() == null).forEach(channels::add); voiceChannels.stream().filter(it -> it.getParentCategory() == null).forEach(channels::add); stageChannels.stream().filter(it -> it.getParentCategory() == null).forEach(channels::add); + forumChannels.stream().filter(it -> it.getParentCategory() == null).forEach(channels::add); Collections.sort(channels); for (Category category : categories) From 9418b61e4629166554eab8a9ffdda1822a4f69fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sun, 31 Jul 2022 14:34:11 +0200 Subject: [PATCH 13/75] Add Category#getForumChannels --- .../dv8tion/jda/api/entities/Category.java | 54 +++++++++++++------ .../jda/api/utils/cache/CacheView.java | 1 - 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Category.java b/src/main/java/net/dv8tion/jda/api/entities/Category.java index e18e1c44e5..9ab83d52a8 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Category.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Category.java @@ -50,10 +50,8 @@ public interface Category extends GuildChannel, ICopyableChannel, IPositionableChannel, IPermissionContainer, IMemberContainer { /** - * All {@link GuildChannel Channels} listed - * for this Category - *
        This may contain {@link net.dv8tion.jda.api.entities.VoiceChannel VoiceChannels}, - * and {@link net.dv8tion.jda.api.entities.TextChannel TextChannels}! + * All {@link GuildChannel Channels} listed for this Category. + *
        Includes all types of channels, except for threads. * * @return Immutable list of all child channels */ @@ -65,6 +63,7 @@ default List getChannels() channels.addAll(getVoiceChannels()); channels.addAll(getStageChannels()); channels.addAll(getNewsChannels()); + channels.addAll(getForumChannels()); Collections.sort(channels); return Collections.unmodifiableList(channels); @@ -79,9 +78,11 @@ default List getChannels() @Nonnull default List getTextChannels() { - return Collections.unmodifiableList(getGuild().getTextChannelCache().stream() - .filter(channel -> equals(channel.getParentCategory())) - .sorted().collect(Collectors.toList())); + return Collections.unmodifiableList(getGuild().getTextChannelCache().applyStream(stream -> + stream.filter(channel -> equals(channel.getParentCategory())) + .sorted() + .collect(Collectors.toList()) + )); } /** @@ -93,9 +94,26 @@ default List getTextChannels() @Nonnull default List getNewsChannels() { - return Collections.unmodifiableList(getGuild().getNewsChannelCache().stream() - .filter(channel -> equals(channel.getParentCategory())) - .sorted().collect(Collectors.toList())); + return Collections.unmodifiableList(getGuild().getNewsChannelCache().applyStream(stream -> + stream.filter(channel -> equals(channel.getParentCategory())) + .sorted() + .collect(Collectors.toList()) + )); + } + + /** + * All {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels} listed for this Category + * + * @return Immutable list of all child ForumChannels + */ + @Nonnull + default List getForumChannels() + { + return Collections.unmodifiableList(getGuild().getForumChannelCache().applyStream(stream -> + stream.filter(channel -> equals(channel.getParentCategory())) + .sorted() + .collect(Collectors.toList()) + )); } /** @@ -107,9 +125,11 @@ default List getNewsChannels() @Nonnull default List getVoiceChannels() { - return Collections.unmodifiableList(getGuild().getVoiceChannelCache().stream() - .filter(channel -> equals(channel.getParentCategory())) - .sorted().collect(Collectors.toList())); + return Collections.unmodifiableList(getGuild().getVoiceChannelCache().applyStream(stream -> + stream.filter(channel -> equals(channel.getParentCategory())) + .sorted() + .collect(Collectors.toList()) + )); } /** @@ -121,9 +141,11 @@ default List getVoiceChannels() @Nonnull default List getStageChannels() { - return Collections.unmodifiableList(getGuild().getStageChannelCache().stream() - .filter(channel -> equals(channel.getParentCategory())) - .sorted().collect(Collectors.toList())); + return Collections.unmodifiableList(getGuild().getStageChannelCache().applyStream(stream -> + stream.filter(channel -> equals(channel.getParentCategory())) + .sorted() + .collect(Collectors.toList()) + )); } /** diff --git a/src/main/java/net/dv8tion/jda/api/utils/cache/CacheView.java b/src/main/java/net/dv8tion/jda/api/utils/cache/CacheView.java index 6a75cac639..ef50e5271b 100644 --- a/src/main/java/net/dv8tion/jda/api/utils/cache/CacheView.java +++ b/src/main/java/net/dv8tion/jda/api/utils/cache/CacheView.java @@ -140,7 +140,6 @@ default void forEachUnordered(@Nonnull final Consumer action) * * @see #acceptStream(Consumer) */ - @Nullable default R applyStream(@Nonnull Function, ? extends R> action) { Checks.notNull(action, "Action"); From 9aaf5f73d0a1c8a214077bf990eb01f56f38092a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sun, 31 Jul 2022 14:36:14 +0200 Subject: [PATCH 14/75] Clear forum channel cache on invalidate --- .../java/net/dv8tion/jda/internal/entities/GuildImpl.java | 6 ++++++ .../net/dv8tion/jda/internal/requests/WebSocketClient.java | 1 + 2 files changed, 7 insertions(+) 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 445af387c2..c5ed0a2738 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -156,6 +156,7 @@ public void invalidate() SnowflakeCacheViewImpl textView = getJDA().getTextChannelsView(); SnowflakeCacheViewImpl threadView = getJDA().getThreadChannelsView(); SnowflakeCacheViewImpl newsView = getJDA().getNewsChannelView(); + SnowflakeCacheViewImpl forumView = getJDA().getForumChannelsView(); SnowflakeCacheViewImpl voiceView = getJDA().getVoiceChannelsView(); SnowflakeCacheViewImpl categoryView = getJDA().getCategoriesView(); @@ -181,6 +182,11 @@ public void invalidate() getNewsChannelCache() .forEachUnordered(chan -> newsView.getMap().remove(chan.getIdLong())); } + try (UnlockHook hook = forumView.writeLock()) + { + getForumChannelCache() + .forEachUnordered(chan -> forumView.getMap().remove(chan.getIdLong())); + } try (UnlockHook hook = voiceView.writeLock()) { getVoiceChannelCache() 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 8f2290d08f..e4a5c66137 100644 --- a/src/main/java/net/dv8tion/jda/internal/requests/WebSocketClient.java +++ b/src/main/java/net/dv8tion/jda/internal/requests/WebSocketClient.java @@ -750,6 +750,7 @@ protected void invalidate() api.getPrivateChannelsView().clear(); api.getStageChannelView().clear(); api.getThreadChannelsView().clear(); + api.getForumChannelsView().clear(); api.getGuildsView().clear(); api.getUsersView().clear(); From a30040e176322a0b6b3ead3812b20fa9b3ad1219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sun, 31 Jul 2022 14:41:08 +0200 Subject: [PATCH 15/75] Reduce code duplication in createXChannel --- .../jda/internal/entities/GuildImpl.java | 44 +++++-------------- 1 file changed, 12 insertions(+), 32 deletions(-) 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 c5ed0a2738..5c557adf2f 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -1681,72 +1681,52 @@ public AuditableRestAction transferOwnership(@Nonnull Member newOwner) @Override public ChannelAction createTextChannel(@Nonnull String name, Category parent) { - checkCanCreateChannel(parent); - - Checks.notBlank(name, "Name"); - name = name.trim(); - Checks.notLonger(name, 100, "Name"); - return new ChannelActionImpl<>(TextChannel.class, name, this, ChannelType.TEXT).setParent(parent); + return createChannel(ChannelType.TEXT, TextChannel.class, name, parent); } @Nonnull @Override public ChannelAction createNewsChannel(@Nonnull String name, Category parent) { - checkCanCreateChannel(parent); - - Checks.notBlank(name, "Name"); - name = name.trim(); - Checks.notLonger(name, 100, "Name"); - return new ChannelActionImpl<>(NewsChannel.class, name, this, ChannelType.NEWS).setParent(parent); + return createChannel(ChannelType.NEWS, NewsChannel.class, name, parent); } @Nonnull @Override public ChannelAction createVoiceChannel(@Nonnull String name, Category parent) { - checkCanCreateChannel(parent); - - Checks.notBlank(name, "Name"); - name = name.trim(); - Checks.notLonger(name, 100, "Name"); - return new ChannelActionImpl<>(VoiceChannel.class, name, this, ChannelType.VOICE).setParent(parent); + return createChannel(ChannelType.VOICE, VoiceChannel.class, name, parent); } @Nonnull @Override public ChannelAction createStageChannel(@Nonnull String name, Category parent) { - checkCanCreateChannel(parent); - - Checks.notBlank(name, "Name"); - name = name.trim(); - Checks.notLonger(name, 100, "Name"); - return new ChannelActionImpl<>(StageChannel.class, name, this, ChannelType.STAGE).setParent(parent); + return createChannel(ChannelType.STAGE, StageChannel.class, name, parent); } @Nonnull @Override public ChannelAction createForumChannel(@Nonnull String name, Category parent) { - checkCanCreateChannel(parent); - - Checks.notBlank(name, "Name"); - name = name.trim(); - Checks.notLonger(name, 100, "Name"); - return new ChannelActionImpl<>(ForumChannel.class, name, this, ChannelType.FORUM).setParent(parent); + return createChannel(ChannelType.FORUM, ForumChannel.class, name, parent); } @Nonnull @Override public ChannelAction createCategory(@Nonnull String name) { - checkPermission(Permission.MANAGE_CHANNEL); + return createChannel(ChannelType.CATEGORY, Category.class, name, null); + } + + private ChannelAction createChannel(ChannelType type, Class clazz, String name, Category parent) + { + checkCanCreateChannel(parent); Checks.notBlank(name, "Name"); name = name.trim(); Checks.notEmpty(name, "Name"); Checks.notLonger(name, 100, "Name"); - return new ChannelActionImpl<>(Category.class, name, this, ChannelType.CATEGORY); + return new ChannelActionImpl<>(clazz, name, this, type).setParent(parent); } @Nonnull From 391919635aa33ea2f82036b1ce02ce160f137ed4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sun, 31 Jul 2022 15:03:28 +0200 Subject: [PATCH 16/75] Improve some documentation --- .../dv8tion/jda/api/entities/Category.java | 16 +-- .../net/dv8tion/jda/api/entities/Channel.java | 2 + .../net/dv8tion/jda/api/entities/Guild.java | 44 ++++---- .../jda/api/entities/IThreadContainer.java | 105 +++++++++++------- .../internal/entities/ForumChannelImpl.java | 9 +- .../attribute/IThreadContainerMixin.java | 30 +++-- 6 files changed, 120 insertions(+), 86 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Category.java b/src/main/java/net/dv8tion/jda/api/entities/Category.java index 9ab83d52a8..3dc58f1f42 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Category.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Category.java @@ -171,12 +171,12 @@ default List getStageChannels() *
      * * @param name - * The name of the TextChannel to create + * The name of the TextChannel 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} or empty or greater than 100 characters in length + * 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 TextChannel before creating it @@ -208,12 +208,12 @@ default List getStageChannels() *
    * * @param name - * The name of the VoiceChannel to create + * The name of the VoiceChannel 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} or empty or greater than 100 characters in length + * 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 VoiceChannel before creating it @@ -245,12 +245,12 @@ default List getStageChannels() * * * @param name - * The name of the StageChannel to create + * The name of the StageChannel 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} or empty or greater than 100 characters in length + * 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 StageChannel before creating it @@ -282,12 +282,12 @@ default List getStageChannels() * * * @param name - * The name of the ForumChannel to create + * The name of the ForumChannel 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} or empty or greater than 100 characters in length + * 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 ForumChannel before creating it diff --git a/src/main/java/net/dv8tion/jda/api/entities/Channel.java b/src/main/java/net/dv8tion/jda/api/entities/Channel.java index 817173ad28..ab267739aa 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Channel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Channel.java @@ -30,6 +30,8 @@ */ public interface Channel extends IMentionable { + int MAX_NAME_LENGTH = 100; + /** * The human readable name of this channel. * 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 dfc0db0de8..1f93942add 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -3906,12 +3906,12 @@ default AuditableRestAction modifyMemberRoles(@Nonnull Member member, @Non * * * @param name - * The name of the TextChannel to create + * The name of the TextChannel 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} or empty or greater than 100 characters in length + * If the provided name is {@code null}, blank, or longer than {@value Channel#MAX_NAME_LENGTH} characters * * @return A specific {@link net.dv8tion.jda.api.requests.restaction.ChannelAction ChannelAction} *
    This action allows to set fields for the new TextChannel before creating it @@ -3938,14 +3938,14 @@ default ChannelAction createTextChannel(@Nonnull String name) * * * @param name - * The name of the TextChannel to create + * The name of the TextChannel 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} or empty or greater than 100 characters in length; + * 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 net.dv8tion.jda.api.requests.restaction.ChannelAction ChannelAction} @@ -3970,12 +3970,12 @@ default ChannelAction createTextChannel(@Nonnull String name) * * * @param name - * The name of the NewsChannel to create + * The name of the NewsChannel 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} or empty or greater than 100 characters in length + * If the provided name is {@code null}, blank, or longer than {@value Channel#MAX_NAME_LENGTH} characters * * @return A specific {@link net.dv8tion.jda.api.requests.restaction.ChannelAction ChannelAction} *
    This action allows to set fields for the new NewsChannel before creating it @@ -4002,14 +4002,14 @@ default ChannelAction createNewsChannel(@Nonnull String name) * * * @param name - * The name of the NewsChannel to create + * The name of the NewsChannel 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} or empty or greater than 100 characters in length; + * 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 net.dv8tion.jda.api.requests.restaction.ChannelAction ChannelAction} @@ -4034,12 +4034,12 @@ default ChannelAction createNewsChannel(@Nonnull String name) * * * @param name - * The name of the VoiceChannel to create + * The name of the VoiceChannel 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} or empty or greater than 100 characters in length + * 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 VoiceChannel before creating it @@ -4066,14 +4066,14 @@ default ChannelAction createVoiceChannel(@Nonnull String name) * * * @param name - * The name of the VoiceChannel to create + * The name of the VoiceChannel 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} or empty or greater than 100 characters in length; + * 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} @@ -4098,12 +4098,12 @@ default ChannelAction createVoiceChannel(@Nonnull String name) * * * @param name - * The name of the StageChannel to create + * The name of the StageChannel 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} or empty or greater than 100 characters in length + * 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 StageChannel before creating it @@ -4130,14 +4130,14 @@ default ChannelAction createStageChannel(@Nonnull String name) * * * @param name - * The name of the StageChannel to create + * The name of the StageChannel 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} or empty or greater than 100 characters in length; + * 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} @@ -4162,12 +4162,12 @@ default ChannelAction createStageChannel(@Nonnull String name) * * * @param name - * The name of the StageChannel to create + * The name of the StageChannel 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} or empty or greater than 100 characters in length + * 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 StageChannel before creating it @@ -4194,14 +4194,14 @@ default ChannelAction createForumChannel(@Nonnull String name) * * * @param name - * The name of the ForumChannel to create + * The name of the ForumChannel 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} or empty or greater than 100 characters in length; + * 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} @@ -4226,12 +4226,12 @@ default ChannelAction createForumChannel(@Nonnull String name) * * * @param name - * The name of the Category to create + * The name of the Category 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} or empty or greater than 100 characters in length + * 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 Category before creating it diff --git a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java index 385b68306a..1f7c49ae2a 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java +++ b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java @@ -19,6 +19,7 @@ import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction; import net.dv8tion.jda.api.requests.restaction.pagination.ThreadChannelPaginationAction; +import net.dv8tion.jda.api.utils.FileUpload; import net.dv8tion.jda.api.utils.MiscUtil; import javax.annotation.CheckReturnValue; @@ -32,24 +33,21 @@ public interface IThreadContainer extends GuildChannel, IPermissionContainer /** * Finds all {@link ThreadChannel ThreadChannels} whose parent is this channel. * - * @return a list of all ThreadChannel children. + * @return Immutable list of all ThreadChannel children. */ default List getThreadChannels() { return Collections.unmodifiableList( - getGuild().getThreadChannels() - .stream() - .filter(thread -> thread.getParentChannel() == this) - .collect(Collectors.toList()) - ); + getGuild().getThreadChannelCache().applyStream(stream -> + stream.filter(thread -> thread.getParentChannel() == this) + .collect(Collectors.toList()) + )); } - /** - * Creates a new, public {@link ThreadChannel} with the parent channel being this {@link IThreadContainer}. - * This requires the bot to have the {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL} and {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS} permissions. + * Creates a new public {@link ThreadChannel} with the parent channel being this {@link IThreadContainer}. * - * The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be either one of: + *

    The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be either one of: *

      *
    • {@link ChannelType#GUILD_PUBLIC_THREAD}
    • *
    • {@link ChannelType#GUILD_NEWS_THREAD}
    • @@ -66,26 +64,35 @@ default List getThreadChannels() * *
    • {@link net.dv8tion.jda.api.requests.ErrorResponse#MAX_ACTIVE_THREADS} *
      The maximum number of active threads has been reached, and no more may be created.
    • - * *
    * - * @param name - * The name of the new ThreadChannel + * @param name + * The name of the new ThreadChannel (up to {@value Channel#MAX_NAME_LENGTH} characters) + * + * @throws IllegalArgumentException + * If the provided name is null, blank, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters + * @throws UnsupportedOperationException + * If this is a forum channel. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. + * @throws InsufficientPermissionException + *
      + *
    • If the bot does not have {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
    • + *
    • If the bot does not have {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS}
    • + *
    * * @return A specific {@link ThreadChannelAction} that may be used to configure the new ThreadChannel before its creation. */ @Nonnull @CheckReturnValue - default ThreadChannelAction createThreadChannel(String name) + default ThreadChannelAction createThreadChannel(@Nonnull String name) { return createThreadChannel(name, false); } /** * Creates a new {@link ThreadChannel} with the parent channel being this {@link IThreadContainer}. - * This requires the bot to have the {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL} and {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS} permissions. * - * The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be one of: + *

    The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be one of: *

      *
    • {@link ChannelType#GUILD_PUBLIC_THREAD}
    • *
    • {@link ChannelType#GUILD_NEWS_THREAD}
    • @@ -106,30 +113,36 @@ default ThreadChannelAction createThreadChannel(String name) * *
    • {@link net.dv8tion.jda.api.requests.ErrorResponse#MISSING_PERMISSIONS} *
      Due to missing private thread permissions.
    • - * *
    * * @param name - * The name of the new ThreadChannel + * The name of the new ThreadChannel (up to {@value Channel#MAX_NAME_LENGTH} characters) * @param isPrivate * The public/private status of the new ThreadChannel. If true, the new ThreadChannel will be private. * + * @throws IllegalArgumentException + * If the provided name is null, blank, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters + * @throws UnsupportedOperationException + * If this is a forum channel. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. * @throws InsufficientPermissionException - * if the ThreadChannel is set to private, and the logged in account does not have {@link net.dv8tion.jda.api.Permission#CREATE_PRIVATE_THREADS}. + *
      + *
    • If the bot does not have {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
    • + *
    • If the thread is {@code private}, and the bot does not have {@link net.dv8tion.jda.api.Permission#CREATE_PRIVATE_THREADS Permission.CREATE_PRIVATE_THREADS}
    • + *
    • If the thread is not {@code private}, and the bot does not have {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS}
    • + *
    * * @return A specific {@link ThreadChannelAction} that may be used to configure the new ThreadChannel before its creation. */ @Nonnull @CheckReturnValue - ThreadChannelAction createThreadChannel(String name, boolean isPrivate); - + ThreadChannelAction createThreadChannel(@Nonnull String name, boolean isPrivate); /** * Creates a new, public {@link ThreadChannel} with the parent channel being this {@link IThreadContainer}. - * This ThreadChannel will be spawned from the given messageID, and will consequently share its ID with the message. - * This requires the bot to have {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL} and {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS} permissions. + *
    The starting message will copy the message for the provided id, and will be of type {@link MessageType#THREAD_STARTER_MESSAGE MessageType.THREAD_STARTER_MESSAGE}. * - * The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be one of: + *

    The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be one of: *

      *
    • {@link ChannelType#GUILD_PUBLIC_THREAD}
    • *
    • {@link ChannelType#GUILD_NEWS_THREAD}
    • @@ -149,27 +162,33 @@ default ThreadChannelAction createThreadChannel(String name) * *
    • {@link net.dv8tion.jda.api.requests.ErrorResponse#MAX_ACTIVE_THREADS} *
      The maximum number of active threads has been reached, and no more may be created.
    • - * *
    * - * @param name - * The name of the new ThreadChannel - * @param messageId - * The ID of the message from which this ThreadChannel will be spawned. + * @param name + * The name of the new ThreadChannel (up to {@value Channel#MAX_NAME_LENGTH} characters) + * @param messageId + * The ID of the message from which this ThreadChannel will be spawned. + * + * @throws IllegalArgumentException + * If the provided name is null, blank, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters + * @throws UnsupportedOperationException + * If this is a forum channel. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. + * @throws InsufficientPermissionException + * If the bot does not have {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS} in this channel * * @return A specific {@link ThreadChannelAction} that may be used to configure the new ThreadChannel before its creation. */ @Nonnull @CheckReturnValue - ThreadChannelAction createThreadChannel(String name, long messageId); + ThreadChannelAction createThreadChannel(@Nonnull String name, long messageId); /** * Creates a new, public {@link ThreadChannel} with the parent channel being this {@link IThreadContainer}. - * This ThreadChannel will be spawned from the given messageID, and will consequently share its ID with the message. - * This requires the bot to have {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL} and {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS} permissions. + *
    The starting message will copy the message for the provided id, and will be of type {@link MessageType#THREAD_STARTER_MESSAGE MessageType.THREAD_STARTER_MESSAGE}. * - * The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be one of: + *

    The resulting {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannel} may be one of: *

      *
    • {@link ChannelType#GUILD_PUBLIC_THREAD}
    • *
    • {@link ChannelType#GUILD_NEWS_THREAD}
    • @@ -189,19 +208,27 @@ default ThreadChannelAction createThreadChannel(String name) * *
    • {@link net.dv8tion.jda.api.requests.ErrorResponse#MAX_ACTIVE_THREADS} *
      The maximum number of active threads has been reached, and no more may be created.
    • - * *
    * - * @param name - * The name of the new ThreadChannel - * @param messageId - * The ID of the message from which this ThreadChannel will be spawned. + * @param name + * The name of the new ThreadChannel (up to {@value Channel#MAX_NAME_LENGTH} characters) + * @param messageId + * The ID of the message from which this ThreadChannel will be spawned. + * + * @throws IllegalArgumentException + * If the provided name is null, blank, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters. + * Or the message id is not a valid snowflake. + * @throws UnsupportedOperationException + * If this is a forum channel. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. + * @throws InsufficientPermissionException + * If the bot does not have {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS} in this channel * * @return A specific {@link ThreadChannelAction} that may be used to configure the new ThreadChannel before its creation. */ @Nonnull @CheckReturnValue - default ThreadChannelAction createThreadChannel(String name, String messageId) + default ThreadChannelAction createThreadChannel(@Nonnull String name, @Nonnull String messageId) { return createThreadChannel(name, MiscUtil.parseSnowflake(messageId)); } diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index 1e6efc258a..fc75c8e3b5 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -41,7 +41,6 @@ import net.dv8tion.jda.internal.utils.Checks; import okhttp3.MultipartBody; import okhttp3.RequestBody; -import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import java.util.*; @@ -212,16 +211,16 @@ private RestAction createForumPost(String name, Message message, }); } - @NotNull + @Nonnull @Override - public ThreadChannelAction createThreadChannel(String name) + public ThreadChannelAction createThreadChannel(@Nonnull String name) { throw new UnsupportedOperationException("You cannot create threads without a message payload in forum channels! Use createForumPost(...) instead."); } - @NotNull + @Nonnull @Override - public ThreadChannelAction createThreadChannel(String name, String messageId) + public ThreadChannelAction createThreadChannel(@Nonnull String name, @Nonnull String messageId) { throw new UnsupportedOperationException("You cannot create threads without a message payload in forum channels! Use createForumPost(...) instead."); } diff --git a/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java b/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java index 9eec35ee54..39a32f6b06 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java @@ -26,11 +26,10 @@ import net.dv8tion.jda.internal.requests.Route; import net.dv8tion.jda.internal.requests.restaction.ThreadChannelActionImpl; import net.dv8tion.jda.internal.requests.restaction.pagination.ThreadChannelPaginationActionImpl; +import net.dv8tion.jda.internal.utils.Checks; -import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; -//TODO-v5: add checks for valid ThreadChannel names (0-100 chars) public interface IThreadContainerMixin> extends IThreadContainer, IThreadContainerUnion, @@ -38,12 +37,15 @@ public interface IThreadContainerMixin> exten { // ---- Default implementations of interface ---- @Nonnull - @CheckReturnValue @Override - default ThreadChannelAction createThreadChannel(String name, boolean isPrivate) + default ThreadChannelAction createThreadChannel(@Nonnull String name, boolean isPrivate) { - checkPermission(Permission.VIEW_CHANNEL); - // TODO: Update these checks for forums! + Checks.notNull(name, "Name"); + name = name.trim(); + Checks.notEmpty(name, "Name"); + Checks.notLonger(name, 100, "Name"); + + Checks.checkAccess(getGuild().getSelfMember(), this); if (isPrivate) { if (!getGuild().getFeatures().contains("PRIVATE_THREADS")) @@ -65,21 +67,25 @@ default ThreadChannelAction createThreadChannel(String name, boolean isPrivate) } @Nonnull - @CheckReturnValue @Override - default ThreadChannelAction createThreadChannel(String name, long messageId) + default ThreadChannelAction createThreadChannel(@Nonnull String name, long messageId) { - checkPermission(Permission.VIEW_CHANNEL); + Checks.notNull(name, "Name"); + name = name.trim(); + Checks.notEmpty(name, "Name"); + Checks.notLonger(name, 100, "Name"); + + Checks.checkAccess(getGuild().getSelfMember(), this); checkPermission(Permission.CREATE_PUBLIC_THREADS); return new ThreadChannelActionImpl(this, name, Long.toUnsignedString(messageId)); } @Nonnull - @CheckReturnValue @Override default ThreadChannelPaginationAction retrieveArchivedPublicThreadChannels() { + Checks.checkAccess(getGuild().getSelfMember(), this); checkPermission(Permission.MESSAGE_HISTORY); Route.CompiledRoute route = Route.Channels.LIST_PUBLIC_ARCHIVED_THREADS.compile(getId()); @@ -87,10 +93,10 @@ default ThreadChannelPaginationAction retrieveArchivedPublicThreadChannels() } @Nonnull - @CheckReturnValue @Override default ThreadChannelPaginationAction retrieveArchivedPrivateThreadChannels() { + Checks.checkAccess(getGuild().getSelfMember(), this); checkPermission(Permission.MESSAGE_HISTORY); checkPermission(Permission.MANAGE_THREADS); @@ -99,10 +105,10 @@ default ThreadChannelPaginationAction retrieveArchivedPrivateThreadChannels() } @Nonnull - @CheckReturnValue @Override default ThreadChannelPaginationAction retrieveArchivedPrivateJoinedThreadChannels() { + Checks.checkAccess(getGuild().getSelfMember(), this); checkPermission(Permission.MESSAGE_HISTORY); Route.CompiledRoute route = Route.Channels.LIST_JOINED_PRIVATE_ARCHIVED_THREADS.compile(getId()); From 628e2f7e03e7c3218805fee5d8c4afb49f8d2cfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sun, 31 Jul 2022 15:08:29 +0200 Subject: [PATCH 17/75] Add Category#createNewsChannel --- .../dv8tion/jda/api/entities/Category.java | 37 +++++++++++++++++++ .../jda/internal/entities/CategoryImpl.java | 8 ++++ 2 files changed, 45 insertions(+) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Category.java b/src/main/java/net/dv8tion/jda/api/entities/Category.java index 3dc58f1f42..1b7ead2be3 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Category.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Category.java @@ -185,6 +185,43 @@ default List getStageChannels() @CheckReturnValue ChannelAction createTextChannel(@Nonnull String name); + /** + * Creates a new {@link net.dv8tion.jda.api.entities.NewsChannel NewsChannel} 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 NewsChannel 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 NewsChannel before creating it + */ + @Nonnull + @CheckReturnValue + ChannelAction createNewsChannel(@Nonnull String name); + /** * Creates a new {@link net.dv8tion.jda.api.entities.VoiceChannel VoiceChannel} with this Category as parent. * For this to be successful, the logged in account has to have the diff --git a/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java index 09849d80d5..d6d0528301 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/CategoryImpl.java @@ -66,6 +66,14 @@ public ChannelAction createTextChannel(@Nonnull String name) return trySync(action); } + @Nonnull + @Override + public ChannelAction createNewsChannel(@Nonnull String name) + { + ChannelAction action = getGuild().createNewsChannel(name, this); + return trySync(action); + } + @Nonnull @Override public ChannelAction createVoiceChannel(@Nonnull String name) From b4739f6db9e9bfd348817cc4996b6689a5510203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sun, 31 Jul 2022 15:17:48 +0200 Subject: [PATCH 18/75] Add missing docs for IThreadContainer --- .../jda/api/entities/IThreadContainer.java | 48 +++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java index 1f7c49ae2a..44bf95c570 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java +++ b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java @@ -28,6 +28,12 @@ import java.util.List; import java.util.stream.Collectors; +/** + * Abstraction of all channel types, which can contain or manage {@link ThreadChannel ThreadChannels}. + * + * @see ThreadChannel#getParentChannel() + * @see net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion IThreadContainerUnion + */ public interface IThreadContainer extends GuildChannel, IPermissionContainer { /** @@ -233,17 +239,53 @@ default ThreadChannelAction createThreadChannel(@Nonnull String name, @Nonnull S return createThreadChannel(name, MiscUtil.parseSnowflake(messageId)); } - //TODO-v5: Docs + /** + * Retrieves the archived public {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannels} for this channel. + *
    This will iterate over all previously opened public threads, that have been archived. + * + *

    You can use {@link #retrieveArchivedPrivateThreadChannels()}, to get all private archived threads. + * + * @throws InsufficientPermissionException + * If the bot does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in this channel + * + * @return {@link ThreadChannelPaginationAction} to iterate over all public archived ThreadChannels + */ @Nonnull @CheckReturnValue ThreadChannelPaginationAction retrieveArchivedPublicThreadChannels(); - //TODO-v5: Docs + /** + * Retrieves the archived private {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannels} for this channel. + *
    This will iterate over all previously opened private threads, that have been archived. + * This is a moderator restricted method, since private threads are only visible to members with {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS Permission.MANAGE_THREADS}. + * + *

    You can use {@link #retrieveArchivedPublicThreadChannels()}, to get all public archived threads. + * + *

    Note that {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels} cannot have private threads. + * + * @throws InsufficientPermissionException + * If the bot does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} + * or {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS Permission.MANAGE_THREADS} in this channel + * + * @return {@link ThreadChannelPaginationAction} to iterate over all private archived ThreadChannels + */ @Nonnull @CheckReturnValue ThreadChannelPaginationAction retrieveArchivedPrivateThreadChannels(); - //TODO-v5: Docs + /** + * Retrieves the archived private {@link net.dv8tion.jda.api.entities.ThreadChannel ThreadChannels} for this channel, that the bot has previously joined or been added to. + *
    Unlike {@link #retrieveArchivedPrivateThreadChannels()}, this only checks for threads which the bot has joined, and thus does not require permissions to manage threads. + * + *

    You can use {@link #retrieveArchivedPrivateThreadChannels()}, to get all private archived threads. + * + *

    Note that {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels} cannot have private threads. + * + * @throws InsufficientPermissionException + * If the bot does not have {@link net.dv8tion.jda.api.Permission#MESSAGE_HISTORY Permission.MESSAGE_HISTORY} in this channel + * + * @return {@link ThreadChannelPaginationAction} to iterate over all joined private archived ThreadChannels + */ @Nonnull @CheckReturnValue ThreadChannelPaginationAction retrieveArchivedPrivateJoinedThreadChannels(); From cb4ed9586ebbb51ff6055d6d1ac8e7f6e9a5def6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 8 Aug 2022 22:57:19 +0200 Subject: [PATCH 19/75] Improve handling of thread parents --- .../channel/IGuildChannelContainer.java | 7 ++++++ .../jda/internal/entities/EntityBuilder.java | 21 +++++++++++++--- .../jda/internal/entities/GuildImpl.java | 14 +++++++++-- .../internal/entities/ThreadChannelImpl.java | 11 ++++----- .../internal/handle/ThreadCreateHandler.java | 16 +++++++++++-- .../handle/ThreadListSyncHandler.java | 14 ++++++++--- .../ThreadChannelPaginationActionImpl.java | 24 ++++++++++++------- 7 files changed, 83 insertions(+), 24 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java b/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java index cae17ffba7..de0fadcfc4 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/IGuildChannelContainer.java @@ -150,6 +150,7 @@ default GuildChannel getGuildChannelById(@Nonnull String id) *

  • {@link #getStageChannelById(long)}
  • *
  • {@link #getVoiceChannelById(long)}
  • *
  • {@link #getCategoryById(long)}
  • + *
  • {@link #getForumChannelById(long)}
  • * * * @param id @@ -172,6 +173,8 @@ default GuildChannel getGuildChannelById(long id) channel = getCategoryById(id); if (channel == null) channel = getThreadChannelById(id); + if (channel == null) + channel = getForumChannelById(id); return channel; } @@ -197,6 +200,7 @@ default GuildChannel getGuildChannelById(long id) *
  • {@link #getStageChannelById(String)}
  • *
  • {@link #getVoiceChannelById(String)}
  • *
  • {@link #getCategoryById(String)}
  • + *
  • {@link #getForumChannelById(String)}
  • * * * @param type @@ -238,6 +242,7 @@ default GuildChannel getGuildChannelById(@Nonnull ChannelType type, @Nonnull Str *
  • {@link #getStageChannelById(long)}
  • *
  • {@link #getVoiceChannelById(long)}
  • *
  • {@link #getCategoryById(long)}
  • + *
  • {@link #getForumChannelById(long)}
  • * * * @param type @@ -263,6 +268,8 @@ default GuildChannel getGuildChannelById(@Nonnull ChannelType type, long id) return getStageChannelById(id); case CATEGORY: return getCategoryById(id); + case FORUM: + return getForumChannelById(id); } if (type.isThread()) 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 149ce89f81..ee672f58ec 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -331,7 +331,17 @@ public GuildImpl createGuild(long guildId, DataObject guildJson, TLongObjectMap< for (int i = 0; i < threadArray.length(); i++) { DataObject threadJson = threadArray.getObject(i); - createThreadChannel(guildObj, threadJson, guildObj.getIdLong()); + try + { + createThreadChannel(guildObj, threadJson, guildObj.getIdLong()); + } + catch (Exception ex) + { + if (MISSING_CHANNEL.equals(ex.getMessage())) + LOG.debug("Discarding thread without cached parent channel. JSON: {}", threadJson); + else + LOG.warn("Failed to create thread channel for guild with id {}.\nJSON: {}", guildId, threadJson, ex); + } } createGuildEmojiPass(guildObj, emojisArray); @@ -1146,12 +1156,17 @@ public ThreadChannel createThreadChannel(DataObject json, long guildId) public ThreadChannel createThreadChannel(GuildImpl guild, DataObject json, long guildId) { boolean playbackCache = false; - final long id = json.getLong("id"); + final long id = json.getUnsignedLong("id"); + final long parentId = json.getUnsignedLong("parent_id"); final ChannelType type = ChannelType.fromId(json.getInt("type")); if (guild == null) guild = (GuildImpl) getJDA().getGuildsView().get(guildId); + IThreadContainer parent = guild.getChannelById(IThreadContainer.class, parentId); + if (parent == null) + throw new IllegalArgumentException(MISSING_CHANNEL); + ThreadChannelImpl channel = ((ThreadChannelImpl) getJDA().getThreadChannelsView().get(id)); if (channel == null) { @@ -1172,7 +1187,7 @@ public ThreadChannel createThreadChannel(GuildImpl guild, DataObject json, long channel .setName(json.getString("name")) - .setParentChannelId(json.getLong("parent_id")) + .setParentChannel(parent) .setOwnerId(json.getLong("owner_id")) .setMemberCount(json.getInt("member_count")) .setMessageCount(json.getInt("message_count")) 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 5c557adf2f..f9af5ed4e6 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -1241,8 +1241,18 @@ public RestAction> retrieveActiveThreads() threadObj.put("member", selfThreadMemberObj); } - ThreadChannel thread = builder.createThreadChannel(threadObj, this.getIdLong()); - list.add(thread); + try + { + ThreadChannel thread = builder.createThreadChannel(threadObj, this.getIdLong()); + list.add(thread); + } + catch (Exception e) + { + if (EntityBuilder.MISSING_CHANNEL.equals(e.getMessage())) + EntityBuilder.LOG.debug("Discarding thread without cached parent channel. JSON: {}", threadObj); + else + EntityBuilder.LOG.warn("Failed to create thread channel. JSON: {}", threadObj, e); + } } return Collections.unmodifiableList(list); diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index 5a626b7283..8c7948ad18 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -50,10 +50,10 @@ public class ThreadChannelImpl extends AbstractGuildChannelImpl threadMembers = new CacheView.SimpleCacheView<>(ThreadMember.class, null); private AutoArchiveDuration autoArchiveDuration; + private IThreadContainerUnion parentChannel; private boolean locked; private boolean archived; private boolean invitable; - private long parentChannelId; private long archiveTimestamp; private long creationTimestamp; private long ownerId; @@ -117,15 +117,14 @@ public boolean canTalk(@Nonnull Member member) @Override public List getMembers() { - return null; + return Collections.emptyList(); } @Nonnull @Override - @SuppressWarnings("ConstantConditions") public IThreadContainerUnion getParentChannel() { - return (IThreadContainerUnion) guild.getGuildChannelById(parentChannelId); + return parentChannel; } @Nonnull @@ -306,9 +305,9 @@ public ThreadChannelImpl setAutoArchiveDuration(AutoArchiveDuration autoArchiveD return this; } - public ThreadChannelImpl setParentChannelId(long parentChannelId) + public ThreadChannelImpl setParentChannel(IThreadContainer channel) { - this.parentChannelId = parentChannelId; + this.parentChannel = (IThreadContainerUnion) channel; return this; } diff --git a/src/main/java/net/dv8tion/jda/internal/handle/ThreadCreateHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/ThreadCreateHandler.java index 4a2b57fc65..6b750157eb 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadCreateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadCreateHandler.java @@ -20,6 +20,7 @@ import net.dv8tion.jda.api.events.channel.ChannelCreateEvent; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.JDAImpl; +import net.dv8tion.jda.internal.entities.EntityBuilder; public class ThreadCreateHandler extends SocketHandler { @@ -35,9 +36,20 @@ protected Long handleInternally(DataObject content) if (api.getGuildSetupController().isLocked(guildId)) return guildId; - ThreadChannel thread = api.getEntityBuilder().createThreadChannel(content, guildId); + try + { + ThreadChannel thread = api.getEntityBuilder().createThreadChannel(content, guildId); + api.handleEvent(new ChannelCreateEvent(api, responseNumber, thread)); + } + catch (IllegalArgumentException ex) + { + if (!EntityBuilder.MISSING_CHANNEL.equals(ex.getMessage())) + throw ex; - api.handleEvent(new ChannelCreateEvent(api, responseNumber, thread)); + long parentId = content.getUnsignedLong("parent_id"); + EventCache.LOG.debug("Caching THREAD_CREATE_EVENT for channel with uncached parent. Parent ID: {}", parentId); + api.getEventCache().cache(EventCache.Type.CHANNEL, parentId, responseNumber, allContent, this::handle); + } return null; } diff --git a/src/main/java/net/dv8tion/jda/internal/handle/ThreadListSyncHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/ThreadListSyncHandler.java index d3dfbcef55..d3457d179b 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadListSyncHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadListSyncHandler.java @@ -42,9 +42,17 @@ protected Long handleInternally(DataObject content) for (int i = 0; i < threadsArrayJson.length(); i++) { DataObject threadJson = threadsArrayJson.getObject(i); - ThreadChannel thread = entityBuilder.createThreadChannel(threadJson, guildId); - - api.handleEvent(new ThreadRevealedEvent(api, responseNumber, thread)); + try + { + ThreadChannel thread = entityBuilder.createThreadChannel(threadJson, guildId); + api.handleEvent(new ThreadRevealedEvent(api, responseNumber, thread)); + } + catch (IllegalArgumentException ex) + { + if (!EntityBuilder.MISSING_CHANNEL.equals(ex.getMessage())) + throw ex; + EntityBuilder.LOG.debug("Discarding thread on sync because of missing parent channel cache. JSON: {}", threadJson); + } } return null; diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/pagination/ThreadChannelPaginationActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/pagination/ThreadChannelPaginationActionImpl.java index c6cb7ffbc0..5cb025e9d5 100644 --- a/src/main/java/net/dv8tion/jda/internal/requests/restaction/pagination/ThreadChannelPaginationActionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/pagination/ThreadChannelPaginationActionImpl.java @@ -1,7 +1,6 @@ package net.dv8tion.jda.internal.requests.restaction.pagination; import gnu.trove.map.TLongObjectMap; -import gnu.trove.map.hash.TLongObjectHashMap; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.IThreadContainer; import net.dv8tion.jda.api.entities.ThreadChannel; @@ -18,7 +17,6 @@ import javax.annotation.Nonnull; import java.time.OffsetDateTime; -import java.time.ZoneId; import java.time.ZoneOffset; import java.util.ArrayList; import java.util.EnumSet; @@ -102,13 +100,23 @@ protected void handleSuccess(Response response, Request> req threadObj.put("member", selfThreadMemberObj); } - ThreadChannel thread = builder.createThreadChannel(threadObj, getGuild().getIdLong()); - list.add(thread); + try + { + ThreadChannel thread = builder.createThreadChannel(threadObj, getGuild().getIdLong()); + list.add(thread); - if (this.useCache) - this.cached.add(thread); - this.last = thread; - this.lastKey = last.getIdLong(); + if (this.useCache) + this.cached.add(thread); + this.last = thread; + this.lastKey = last.getIdLong(); + } + catch (Exception e) + { + if (EntityBuilder.MISSING_CHANNEL.equals(e.getMessage())) + EntityBuilder.LOG.debug("Discarding thread without cached parent channel. JSON: {}", threadObj); + else + EntityBuilder.LOG.warn("Failed to create thread channel. JSON: {}", threadObj, e); + } } catch (ParsingException | NullPointerException e) { From 0f37bffcb1cdd15b7ced8b08da567eaf3d85bd77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 8 Aug 2022 22:57:51 +0200 Subject: [PATCH 20/75] Update docs for ThreadChannel --- .../jda/api/entities/ThreadChannel.java | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java index 1bb4a6c25e..785f34fecf 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java @@ -93,12 +93,12 @@ default boolean isJoined() /** * Whether this thread is locked or not. * - * Locked threads cannot have new messages posted to them, or members join or leave them. + *

    Locked threads cannot have new messages posted to them, or members join or leave them. * Threads can only be locked and unlocked by moderators. * * @return true if this thread is locked, false otherwise. * - * @see ChannelField#LOCKED + * @see ChannelField#LOCKED */ boolean isLocked(); @@ -115,37 +115,34 @@ default boolean isJoined() * * @return true if this thread is invitable, false otherwise. * - * @see ChannelField#INVITABLE + * @see ChannelField#INVITABLE */ boolean isInvitable(); /** * Gets the {@link IThreadContainer parent channel} of this thread. * - * @see IThreadContainer#getThreadChannels() - * * @return The parent channel of this thread. + * + * @see IThreadContainer#getThreadChannels() */ @Nonnull IThreadContainerUnion getParentChannel(); - //todo-v5: document additional subclasses of GuildMessageChannel (VoiceChannels and ForumChannels, when needed) /** - * Gets the {@link GuildMessageChannel parent channel} of this thread, if it is a {@link TextChannel} or {@link NewsChannel}. - *
    - * This is a convenience method that will perform the cast if possible, throwing otherwise. - * - * @return The parent channel of this thread, as a {@link GuildMessageChannel}. + * Gets the {@link GuildMessageChannelUnion parent channel} of this thread, if it is a {@link TextChannel}, {@link NewsChannel}, or {@link VoiceChannel}. + *
    This is a convenience method that will perform the cast if possible, throwing otherwise. * * @throws UnsupportedOperationException * If the parent channel is not a {@link GuildMessageChannel}. + * + * @return The parent channel of this thread, as a {@link GuildMessageChannelUnion}. */ @Nonnull default GuildMessageChannelUnion getParentMessageChannel() { - if (getParentChannel() instanceof GuildMessageChannel) { + if (getParentChannel() instanceof GuildMessageChannel) return (GuildMessageChannelUnion) getParentChannel(); - } throw new UnsupportedOperationException("Parent of this thread is not a MessageChannel. Parent is type: " + getParentChannel().getType().getId()); } From bc34c48d2e9a5cec05bd5f90aaf690e31fce3a40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 8 Aug 2022 23:13:35 +0200 Subject: [PATCH 21/75] Update more docs of thread channel --- .../jda/api/entities/ThreadChannel.java | 168 +++++++++--------- .../internal/entities/ThreadChannelImpl.java | 3 +- 2 files changed, 89 insertions(+), 82 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java index 785f34fecf..6ae7de87e2 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java @@ -32,13 +32,29 @@ import java.util.Formatter; import java.util.List; +/** + * Represents Discord Message Threads of all kinds. + *

    This includes all thread channel types, namely: + *

      + *
    • {@link ChannelType#GUILD_PUBLIC_THREAD}
    • + *
    • {@link ChannelType#GUILD_PRIVATE_THREAD}
    • + *
    • {@link ChannelType#GUILD_NEWS_THREAD}
    • + *
    + * + *

    When a thread channel is {@link #isArchived() archived}, no new members can be added. + * You can use the {@link #getManager() manager} to {@link ThreadChannelManager#setArchived(boolean) unarchive} the thread. + * + * @see Guild#getThreadChannels() + * @see Guild#getThreadChannelById(long) + * @see Guild#getThreadChannelCache() + */ public interface ThreadChannel extends GuildMessageChannel, IMemberContainer { //TODO fields that need to be researched: // - rate_limit_per_user // - last_pin_timestamp (do we even use this for Text/News channels?) - int NAME_MAX_LENGTH = 100; + int NAME_MAX_LENGTH = 100; // TODO: Remove this in favor of Channel.MAX_NAME_LENGTH /** * Whether this thread is public or not. @@ -191,11 +207,11 @@ default GuildMessageChannelUnion getParentMessageChannel() /** * Gets the self member, as a member of this thread. * - *
    If the current account is not a member of this thread, this will return null. + *

    If the current account is not a member of this thread, this will return null. * * @return The self member of this thread, null if the current account is not a member of this thread. * - * @see #isJoined() + * @see #isJoined() */ @Nullable default ThreadMember getSelfThreadMember() @@ -206,8 +222,8 @@ default ThreadMember getSelfThreadMember() /** * Gets a List of all cached {@link ThreadMember members} of this thread. - *
    - *
    The thread owner is not included in this list, unless the current account is the owner. + * + *

    The thread owner is not included in this list, unless the current account is the owner. * Any updates to this cache are lost when JDA is shutdown, and this list is not sent to JDA on startup. * For this reason, {@link #retrieveThreadMembers()} should be used instead in most cases. * @@ -220,9 +236,9 @@ default ThreadMember getSelfThreadMember() *

  • the bot must have be online to receive the update
  • * * - * @return a List of all {@link ThreadMember members} of this thread. This list may be empty, but not null. + * @return List of all {@link ThreadMember members} of this thread. This list may be empty, but not null. * - * @see #retrieveThreadMembers() + * @see #retrieveThreadMembers() */ @Nonnull List getThreadMembers(); @@ -230,20 +246,20 @@ default ThreadMember getSelfThreadMember() /** * Gets a {@link ThreadMember} of this thread by their {@link Member}. * - * Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. + *

    Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. * As the cache is likely to be unpopulated, this method is likely to return null. * - * Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. + *

    Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. * - * @param member - * The member to get the {@link ThreadMember} for. - * - * @return The {@link ThreadMember} of this thread for the given member. + * @param member + * The member to get the {@link ThreadMember} for. * * @throws IllegalArgumentException * If the given member is null. * - * @see #retrieveThreadMember(Member) + * @return The {@link ThreadMember} of this thread for the given member. + * + * @see #retrieveThreadMember(Member) */ @Nullable default ThreadMember getThreadMember(Member member) @@ -255,20 +271,20 @@ default ThreadMember getThreadMember(Member member) /** * Gets a {@link ThreadMember} of this thread by their {@link Member}. * - * Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. + *

    Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. * As the cache is likely to be unpopulated, this method is likely to return null. * - * Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. + *

    Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. * - * @param user - * The user to get the {@link ThreadMember} for. - * - * @return The {@link ThreadMember} of this thread for the given member. + * @param user + * The user to get the {@link ThreadMember} for. * * @throws IllegalArgumentException * If the given user is null. * - * @see #retrieveThreadMember(Member) + * @return The {@link ThreadMember} of this thread for the given member. + * + * @see #retrieveThreadMember(Member) */ @Nullable default ThreadMember getThreadMember(User user) @@ -280,20 +296,20 @@ default ThreadMember getThreadMember(User user) /** * Gets a {@link ThreadMember} of this thread by their {@link Member}. * - * Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. + *

    Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. * As the cache is likely to be unpopulated, this method is likely to return null. * - * Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. + *

    Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. * * @param id * The ID of the member to get the {@link ThreadMember} for. * - * @return The {@link ThreadMember} of this thread for the given member. - * * @throws IllegalArgumentException * If the given id is null or empty. * - * @see #retrieveThreadMember(Member) + * @return The {@link ThreadMember} of this thread for the given member. + * + * @see #retrieveThreadMember(Member) */ @Nullable default ThreadMember getThreadMemberById(String id) @@ -304,17 +320,17 @@ default ThreadMember getThreadMemberById(String id) /** * Gets a {@link ThreadMember} of this thread by their {@link Member}. * - * Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. + *

    Note that this operation relies on the {@link #getThreadMembers() ThreadMember cache} for this ThreadChannel. * As the cache is likely to be unpopulated, this method is likely to return null. * - * Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. + *

    Use of {@link #retrieveThreadMember(Member)} is preferred instead, once it is released. * * @param id * The member to get the {@link ThreadMember} for. * * @return The {@link ThreadMember} of this thread for the given member. * - * @see #retrieveThreadMember(Member) + * @see #retrieveThreadMember(Member) */ @Nullable ThreadMember getThreadMemberById(long id); @@ -404,7 +420,7 @@ default CacheRestAction retrieveThreadMemberById(@Nonnull String i /** * Retrieves the {@link ThreadMember ThreadMembers} of this thread. * - * This requires the {@link net.dv8tion.jda.api.requests.GatewayIntent#GUILD_MEMBERS} intent to be enabled. + *

    This requires the {@link net.dv8tion.jda.api.requests.GatewayIntent#GUILD_MEMBERS} intent to be enabled. * * @return a RestAction that resolves into a List of {@link ThreadMember ThreadMembers} of this thread. */ @@ -442,13 +458,14 @@ default String getOwnerId() /** * Gets the {@link Member} that created and owns this thread. - *
    - * This will be null if the member is not cached, and so it is recommended to {@link Guild#retrieveMemberById(long) retrieve this member from the guild} using {@link #getOwnerIdLong() the owner'd ID}. + *
    This will be null if the member is not cached, + * and so it is recommended to {@link Guild#retrieveMemberById(long) retrieve this member from the guild} + * using {@link #getOwnerIdLong() the owner'd ID}. * * @return The {@link Member} of the member who created this thread. * - * @see #getThreadMemberById(long) - * @see Guild#retrieveMemberById(long) + * @see #getThreadMemberById(long) + * @see Guild#retrieveMemberById(long) */ @Nullable default Member getOwner() @@ -458,14 +475,15 @@ default Member getOwner() /** * Gets the owner of this thread as a {@link ThreadMember}. - *
    - * This will be null if the member is not cached, and so it is recommended to retrieve the owner instead. + *
    This will be null if the member is not cached, and so it is recommended to retrieve the owner instead. * - *
    This method relies on the {@link #getThreadMembers()} cache, and so it is recommended to {@link #retrieveThreadMemberById(long) retrieve the ThreadMember} by {@link #getOwnerIdLong() their ID} instead. + *

    This method relies on the {@link #getThreadMembers()} cache, + * and so it is recommended to {@link #retrieveThreadMemberById(long) retrieve the ThreadMember} + * by {@link #getOwnerIdLong() their ID} instead. * * @return The owner of this thread as a {@link ThreadMember}. * - * @see #getThreadMemberById(long) + * @see #getThreadMemberById(long) */ @Nullable default ThreadMember getOwnerThreadMember() @@ -476,7 +494,7 @@ default ThreadMember getOwnerThreadMember() /** * Whether this thread has been archived. * - * This method will consider locked channels to also be archived. + *

    This method will consider locked channels to also be archived. * *

    Archived threads are not deleted threads, but are considered inactive. * They are not shown to clients in the channels list, but can still be navigated to and read. @@ -484,10 +502,10 @@ default ThreadMember getOwnerThreadMember() * * @return true if this thread has been archived, false otherwise. * - * @see #isLocked() - * @see ThreadChannelManager#setArchived(boolean) - * @see #getAutoArchiveDuration() - * @see ChannelField#ARCHIVED + * @see #isLocked() + * @see ThreadChannelManager#setArchived(boolean) + * @see #getAutoArchiveDuration() + * @see ChannelField#ARCHIVED */ boolean isArchived(); @@ -503,20 +521,20 @@ default ThreadMember getOwnerThreadMember() * * @return the time of the last archive info update. * - * @see ChannelField#ARCHIVED_TIMESTAMP + * @see ChannelField#ARCHIVED_TIMESTAMP */ OffsetDateTime getTimeArchiveInfoLastModified(); /** * The inactivity timeout of this thread. * - * If a message is not sent within this amount of time, the thread will be automatically archived. + *

    If a message is not sent within this amount of time, the thread will be automatically archived. * - * A thread archived this way can be unarchived by any member. + *

    A thread archived this way can be unarchived by any member. * * @return the time before which a thread will automatically be archived. * - * @see ChannelField#AUTO_ARCHIVE_DURATION + * @see ChannelField#AUTO_ARCHIVE_DURATION */ @Nonnull AutoArchiveDuration getAutoArchiveDuration(); @@ -536,14 +554,14 @@ default ThreadMember getOwnerThreadMember() * * @return The amount of time in seconds a ThreadMember must wait between sending messages. * - * @see net.dv8tion.jda.api.managers.channel.concrete.ThreadChannelManager#setSlowmode(int) + * @see net.dv8tion.jda.api.managers.channel.concrete.ThreadChannelManager#setSlowmode(int) */ int getSlowmode(); /** * Joins this thread, adding the current account to the member list of this thread. * - * Note that joining threads is not a requirement of getting events about the thread. + *

    Note that joining threads is not a requirement of getting events about the thread. * *
    This will have no effect if the current account is already a member of this thread. * @@ -568,7 +586,6 @@ default ThreadMember getOwnerThreadMember() /** * Leaves this thread, removing the current account from the member list of this thread. - * *
    This will have no effect if the current account is not a member of this thread. * *

    The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible: @@ -593,7 +610,6 @@ default ThreadMember getOwnerThreadMember() //this is probably also affected by private threads that are not invitable /** * Adds a member to this thread. - * *
    This will have no effect if the member is already a member of this thread. * *

    The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible: @@ -655,16 +671,14 @@ default ThreadMember getOwnerThreadMember() * *

  • {@link net.dv8tion.jda.api.requests.ErrorResponse#INVALID_FORM_BODY INVALID_FORM_BODY} *
    The provided User ID is not a valid snowflake.
  • - * * * * @param id * The id of the member to add. * * @throws IllegalStateException - * If this thread is locked or archived. - * - * @throws NumberFormatException + * If this thread is locked or archived + * @throws IllegalArgumentException * If the provided id is not a valid snowflake. * * @return {@link RestAction} @@ -677,7 +691,6 @@ default RestAction addThreadMemberById(@Nonnull String id) /** * Adds a member to this thread. - * *
    This will have no effect if the member is already a member of this thread. * *

    The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible: @@ -694,7 +707,6 @@ default RestAction addThreadMemberById(@Nonnull String id) * *

  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL} *
    The request was attempted after the channel was deleted.
  • - * * * * @param user @@ -702,9 +714,8 @@ default RestAction addThreadMemberById(@Nonnull String id) * * @throws IllegalStateException * If this thread is locked or archived. - * * @throws IllegalArgumentException - * If the provided user was null. + * If the provided user is null. * * @return {@link RestAction} */ @@ -717,7 +728,6 @@ default RestAction addThreadMember(@Nonnull User user) /** * Adds a member to this thread. - * *
    This will have no effect if the member is already a member of this thread. * *

    The following {@link net.dv8tion.jda.api.requests.ErrorResponse ErrorResponses} are possible: @@ -734,7 +744,6 @@ default RestAction addThreadMember(@Nonnull User user) * *

  • {@link net.dv8tion.jda.api.requests.ErrorResponse#UNKNOWN_CHANNEL UNKNOWN_CHANNEL} *
    The request was attempted after the channel was deleted.
  • - * * * * @param member @@ -742,9 +751,8 @@ default RestAction addThreadMember(@Nonnull User user) * * @throws IllegalStateException * If this thread is locked or archived. - * * @throws IllegalArgumentException - * If the provided member was null. + * If the provided member is null. * * @return {@link RestAction} */ @@ -778,11 +786,12 @@ default RestAction addThreadMember(@Nonnull Member member) * * * - * @param id - * The id of the member to remove from this thread. + * @param id + * The id of the member to remove from this thread. * * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException - * If the account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS} permission, and this isn't a private thread channel this account owns. + * If the account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS} permission, + * and this is not a private thread channel this account owns. * * @return {@link RestAction} */ @@ -812,13 +821,13 @@ default RestAction addThreadMember(@Nonnull Member member) * * * - * @param id - * The id of the member to remove from this thread. + * @param id + * The id of the member to remove from this thread. * * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException - * If the account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS} permission, and this isn't a private thread channel this account owns. - * - * @throws NumberFormatException + * If the account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS} permission, + * and this is not a private thread channel this account owns. + * @throws IllegalArgumentException * If the provided id is not a valid snowflake. * * @return {@link RestAction} @@ -846,14 +855,14 @@ default RestAction removeThreadMemberById(@Nonnull String id) * * * - * @param user - * The user to remove from this thread. + * @param user + * The user to remove from this thread. * * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException - * If the account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS} permission, and this isn't a private thread channel this account owns. - * + * If the account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS} permission, + * and this is not a private thread channel this account owns. * @throws IllegalArgumentException - * If the provided user was null. + * If the provided user is null. * * @return {@link RestAction} */ @@ -887,9 +896,8 @@ default RestAction removeThreadMember(@Nonnull User user) * * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException * If the account does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS} permission, and this isn't a private thread channel this account owns. - * * @throws IllegalArgumentException - * If the provided member was null. + * If the provided member is null. * * @return {@link RestAction} */ @@ -925,9 +933,9 @@ default void formatTo(Formatter formatter, int flags, int width, int precision) /** * The values permitted for the auto archive duration of a {@link ThreadChannel}. * - * This is the time before an idle thread will be automatically archived. + *

    This is the time before an idle thread will be automatically archived. * - * Sending a message to the thread will reset the timer. + *

    Sending a message to the thread will reset the timer. * * @see ChannelField#AUTO_ARCHIVE_DURATION */ diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index 8c7948ad18..991c7cc77f 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -387,8 +387,7 @@ public String toString() private void checkUnarchived() { - if (archived) { + if (archived) throw new IllegalStateException("Cannot modify a ThreadChannel while it is archived!"); - } } } From 3d2f7e9542f917829c7d5eb074893f6f963cb97e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 8 Aug 2022 23:14:56 +0200 Subject: [PATCH 22/75] Make getForumChannelCache return the cache instead of null --- src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f9af5ed4e6..3eb09ca936 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/GuildImpl.java @@ -653,7 +653,7 @@ public SortedSnowflakeCacheView getVoiceChannelCache() @Override public SortedSnowflakeCacheView getForumChannelCache() { - return null; + return forumChannelCache; } @Nonnull From a689e3e21ff2a3eb20084b497fca32b5f0112260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 16 Aug 2022 20:37:52 +0200 Subject: [PATCH 23/75] Add ForumPostAction --- .../dv8tion/jda/api/entities/ForumPost.java | 43 +++++++ .../channel/concrete/ForumChannel.java | 56 ++------- .../AbstractThreadCreateAction.java | 62 ++++++++++ .../requests/restaction/ForumPostAction.java | 24 ++++ .../restaction/ThreadChannelAction.java | 42 +------ .../internal/entities/ForumChannelImpl.java | 93 ++------------ .../restaction/ForumPostActionImpl.java | 116 ++++++++++++++++++ 7 files changed, 269 insertions(+), 167 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/api/entities/ForumPost.java create mode 100644 src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java create mode 100644 src/main/java/net/dv8tion/jda/api/requests/restaction/ForumPostAction.java create mode 100644 src/main/java/net/dv8tion/jda/internal/requests/restaction/ForumPostActionImpl.java diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java b/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java new file mode 100644 index 0000000000..89d47c77ab --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java @@ -0,0 +1,43 @@ +/* + * 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; + +import javax.annotation.Nonnull; + +public class ForumPost +{ + private final Message message; + private final ThreadChannel thread; + + public ForumPost(@Nonnull Message message, @Nonnull ThreadChannel thread) + { + this.message = message; + this.thread = thread; + } + + @Nonnull + public Message getMessage() + { + return message; + } + + @Nonnull + public ThreadChannel getThread() + { + return thread; + } +} 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 5a55bf5e2a..03c060ba52 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 @@ -20,9 +20,9 @@ import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; -import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.restaction.ChannelAction; -import net.dv8tion.jda.api.utils.FileUpload; +import net.dv8tion.jda.api.requests.restaction.ForumPostAction; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; @@ -79,46 +79,6 @@ default ChannelAction createCopy() @Nullable String getTopic(); -// TODO-message-rework: Specializing by combining message send with thread create into a unified interface -// -// Note: This requires changes coming with the message-rework. Specifically, you need a nice way to create a complete message and pass it to the method. -// In addition, we need a comprehensive abstraction for all the message specific setters, coming with the MessageSend interface in the message rework. -// -// There is a temporary implementation available, which will most definitely be replaced in a future release. - - /** - * 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#REQUEST_ENTITY_TOO_LARGE REQUEST_ENTITY_TOO_LARGE} - *
      If the total sum of uploaded bytes exceeds the guild's {@link Guild#getMaxFileSize() upload limit}
    • - *
    - * - * @param name - * The name of the post - * @param upload - * A file attachment to upload as the post content - * @param uploads - * Additional files to attach to the post - * - * @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 100 characters
    • - *
    - * - * @return {@link RestAction} - Type: {@link ThreadChannel} - */ - @Nonnull - @Incubating - @CheckReturnValue - RestAction createForumPost(@Nonnull String name, @Nonnull FileUpload upload, @Nonnull FileUpload... uploads); - /** * Creates a new forum post (thread) in this forum. * @@ -131,24 +91,22 @@ default ChannelAction createCopy() * * * @param name - * The name of the post + * The name of the post (up to {@value Channel#MAX_NAME_LENGTH} characters) * @param message - * The post message content - * @param uploads - * Additional files to attach to the post + * 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 100 characters
    • + *
    • If the name is empty or longer than {@value Channel#MAX_NAME_LENGTH} characters
    • *
    * - * @return {@link RestAction} - Type: {@link ThreadChannel} + * @return {@link ForumPostAction} */ @Nonnull @Incubating @CheckReturnValue - RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull FileUpload... uploads); + ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message); } diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java new file mode 100644 index 0000000000..bb6f1583d6 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.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.requests.restaction; + +import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.requests.RestAction; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; + +public interface AbstractThreadCreateAction> extends RestAction +{ + /** + * The guild to create this {@link GuildChannel} in + * + * @return The guild + */ + @Nonnull + Guild getGuild(); + + /** + * The {@link ChannelType} for the resulting channel + * + * @return The channel type + */ + @Nonnull + ChannelType getType(); + + /** + * Sets the name for the new GuildChannel + * + * @param name + * The not-null name for the new GuildChannel (up to {@value Channel#MAX_NAME_LENGTH} characters) + * + * @throws IllegalArgumentException + * If the provided name is null, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters + * + * @return The current action, for chaining convenience + */ + @Nonnull + @CheckReturnValue + R setName(@Nonnull String name); + + //TODO-v5: Docs + @Nonnull + @CheckReturnValue + R setAutoArchiveDuration(@Nonnull ThreadChannel.AutoArchiveDuration autoArchiveDuration); +} 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 new file mode 100644 index 0000000000..48f2de9e3e --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/ForumPostAction.java @@ -0,0 +1,24 @@ +/* + * 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.requests.restaction; + +import net.dv8tion.jda.api.entities.ForumPost; +import net.dv8tion.jda.api.utils.messages.MessageCreateRequest; + +public interface ForumPostAction extends AbstractThreadCreateAction, MessageCreateRequest +{ +} diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java index a5f8268f95..f888198c70 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java @@ -16,7 +16,9 @@ package net.dv8tion.jda.api.requests.restaction; -import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.IThreadContainer; +import net.dv8tion.jda.api.entities.Message; +import net.dv8tion.jda.api.entities.ThreadChannel; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; @@ -35,7 +37,7 @@ * @see IThreadContainer#createThreadChannel(String, long) * @see IThreadContainer#createThreadChannel(String, String) */ -public interface ThreadChannelAction extends AuditableRestAction +public interface ThreadChannelAction extends AbstractThreadCreateAction, AuditableRestAction { @Nonnull @Override @@ -49,42 +51,6 @@ public interface ThreadChannelAction extends AuditableRestAction @Override ThreadChannelAction deadline(long timestamp); - /** - * The guild to create this {@link GuildChannel} in - * - * @return The guild - */ - @Nonnull - Guild getGuild(); - - /** - * The {@link ChannelType} for the resulting channel - * - * @return The channel type - */ - @Nonnull - ChannelType getType(); - - /** - * Sets the name for the new GuildChannel - * - * @param name - * The not-null name for the new GuildChannel (1-100 chars long) - * - * @throws IllegalArgumentException - * If the provided name is null or not between 1-100 chars long - * - * @return The current ChannelAction, for chaining convenience - */ - @Nonnull - @CheckReturnValue - ThreadChannelAction setName(@Nonnull String name); - - //TODO-v5: Docs - @Nonnull - @CheckReturnValue - ThreadChannelAction setAutoArchiveDuration(@Nonnull ThreadChannel.AutoArchiveDuration autoArchiveDuration); - //TODO-v5: Docs @Nonnull @CheckReturnValue diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index fc75c8e3b5..d58af631fd 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -18,32 +18,28 @@ import gnu.trove.map.TLongObjectMap; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.Category; +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.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; -import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; -import net.dv8tion.jda.api.exceptions.MissingAccessException; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; -import net.dv8tion.jda.api.requests.RestAction; 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.AttachedFile; -import net.dv8tion.jda.api.utils.FileUpload; import net.dv8tion.jda.api.utils.MiscUtil; -import net.dv8tion.jda.api.utils.data.DataArray; -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.mixin.channel.attribute.IThreadContainerMixin; import net.dv8tion.jda.internal.entities.mixin.channel.middleman.StandardGuildChannelMixin; import net.dv8tion.jda.internal.managers.channel.concrete.ForumChannelManagerImpl; -import net.dv8tion.jda.internal.requests.Requester; -import net.dv8tion.jda.internal.requests.RestActionImpl; -import net.dv8tion.jda.internal.requests.Route; +import net.dv8tion.jda.internal.requests.restaction.ForumPostActionImpl; import net.dv8tion.jda.internal.utils.Checks; -import okhttp3.MultipartBody; -import okhttp3.RequestBody; import javax.annotation.Nonnull; -import java.util.*; +import java.util.Collections; +import java.util.List; import java.util.stream.Collectors; public class ForumChannelImpl extends AbstractGuildChannelImpl @@ -142,73 +138,10 @@ public String getTopic() @Nonnull @Override - public RestAction createForumPost(@Nonnull String name, @Nonnull FileUpload upload, @Nonnull FileUpload... uploads) + public ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message) { - Checks.notNull(upload, "Uploads"); - Checks.notNull(uploads, "Uploads"); - List files = new ArrayList<>(1 + uploads.length); - files.add(upload); - Collections.addAll(files, uploads); - return createForumPost(name, null, files); - } - - @Nonnull - @Override - public RestAction createForumPost(@Nonnull String name, @Nonnull Message message, @Nonnull FileUpload... uploads) - { - Checks.notNull(message, "Message"); - return createForumPost(name, message, Arrays.asList(uploads)); - } - - private RestAction createForumPost(String name, Message message, Collection uploads) - { - Checks.notBlank(name, "Name"); - Checks.noneNull(uploads, "Uploads"); - Checks.notLonger(name, ThreadChannel.NAME_MAX_LENGTH, "Name"); - - Member selfMember = getGuild().getSelfMember(); - if (!selfMember.hasAccess(this)) - throw new MissingAccessException(this, Permission.VIEW_CHANNEL); - if (!selfMember.hasPermission(this, Permission.MESSAGE_SEND)) - throw new InsufficientPermissionException(this, Permission.MESSAGE_SEND); - - DataObject payload = DataObject.empty(); - payload.put("name", name); - - if (message != null) - { - DataObject messageJson; - payload.put("message", messageJson = DataObject.empty()); - - messageJson.put("content", message.getContentRaw()); - messageJson.put("embeds", DataArray.fromCollection(message.getEmbeds())); - } - - RequestBody body; - - if (!uploads.isEmpty()) - { - List files = new ArrayList<>(uploads); - MultipartBody.Builder form = AttachedFile.createMultipartBody(files, null); - - DataArray attachments = DataArray.empty(); - for (int i = 0; i < files.size(); i++) - attachments.add(files.get(i).toAttachmentData(i)); - - form.addFormDataPart("payload_json", payload.toString()); - body = form.build(); - } - else - { - body = RequestBody.create(payload.toString(), Requester.MEDIA_TYPE_JSON); - } - - Route.CompiledRoute route = Route.Channels.CREATE_THREAD_WITHOUT_MESSAGE.compile(getId()); - return new RestActionImpl<>(getJDA(), route, body, (response, request) -> { - DataObject json = response.getObject(); - EntityBuilder builder = api.getEntityBuilder(); - return builder.createThreadChannel(getGuild(), json, guild.getIdLong()); - }); + checkPermission(Permission.MESSAGE_SEND); + return new ForumPostActionImpl(this, name, new MessageCreateBuilder().applyData(message)); } @Nonnull 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 new file mode 100644 index 0000000000..bbc7faf00f --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ForumPostActionImpl.java @@ -0,0 +1,116 @@ +/* + * 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.requests.restaction; + +import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.requests.Request; +import net.dv8tion.jda.api.requests.Response; +import net.dv8tion.jda.api.requests.restaction.ForumPostAction; +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.EntityBuilder; +import net.dv8tion.jda.internal.requests.RestActionImpl; +import net.dv8tion.jda.internal.requests.Route; +import net.dv8tion.jda.internal.utils.Checks; +import net.dv8tion.jda.internal.utils.message.MessageCreateBuilderMixin; +import okhttp3.RequestBody; + +import javax.annotation.Nonnull; + +public class ForumPostActionImpl extends RestActionImpl implements ForumPostAction, MessageCreateBuilderMixin +{ + private final MessageCreateBuilder builder; + private final ForumChannel channel; + private String name; + private ThreadChannel.AutoArchiveDuration autoArchiveDuration; + + public ForumPostActionImpl(ForumChannel channel, String name, MessageCreateBuilder builder) + { + super(channel.getJDA(), Route.Channels.CREATE_THREAD_WITHOUT_MESSAGE.compile(channel.getId())); + this.builder = builder; + this.channel = channel; + setName(name); + } + + @Nonnull + @Override + public Guild getGuild() + { + return channel.getGuild(); + } + + @Nonnull + @Override + public ChannelType getType() + { + return ChannelType.GUILD_PUBLIC_THREAD; + } + + @Nonnull + @Override + public ForumPostAction setName(@Nonnull String name) + { + Checks.notEmpty(name, "Name"); + Checks.notLonger(name, Channel.MAX_NAME_LENGTH, "Name"); + this.name = name.trim(); + return this; + } + + @Nonnull + @Override + public ForumPostAction setAutoArchiveDuration(@Nonnull ThreadChannel.AutoArchiveDuration autoArchiveDuration) + { + Checks.notNull(autoArchiveDuration, "AutoArchiveDuration"); + this.autoArchiveDuration = autoArchiveDuration; + return this; + } + + @Override + public MessageCreateBuilder getBuilder() + { + return builder; + } + + @Override + protected RequestBody finalizeData() + { + try (MessageCreateData message = builder.build()) + { + DataObject json = DataObject.empty(); + json.put("message", message); + json.put("name", name); + if (autoArchiveDuration != null) + json.put("auto_archive_duration", autoArchiveDuration.getMinutes()); + return getMultipartBody(message.getFiles(), json); + } + } + + @Override + protected void handleSuccess(Response response, Request request) + { + DataObject json = response.getObject(); + + EntityBuilder entityBuilder = api.getEntityBuilder(); + + ThreadChannel thread = entityBuilder.createThreadChannel(json, getGuild().getIdLong()); + Message message = entityBuilder.createMessageWithChannel(json.getObject("message"), thread, false); + + request.onSuccess(new ForumPost(message, thread)); + } +} From 32cfbd674c3a50d4d363441e6f1f5c811f567dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 16 Aug 2022 20:52:06 +0200 Subject: [PATCH 24/75] Update some docs --- .../net/dv8tion/jda/api/entities/Channel.java | 3 ++ .../jda/api/entities/ChannelField.java | 39 ++++++++++--------- .../dv8tion/jda/api/entities/ChannelType.java | 3 ++ .../dv8tion/jda/api/entities/ForumPost.java | 24 +++++++++++- .../jda/api/entities/ThreadChannel.java | 4 +- .../channel/concrete/ForumChannel.java | 10 +++++ 6 files changed, 60 insertions(+), 23 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/Channel.java b/src/main/java/net/dv8tion/jda/api/entities/Channel.java index ab267739aa..0dbf64b52a 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Channel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Channel.java @@ -30,6 +30,9 @@ */ public interface Channel extends IMentionable { + /** + * The maximum length a channel name can be. ({@value #MAX_NAME_LENGTH}) + */ int MAX_NAME_LENGTH = 100; /** diff --git a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java index 85168f7046..02510277a9 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java @@ -55,7 +55,7 @@ public enum ChannelField /** * The {@link Category parent} of the channel. * - * Limited to {@link ICategorizableChannel Categorizable Channels} (and implementations). + *

    Limited to {@link ICategorizableChannel Categorizable Channels} (and implementations). * * @see ICategorizableChannel#getParentCategory() */ @@ -76,7 +76,7 @@ public enum ChannelField /** * The topic of the channel. * - * Limited to {@link NewsChannel NewsChannels} and {@link TextChannel TextChannels}. + *

    Limited to {@link NewsChannel NewsChannels} and {@link TextChannel TextChannels}. * * @see StandardGuildMessageChannel#getTopic() */ @@ -85,7 +85,7 @@ public enum ChannelField /** * The NSFW state of the channel. * - * Limited to {@link StandardGuildMessageChannel StandardGuildMessageChannels} (and implementations). + *

    Limited to {@link StandardGuildMessageChannel StandardGuildMessageChannels} (and implementations). * * @see StandardGuildMessageChannel#isNSFW() */ @@ -94,7 +94,7 @@ public enum ChannelField /** * The state of slow mode in the channel. This defines the minimum time between message sends. * - * Limited to {@link TextChannel Text Channels}. + *

    Limited to {@link TextChannel Text Channels}. * * @see TextChannel#getSlowmode() */ @@ -106,13 +106,13 @@ public enum ChannelField /** * The bitrate (in bits per second) of the audio in this channel. * - * For standard channels this is between 8000 and 96000. + *

    For standard channels this is between 8000 and 96000. * - * VIP servers extend this limit to 128000. + *

    VIP servers extend this limit to 128000. *
    * The bitrates of boost tiers may be found in {@link Guild.BoostTier the boost tiers}. * - * Limited to {@link AudioChannel Audio Channels}. + *

    Limited to {@link AudioChannel Audio Channels}. * * @see AudioChannel#getBitrate() */ @@ -121,7 +121,7 @@ public enum ChannelField /** * The region of the channel. * - * Limited to {@link AudioChannel Audio Channels}. + *

    Limited to {@link AudioChannel Audio Channels}. * * @see AudioChannel#getRegion() * @see net.dv8tion.jda.api.Region @@ -131,7 +131,7 @@ public enum ChannelField /** * The maximum user count of this channel. * - * Limited to {@link VoiceChannel Voice Channels}. + *

    Limited to {@link VoiceChannel Voice Channels}. * * @see VoiceChannel#getUserLimit() */ @@ -143,9 +143,9 @@ public enum ChannelField /** * The auto archive duration of this channel. * - * If the thread is inactive for this long, it becomes auto-archived. + *

    If the thread is inactive for this long, it becomes auto-archived. * - * Limited to {@link ThreadChannel Thread Channels}. + *

    Limited to {@link ThreadChannel Thread Channels}. * * @see ThreadChannel#getAutoArchiveDuration() * @see net.dv8tion.jda.api.entities.ThreadChannel.AutoArchiveDuration @@ -155,9 +155,9 @@ public enum ChannelField /** * The archive state of this channel. * - * If the channel is archived, this is true. + *

    If the channel is archived, this is true. * - * Limited to {@link ThreadChannel Thread Channels}. + *

    Limited to {@link ThreadChannel Thread Channels}. * * @see ThreadChannel#isArchived() */ @@ -166,7 +166,7 @@ public enum ChannelField /** * The time this channel's archival information was last updated. * - * This timestamp will be updated when any of the following happen: + *

    This timestamp will be updated when any of the following happen: *

      *
    • The channel is archived
    • *
    • The channel is unarchived
    • @@ -175,7 +175,6 @@ public enum ChannelField * * Limited to {@link ThreadChannel Thread Channels}. * - * * @see ThreadChannel#getTimeArchiveInfoLastModified() */ ARCHIVED_TIMESTAMP("archiveTimestamp", null), @@ -183,9 +182,9 @@ public enum ChannelField /** * The locked state of this channel. * - * If the channel is locked, this is true. + *

      If the channel is locked, this is true. * - * Limited to {@link ThreadChannel Thread Channels}. + *

      Limited to {@link ThreadChannel Thread Channels}. * * @see ThreadChannel#isLocked() */ @@ -194,9 +193,9 @@ public enum ChannelField /** * The invite state of this channel. * - * If the channel is invitable, this is true. + *

      If the channel is invitable, this is true. * - * Limited to {@link ThreadChannel Thread Channels}. + *

      Limited to {@link ThreadChannel Thread Channels}. * * @see ThreadChannel#isInvitable() */ @@ -224,6 +223,8 @@ public AuditLogKey getAuditLogKey() return auditLogKey; } + @Nonnull + @Override public String toString() { return "ChannelField." + name() + '(' + fieldName + ')'; diff --git a/src/main/java/net/dv8tion/jda/api/entities/ChannelType.java b/src/main/java/net/dv8tion/jda/api/entities/ChannelType.java index 99c2e0f234..f1a9da0a44 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ChannelType.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ChannelType.java @@ -56,6 +56,9 @@ public enum ChannelType GUILD_PUBLIC_THREAD(11, -1, true), GUILD_PRIVATE_THREAD(12, -1, true), + /** + * A {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannel}, Guild-Only. + */ FORUM(15, 0, true), /** diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java b/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java index 89d47c77ab..08a4d221dd 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java @@ -16,8 +16,18 @@ package net.dv8tion.jda.api.entities; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; + import javax.annotation.Nonnull; +/** + * Result of creating a post in a {@link ForumChannel}. + * + * @see ForumChannel#createForumPost(String, MessageCreateData) + * @see #getThreadChannel() + * @see #getMessage() + */ public class ForumPost { private final Message message; @@ -29,14 +39,26 @@ public ForumPost(@Nonnull Message message, @Nonnull ThreadChannel thread) this.thread = thread; } + /** + * The starter message of the post. + *
      This is created from the {@link MessageCreateData} passed to {@link ForumChannel#createForumPost(String, MessageCreateData)}. + * + * @return {@link Message} + */ @Nonnull public Message getMessage() { return message; } + /** + * The {@link ThreadChannel} of the post. + *
      This will use the name provided to {@link ForumChannel#createForumPost(String, MessageCreateData)}. + * + * @return The forum post thread channel + */ @Nonnull - public ThreadChannel getThread() + public ThreadChannel getThreadChannel() { return thread; } diff --git a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java index 6ae7de87e2..e9a1f0ae3f 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java @@ -54,12 +54,10 @@ public interface ThreadChannel extends GuildMessageChannel, IMemberContainer // - rate_limit_per_user // - last_pin_timestamp (do we even use this for Text/News channels?) - int NAME_MAX_LENGTH = 100; // TODO: Remove this in favor of Channel.MAX_NAME_LENGTH - /** * Whether this thread is public or not. * - * Public threads can be read and joined by anyone with read access to its {@link IThreadContainer parent channel}. + *

      Public threads can be read and joined by anyone with read access to its {@link IThreadContainer parent channel}. * * @return true if this thread is public, false otherwise. */ 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 03c060ba52..9c57b3f8e4 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 @@ -28,6 +28,16 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +/** + * A Forum 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#createForumChannel(String, Category) + * @see #createForumPost(String, MessageCreateData) + */ public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IAgeRestrictedChannel { @Nonnull From 11517ad05772df700494c1303e49901dbedd4c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 16 Aug 2022 20:54:35 +0200 Subject: [PATCH 25/75] Update src/main/java/net/dv8tion/jda/api/entities/Guild.java Co-authored-by: Marcel Korzonek --- src/main/java/net/dv8tion/jda/api/entities/Guild.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 1f93942add..a3ec14465d 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Guild.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Guild.java @@ -4148,7 +4148,7 @@ default ChannelAction createStageChannel(@Nonnull String name) ChannelAction createStageChannel(@Nonnull String name, @Nullable Category parent); /** - * Creates a new {@link net.dv8tion.jda.api.entities.StageChannel StageChannel} in this Guild. + * Creates a new {@link ForumChannel} 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 @@ -4162,7 +4162,7 @@ default ChannelAction createStageChannel(@Nonnull String name) *

    * * @param name - * The name of the StageChannel to create (up to {@value Channel#MAX_NAME_LENGTH} characters) + * The name of the ForumChannel 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 @@ -4170,7 +4170,7 @@ default ChannelAction createStageChannel(@Nonnull String name) * 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 StageChannel before creating it + *
    This action allows to set fields for the new ForumChannel before creating it */ @Nonnull @CheckReturnValue From 8770569a40ceaf0be4fe94545a8e6c28f16221bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 16 Aug 2022 20:58:00 +0200 Subject: [PATCH 26/75] Fix javadoc errors --- .../net/dv8tion/jda/api/entities/IThreadContainer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java index 44bf95c570..a4ab37c39f 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java +++ b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java @@ -19,8 +19,8 @@ import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.requests.restaction.ThreadChannelAction; import net.dv8tion.jda.api.requests.restaction.pagination.ThreadChannelPaginationAction; -import net.dv8tion.jda.api.utils.FileUpload; import net.dv8tion.jda.api.utils.MiscUtil; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; @@ -79,7 +79,7 @@ default List getThreadChannels() * If the provided name is null, blank, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters * @throws UnsupportedOperationException * If this is a forum channel. - * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, MessageCreateData) createForumPost(...)} instead. * @throws InsufficientPermissionException *
      *
    • If the bot does not have {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
    • @@ -130,7 +130,7 @@ default ThreadChannelAction createThreadChannel(@Nonnull String name) * If the provided name is null, blank, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters * @throws UnsupportedOperationException * If this is a forum channel. - * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, MessageCreateData) createForumPost(...)} instead. * @throws InsufficientPermissionException *
        *
      • If the bot does not have {@link net.dv8tion.jda.api.Permission#VIEW_CHANNEL Permission.VIEW_CHANNEL}
      • @@ -179,7 +179,7 @@ default ThreadChannelAction createThreadChannel(@Nonnull String name) * If the provided name is null, blank, empty, or longer than {@value Channel#MAX_NAME_LENGTH} characters * @throws UnsupportedOperationException * If this is a forum channel. - * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, MessageCreateData) createForumPost(...)} instead. * @throws InsufficientPermissionException * If the bot does not have {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS} in this channel * @@ -226,7 +226,7 @@ default ThreadChannelAction createThreadChannel(@Nonnull String name) * Or the message id is not a valid snowflake. * @throws UnsupportedOperationException * If this is a forum channel. - * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, Message, FileUpload...) createForumPost(...)} instead. + * You must use {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, MessageCreateData) createForumPost(...)} instead. * @throws InsufficientPermissionException * If the bot does not have {@link net.dv8tion.jda.api.Permission#CREATE_PUBLIC_THREADS Permission.CREATE_PUBLIC_THREADS} in this channel * From 346c3a4517e727ee73b98f310c306c5fc13443d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 11:26:57 +0200 Subject: [PATCH 27/75] Add missing break --- .../net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java | 1 + 1 file changed, 1 insertion(+) 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 b2e67a379e..187a335872 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java @@ -152,6 +152,7 @@ protected Long handleInternally(DataObject content) new ChannelDeleteEvent( getJDA(), responseNumber, channel)); + break; } case PRIVATE: { From 6b28ff9c1da79d5a0dcc37894ac261e2df71b24d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 11:27:24 +0200 Subject: [PATCH 28/75] Add another missing break --- .../net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java | 1 + 1 file changed, 1 insertion(+) 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 187a335872..25ea1a20b9 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelDeleteHandler.java @@ -120,6 +120,7 @@ protected Long handleInternally(DataObject content) new ChannelDeleteEvent( getJDA(), responseNumber, channel)); + break; } case CATEGORY: From d7ebf59bcaf65637abc658cf8817f85c44df2a1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 11:32:35 +0200 Subject: [PATCH 29/75] Add missing docs --- .../channel/concrete/CategoryManager.java | 8 ++++++++ .../channel/concrete/ForumChannelManager.java | 16 +++++++++++++++- .../channel/concrete/NewsChannelManager.java | 10 ++++++++++ .../channel/concrete/StageChannelManager.java | 11 ++++++++++- 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/CategoryManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/CategoryManager.java index 6c80bc640f..086e3a72a4 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/CategoryManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/CategoryManager.java @@ -20,6 +20,14 @@ import net.dv8tion.jda.api.managers.channel.attribute.IPermissionContainerManager; import net.dv8tion.jda.api.managers.channel.attribute.IPositionableChannelManager; +/** + * Manager providing methods to modify a {@link Category}. + * + *

        Example + *

        {@code
        + * manager.setName("Cool People Only").queue();
        + * }
        + */ public interface CategoryManager extends IPermissionContainerManager, IPositionableChannelManager 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 47daecc056..ed76c2832f 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 @@ -25,7 +25,21 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; -// TODO implementation +/** + * Manager providing functionality to modify a {@link ForumChannel ForumChannel}. + * + *

        Example + *

        {@code
        + * manager.setName("gamer-forum")
        + *  .setSlowmode(10)
        + *  .setTopic("Welcome to the gamer forum!")
        + *  .queue();
        + * manager.reset(ChannelManager.NSFW | ChannelManager.NAME)
        + *  .setName("gamer-forum-nsfw")
        + *  .setNSFW(true)
        + *  .queue();
        + * }
        + */ public interface ForumChannelManager extends StandardGuildChannelManager, IAgeRestrictedChannelManager diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/NewsChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/NewsChannelManager.java index cf698bd417..ab61434825 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/NewsChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/NewsChannelManager.java @@ -25,6 +25,16 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +/** + * Manager providing methods to modify a {@link NewsChannel}. + * + *

        Example + *

        {@code
        + * manager.setName("no-more-news")
        + *        .setType(ChannelType.TEXT) // Changes channel type to TextChannel
        + *        .queue();
        + * }
        + */ public interface NewsChannelManager extends StandardGuildMessageChannelManager { /** diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/StageChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/StageChannelManager.java index b61304d333..21f5863723 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/StageChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/StageChannelManager.java @@ -20,7 +20,16 @@ import net.dv8tion.jda.api.managers.channel.middleman.AudioChannelManager; import net.dv8tion.jda.api.managers.channel.middleman.StandardGuildChannelManager; -//TODO-v5: Docs +/** + * Manager providing methods to modify a {@link StageChannel}. + * + *

        Example + *

        {@code
        + * manager.setName("School Presentations")
        + *        .setBitrate(96000)
        + *        .queue();
        + * }
        + */ public interface StageChannelManager extends AudioChannelManager, StandardGuildChannelManager From 394080608bfc351fad684d6b497f4e1e994f6e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 11:40:45 +0200 Subject: [PATCH 30/75] Update docs for archives and add some more missing docs --- .../jda/api/entities/ThreadChannel.java | 27 ++++++++++++++----- .../AbstractThreadCreateAction.java | 23 +++++++++++++++- .../requests/restaction/ForumPostAction.java | 20 ++++++++++++++ .../restaction/ForumPostActionImpl.java | 7 +++++ 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java index e9a1f0ae3f..2210aa6861 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java @@ -526,11 +526,11 @@ default ThreadMember getOwnerThreadMember() /** * The inactivity timeout of this thread. * - *

        If a message is not sent within this amount of time, the thread will be automatically archived. + *

        If a message is not sent within this amount of time, the thread will be automatically hidden. * *

        A thread archived this way can be unarchived by any member. * - * @return the time before which a thread will automatically be archived. + * @return The inactivity timeframe until a thread is automatically hidden. * * @see ChannelField#AUTO_ARCHIVE_DURATION */ @@ -926,18 +926,17 @@ default void formatTo(Formatter formatter, int flags, int width, int precision) MiscUtil.appendTo(formatter, width, precision, leftJustified, out); } - ////////////////////////// - /** * The values permitted for the auto archive duration of a {@link ThreadChannel}. * - *

        This is the time before an idle thread will be automatically archived. + *

        This is the time before an idle thread will be automatically hidden. * *

        Sending a message to the thread will reset the timer. * * @see ChannelField#AUTO_ARCHIVE_DURATION */ - enum AutoArchiveDuration { + enum AutoArchiveDuration + { //TODO: I dislike this naming scheme. Need to come up with something better. TIME_1_HOUR(60), TIME_24_HOURS(1440), @@ -951,11 +950,27 @@ enum AutoArchiveDuration { this.minutes = minutes; } + /** + * The number of minutes before an idle thread will be automatically hidden. + * + * @return The number of minutes + */ public int getMinutes() { return minutes; } + /** + * Provides the corresponding enum constant for the provided number of minutes. + * + * @param minutes + * The number of minutes. (must be one of the valid values) + * + * @throws IllegalArgumentException + * If the provided minutes is not a valid value. + * + * @return The corresponding enum constant. + */ @Nonnull public static AutoArchiveDuration fromKey(int minutes) { diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java index bb6f1583d6..f3f356a36e 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java @@ -21,7 +21,16 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +import java.util.function.Consumer; +/** + * Common features of all {@link RestAction RestActions} that create a new thread. + * + * @param + * The success type given to the {@link #queue(Consumer, Consumer)} success consumer + * @param + * The common return type of setters, allowing for fluid interface design + */ public interface AbstractThreadCreateAction> extends RestAction { /** @@ -55,7 +64,19 @@ public interface AbstractThreadCreateActionThis is primarily used to hide threads after the provided time of inactivity. + * Threads are automatically archived after 7 days of inactivity regardless. + * + * @param autoArchiveDuration + * The new archive inactivity duration (which hides the thread) + * + * @throws IllegalArgumentException + * If the provided duration is null + * + * @return The current action, for chaining convenience + */ @Nonnull @CheckReturnValue R setAutoArchiveDuration(@Nonnull ThreadChannel.AutoArchiveDuration autoArchiveDuration); 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 48f2de9e3e..b6a0fe87fa 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 @@ -17,8 +17,28 @@ package net.dv8tion.jda.api.requests.restaction; import net.dv8tion.jda.api.entities.ForumPost; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageCreateRequest; +import javax.annotation.Nonnull; + +/** + * Extension of {@link net.dv8tion.jda.api.requests.RestAction RestAction} specifically + * designed to create new Forum Post Threads. + * + *

        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) + */ public interface ForumPostAction extends AbstractThreadCreateAction, MessageCreateRequest { + /** + * The {@link ForumChannel} to create the post in + * + * @return The {@link ForumChannel} + */ + @Nonnull + ForumChannel getChannel(); } 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 bbc7faf00f..89f93d4ff9 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 @@ -55,6 +55,13 @@ public Guild getGuild() return channel.getGuild(); } + @Nonnull + @Override + public ForumChannel getChannel() + { + return channel; + } + @Nonnull @Override public ChannelType getType() From 6e4d5f11636172240ec056e7ed9215a5b41b0e9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 11:52:31 +0200 Subject: [PATCH 31/75] Add handling for forum topic length --- .../api/entities/channel/concrete/ForumChannel.java | 5 +++++ .../internal/managers/channel/ChannelManagerImpl.java | 8 +++++++- .../requests/restaction/ChannelActionImpl.java | 10 ++++++++-- 3 files changed, 20 insertions(+), 3 deletions(-) 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 9c57b3f8e4..4e3b4113e0 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 @@ -40,6 +40,11 @@ */ public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IAgeRestrictedChannel { + /** + * The maximum length of a forum topic ({@value #MAX_FORUM_TOPIC_LENGTH}) + */ + int MAX_FORUM_TOPIC_LENGTH = 4096; + @Nonnull @Override default ChannelType getType() 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 570ebc7f3f..3f2cd90f38 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 @@ -22,6 +22,7 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.managers.channel.ChannelManager; import net.dv8tion.jda.api.utils.data.DataObject; @@ -401,7 +402,12 @@ public M setTopic(String topic) if (TOPIC_SUPPORTED.contains(type)) throw new IllegalStateException("Can only set topic on text, forum, and news channels"); if (topic != null) - Checks.notLonger(topic, 1024, "Topic"); + { + if (type == ChannelType.FORUM) + Checks.notLonger(topic, ForumChannel.MAX_FORUM_TOPIC_LENGTH, "Topic"); + else + Checks.notLonger(topic, 1024, "Topic"); + } this.topic = topic; set |= TOPIC; return (M) this; 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 231dfbdba3..6ebdc78084 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 @@ -20,6 +20,7 @@ import gnu.trove.map.hash.TLongObjectHashMap; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.requests.Request; import net.dv8tion.jda.api.requests.Response; @@ -175,8 +176,13 @@ public ChannelActionImpl setPosition(Integer position) public ChannelActionImpl setTopic(String topic) { checkTypes(TOPIC_SUPPORTED, "Topic"); - if (topic != null && topic.length() > 1024) - throw new IllegalArgumentException("Channel Topic must not be greater than 1024 in length!"); + if (topic != null) + { + if (type == ChannelType.FORUM) + Checks.notLonger(topic, ForumChannel.MAX_FORUM_TOPIC_LENGTH, "Topic"); + else + Checks.notLonger(topic, 1024, "Topic"); + } this.topic = topic; return this; } From a3367399c53428043c400e589ccfbb0abe63d792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 12:21:19 +0200 Subject: [PATCH 32/75] Add basic support for applying tags --- .../dv8tion/jda/api/entities/ForumTag.java | 57 +++++++++++++++++ .../jda/api/entities/ForumTagSnowflake.java | 62 ++++++++++++++++++ .../channel/concrete/ForumChannel.java | 11 ++++ .../requests/restaction/ForumPostAction.java | 40 ++++++++++++ .../jda/internal/entities/EntityBuilder.java | 26 ++++++++ .../internal/entities/ForumChannelImpl.java | 15 +++-- .../jda/internal/entities/ForumTagImpl.java | 63 +++++++++++++++++++ .../entities/ForumTagSnowflakeImpl.java | 57 +++++++++++++++++ .../restaction/ForumPostActionImpl.java | 16 +++++ 9 files changed, 343 insertions(+), 4 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/api/entities/ForumTag.java create mode 100644 src/main/java/net/dv8tion/jda/api/entities/ForumTagSnowflake.java create mode 100644 src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java create mode 100644 src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java b/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java new file mode 100644 index 0000000000..d20b7bda0f --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java @@ -0,0 +1,57 @@ +/* + * 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; + +import net.dv8tion.jda.internal.utils.Checks; + +import javax.annotation.Nonnull; + +/** + * Represents a Discord Forum Tag. + *
        These tags can be applied to forum posts to help categorize them. + */ +public interface ForumTag extends ISnowflake, Comparable +{ + /** + * The maximum length of a forum tag name ({@value #MAX_NAME_LENGTH}) + */ + int MAX_NAME_LENGTH = 20; + + /** + * The name of the tag. + * + * @return The name + */ + @Nonnull + String getName(); + + /** + * Whether this tag can only be applied by moderators with the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS MANAGE_THREADS} permission (aka Manage Posts). + * + * @return True, if this tag can only be applied by moderators with the required permission + */ + boolean isModerated(); + + // TODO: Emoji + + @Override + default int compareTo(@Nonnull ForumTag o) + { + Checks.notNull(o, "ForumTag"); + return Long.compare(getIdLong(), o.getIdLong()); + } +} diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumTagSnowflake.java b/src/main/java/net/dv8tion/jda/api/entities/ForumTagSnowflake.java new file mode 100644 index 0000000000..244013fa58 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/ForumTagSnowflake.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.entities; + +import net.dv8tion.jda.api.requests.restaction.ForumPostAction; +import net.dv8tion.jda.api.utils.MiscUtil; +import net.dv8tion.jda.internal.entities.ForumTagSnowflakeImpl; + +import javax.annotation.Nonnull; +import java.util.Collection; + +/** + * Minimal representation for a forum tag. + *
        This is primarily useful for creating posts with {@link ForumPostAction#setTags(Collection)}. + */ +public interface ForumTagSnowflake extends ISnowflake +{ + /** + * Wraps the provided id into a ForumTagSnowflake instance. + * + * @param id + * The id of an existing forum tag + * + * @return ForumTagSnowflake instance for the provided id + */ + @Nonnull + static ForumTagSnowflake fromId(long id) + { + return new ForumTagSnowflakeImpl(id); + } + + /** + * Wraps the provided id into a ForumTagSnowflake instance. + * + * @param id + * The id of an existing forum tag + * + * @throws IllegalArgumentException + * If the provided id is not a valid snowflake + * + * @return ForumTagSnowflake instance for the provided id + */ + @Nonnull + static ForumTagSnowflake fromId(@Nonnull String id) + { + return new ForumTagSnowflakeImpl(MiscUtil.parseSnowflake(id)); + } +} 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 4e3b4113e0..263034412c 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 @@ -22,11 +22,13 @@ 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.List; /** * A Forum Channel which contains {@link #createForumPost(String, MessageCreateData) Forum Posts}. @@ -67,6 +69,15 @@ default ChannelAction createCopy() return createCopy(getGuild()); } + @Nonnull + SortedSnowflakeCacheView getAvailableTagCache(); + + @Nonnull + default List getAvailableTags() + { + return getAvailableTagCache().asList(); + } + // TODO: Should this be in StandardGuildMessageChannel? /** 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 b6a0fe87fa..720664efd8 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 @@ -17,11 +17,14 @@ package net.dv8tion.jda.api.requests.restaction; import net.dv8tion.jda.api.entities.ForumPost; +import net.dv8tion.jda.api.entities.ForumTagSnowflake; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageCreateRequest; import javax.annotation.Nonnull; +import java.util.Arrays; +import java.util.Collection; /** * Extension of {@link net.dv8tion.jda.api.requests.RestAction RestAction} specifically @@ -41,4 +44,41 @@ public interface ForumPostAction extends AbstractThreadCreateActionSome forums require setting at least one tag. + * + * @param tags + * The tags to apply + * + * @throws IllegalArgumentException + * If null is provided + * + * @return The current ForumPostAction for chaining convenience + * + * @see ForumTagSnowflake#fromId(long) + */ + @Nonnull + ForumPostAction setTags(@Nonnull Collection tags); + + /** + * Configures that tags which should be applied to the new post. + *
        Some forums require setting at least one tag. + * + * @param tags + * The tags to apply + * + * @throws IllegalArgumentException + * If null is provided + * + * @return The current ForumPostAction for chaining convenience + * + * @see ForumTagSnowflake#fromId(long) + */ + @Nonnull + default ForumPostAction setTags(@Nonnull ForumTagSnowflake... tags) + { + return setTags(Arrays.asList(tags)); + } } 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 ffc201107d..2b1a98171a 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -64,6 +64,7 @@ import net.dv8tion.jda.internal.utils.UnlockHook; import net.dv8tion.jda.internal.utils.cache.MemberCacheViewImpl; import net.dv8tion.jda.internal.utils.cache.SnowflakeCacheViewImpl; +import net.dv8tion.jda.internal.utils.cache.SortedSnowflakeCacheViewImpl; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.map.CaseInsensitiveMap; import org.slf4j.Logger; @@ -1263,6 +1264,11 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu } } + ForumChannelImpl tmp = channel; + json.getArray("available_tags") + .stream(DataArray::getObject) + .forEach(obj -> createForumTag(tmp, obj)); + channel .setParentCategory(json.getLong("parent_id", 0)) .setName(json.getString("name")) @@ -1277,6 +1283,26 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu return channel; } + public ForumTagImpl createForumTag(ForumChannelImpl channel, DataObject json) + { + final long id = json.getUnsignedLong("id"); + SortedSnowflakeCacheViewImpl cache = channel.getAvailableTagCache(); + ForumTagImpl tag = (ForumTagImpl) cache.get(id); + + if (tag == null) + { + try (UnlockHook lock = cache.writeLock()) + { + tag = new ForumTagImpl(id); + cache.getMap().put(id, tag); + } + } + + tag.setName(json.getString("name")) + .setModerated(json.getBoolean("moderated")); + return tag; + } + public PrivateChannel createPrivateChannel(DataObject json) { return createPrivateChannel(json, null); diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index d58af631fd..7a534902c0 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -18,10 +18,7 @@ import gnu.trove.map.TLongObjectMap; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.Category; -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.*; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; @@ -36,9 +33,11 @@ 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; import javax.annotation.Nonnull; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -49,6 +48,7 @@ public class ForumChannelImpl extends AbstractGuildChannelImpl IThreadContainerMixin { private final TLongObjectMap overrides = MiscUtil.newLongMap(); + private final SortedSnowflakeCacheViewImpl tagCache = new SortedSnowflakeCacheViewImpl<>(ForumTag.class, ForumTag::getName, Comparator.naturalOrder()); private String topic; private long parentCategoryId; @@ -100,6 +100,13 @@ public ChannelAction createCopy(@Nonnull Guild guild) return action; } + @Nonnull + @Override + public SortedSnowflakeCacheViewImpl getAvailableTagCache() + { + return tagCache; + } + @Override public TLongObjectMap getPermissionOverrideMap() { diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java new file mode 100644 index 0000000000..c87cc7ef48 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java @@ -0,0 +1,63 @@ +/* + * 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; + +import net.dv8tion.jda.api.entities.ForumTag; + +import javax.annotation.Nonnull; + +public class ForumTagImpl extends ForumTagSnowflakeImpl implements ForumTag +{ + private boolean moderated; + private String name; + + public ForumTagImpl(long id) + { + super(id); + } + + @Nonnull + @Override + public String getName() + { + return name; + } + + @Override + public boolean isModerated() + { + return moderated; + } + + public ForumTagImpl setModerated(boolean moderated) + { + this.moderated = moderated; + return this; + } + + public ForumTagImpl setName(String name) + { + this.name = name; + return this; + } + + @Override + public String toString() + { + return "ForumTag:" + name + "(" + id + ')'; + } +} diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java new file mode 100644 index 0000000000..035ab1409e --- /dev/null +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java @@ -0,0 +1,57 @@ +/* + * 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; + +import net.dv8tion.jda.api.entities.ForumTagSnowflake; + +public class ForumTagSnowflakeImpl implements ForumTagSnowflake +{ + protected final long id; + + public ForumTagSnowflakeImpl(long id) + { + this.id = id; + } + + @Override + public long getIdLong() + { + return id; + } + + @Override + public String toString() + { + return "ForumTag(" + id + ')'; + } + + @Override + public int hashCode() + { + return Long.hashCode(id); + } + + @Override + public boolean equals(Object obj) + { + if (obj == this) + return true; + if (!(obj instanceof ForumTagSnowflakeImpl)) + return false; + return ((ForumTagSnowflakeImpl) obj).id == id; + } +} 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 89f93d4ff9..bd562c0420 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 @@ -16,6 +16,8 @@ package net.dv8tion.jda.internal.requests.restaction; +import gnu.trove.set.TLongSet; +import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.requests.Request; @@ -32,11 +34,13 @@ import okhttp3.RequestBody; import javax.annotation.Nonnull; +import java.util.Collection; public class ForumPostActionImpl extends RestActionImpl implements ForumPostAction, MessageCreateBuilderMixin { private final MessageCreateBuilder builder; private final ForumChannel channel; + private final TLongSet appliedTags = new TLongHashSet(); private String name; private ThreadChannel.AutoArchiveDuration autoArchiveDuration; @@ -62,6 +66,16 @@ public ForumChannel getChannel() return channel; } + @Nonnull + @Override + public ForumPostAction setTags(@Nonnull Collection tags) + { + Checks.noneNull(tags, "Tags"); + this.appliedTags.clear(); + tags.forEach(t -> this.appliedTags.add(t.getIdLong())); + return this; + } + @Nonnull @Override public ChannelType getType() @@ -104,6 +118,8 @@ protected RequestBody finalizeData() json.put("name", name); if (autoArchiveDuration != null) json.put("auto_archive_duration", autoArchiveDuration.getMinutes()); + if (!appliedTags.isEmpty()) + json.put("applied_tags", appliedTags.toArray()); return getMultipartBody(message.getFiles(), json); } } From bed9213749394d3ad0bbd6c71748eff241f9a3c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 15:30:11 +0200 Subject: [PATCH 33/75] Add check for max tags --- .../jda/api/entities/channel/concrete/ForumChannel.java | 5 +++++ .../jda/api/requests/restaction/ForumPostAction.java | 8 ++++---- .../internal/requests/restaction/ForumPostActionImpl.java | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) 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 263034412c..7bc189f1f8 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 @@ -28,6 +28,7 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collection; import java.util.List; /** @@ -46,6 +47,10 @@ public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IA * The maximum length of a forum topic ({@value #MAX_FORUM_TOPIC_LENGTH}) */ int MAX_FORUM_TOPIC_LENGTH = 4096; + /** + * 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; @Nonnull @Override 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 720664efd8..f9a886a944 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 @@ -50,10 +50,10 @@ public interface ForumPostAction extends AbstractThreadCreateActionSome forums require setting at least one tag. * * @param tags - * The tags to apply + * Up to {@value ForumChannel#MAX_POST_TAGS} tags to apply * * @throws IllegalArgumentException - * If null is provided + * If null is provided or more than {@value ForumChannel#MAX_POST_TAGS} tags are provided * * @return The current ForumPostAction for chaining convenience * @@ -67,10 +67,10 @@ public interface ForumPostAction extends AbstractThreadCreateActionSome forums require setting at least one tag. * * @param tags - * The tags to apply + * Up to {@value ForumChannel#MAX_POST_TAGS} tags to apply * * @throws IllegalArgumentException - * If null is provided + * If null is provided or more than {@value ForumChannel#MAX_POST_TAGS} tags are provided * * @return The current ForumPostAction for chaining convenience * 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 bd562c0420..87a6996732 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 @@ -71,6 +71,7 @@ public ForumChannel getChannel() public ForumPostAction setTags(@Nonnull Collection tags) { Checks.noneNull(tags, "Tags"); + Checks.check(tags.size() <= ForumChannel.MAX_POST_TAGS, "Provided more than %d tags.", ForumChannel.MAX_POST_TAGS); this.appliedTags.clear(); tags.forEach(t -> this.appliedTags.add(t.getIdLong())); return this; From c86264e487e47577415498c25852a1b8e73311ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 15:47:38 +0200 Subject: [PATCH 34/75] Add support for applied tags on threads --- .../jda/api/entities/ThreadChannel.java | 9 +++++++ .../jda/internal/entities/EntityBuilder.java | 7 +++++ .../internal/entities/ThreadChannelImpl.java | 26 +++++++++++++++++++ 3 files changed, 42 insertions(+) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java index 2210aa6861..f052f3e45a 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ThreadChannel.java @@ -161,6 +161,15 @@ default GuildMessageChannelUnion getParentMessageChannel() throw new UnsupportedOperationException("Parent of this thread is not a MessageChannel. Parent is type: " + getParentChannel().getType().getId()); } + /** + * The {@link ForumTag forum tags} applied to this thread. + *
        This will be an empty list if the thread was not created in a {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannel}. + * + * @return Immutable {@link List} of {@link ForumTag ForumTags} applied to this post + */ + @Nonnull + List getAppliedTags(); + /** * Attempts to get the {@link net.dv8tion.jda.api.entities.Message Message} from Discord's servers that started this thread. * 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 2b1a98171a..9aac90dd5f 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -79,6 +79,7 @@ import java.util.function.Function; import java.util.function.UnaryOperator; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.StreamSupport; public class EntityBuilder @@ -1186,6 +1187,12 @@ public ThreadChannel createThreadChannel(GuildImpl guild, DataObject json, long DataObject threadMetadata = json.getObject("thread_metadata"); + if (!json.isNull("applied_tags")) + { + DataArray array = json.getArray("applied_tags"); + channel.setAppliedTags(IntStream.range(0, array.length()).mapToLong(array::getUnsignedLong)); + } + channel .setName(json.getString("name")) .setParentChannel(parent) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index 991c7cc77f..30fc3e293b 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -16,8 +16,11 @@ package net.dv8tion.jda.internal.entities; +import gnu.trove.set.TLongSet; +import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion; import net.dv8tion.jda.api.managers.channel.concrete.ThreadChannelManager; import net.dv8tion.jda.api.requests.RestAction; @@ -41,6 +44,7 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; +import java.util.stream.LongStream; public class ThreadChannelImpl extends AbstractGuildChannelImpl implements ThreadChannel, @@ -48,6 +52,7 @@ public class ThreadChannelImpl extends AbstractGuildChannelImpl threadMembers = new CacheView.SimpleCacheView<>(ThreadMember.class, null); + private final TLongSet appliedTags = new TLongHashSet(ForumChannel.MAX_POST_TAGS); private AutoArchiveDuration autoArchiveDuration; private IThreadContainerUnion parentChannel; @@ -127,6 +132,20 @@ public IThreadContainerUnion getParentChannel() return parentChannel; } + @Nonnull + @Override + public List getAppliedTags() + { + IThreadContainerUnion parent = getParentChannel(); + if (parent.getType() != ChannelType.FORUM) + return Collections.emptyList(); + return parent.asForumChannel() + .getAvailableTagCache() + .streamUnordered() + .filter(tag -> this.appliedTags.contains(tag.getIdLong())) + .collect(Helpers.toUnmodifiableList()); + } + @Nonnull @Override public RestAction retrieveParentMessage() @@ -371,6 +390,13 @@ public ThreadChannelImpl setSlowmode(int slowmode) return this; } + public ThreadChannelImpl setAppliedTags(LongStream tags) + { + this.appliedTags.clear(); + tags.forEach(this.appliedTags::add); + return this; + } + public long getArchiveTimestamp() { return archiveTimestamp; From f3fbf18e5e70e744c24cba9e92ed9ea86a21b1b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Tue, 30 Aug 2022 16:39:01 +0200 Subject: [PATCH 35/75] Add handling for tag updates --- .../dv8tion/jda/api/audit/AuditLogKey.java | 14 ++++ .../jda/api/entities/ChannelField.java | 20 ++++- .../update/ChannelUpdateAppliedTagsEvent.java | 77 +++++++++++++++++++ .../jda/api/hooks/ListenerAdapter.java | 1 + .../internal/entities/ThreadChannelImpl.java | 5 ++ .../internal/handle/ChannelUpdateHandler.java | 55 +++++++++++++ .../internal/handle/ThreadUpdateHandler.java | 19 +++++ 7 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateAppliedTagsEvent.java 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 f38d2b53f6..22bea843f8 100644 --- a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java +++ b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java @@ -274,6 +274,13 @@ public enum AuditLogKey */ CHANNEL_OVERRIDES("permission_overwrites"), + /** + * The available tags of this {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannel}. + * + *

        Expected type: List{@literal >} + */ + CHANNEL_AVAILABLE_TAGS("available_tags"), + // THREADS /** @@ -319,6 +326,13 @@ public enum AuditLogKey */ THREAD_INVITABLE("invitable"), + /** + * The applied tags of this {@link ThreadChannel}, given that it is a forum post. + * + *

        Expected type: List{@literal } + */ + THREAD_APPLIED_TAGS("applied_tags"), + // STAGE_INSTANCE /** diff --git a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java index 02510277a9..2670d6e10d 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.entities; import net.dv8tion.jda.api.audit.AuditLogKey; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -100,6 +101,13 @@ public enum ChannelField */ SLOWMODE("slowmode", AuditLogKey.CHANNEL_SLOWMODE), + /** + * The applied tags of a {@link ForumChannel}. + * + * @see ForumChannel#getAvailableTags() + */ + AVAILABLE_TAGS("available_tags", AuditLogKey.CHANNEL_AVAILABLE_TAGS), + //Voice Specific @@ -199,7 +207,17 @@ public enum ChannelField * * @see ThreadChannel#isInvitable() */ - INVITABLE("invitable", AuditLogKey.THREAD_INVITABLE) + INVITABLE("invitable", AuditLogKey.THREAD_INVITABLE), + + /** + * The tags applied to a forum post thread. + * + *

        Limited to {@link ThreadChannel ThreadChannels} inside {@link ForumChannel ForumChannels} + * + * @see ThreadChannel#getAppliedTags() + */ + APPLIED_TAGS("applied_tags", AuditLogKey.THREAD_APPLIED_TAGS), + ; private final String fieldName; 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 new file mode 100644 index 0000000000..3b70278fef --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateAppliedTagsEvent.java @@ -0,0 +1,77 @@ +/* + * 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.ChannelField; +import net.dv8tion.jda.api.entities.ForumTag; +import net.dv8tion.jda.api.entities.ThreadChannel; + +import javax.annotation.Nonnull; +import java.util.ArrayList; +import java.util.List; + +/** + * Indicates that the tags applied to a {@link ThreadChannel} forum post have been updated. + */ +public class ChannelUpdateAppliedTagsEvent extends GenericChannelUpdateEvent> +{ + public ChannelUpdateAppliedTagsEvent(@Nonnull JDA api, long responseNumber, @Nonnull ThreadChannel channel, @Nonnull List oldValue) + { + super(api, responseNumber, channel, ChannelField.APPLIED_TAGS, oldValue, channel.getAppliedTags()); + } + + /** + * The newly added tags. + * + * @return The tags that were added to the post + */ + @Nonnull + public List getAddedTags() + { + List newTags = new ArrayList<>(getNewValue()); + newTags.removeAll(getOldValue()); + return newTags; + } + + /** + * The removed tags. + * + * @return The tags that were removed from the post + */ + @Nonnull + public List getRemovedTags() + { + List oldTags = new ArrayList<>(getOldValue()); + oldTags.removeAll(getNewValue()); + return oldTags; + } + + @Nonnull + @Override + public List getOldValue() + { + return super.getOldValue(); + } + + @Nonnull + @Override + public List getNewValue() + { + return super.getNewValue(); + } +} 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 56028d45b1..eb6beda439 100644 --- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java +++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java @@ -195,6 +195,7 @@ public void onChannelUpdateArchiveTimestamp(@Nonnull ChannelUpdateArchiveTimesta public void onChannelUpdateAutoArchiveDuration(@Nonnull ChannelUpdateAutoArchiveDurationEvent event) {} public void onChannelUpdateLocked(@Nonnull ChannelUpdateLockedEvent event) {} public void onChannelUpdateInvitable(@Nonnull ChannelUpdateInvitableEvent event) {} + public void onChannelUpdateAppliedTags(@Nonnull ChannelUpdateAppliedTagsEvent event) {} //Thread Events public void onThreadRevealed(@Nonnull ThreadRevealedEvent event) {} diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index 30fc3e293b..61324df8b8 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -402,6 +402,11 @@ public long getArchiveTimestamp() return archiveTimestamp; } + public TLongSet getAppliedTagsSet() + { + return appliedTags; + } + // -- Object overrides -- 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 e9744ae7cf..3023c71684 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -18,6 +18,7 @@ import gnu.trove.map.TLongObjectMap; import gnu.trove.map.hash.TLongObjectHashMap; +import gnu.trove.set.TLongSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.*; @@ -35,6 +36,7 @@ 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.List; @@ -156,6 +158,7 @@ protected Long handleInternally(DataObject content) final String topic = content.getString("topic", null); ForumChannelImpl forumChannel = (ForumChannelImpl) channel; + content.optArray("available_tags").ifPresent(array -> handleTagsUpdate(forumChannel, array)); //If any properties changed, update the values and fire the proper events. final long oldParentId = forumChannel.getParentCategoryIdLong(); @@ -164,6 +167,7 @@ protected Long handleInternally(DataObject content) final int oldPosition = forumChannel.getPositionRaw(); final boolean oldNsfw = forumChannel.isNSFW(); final int oldSlowmode = forumChannel.getSlowmode(); + if (!Objects.equals(oldName, name)) { forumChannel.setName(name); @@ -627,4 +631,55 @@ private void handleHideChildThreads(IThreadContainer channel) api.handleEvent(new ThreadHiddenEvent(api, responseNumber, thread)); } } + + private void handleTagsUpdate(ForumChannelImpl channel, DataArray tags) + { + EntityBuilder builder = api.getEntityBuilder(); + + SortedSnowflakeCacheViewImpl view = channel.getAvailableTagCache(); + + try (UnlockHook hook = view.writeLock()) + { + TLongObjectMap cache = view.getMap(); + TLongSet removedTags = cache.keySet(); + + for (int i = 0; i < tags.length(); i++) + { + DataObject tagJson = tags.getObject(i); + long id = tagJson.getUnsignedLong("id"); + if (removedTags.remove(id)) + { + ForumTagImpl impl = (ForumTagImpl) cache.get(id); + if (impl == null) + continue; + + String name = tagJson.getString("name"); + boolean moderated = tagJson.getBoolean("moderated"); + // TODO: Emoji + + // TODO: Events? + String oldName = impl.getName(); + if (!name.equals(oldName)) + { + impl.setName(name); + } + if (moderated != impl.isModerated()) + { + impl.setModerated(moderated); + } + } + else + { + ForumTag tag = builder.createForumTag(channel, tagJson); + cache.put(id, tag); + } + } + + // TODO: Events? + removedTags.forEach(id -> { + ForumTag tag = cache.remove(id); + return true; + }); + } + } } 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 a4f2fd7103..c9524a759c 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java @@ -16,6 +16,9 @@ package net.dv8tion.jda.internal.handle; +import gnu.trove.set.TLongSet; +import gnu.trove.set.hash.TLongHashSet; +import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.ThreadChannel; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.utils.data.DataObject; @@ -23,7 +26,9 @@ import net.dv8tion.jda.internal.entities.ThreadChannelImpl; import net.dv8tion.jda.internal.utils.Helpers; +import java.util.List; import java.util.Objects; +import java.util.stream.IntStream; public class ThreadUpdateHandler extends SocketHandler { @@ -68,6 +73,11 @@ protected Long handleInternally(DataObject content) final boolean invitable = threadMetadata.getBoolean("invitable"); final long archiveTimestamp = Helpers.toTimestamp(threadMetadata.getString("archive_timestamp")); final int slowmode = content.getInt("rate_limit_per_user", 0); + final TLongSet tags = content.optArray("applied_tags").map(array -> + new TLongHashSet(IntStream.range(0, array.length()) + .mapToLong(array::getUnsignedLong) + .toArray()) + ).orElseGet(TLongHashSet::new); final String oldName = thread.getName(); final ThreadChannel.AutoArchiveDuration oldAutoArchiveDuration = thread.getAutoArchiveDuration(); @@ -76,6 +86,7 @@ protected Long handleInternally(DataObject content) final boolean oldInvitable = !thread.isPublic() && thread.isInvitable(); final long oldArchiveTimestamp = thread.getArchiveTimestamp(); final int oldSlowmode = thread.getSlowmode(); + final TLongSet oldTags = thread.getAppliedTagsSet(); //TODO should these be Thread specific events? if (!Objects.equals(oldName, name)) @@ -134,6 +145,14 @@ protected Long handleInternally(DataObject content) api, responseNumber, thread, oldInvitable, invitable)); } + if (!oldTags.equals(tags)) + { + List oldTagList = thread.getAppliedTags(); + api.handleEvent( + new ChannelUpdateAppliedTagsEvent( + api, responseNumber, + thread, oldTagList)); + } return null; } From 9160ed7ed895fb33e5e05847d5f87f31a370f059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 31 Aug 2022 16:06:27 +0200 Subject: [PATCH 36/75] Add cache flag for forum tags --- .../jda/api/utils/cache/CacheFlag.java | 6 ++++ .../jda/internal/entities/EntityBuilder.java | 13 +++++--- .../internal/handle/ChannelUpdateHandler.java | 2 ++ .../internal/handle/ThreadUpdateHandler.java | 31 ++++++++++++------- 4 files changed, 35 insertions(+), 17 deletions(-) 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 ea22e1603d..55251e6123 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,6 +19,8 @@ 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.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.requests.GatewayIntent; import javax.annotation.Nonnull; @@ -70,6 +72,10 @@ public enum CacheFlag * Enables cache for {@link Role#getTags()} */ ROLE_TAGS, + /** + * Enables cache for {@link ForumChannel#getAvailableTagCache()} and {@link ThreadChannel#getAppliedTags()} + */ + FORUM_TAGS, /** * Enables cache for {@link Member#getOnlineStatus()} *
        This is enabled implicitly by {@link #ACTIVITY} and {@link #CLIENT_STATUS}. 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 9aac90dd5f..be6ceff7d9 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1187,7 +1187,7 @@ public ThreadChannel createThreadChannel(GuildImpl guild, DataObject json, long DataObject threadMetadata = json.getObject("thread_metadata"); - if (!json.isNull("applied_tags")) + if (!json.isNull("applied_tags") && api.isCacheFlagSet(CacheFlag.FORUM_TAGS)) { DataArray array = json.getArray("applied_tags"); channel.setAppliedTags(IntStream.range(0, array.length()).mapToLong(array::getUnsignedLong)); @@ -1271,10 +1271,13 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu } } - ForumChannelImpl tmp = channel; - json.getArray("available_tags") - .stream(DataArray::getObject) - .forEach(obj -> createForumTag(tmp, obj)); + if (api.isCacheFlagSet(CacheFlag.FORUM_TAGS)) + { + ForumChannelImpl tmp = channel; + json.getArray("available_tags") + .stream(DataArray::getObject) + .forEach(obj -> createForumTag(tmp, obj)); + } channel .setParentCategory(json.getLong("parent_id", 0)) 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 3023c71684..801b6e6fa2 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -634,6 +634,8 @@ private void handleHideChildThreads(IThreadContainer channel) private void handleTagsUpdate(ForumChannelImpl channel, DataArray tags) { + if (!api.isCacheFlagSet(CacheFlag.FORUM_TAGS)) + return; EntityBuilder builder = api.getEntityBuilder(); SortedSnowflakeCacheViewImpl view = channel.getAvailableTagCache(); 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 c9524a759c..c595e1ee5e 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.ThreadChannel; import net.dv8tion.jda.api.events.channel.update.*; +import net.dv8tion.jda.api.utils.cache.CacheFlag; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.JDAImpl; import net.dv8tion.jda.internal.entities.ThreadChannelImpl; @@ -73,11 +74,6 @@ protected Long handleInternally(DataObject content) final boolean invitable = threadMetadata.getBoolean("invitable"); final long archiveTimestamp = Helpers.toTimestamp(threadMetadata.getString("archive_timestamp")); final int slowmode = content.getInt("rate_limit_per_user", 0); - final TLongSet tags = content.optArray("applied_tags").map(array -> - new TLongHashSet(IntStream.range(0, array.length()) - .mapToLong(array::getUnsignedLong) - .toArray()) - ).orElseGet(TLongHashSet::new); final String oldName = thread.getName(); final ThreadChannel.AutoArchiveDuration oldAutoArchiveDuration = thread.getAutoArchiveDuration(); @@ -86,7 +82,7 @@ protected Long handleInternally(DataObject content) final boolean oldInvitable = !thread.isPublic() && thread.isInvitable(); final long oldArchiveTimestamp = thread.getArchiveTimestamp(); final int oldSlowmode = thread.getSlowmode(); - final TLongSet oldTags = thread.getAppliedTagsSet(); + //TODO should these be Thread specific events? if (!Objects.equals(oldName, name)) @@ -145,13 +141,24 @@ protected Long handleInternally(DataObject content) api, responseNumber, thread, oldInvitable, invitable)); } - if (!oldTags.equals(tags)) + + if (api.isCacheFlagSet(CacheFlag.FORUM_TAGS)) { - List oldTagList = thread.getAppliedTags(); - api.handleEvent( - new ChannelUpdateAppliedTagsEvent( - api, responseNumber, - thread, oldTagList)); + final TLongSet oldTags = thread.getAppliedTagsSet(); + final TLongSet tags = content.optArray("applied_tags").map(array -> + new TLongHashSet(IntStream.range(0, array.length()) + .mapToLong(array::getUnsignedLong) + .toArray()) + ).orElseGet(TLongHashSet::new); + + if (!oldTags.equals(tags)) + { + List oldTagList = thread.getAppliedTags(); + api.handleEvent( + new ChannelUpdateAppliedTagsEvent( + api, responseNumber, + thread, oldTagList)); + } } return null; From a1d3c46b1d46a18e3b62bdbc42e856a29d7650a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 1 Sep 2022 15:00:13 +0200 Subject: [PATCH 37/75] Handle default thread slowmode --- .../dv8tion/jda/api/audit/AuditLogKey.java | 12 +++-- .../jda/api/entities/ChannelField.java | 1 + .../jda/api/entities/IThreadContainer.java | 8 ++++ ...annelUpdateDefaultThreadSlowmodeEvent.java | 45 +++++++++++++++++++ .../jda/api/hooks/ListenerAdapter.java | 1 + ...stractStandardGuildMessageChannelImpl.java | 15 +++++++ .../jda/internal/entities/EntityBuilder.java | 2 + .../internal/entities/ForumChannelImpl.java | 14 ++++++ .../attribute/IThreadContainerMixin.java | 2 + .../internal/handle/ChannelUpdateHandler.java | 23 ++++++++-- 10 files changed, 115 insertions(+), 8 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultThreadSlowmodeEvent.java 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 22bea843f8..83c1c3f65c 100644 --- a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java +++ b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java @@ -16,10 +16,7 @@ package net.dv8tion.jda.api.audit; -import net.dv8tion.jda.api.entities.Guild; -import net.dv8tion.jda.api.entities.GuildChannel; -import net.dv8tion.jda.api.entities.ICategorizableChannel; -import net.dv8tion.jda.api.entities.ThreadChannel; +import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.emoji.RichCustomEmoji; import net.dv8tion.jda.api.entities.sticker.GuildSticker; @@ -228,6 +225,13 @@ public enum AuditLogKey */ CHANNEL_SLOWMODE("rate_limit_per_user"), + /** + * Change of the {@link IThreadContainer#getDefaultThreadSlowmode()} value. + * + *

        Expected type: Integer + */ + CHANNEL_DEFAULT_THREAD_SLOWMODE("default_thread_rate_limit_per_user"), + /** * Change of the {@link net.dv8tion.jda.api.entities.VoiceChannel#getBitrate() VoiceChannel.getBitrate()} value. *
        Only for {@link net.dv8tion.jda.api.entities.ChannelType#VOICE ChannelType.VOICE} diff --git a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java index 2670d6e10d..26ba02c612 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java @@ -71,6 +71,7 @@ public enum ChannelField */ POSITION("position", null), //Discord doesn't track Channel position changes in AuditLog. + DEFAULT_THREAD_SLOWMODE("default_thread_slowmode", AuditLogKey.CHANNEL_DEFAULT_THREAD_SLOWMODE), //Text Specific diff --git a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java index a4ab37c39f..c07808ca45 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java +++ b/src/main/java/net/dv8tion/jda/api/entities/IThreadContainer.java @@ -36,6 +36,14 @@ */ public interface IThreadContainer extends GuildChannel, IPermissionContainer { + /** + * The default {@link ThreadChannel#getSlowmode() slowmode} for thread channels that is copied on thread creation. + *
        Users have to wait this amount of seconds before sending another message to the same thread. + * + * @return The default slowmode seconds for new threads, or {@code 0} if unset + */ + int getDefaultThreadSlowmode(); + /** * Finds all {@link ThreadChannel ThreadChannels} whose parent is this channel. * 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 new file mode 100644 index 0000000000..5dcf60ba38 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultThreadSlowmodeEvent.java @@ -0,0 +1,45 @@ +/* + * 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; +import net.dv8tion.jda.api.entities.ChannelField; + +import javax.annotation.Nonnull; + +public class ChannelUpdateDefaultThreadSlowmodeEvent extends GenericChannelUpdateEvent +{ + public ChannelUpdateDefaultThreadSlowmodeEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, int oldValue, int newValue) + { + super(api, responseNumber, channel, ChannelField.DEFAULT_THREAD_SLOWMODE, oldValue, newValue); + } + + @Nonnull + @Override + public Integer getOldValue() + { + return super.getOldValue(); + } + + @Nonnull + @Override + public Integer getNewValue() + { + return super.getNewValue(); + } +} 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 eb6beda439..f521db267e 100644 --- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java +++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java @@ -187,6 +187,7 @@ public void onChannelUpdateParent(@Nonnull ChannelUpdateParentEvent event) {} public void onChannelUpdatePosition(@Nonnull ChannelUpdatePositionEvent event) {} public void onChannelUpdateRegion(@Nonnull ChannelUpdateRegionEvent event) {} public void onChannelUpdateSlowmode(@Nonnull ChannelUpdateSlowmodeEvent event) {} + public void onChannelUpdateDefaultThreadSlowmode(@Nonnull ChannelUpdateDefaultThreadSlowmodeEvent event) {} public void onChannelUpdateTopic(@Nonnull ChannelUpdateTopicEvent event) {} public void onChannelUpdateType(@Nonnull ChannelUpdateTypeEvent event) {} public void onChannelUpdateUserLimit(@Nonnull ChannelUpdateUserLimitEvent event) {} diff --git a/src/main/java/net/dv8tion/jda/internal/entities/AbstractStandardGuildMessageChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/AbstractStandardGuildMessageChannelImpl.java index ec7cf554fc..cea7ca2b0f 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/AbstractStandardGuildMessageChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/AbstractStandardGuildMessageChannelImpl.java @@ -26,6 +26,7 @@ public abstract class AbstractStandardGuildMessageChannelImpl private boolean nsfw = false; private int position; private int slowmode; + protected int defaultThreadSlowmode; public ForumChannelImpl(long id, GuildImpl guild) { @@ -143,6 +144,12 @@ public String getTopic() return topic; } + @Override + public int getDefaultThreadSlowmode() + { + return defaultThreadSlowmode; + } + @Nonnull @Override public ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message) @@ -181,6 +188,13 @@ public ForumChannelImpl setPosition(int position) return this; } + @Override + public ForumChannelImpl setDefaultThreadSlowmode(int defaultThreadSlowmode) + { + this.defaultThreadSlowmode = defaultThreadSlowmode; + return this; + } + public ForumChannelImpl setNSFW(boolean nsfw) { this.nsfw = nsfw; diff --git a/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java b/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java index 39a32f6b06..52eee602f9 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/mixin/channel/attribute/IThreadContainerMixin.java @@ -114,4 +114,6 @@ default ThreadChannelPaginationAction retrieveArchivedPrivateJoinedThreadChannel Route.CompiledRoute route = Route.Channels.LIST_JOINED_PRIVATE_ARCHIVED_THREADS.compile(getId()); return new ThreadChannelPaginationActionImpl(getJDA(), route, this, true); } + + T setDefaultThreadSlowmode(int slowmode); } 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 801b6e6fa2..547122176b 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -70,6 +70,7 @@ protected Long handleInternally(DataObject content) final int position = content.getInt("position"); final String name = content.getString("name"); final boolean nsfw = content.getBoolean("nsfw"); + final int defaultThreadSlowmode = content.getInt("default_thread_rate_limit_per_user", 0); final int slowmode = content.getInt("rate_limit_per_user", 0); final DataArray permOverwrites = content.getArray("permission_overwrites"); @@ -100,6 +101,7 @@ protected Long handleInternally(DataObject content) final int oldPosition = textChannel.getPositionRaw(); final boolean oldNsfw = textChannel.isNSFW(); final int oldSlowmode = textChannel.getSlowmode(); + final int oldDefaultThreadSlowmode = textChannel.getDefaultThreadSlowmode(); if (!Objects.equals(oldName, name)) { textChannel.setName(name); @@ -133,7 +135,6 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, textChannel, oldPosition, position)); } - if (oldNsfw != nsfw) { textChannel.setNSFW(nsfw); @@ -142,7 +143,6 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, textChannel, oldNsfw, nsfw)); } - if (oldSlowmode != slowmode) { textChannel.setSlowmode(slowmode); @@ -151,6 +151,14 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, textChannel, oldSlowmode, slowmode)); } + if (oldDefaultThreadSlowmode != defaultThreadSlowmode) + { + textChannel.setDefaultThreadSlowmode(defaultThreadSlowmode); + getJDA().handleEvent( + new ChannelUpdateDefaultThreadSlowmodeEvent( + getJDA(), responseNumber, + textChannel, oldDefaultThreadSlowmode, defaultThreadSlowmode)); + } break; } case FORUM: @@ -167,6 +175,7 @@ protected Long handleInternally(DataObject content) final int oldPosition = forumChannel.getPositionRaw(); final boolean oldNsfw = forumChannel.isNSFW(); final int oldSlowmode = forumChannel.getSlowmode(); + final int oldDefaultThreadSlowmode = forumChannel.getDefaultThreadSlowmode(); if (!Objects.equals(oldName, name)) { @@ -201,7 +210,6 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, forumChannel, oldPosition, position)); } - if (oldNsfw != nsfw) { forumChannel.setNSFW(nsfw); @@ -210,7 +218,6 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, forumChannel, oldNsfw, nsfw)); } - if (oldSlowmode != slowmode) { forumChannel.setSlowmode(slowmode); @@ -219,6 +226,14 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, forumChannel, oldSlowmode, slowmode)); } + if (oldDefaultThreadSlowmode != defaultThreadSlowmode) + { + forumChannel.setDefaultThreadSlowmode(defaultThreadSlowmode); + getJDA().handleEvent( + new ChannelUpdateDefaultThreadSlowmodeEvent( + getJDA(), responseNumber, + forumChannel, oldDefaultThreadSlowmode, defaultThreadSlowmode)); + } break; } case NEWS: From dfccd6234c8c923e7c5ee6bc3e879eaf1f00f057 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 1 Sep 2022 15:14:08 +0200 Subject: [PATCH 38/75] Handle channel flags for forums --- .../dv8tion/jda/api/audit/AuditLogKey.java | 7 ++ .../net/dv8tion/jda/api/entities/Channel.java | 14 ++++ .../jda/api/entities/ChannelField.java | 7 ++ .../jda/api/entities/channel/ChannelFlag.java | 79 +++++++++++++++++++ .../update/ChannelUpdateFlagsEvent.java | 47 +++++++++++ .../jda/api/hooks/ListenerAdapter.java | 1 + .../jda/internal/entities/EntityBuilder.java | 1 + .../internal/entities/ForumChannelImpl.java | 21 +++++ .../internal/handle/ChannelUpdateHandler.java | 11 +++ 9 files changed, 188 insertions(+) create mode 100644 src/main/java/net/dv8tion/jda/api/entities/channel/ChannelFlag.java create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateFlagsEvent.java 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 83c1c3f65c..8a3eaa25da 100644 --- a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java +++ b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java @@ -201,6 +201,13 @@ public enum AuditLogKey */ CHANNEL_NAME("name"), + /** + * Change of the {@link Channel#getFlags() flags} value. + * + *

        Expected type: Integer + */ + CHANNEL_FLAGS("flags"), + /** * Change of the {@link ICategorizableChannel#getParentCategory()} ICategorizable.getParentCategory()} value. *
        Use with {@link net.dv8tion.jda.api.entities.Guild#getCategoryById(String) Guild.getCategoryById(String)} diff --git a/src/main/java/net/dv8tion/jda/api/entities/Channel.java b/src/main/java/net/dv8tion/jda/api/entities/Channel.java index 0dbf64b52a..95b75e39a7 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/Channel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/Channel.java @@ -17,11 +17,13 @@ package net.dv8tion.jda.api.entities; import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.utils.MiscUtil; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +import java.util.EnumSet; import java.util.FormattableFlags; import java.util.Formatter; @@ -35,6 +37,18 @@ public interface Channel extends IMentionable */ int MAX_NAME_LENGTH = 100; + /** + * The flags configured for this channel. + *
        This feature is currently primarily used for {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels}. + * + * @return {@link EnumSet} of the configured {@link ChannelFlag ChannelFlags}, changes to this enum set are not reflected in the API. + */ + @Nonnull + default EnumSet getFlags() + { + return EnumSet.noneOf(ChannelFlag.class); + } + /** * The human readable name of this channel. * diff --git a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java index 26ba02c612..d36241b966 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ChannelField.java @@ -53,6 +53,13 @@ public enum ChannelField */ NAME("name", AuditLogKey.CHANNEL_NAME), + /** + * The flags of the channel. + * + * @see Channel#getFlags() + */ + FLAGS("flags", AuditLogKey.CHANNEL_FLAGS), + /** * The {@link Category parent} of the channel. * 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 new file mode 100644 index 0000000000..fee38025fc --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/ChannelFlag.java @@ -0,0 +1,79 @@ +/* + * 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; + +import net.dv8tion.jda.api.entities.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; + +import javax.annotation.Nonnull; +import java.util.EnumSet; + +/** + * Flags for specific channel settings. + */ +public enum ChannelFlag +{ + /** + * This is a forum post {@link ThreadChannel} which is pinned in the {@link ForumChannel}. + */ + PINNED(1 << 1), + /** + * This is a {@link ForumChannel} which requires all new post threads to have at least one applied tag. + */ + REQUIRE_TAG(1 << 4); + + private final int value; + + ChannelFlag(int value) + { + this.value = value; + } + + /** + * The raw bitset value of this flag. + * + * @return The raw value + */ + public int getRaw() + { + return value; + } + + /** + * Parses the provided bitset to the corresponding enum constants. + * + * @param bitset + * The bitset of channel flags + * + * @return The enum constants of the provided bitset + */ + @Nonnull + public static EnumSet fromRaw(int bitset) + { + EnumSet set = EnumSet.noneOf(ChannelFlag.class); + if (bitset == 0) + return set; + + for (ChannelFlag flag : values()) + { + if (flag.value == bitset) + set.add(flag); + } + + return set; + } +} 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 new file mode 100644 index 0000000000..f5deb1a87d --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateFlagsEvent.java @@ -0,0 +1,47 @@ +/* + * 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; +import net.dv8tion.jda.api.entities.ChannelField; +import net.dv8tion.jda.api.entities.channel.ChannelFlag; + +import javax.annotation.Nonnull; +import java.util.EnumSet; + +public class ChannelUpdateFlagsEvent extends GenericChannelUpdateEvent> +{ + public ChannelUpdateFlagsEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nonnull EnumSet oldValue, @Nonnull EnumSet newValue) + { + super(api, responseNumber, channel, ChannelField.FLAGS, oldValue, newValue); + } + + @Nonnull + @Override + public EnumSet getOldValue() + { + return super.getOldValue(); + } + + @Nonnull + @Override + public EnumSet getNewValue() + { + return super.getNewValue(); + } +} 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 f521db267e..4263db6d60 100644 --- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java +++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java @@ -182,6 +182,7 @@ public void onChannelDelete(@Nonnull ChannelDeleteEvent event) {} //Channel Update Events public void onChannelUpdateBitrate(@Nonnull ChannelUpdateBitrateEvent event) {} public void onChannelUpdateName(@Nonnull ChannelUpdateNameEvent event) {} + public void onChannelUpdateFlags(@Nonnull ChannelUpdateFlagsEvent event) {} public void onChannelUpdateNSFW(@Nonnull ChannelUpdateNSFWEvent event) {} public void onChannelUpdateParent(@Nonnull ChannelUpdateParentEvent event) {} public void onChannelUpdatePosition(@Nonnull ChannelUpdatePositionEvent event) {} 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 e5be032118..5d6ab50d7c 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1282,6 +1282,7 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu channel .setParentCategory(json.getLong("parent_id", 0)) + .setFlags(json.getInt("flags", 0)) .setName(json.getString("name")) .setTopic(json.getString("topic", null)) .setPosition(json.getInt("position")) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index ba7d0ec7d9..683411b798 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -19,6 +19,7 @@ import gnu.trove.map.TLongObjectMap; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; @@ -38,6 +39,7 @@ 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; @@ -54,6 +56,7 @@ public class ForumChannelImpl extends AbstractGuildChannelImpl private long parentCategoryId; private boolean nsfw = false; private int position; + private int flags; private int slowmode; protected int defaultThreadSlowmode; @@ -101,6 +104,13 @@ public ChannelAction createCopy(@Nonnull Guild guild) return action; } + @Nonnull + @Override + public EnumSet getFlags() + { + return ChannelFlag.fromRaw(flags); + } + @Nonnull @Override public SortedSnowflakeCacheViewImpl getAvailableTagCache() @@ -172,6 +182,11 @@ public ThreadChannelAction createThreadChannel(@Nonnull String name, @Nonnull St throw new UnsupportedOperationException("You cannot create threads without a message payload in forum channels! Use createForumPost(...) instead."); } + public int getRawFlags() + { + return flags; + } + // Setters @Override @@ -212,4 +227,10 @@ public ForumChannelImpl setTopic(String topic) this.topic = topic; return this; } + + public ForumChannelImpl setFlags(int flags) + { + this.flags = flags; + return this; + } } 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 547122176b..df66860c33 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -22,6 +22,7 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.events.guild.override.PermissionOverrideCreateEvent; import net.dv8tion.jda.api.events.guild.override.PermissionOverrideDeleteEvent; @@ -68,6 +69,7 @@ protected Long handleInternally(DataObject content) final long channelId = content.getLong("id"); final long parentId = content.isNull("parent_id") ? 0 : content.getLong("parent_id"); final int position = content.getInt("position"); + final int flags = content.getInt("flags", 0); final String name = content.getString("name"); final boolean nsfw = content.getBoolean("nsfw"); final int defaultThreadSlowmode = content.getInt("default_thread_rate_limit_per_user", 0); @@ -176,6 +178,7 @@ protected Long handleInternally(DataObject content) final boolean oldNsfw = forumChannel.isNSFW(); final int oldSlowmode = forumChannel.getSlowmode(); final int oldDefaultThreadSlowmode = forumChannel.getDefaultThreadSlowmode(); + final int oldFlags = forumChannel.getRawFlags(); if (!Objects.equals(oldName, name)) { @@ -234,6 +237,14 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, forumChannel, oldDefaultThreadSlowmode, defaultThreadSlowmode)); } + if (oldFlags != flags) + { + forumChannel.setFlags(flags); + getJDA().handleEvent( + new ChannelUpdateFlagsEvent( + getJDA(), responseNumber, + forumChannel, ChannelFlag.fromRaw(oldFlags), ChannelFlag.fromRaw(flags))); + } break; } case NEWS: From ae85f75470b5e015eeb16c22c69cde7b109f3d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 1 Sep 2022 18:47:44 +0200 Subject: [PATCH 39/75] Handle thread flags --- .../jda/internal/entities/EntityBuilder.java | 1 + .../internal/entities/ThreadChannelImpl.java | 21 +++++++++++++++++++ .../internal/handle/ThreadUpdateHandler.java | 11 ++++++++++ 3 files changed, 33 insertions(+) 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 5d6ab50d7c..9a4d694005 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1196,6 +1196,7 @@ public ThreadChannel createThreadChannel(GuildImpl guild, DataObject json, long channel .setName(json.getString("name")) + .setFlags(json.getInt("flags", 0)) .setParentChannel(parent) .setOwnerId(json.getLong("owner_id")) .setMemberCount(json.getInt("member_count")) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java index 61324df8b8..d351d5a40d 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ThreadChannelImpl.java @@ -20,6 +20,7 @@ import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion; import net.dv8tion.jda.api.managers.channel.concrete.ThreadChannelManager; @@ -42,6 +43,7 @@ import javax.annotation.Nullable; import java.time.OffsetDateTime; import java.util.Collections; +import java.util.EnumSet; import java.util.LinkedList; import java.util.List; import java.util.stream.LongStream; @@ -67,6 +69,7 @@ public class ThreadChannelImpl extends AbstractGuildChannelImpl getFlags() + { + return ChannelFlag.fromRaw(flags); + } + @Nonnull @Override public ChannelType getType() @@ -397,6 +407,12 @@ public ThreadChannelImpl setAppliedTags(LongStream tags) return this; } + public ThreadChannelImpl setFlags(int flags) + { + this.flags = flags; + return this; + } + public long getArchiveTimestamp() { return archiveTimestamp; @@ -408,6 +424,11 @@ public TLongSet getAppliedTagsSet() } + public int getRawFlags() + { + return flags; + } + // -- Object overrides -- @Override 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 c595e1ee5e..6c28607031 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java @@ -20,6 +20,7 @@ import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.utils.cache.CacheFlag; import net.dv8tion.jda.api.utils.data.DataObject; @@ -68,6 +69,7 @@ protected Long handleInternally(DataObject content) final DataObject threadMetadata = content.getObject("thread_metadata"); final String name = content.getString("name"); + final int flags = content.getInt("flags", 0); final ThreadChannel.AutoArchiveDuration autoArchiveDuration = ThreadChannel.AutoArchiveDuration.fromKey(threadMetadata.getInt("auto_archive_duration")); final boolean locked = threadMetadata.getBoolean("locked"); final boolean archived = threadMetadata.getBoolean("archived"); @@ -82,6 +84,7 @@ protected Long handleInternally(DataObject content) final boolean oldInvitable = !thread.isPublic() && thread.isInvitable(); final long oldArchiveTimestamp = thread.getArchiveTimestamp(); final int oldSlowmode = thread.getSlowmode(); + final int oldFlags = thread.getRawFlags(); //TODO should these be Thread specific events? @@ -93,6 +96,14 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, thread, oldName, name)); } + if (oldFlags != flags) + { + thread.setFlags(flags); + api.handleEvent( + new ChannelUpdateFlagsEvent( + getJDA(), responseNumber, + thread, ChannelFlag.fromRaw(oldFlags), ChannelFlag.fromRaw(flags))); + } if (oldSlowmode != slowmode) { thread.setSlowmode(slowmode); From 191acca97fe1def75bb2cac5713b8e26f508844b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 14 Sep 2022 19:11:36 +0200 Subject: [PATCH 40/75] Implement tag ordering by position --- .../java/net/dv8tion/jda/api/entities/ForumTag.java | 9 ++++++++- .../jda/internal/entities/EntityBuilder.java | 12 ++++++------ .../dv8tion/jda/internal/entities/ForumTagImpl.java | 13 +++++++++++++ .../jda/internal/handle/ChannelUpdateHandler.java | 6 ++++-- 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java b/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java index d20b7bda0f..634f67811c 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java @@ -31,6 +31,13 @@ public interface ForumTag extends ISnowflake, Comparable */ int MAX_NAME_LENGTH = 20; + /** + * The tag position, used for sorting. + * + * @return The tag position. + */ + int getPosition(); + /** * The name of the tag. * @@ -52,6 +59,6 @@ public interface ForumTag extends ISnowflake, Comparable default int compareTo(@Nonnull ForumTag o) { Checks.notNull(o, "ForumTag"); - return Long.compare(getIdLong(), o.getIdLong()); + return Integer.compare(getPosition(), o.getPosition()); } } 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 844f278a92..5841fd663e 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1283,10 +1283,9 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu if (api.isCacheFlagSet(CacheFlag.FORUM_TAGS)) { - ForumChannelImpl tmp = channel; - json.getArray("available_tags") - .stream(DataArray::getObject) - .forEach(obj -> createForumTag(tmp, obj)); + DataArray tags = json.getArray("available_tags"); + for (int i = 0; i < tags.length(); i++) + createForumTag(channel, tags.getObject(i), i); } channel @@ -1305,7 +1304,7 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu return channel; } - public ForumTagImpl createForumTag(ForumChannelImpl channel, DataObject json) + public ForumTagImpl createForumTag(ForumChannelImpl channel, DataObject json, int index) { final long id = json.getUnsignedLong("id"); SortedSnowflakeCacheViewImpl cache = channel.getAvailableTagCache(); @@ -1321,7 +1320,8 @@ public ForumTagImpl createForumTag(ForumChannelImpl channel, DataObject json) } tag.setName(json.getString("name")) - .setModerated(json.getBoolean("moderated")); + .setModerated(json.getBoolean("moderated")) + .setPosition(index); return tag; } diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java index c87cc7ef48..75aa607436 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java @@ -24,12 +24,19 @@ public class ForumTagImpl extends ForumTagSnowflakeImpl implements ForumTag { private boolean moderated; private String name; + private int position; public ForumTagImpl(long id) { super(id); } + @Override + public int getPosition() + { + return position; + } + @Nonnull @Override public String getName() @@ -55,6 +62,12 @@ public ForumTagImpl setName(String name) return this; } + public ForumTagImpl setPosition(int position) + { + this.position = position; + return this; + } + @Override public String toString() { 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 3746ce7cae..7615f7c4cb 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -19,6 +19,7 @@ import gnu.trove.map.TLongObjectMap; import gnu.trove.map.hash.TLongObjectHashMap; import gnu.trove.set.TLongSet; +import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.ForumTag; @@ -680,7 +681,7 @@ private void handleTagsUpdate(ForumChannelImpl channel, DataArray tags) try (UnlockHook hook = view.writeLock()) { TLongObjectMap cache = view.getMap(); - TLongSet removedTags = cache.keySet(); + TLongSet removedTags = new TLongHashSet(cache.keySet()); for (int i = 0; i < tags.length(); i++) { @@ -697,6 +698,7 @@ private void handleTagsUpdate(ForumChannelImpl channel, DataArray tags) // TODO: Emoji // TODO: Events? + impl.setPosition(i); String oldName = impl.getName(); if (!name.equals(oldName)) { @@ -709,7 +711,7 @@ private void handleTagsUpdate(ForumChannelImpl channel, DataArray tags) } else { - ForumTag tag = builder.createForumTag(channel, tagJson); + ForumTag tag = builder.createForumTag(channel, tagJson, i); cache.put(id, tag); } } From bca3972ddbdd20fbb52a4f34ba59ac701cc7afac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 14 Sep 2022 19:27:27 +0200 Subject: [PATCH 41/75] Implement tag emoji and setting available tags on managers --- .../dv8tion/jda/api/entities/ForumTag.java | 33 +++++++++++++++++-- .../api/managers/channel/ChannelManager.java | 30 +++++++++-------- .../channel/concrete/ForumChannelManager.java | 6 ++++ .../jda/internal/entities/EntityBuilder.java | 1 + .../jda/internal/entities/ForumTagImpl.java | 22 +++++++++++++ .../internal/handle/ChannelUpdateHandler.java | 2 +- .../managers/channel/ChannelManagerImpl.java | 24 +++++++++++--- 7 files changed, 97 insertions(+), 21 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java b/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java index 634f67811c..a8e87fcceb 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java +++ b/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java @@ -16,15 +16,21 @@ package net.dv8tion.jda.api.entities; +import net.dv8tion.jda.api.entities.emoji.CustomEmoji; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; +import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.api.utils.data.SerializableData; import net.dv8tion.jda.internal.utils.Checks; import javax.annotation.Nonnull; +import javax.annotation.Nullable; /** * Represents a Discord Forum Tag. *
        These tags can be applied to forum posts to help categorize them. */ -public interface ForumTag extends ISnowflake, Comparable +public interface ForumTag extends ISnowflake, Comparable, SerializableData { /** * The maximum length of a forum tag name ({@value #MAX_NAME_LENGTH}) @@ -53,7 +59,14 @@ public interface ForumTag extends ISnowflake, Comparable */ boolean isModerated(); - // TODO: Emoji + /** + * The emoji used as the tag icon. + *
        For custom emoji, this will have an empty name and {@link CustomEmoji#isAnimated()} is always {@code false}, due to discord chicanery. + * + * @return {@link EmojiUnion} representing the tag emoji, or null if no emoji is applied. + */ + @Nullable + EmojiUnion getEmoji(); @Override default int compareTo(@Nonnull ForumTag o) @@ -61,4 +74,20 @@ default int compareTo(@Nonnull ForumTag o) Checks.notNull(o, "ForumTag"); return Integer.compare(getPosition(), o.getPosition()); } + + @Nonnull + @Override + default DataObject toData() + { + DataObject json = DataObject.empty() + .put("id", getId()) + .put("name", getName()) + .put("moderated", isModerated()); + EmojiUnion emoji = getEmoji(); + if (emoji instanceof UnicodeEmoji) + json.put("emoji_name", emoji.getName()); + else if (emoji instanceof CustomEmoji) + json.put("emoji_id", ((CustomEmoji) emoji).getId()); + return json; + } } 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 99988effcd..dabe6e8e13 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 @@ -45,35 +45,37 @@ public interface ChannelManager> extends Manager { /** Used to reset the name field */ - long NAME = 1; + long NAME = 1; /** Used to reset the parent field */ - long PARENT = 1 << 1; + long PARENT = 1 << 1; /** Used to reset the topic field */ - long TOPIC = 1 << 2; + long TOPIC = 1 << 2; /** Used to reset the position field */ - long POSITION = 1 << 3; + long POSITION = 1 << 3; /** Used to reset the nsfw field */ - long NSFW = 1 << 4; + long NSFW = 1 << 4; /** Used to reset the userlimit field */ - long USERLIMIT = 1 << 5; + long USERLIMIT = 1 << 5; /** Used to reset the bitrate field */ - long BITRATE = 1 << 6; + long BITRATE = 1 << 6; /** Used to reset the permission field */ - long PERMISSION = 1 << 7; + long PERMISSION = 1 << 7; /** Used to reset the rate-limit per user field */ - long SLOWMODE = 1 << 8; + long SLOWMODE = 1 << 8; /** Used to reset the channel type field */ - long TYPE = 1 << 9; + long TYPE = 1 << 9; /** Used to reset the region field */ - long REGION = 1 << 10; + long REGION = 1 << 10; /** Used to reset the auto-archive-duration field */ long AUTO_ARCHIVE_DURATION = 1 << 11; /** Used to reset the archived field */ - long ARCHIVED = 1 << 12; + long ARCHIVED = 1 << 12; /** Used to reset the locked field */ - long LOCKED = 1 << 13; + long LOCKED = 1 << 13; /** Used to reset the invitable field */ - long INVITEABLE = 1 << 14; + long INVITEABLE = 1 << 14; + /** Used to reset the available tags field */ + long AVAILABLE_TAGS = 1 << 15; /** * Resets the fields specified by the provided bit-flag pattern. 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 aae6adc1cb..08a608a064 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,6 +17,7 @@ package net.dv8tion.jda.api.managers.channel.concrete; import net.dv8tion.jda.api.Permission; +import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.managers.channel.attribute.IAgeRestrictedChannelManager; @@ -24,6 +25,7 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +import java.util.List; /** * Manager providing functionality to modify a {@link ForumChannel ForumChannel}. @@ -68,4 +70,8 @@ public interface ForumChannelManager extends @Nonnull @CheckReturnValue ForumChannelManager setSlowmode(int slowmode); + + @Nonnull + @CheckReturnValue + ForumChannelManager setAvailableTags(@Nonnull List tags); } 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 5841fd663e..116cdb498b 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1321,6 +1321,7 @@ public ForumTagImpl createForumTag(ForumChannelImpl channel, DataObject json, in tag.setName(json.getString("name")) .setModerated(json.getBoolean("moderated")) + .setEmoji(json) .setPosition(index); return tag; } diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java index 75aa607436..dbf5b424de 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java @@ -17,6 +17,10 @@ package net.dv8tion.jda.internal.entities; import net.dv8tion.jda.api.entities.ForumTag; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.entities.emoji.CustomEmojiImpl; import javax.annotation.Nonnull; @@ -25,6 +29,7 @@ public class ForumTagImpl extends ForumTagSnowflakeImpl implements ForumTag private boolean moderated; private String name; private int position; + private Emoji emoji; public ForumTagImpl(long id) { @@ -50,6 +55,12 @@ public boolean isModerated() return moderated; } + @Override + public EmojiUnion getEmoji() + { + return (EmojiUnion) emoji; + } + public ForumTagImpl setModerated(boolean moderated) { this.moderated = moderated; @@ -68,6 +79,17 @@ public ForumTagImpl setPosition(int position) return this; } + public ForumTagImpl setEmoji(DataObject json) + { + if (!json.isNull("emoji_id")) + this.emoji = new CustomEmojiImpl("", json.getUnsignedLong("emoji_id"), false); + else if (!json.isNull("emoji_name")) + this.emoji = Emoji.fromUnicode(json.getString("emoji_name")); + else + this.emoji = null; + return this; + } + @Override public String toString() { 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 7615f7c4cb..cfc5a2b88e 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -695,10 +695,10 @@ private void handleTagsUpdate(ForumChannelImpl channel, DataArray tags) String name = tagJson.getString("name"); boolean moderated = tagJson.getBoolean("moderated"); - // TODO: Emoji // TODO: Events? impl.setPosition(i); + impl.setEmoji(tagJson); String oldName = impl.getName(); if (!name.equals(oldName)) { 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 b69be7a34c..0205c354e9 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 @@ -21,10 +21,7 @@ import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; -import net.dv8tion.jda.api.entities.IPermissionHolder; -import net.dv8tion.jda.api.entities.Member; -import net.dv8tion.jda.api.entities.PermissionOverride; -import net.dv8tion.jda.api.entities.Role; +import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.attribute.IPermissionContainer; import net.dv8tion.jda.api.entities.channel.concrete.Category; @@ -34,6 +31,7 @@ import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.managers.channel.ChannelManager; +import net.dv8tion.jda.api.utils.data.DataArray; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IPermissionContainerMixin; import net.dv8tion.jda.internal.entities.channel.mixin.middleman.GuildChannelMixin; @@ -46,8 +44,10 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; +import java.util.List; import java.util.stream.Collectors; @SuppressWarnings("unchecked") //We do a lot of (M) and (T) casting that we know is correct but the compiler warns about. @@ -60,6 +60,7 @@ public class ChannelManagerImpl availableTags; protected ChannelType type; protected String name; protected String parent; @@ -116,6 +117,8 @@ public M reset(long fields) this.topic = null; if ((fields & REGION) == REGION) this.region = null; + if ((fields & AVAILABLE_TAGS) == AVAILABLE_TAGS) + this.availableTags = null; if ((fields & PERMISSION) == PERMISSION) { withLock(lock, (lock) -> @@ -147,6 +150,7 @@ public M reset() this.parent = null; this.topic = null; this.region = null; + this.availableTags = null; withLock(lock, (lock) -> { this.overridesRem.clear(); @@ -532,6 +536,16 @@ public M setInvitable(boolean invitable) return (M) this; } + public M setAvailableTags(List tags) + { + if (type != ChannelType.FORUM) + throw new IllegalStateException("Can only set available tags on forum channels."); + Checks.noneNull(tags, "Available Tags"); + this.availableTags = new ArrayList<>(tags); + set |= AVAILABLE_TAGS; + return (M) this; + } + @Override protected RequestBody finalizeData() { @@ -564,6 +578,8 @@ protected RequestBody finalizeData() frame.put("locked", locked); if (shouldUpdate(INVITEABLE)) frame.put("invitable", invitable); + if (shouldUpdate(AVAILABLE_TAGS)) + frame.put("available_tags", DataArray.fromCollection(availableTags)); withLock(lock, (lock) -> { From 2082c830eab3056625fa255e4a97d99c2b60905e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 14 Sep 2022 20:10:01 +0200 Subject: [PATCH 42/75] Add support to manage available tags --- .../channel/concrete/ForumChannel.java | 2 +- .../channel/concrete/ThreadChannel.java | 5 +- .../forums/BaseForumTag.java} | 29 +-- .../{ => channel/forums}/ForumPost.java | 3 +- .../api/entities/channel/forums/ForumTag.java | 56 ++++++ .../entities/channel/forums/ForumTagData.java | 168 ++++++++++++++++++ .../forums}/ForumTagSnowflake.java | 3 +- .../update/ChannelUpdateAppliedTagsEvent.java | 2 +- .../channel/concrete/ForumChannelManager.java | 31 +++- .../requests/restaction/ForumPostAction.java | 4 +- .../jda/internal/entities/EntityBuilder.java | 1 + .../internal/entities/ForumChannelImpl.java | 2 +- .../jda/internal/entities/ForumTagImpl.java | 2 +- .../entities/ForumTagSnowflakeImpl.java | 2 +- .../channel/concrete/ThreadChannelImpl.java | 2 +- .../internal/handle/ChannelUpdateHandler.java | 2 +- .../internal/handle/ThreadUpdateHandler.java | 2 +- .../managers/channel/ChannelManagerImpl.java | 12 +- .../restaction/ForumPostActionImpl.java | 4 +- 19 files changed, 283 insertions(+), 49 deletions(-) rename src/main/java/net/dv8tion/jda/api/entities/{ForumTag.java => channel/forums/BaseForumTag.java} (75%) rename src/main/java/net/dv8tion/jda/api/entities/{ => channel/forums}/ForumPost.java (95%) create mode 100644 src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTag.java create mode 100644 src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java rename src/main/java/net/dv8tion/jda/api/entities/{ => channel/forums}/ForumTagSnowflake.java (94%) 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 2e049356b6..776521205d 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 @@ -17,12 +17,12 @@ package net.dv8tion.jda.api.entities.channel.concrete; import net.dv8tion.jda.annotations.Incubating; -import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.channel.Channel; 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.IThreadContainer; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildChannel; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; import net.dv8tion.jda.api.requests.restaction.ChannelAction; diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java index b7c18b45a2..f8967c06f8 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.attribute.IMemberContainer; import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; import net.dv8tion.jda.api.entities.channel.unions.GuildMessageChannelUnion; import net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion; @@ -168,10 +169,10 @@ default GuildMessageChannelUnion getParentMessageChannel() } /** - * The {@link ForumTag forum tags} applied to this thread. + * The {@link net.dv8tion.jda.api.entities.channel.forums.ForumTag forum tags} applied to this thread. *
        This will be an empty list if the thread was not created in a {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannel}. * - * @return Immutable {@link List} of {@link ForumTag ForumTags} applied to this post + * @return Immutable {@link List} of {@link net.dv8tion.jda.api.entities.channel.forums.ForumTag ForumTags} applied to this post */ @Nonnull List getAppliedTags(); diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/BaseForumTag.java similarity index 75% rename from src/main/java/net/dv8tion/jda/api/entities/ForumTag.java rename to src/main/java/net/dv8tion/jda/api/entities/channel/forums/BaseForumTag.java index a8e87fcceb..96d01665d6 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ForumTag.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/BaseForumTag.java @@ -14,36 +14,19 @@ * limitations under the License. */ -package net.dv8tion.jda.api.entities; +package net.dv8tion.jda.api.entities.channel.forums; import net.dv8tion.jda.api.entities.emoji.CustomEmoji; import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.api.utils.data.SerializableData; -import net.dv8tion.jda.internal.utils.Checks; import javax.annotation.Nonnull; import javax.annotation.Nullable; -/** - * Represents a Discord Forum Tag. - *
        These tags can be applied to forum posts to help categorize them. - */ -public interface ForumTag extends ISnowflake, Comparable, SerializableData +public interface BaseForumTag extends SerializableData { - /** - * The maximum length of a forum tag name ({@value #MAX_NAME_LENGTH}) - */ - int MAX_NAME_LENGTH = 20; - - /** - * The tag position, used for sorting. - * - * @return The tag position. - */ - int getPosition(); - /** * The name of the tag. * @@ -68,19 +51,11 @@ public interface ForumTag extends ISnowflake, Comparable, Serializable @Nullable EmojiUnion getEmoji(); - @Override - default int compareTo(@Nonnull ForumTag o) - { - Checks.notNull(o, "ForumTag"); - return Integer.compare(getPosition(), o.getPosition()); - } - @Nonnull @Override default DataObject toData() { DataObject json = DataObject.empty() - .put("id", getId()) .put("name", getName()) .put("moderated", isModerated()); EmojiUnion emoji = getEmoji(); diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumPost.java similarity index 95% rename from src/main/java/net/dv8tion/jda/api/entities/ForumPost.java rename to src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumPost.java index 4e0bf85209..b2b6b58f38 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ForumPost.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumPost.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package net.dv8tion.jda.api.entities; +package net.dv8tion.jda.api.entities.channel.forums; +import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.utils.messages.MessageCreateData; diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTag.java b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTag.java new file mode 100644 index 0000000000..989dfde283 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTag.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.entities.channel.forums; + +import net.dv8tion.jda.api.entities.ISnowflake; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.utils.Checks; + +import javax.annotation.Nonnull; + +/** + * Represents a Discord Forum Tag. + *
        These tags can be applied to forum posts to help categorize them. + */ +public interface ForumTag extends ISnowflake, Comparable, BaseForumTag +{ + /** + * The maximum length of a forum tag name ({@value #MAX_NAME_LENGTH}) + */ + int MAX_NAME_LENGTH = 20; + + /** + * The tag position, used for sorting. + * + * @return The tag position. + */ + int getPosition(); + + @Override + default int compareTo(@Nonnull ForumTag o) + { + Checks.notNull(o, "ForumTag"); + return Integer.compare(getPosition(), o.getPosition()); + } + + @Nonnull + @Override + default DataObject toData() + { + return BaseForumTag.super.toData().put("id", getId()); + } +} diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java new file mode 100644 index 0000000000..78d20a28f1 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java @@ -0,0 +1,168 @@ +/* + * 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.forums; + +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; +import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; +import net.dv8tion.jda.api.utils.data.DataObject; +import net.dv8tion.jda.internal.utils.Checks; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +/** + * Data class used to create or update existing forum tags. + * + * @see ForumChannelManager#setAvailableTags(List) + */ +public class ForumTagData implements BaseForumTag +{ + private String name; + private Emoji emoji; + private boolean moderated; + private long id; + + /** + * Create a new {@link ForumTagData} instance. + * + * @param name + * The tag name (1-{@value ForumTag#MAX_NAME_LENGTH} characters) + * + * @throws IllegalArgumentException + * If the provided name is null or not between 1 and {@value ForumTag#MAX_NAME_LENGTH} characters long + */ + public ForumTagData(@Nonnull String name) + { + setName(name); + } + + /** + * Creates a new {@link ForumTagData} instance based on the provided {@link BaseForumTag}. + *
        This also binds to the id of the provided tag, if available. + * + * @param tag + * The base tag to use + * + * @throws IllegalArgumentException + * If null is provided or the tag has an invalid name + * + * @return The new {@link ForumTagData} instance + */ + @Nonnull + public static ForumTagData from(@Nonnull BaseForumTag tag) + { + Checks.notNull(tag, "Tag"); + ForumTagData data = new ForumTagData(tag.getName()) + .setEmoji(tag.getEmoji()) + .setModerated(tag.isModerated()); + if (tag instanceof ForumTagSnowflake) + data.id = ((ForumTagSnowflake) tag).getIdLong(); + return data; + } + + /** + * Set the new tag name to use. + * + * @param name + * The new tag name (1-{@value ForumTag#MAX_NAME_LENGTH} characters) + * + * @throws IllegalArgumentException + * If the provided name is null or not between 1 and {@value ForumTag#MAX_NAME_LENGTH} characters long + * + * @return The updated ForumTagData instance + */ + @Nonnull + public ForumTagData setName(@Nonnull String name) + { + Checks.notEmpty(name, "Name"); + Checks.notLonger(name, ForumTag.MAX_NAME_LENGTH, "Name"); + this.name = name; + return this; + } + + /** + * Set whether the tag can only be applied by forum moderators. + * + * @param moderated + * True, if the tag is restricted to moderators + * + * @return The updated ForumTagData instance + * + * @see #isModerated() + */ + @Nonnull + public ForumTagData setModerated(boolean moderated) + { + this.moderated = moderated; + return this; + } + + /** + * Set the emoji to use for this tag. + *
        This emoji is displayed as an icon attached to the tag. + * + * @param emoji + * The emoji icon of the tag + * + * @return The updated ForumTagData instance + */ + @Nonnull + public ForumTagData setEmoji(@Nullable Emoji emoji) + { + this.emoji = emoji; + return this; + } + + @Nonnull + @Override + public String getName() + { + return name; + } + + @Override + public boolean isModerated() + { + return moderated; + } + + @Nullable + @Override + public EmojiUnion getEmoji() + { + return (EmojiUnion) emoji; + } + + @NotNull + @Override + public DataObject toData() + { + DataObject json = BaseForumTag.super.toData(); + if (id != 0) + json.put("id", Long.toUnsignedString(id)); + return json; + } + + @Override + public String toString() + { + return toData().toString(); + } +} diff --git a/src/main/java/net/dv8tion/jda/api/entities/ForumTagSnowflake.java b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagSnowflake.java similarity index 94% rename from src/main/java/net/dv8tion/jda/api/entities/ForumTagSnowflake.java rename to src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagSnowflake.java index 244013fa58..76074da16d 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/ForumTagSnowflake.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagSnowflake.java @@ -14,8 +14,9 @@ * limitations under the License. */ -package net.dv8tion.jda.api.entities; +package net.dv8tion.jda.api.entities.channel.forums; +import net.dv8tion.jda.api.entities.ISnowflake; import net.dv8tion.jda.api.requests.restaction.ForumPostAction; import net.dv8tion.jda.api.utils.MiscUtil; import net.dv8tion.jda.internal.entities.ForumTagSnowflakeImpl; 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 db080dd746..9cc255279f 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 @@ -17,9 +17,9 @@ package net.dv8tion.jda.api.events.channel.update; import net.dv8tion.jda.api.JDA; -import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.channel.ChannelField; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import javax.annotation.Nonnull; import java.util.ArrayList; 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 08a608a064..112e786faf 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,9 +17,10 @@ package net.dv8tion.jda.api.managers.channel.concrete; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag; +import net.dv8tion.jda.api.entities.channel.forums.ForumTagData; import net.dv8tion.jda.api.managers.channel.attribute.IAgeRestrictedChannelManager; import net.dv8tion.jda.api.managers.channel.middleman.StandardGuildChannelManager; @@ -71,7 +72,33 @@ public interface ForumChannelManager extends @CheckReturnValue ForumChannelManager setSlowmode(int slowmode); + /** + * 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 tags); + ForumChannelManager setAvailableTags(@Nonnull List tags); } 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 f9a886a944..3ee6ca0763 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,9 +16,9 @@ package net.dv8tion.jda.api.requests.restaction; -import net.dv8tion.jda.api.entities.ForumPost; -import net.dv8tion.jda.api.entities.ForumTagSnowflake; 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; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageCreateRequest; 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 116cdb498b..79f2a294c7 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -33,6 +33,7 @@ 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.concrete.*; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index d83c042fa9..180e32a997 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -18,13 +18,13 @@ import gnu.trove.map.TLongObjectMap; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.ForumTag; 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.ForumChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.unions.GuildChannelUnion; import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; import net.dv8tion.jda.api.requests.restaction.ChannelAction; diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java index dbf5b424de..d21f7ce051 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagImpl.java @@ -16,7 +16,7 @@ package net.dv8tion.jda.internal.entities; -import net.dv8tion.jda.api.entities.ForumTag; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.utils.data.DataObject; diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java index 035ab1409e..40e7c53e92 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumTagSnowflakeImpl.java @@ -16,7 +16,7 @@ package net.dv8tion.jda.internal.entities; -import net.dv8tion.jda.api.entities.ForumTagSnowflake; +import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; public class ForumTagSnowflakeImpl implements ForumTagSnowflake { 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 1fdbebe3bd..c4f508a3d7 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 @@ -19,7 +19,6 @@ import gnu.trove.set.TLongSet; import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.Permission; -import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.ThreadMember; @@ -29,6 +28,7 @@ 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.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion; import net.dv8tion.jda.api.managers.channel.concrete.ThreadChannelManager; import net.dv8tion.jda.api.requests.RestAction; 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 cfc5a2b88e..a825707ec5 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -22,7 +22,6 @@ import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; -import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.IPermissionHolder; import net.dv8tion.jda.api.entities.PermissionOverride; @@ -33,6 +32,7 @@ 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.concrete.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.events.guild.override.PermissionOverrideCreateEvent; 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 c59095fb52..778e6690e4 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java @@ -18,9 +18,9 @@ import gnu.trove.set.TLongSet; import gnu.trove.set.hash.TLongHashSet; -import net.dv8tion.jda.api.entities.ForumTag; import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.utils.cache.CacheFlag; import net.dv8tion.jda.api.utils.data.DataObject; 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 0205c354e9..5483fdc55e 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 @@ -21,13 +21,17 @@ import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; -import net.dv8tion.jda.api.entities.*; +import net.dv8tion.jda.api.entities.IPermissionHolder; +import net.dv8tion.jda.api.entities.Member; +import net.dv8tion.jda.api.entities.PermissionOverride; +import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.attribute.IPermissionContainer; 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.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.managers.channel.ChannelManager; @@ -60,7 +64,7 @@ public class ChannelManagerImpl availableTags; + protected List availableTags; protected ChannelType type; protected String name; protected String parent; @@ -536,7 +540,7 @@ public M setInvitable(boolean invitable) return (M) this; } - public M setAvailableTags(List tags) + public M setAvailableTags(List tags) { if (type != ChannelType.FORUM) throw new IllegalStateException("Can only set available tags on forum channels."); @@ -549,7 +553,7 @@ public M setAvailableTags(List tags) @Override protected RequestBody finalizeData() { - DataObject frame = DataObject.empty().put("name", getChannel().getName()); + DataObject frame = DataObject.empty(); if (shouldUpdate(NAME)) frame.put("name", name); if (shouldUpdate(TYPE)) 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 729d72ac89..4631003fc3 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 @@ -18,14 +18,14 @@ import gnu.trove.set.TLongSet; import gnu.trove.set.hash.TLongHashSet; -import net.dv8tion.jda.api.entities.ForumPost; -import net.dv8tion.jda.api.entities.ForumTagSnowflake; import net.dv8tion.jda.api.entities.Guild; 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.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumPost; +import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; import net.dv8tion.jda.api.requests.Request; import net.dv8tion.jda.api.requests.Response; import net.dv8tion.jda.api.requests.restaction.ForumPostAction; From 0e1906a59a711a9a68ce40b224d2fa426bcabc1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 14 Sep 2022 20:46:06 +0200 Subject: [PATCH 43/75] Add webhook support to forums --- .../jda/api/entities/channel/concrete/ForumChannel.java | 3 ++- .../net/dv8tion/jda/internal/entities/ForumChannelImpl.java | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) 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 776521205d..54e803b25b 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 @@ -22,6 +22,7 @@ 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.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.managers.channel.concrete.ForumChannelManager; @@ -46,7 +47,7 @@ * @see Guild#createForumChannel(String, Category) * @see #createForumPost(String, MessageCreateData) */ -public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IAgeRestrictedChannel +public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IWebhookContainer, IAgeRestrictedChannel { /** * The maximum length of a forum topic ({@value #MAX_FORUM_TOPIC_LENGTH}) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index 180e32a997..c723f136b4 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -35,6 +35,7 @@ import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.internal.entities.channel.middleman.AbstractGuildChannelImpl; import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IThreadContainerMixin; +import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IWebhookContainerMixin; import net.dv8tion.jda.internal.entities.channel.mixin.middleman.StandardGuildChannelMixin; import net.dv8tion.jda.internal.managers.channel.concrete.ForumChannelManagerImpl; import net.dv8tion.jda.internal.requests.restaction.ForumPostActionImpl; @@ -52,6 +53,7 @@ public class ForumChannelImpl extends AbstractGuildChannelImpl implements ForumChannel, GuildChannelUnion, StandardGuildChannelMixin, + IWebhookContainerMixin, IThreadContainerMixin { private final TLongObjectMap overrides = MiscUtil.newLongMap(); From 64162ccc936f6da9f3fafbc551de0cb36b34865a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 14 Sep 2022 21:10:24 +0200 Subject: [PATCH 44/75] Add convenience getters and support modifying tags --- .../channel/concrete/ForumChannel.java | 11 ++++ .../channel/concrete/ThreadChannel.java | 11 ++++ .../api/managers/channel/ChannelManager.java | 14 +++++ .../concrete/ThreadChannelManager.java | 56 +++++++++++++++---- .../requests/restaction/ForumPostAction.java | 6 +- .../managers/channel/ChannelManagerImpl.java | 30 ++++++++-- .../restaction/ForumPostActionImpl.java | 3 + 7 files changed, 115 insertions(+), 16 deletions(-) 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 54e803b25b..7642248da4 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 @@ -19,6 +19,7 @@ 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.IThreadContainer; @@ -116,6 +117,16 @@ default List getAvailableTags() @Nullable String getTopic(); + /** + * Whether all new forum posts must have a tag. + * + * @return True, if all new posts must have a tag. + */ + default boolean isRequireTag() + { + return getFlags().contains(ChannelFlag.REQUIRE_TAG); + } + /** * Creates a new forum post (thread) in this forum. * diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java index f8967c06f8..3d678c4406 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java @@ -18,6 +18,7 @@ import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.channel.ChannelField; +import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.attribute.IMemberContainer; import net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer; @@ -140,6 +141,16 @@ default boolean isJoined() */ boolean isInvitable(); + /** + * Whether this thread is a pinned forum post. + * + * @return True, if this is a pinned forum post. + */ + default boolean isPinned() + { + return getFlags().contains(ChannelFlag.PINNED); + } + /** * Gets the {@link IThreadContainer parent channel} of this thread. * 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 dabe6e8e13..ff19c734af 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 @@ -76,6 +76,8 @@ public interface ChannelManager{@link #PERMISSION} *
      • {@link #TYPE}
      • *
      • {@link #REGION}
      • + *
      • {@link #AUTO_ARCHIVE_DURATION}
      • + *
      • {@link #ARCHIVED}
      • + *
      • {@link #LOCKED}
      • + *
      • {@link #INVITEABLE}
      • + *
      • {@link #AVAILABLE_TAGS}
      • + *
      • {@link #APPLIED_TAGS}
      • *
      * * @param fields @@ -122,6 +130,12 @@ public interface ChannelManager{@link #PERMISSION} *
    • {@link #TYPE}
    • *
    • {@link #REGION}
    • + *
    • {@link #AUTO_ARCHIVE_DURATION}
    • + *
    • {@link #ARCHIVED}
    • + *
    • {@link #LOCKED}
    • + *
    • {@link #INVITEABLE}
    • + *
    • {@link #AVAILABLE_TAGS}
    • + *
    • {@link #APPLIED_TAGS}
    • *
    * * @param fields diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java index fc56d6e02c..42b915ea87 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java @@ -16,9 +16,15 @@ package net.dv8tion.jda.api.managers.channel.concrete; +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.ForumTagSnowflake; import net.dv8tion.jda.api.managers.channel.ChannelManager; +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; +import java.util.Collection; + /** * Manager providing functionality common for all {@link ThreadChannel ThreadChannels}. * @@ -39,7 +45,6 @@ */ public interface ThreadChannelManager extends ChannelManager { - /** * Sets the slowmode of the selected {@link ThreadChannel}. *
    Provide {@code 0} to reset the slowmode of the {@link ThreadChannel}. @@ -61,6 +66,8 @@ public interface ThreadChannelManager extends ChannelManagerThis is only applicable to public threads inside forum channels. The tags must be from the forum channel. + * You can get the list of available tags with {@link ForumChannel#getAvailableTags()}. + * + * @param tags + * The new tags for the thread + * + * @throws IllegalStateException + * If the thread is not a forum post + * @throws IllegalArgumentException + *
      + *
    • If null is provided
    • + *
    • If more than {@value ForumChannel#MAX_POST_TAGS} tags are provided
    • + *
    • If at least one tag is {@link ForumChannel#isRequireTag() required} and none were provided
    • + *
    + * + * @return this ThreadChannelManager for chaining convenience. + */ + @Nonnull + @CheckReturnValue + ThreadChannelManager setAppliedTags(@Nonnull Collection tags); } 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 3ee6ca0763..93983f9262 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 @@ -53,7 +53,8 @@ public interface ForumPostAction extends AbstractThreadCreateAction availableTags; + protected List appliedTags; protected ChannelType type; protected String name; protected String parent; @@ -123,6 +123,8 @@ public M reset(long fields) this.region = null; if ((fields & AVAILABLE_TAGS) == AVAILABLE_TAGS) this.availableTags = null; + if ((fields & APPLIED_TAGS) == APPLIED_TAGS) + this.appliedTags = null; if ((fields & PERMISSION) == PERMISSION) { withLock(lock, (lock) -> @@ -155,6 +157,7 @@ public M reset() this.topic = null; this.region = null; this.availableTags = null; + this.appliedTags = null; withLock(lock, (lock) -> { this.overridesRem.clear(); @@ -550,6 +553,23 @@ public M setAvailableTags(List tags) return (M) this; } + public M setAppliedTags(Collection tags) + { + if (type != ChannelType.GUILD_PUBLIC_THREAD) + throw new IllegalStateException("Can only set applied tags on public 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); + 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 (tags.isEmpty() && parentChannel.asForumChannel().isRequireTag()) + throw new IllegalArgumentException("Cannot remove all tags from a forum post which requires at least one tag! See ForumChannel#isRequireTag()"); + this.appliedTags = tags.stream().map(ISnowflake::getId).collect(Collectors.toList()); + set |= APPLIED_TAGS; + return (M) this; + } + @Override protected RequestBody finalizeData() { @@ -584,6 +604,8 @@ protected RequestBody finalizeData() frame.put("invitable", invitable); if (shouldUpdate(AVAILABLE_TAGS)) frame.put("available_tags", DataArray.fromCollection(availableTags)); + if (shouldUpdate(APPLIED_TAGS)) + frame.put("applied_tags", DataArray.fromCollection(appliedTags)); withLock(lock, (lock) -> { 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 4631003fc3..5bc199e976 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 @@ -78,6 +78,7 @@ public ForumPostAction setTags(@Nonnull Collection { Checks.noneNull(tags, "Tags"); Checks.check(tags.size() <= ForumChannel.MAX_POST_TAGS, "Provided more than %d tags.", ForumChannel.MAX_POST_TAGS); + Checks.check(!channel.isRequireTag() || !tags.isEmpty(), "This forum requires at least one tag per post! See ForumChannel#isRequireTag()"); this.appliedTags.clear(); tags.forEach(t -> this.appliedTags.add(t.getIdLong())); return this; @@ -127,6 +128,8 @@ protected RequestBody finalizeData() json.put("auto_archive_duration", autoArchiveDuration.getMinutes()); if (!appliedTags.isEmpty()) json.put("applied_tags", appliedTags.toArray()); + else if (getChannel().isRequireTag()) + throw new IllegalStateException("Cannot create posts without a tag in this forum. Apply at least one tag!"); return getMultipartBody(message.getFiles(), json); } } From f7ace1962b2370e7896e89828b0c8c3a269117bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Wed, 14 Sep 2022 21:20:41 +0200 Subject: [PATCH 45/75] Support changing channel flags --- .../jda/api/entities/channel/ChannelFlag.java | 16 +++++++ .../api/managers/channel/ChannelManager.java | 12 +++++ .../channel/concrete/ForumChannelManager.java | 15 +++++++ .../concrete/ThreadChannelManager.java | 21 +++++++++ .../managers/channel/ChannelManagerImpl.java | 44 +++++++++++++++++++ 5 files changed, 108 insertions(+) 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 2d88b9d5f5..a807d7174e 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 @@ -18,8 +18,10 @@ import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; +import net.dv8tion.jda.internal.utils.Checks; import javax.annotation.Nonnull; +import java.util.Collection; import java.util.EnumSet; /** @@ -76,4 +78,18 @@ public static EnumSet fromRaw(int bitset) return set; } + + /** + * The raw bitset value for the provided flags. + * + * @return The raw value + */ + public static int getRaw(@Nonnull Collection flags) + { + Checks.notNull(flags, "Flags"); + int raw = 0; + for (ChannelFlag flag : flags) + raw |= flag.getRaw(); + return raw; + } } 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 ff19c734af..dc4df1238f 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 @@ -78,6 +78,14 @@ public interface ChannelManager{@link #INVITEABLE} *
  • {@link #AVAILABLE_TAGS}
  • *
  • {@link #APPLIED_TAGS}
  • + *
  • {@link #PINNED}
  • + *
  • {@link #REQUIRE_TAG}
  • * * * @param fields @@ -136,6 +146,8 @@ public interface ChannelManager{@link #INVITEABLE} *
  • {@link #AVAILABLE_TAGS}
  • *
  • {@link #APPLIED_TAGS}
  • + *
  • {@link #PINNED}
  • + *
  • {@link #REQUIRE_TAG}
  • * * * @param fields 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 112e786faf..197545c5de 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 @@ -47,6 +47,21 @@ public interface ForumChannelManager extends StandardGuildChannelManager, IAgeRestrictedChannelManager { + /** + * 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#isRequireTag() + */ + @Nonnull + @CheckReturnValue + ForumChannelManager setRequireTag(boolean requireTag); + /** * Sets the slowmode of the selected {@link ForumChannel}. *
    Provide {@code 0} to reset the slowmode of the {@link ForumChannel} diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java index 42b915ea87..274bafdf31 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java @@ -146,6 +146,27 @@ public interface ThreadChannelManager extends ChannelManagerThis property can only be set on forum post threads. + * + * @param pinned + * The new pinned state for the selected {@link ThreadChannel} + * + * @throws IllegalStateException + * If the selected {@link ThreadChannel} is not a forum post thread + * @throws net.dv8tion.jda.api.exceptions.InsufficientPermissionException + * If the currently logged in account is not the thread owner or does not have the {@link net.dv8tion.jda.api.Permission#MANAGE_THREADS MANAGE_THREADS} permission. + * + * @return this ThreadChannelManager for chaining convenience. + * + * @see ThreadChannel#isPinned() + */ + @Nonnull + @CheckReturnValue + ThreadChannelManager setPinned(boolean pinned); + /** * Sets the applied {@link net.dv8tion.jda.api.entities.channel.forums.ForumTag ForumTags} for this forum post thread. *
    This is only applicable to public threads inside forum channels. The tags must be from the forum channel. 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 da7da8b7f6..a67b9c2655 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 @@ -22,6 +22,7 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.*; +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.concrete.Category; @@ -62,6 +63,7 @@ public class ChannelManagerImpl flags; protected ThreadChannel.AutoArchiveDuration autoArchiveDuration; protected List availableTags; protected List appliedTags; @@ -88,6 +90,7 @@ public ChannelManagerImpl(T channel) super(channel.getJDA(), Route.Channels.MODIFY_CHANNEL.compile(channel.getId())); this.channel = channel; this.type = channel.getType(); + this.flags = channel.getFlags(); if (isPermissionChecksEnabled()) checkPermissions(); @@ -133,6 +136,23 @@ public M reset(long fields) this.overridesAdd.clear(); }); } + + if ((fields & PINNED) == PINNED) + { + if (channel.getFlags().contains(ChannelFlag.PINNED)) + this.flags.add(ChannelFlag.PINNED); + else + this.flags.remove(ChannelFlag.PINNED); + } + + if ((fields & REQUIRE_TAG) == REQUIRE_TAG) + { + if (channel.getFlags().contains(ChannelFlag.REQUIRE_TAG)) + this.flags.add(ChannelFlag.REQUIRE_TAG); + else + this.flags.remove(ChannelFlag.REQUIRE_TAG); + } + return (M) this; } @@ -158,6 +178,8 @@ public M reset() this.region = null; this.availableTags = null; this.appliedTags = null; + this.flags.clear(); + this.flags.addAll(channel.getFlags()); withLock(lock, (lock) -> { this.overridesRem.clear(); @@ -543,6 +565,26 @@ public M setInvitable(boolean invitable) return (M) this; } + public M setPinned(boolean pinned) + { + if (pinned) + flags.add(ChannelFlag.PINNED); + else + flags.remove(ChannelFlag.PINNED); + set |= PINNED; + return (M) this; + } + + public M setRequireTag(boolean requireTag) + { + if (requireTag) + flags.add(ChannelFlag.REQUIRE_TAG); + else + flags.remove(ChannelFlag.REQUIRE_TAG); + set |= REQUIRE_TAG; + return (M) this; + } + public M setAvailableTags(List tags) { if (type != ChannelType.FORUM) @@ -606,6 +648,8 @@ 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)) + frame.put("flags", ChannelFlag.getRaw(flags)); withLock(lock, (lock) -> { From 22fbb466c9f81c6b3c01900029695ef2d24dceca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 12:37:53 +0200 Subject: [PATCH 46/75] Add support for default reactions --- .../dv8tion/jda/api/audit/AuditLogKey.java | 8 +++++ .../jda/api/entities/channel/Channel.java | 1 + .../api/entities/channel/ChannelField.java | 1 + .../channel/concrete/ForumChannel.java | 9 +++++ .../ChannelUpdateDefaultReactionEvent.java | 33 +++++++++++++++++++ .../jda/api/hooks/ListenerAdapter.java | 1 + .../api/managers/channel/ChannelManager.java | 4 +++ .../channel/concrete/ForumChannelManager.java | 17 ++++++++++ .../jda/internal/entities/EntityBuilder.java | 1 + .../internal/entities/ForumChannelImpl.java | 22 +++++++++++++ .../internal/handle/ChannelUpdateHandler.java | 17 ++++++++++ .../managers/channel/ChannelManagerImpl.java | 25 ++++++++++++++ 12 files changed, 139 insertions(+) create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultReactionEvent.java 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 25a2024aa6..07f11cae87 100644 --- a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java +++ b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.attribute.ICategorizableChannel; 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.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel; @@ -247,6 +248,13 @@ public enum AuditLogKey */ CHANNEL_DEFAULT_THREAD_SLOWMODE("default_thread_rate_limit_per_user"), + /** + * Change of the {@link ForumChannel#getDefaultReaction()} value. + * + *

    Expected type: Map containing {@code emoji_id} and {@code emoji_name} + */ + CHANNEL_DEFAULT_REACTION_EMOJI("default_reaction_emoji"), + /** * Change of the {@link VoiceChannel#getBitrate() VoiceChannel.getBitrate()} value. *
    Only for {@link ChannelType#VOICE ChannelType.VOICE} diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/Channel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/Channel.java index 074b640b5c..b3101cc2fa 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/Channel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/Channel.java @@ -89,6 +89,7 @@ default EnumSet getFlags() @CheckReturnValue RestAction delete(); + @Nonnull @Override default String getAsMention() { 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 32db104bff..1e74adf0f2 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 @@ -82,6 +82,7 @@ public enum ChannelField POSITION("position", null), //Discord doesn't track Channel position changes in AuditLog. DEFAULT_THREAD_SLOWMODE("default_thread_slowmode", AuditLogKey.CHANNEL_DEFAULT_THREAD_SLOWMODE), + DEFAULT_REACTION_EMOJI("default_reaction_emoji", AuditLogKey.CHANNEL_DEFAULT_REACTION_EMOJI), //Text Specific 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 7642248da4..e84b058e59 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 @@ -26,6 +26,7 @@ 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; @@ -127,6 +128,14 @@ default boolean isRequireTag() 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(); + /** * Creates a new forum post (thread) in this forum. * 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 new file mode 100644 index 0000000000..f3a8e3dc1e --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultReactionEvent.java @@ -0,0 +1,33 @@ +/* + * 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.Channel; +import net.dv8tion.jda.api.entities.channel.ChannelField; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ChannelUpdateDefaultReactionEvent extends GenericChannelUpdateEvent +{ + public ChannelUpdateDefaultReactionEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nullable EmojiUnion oldValue, @Nullable EmojiUnion newValue) + { + super(api, responseNumber, channel, ChannelField.DEFAULT_REACTION_EMOJI, oldValue, newValue); + } +} 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 4263db6d60..fe5787e9d6 100644 --- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java +++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java @@ -189,6 +189,7 @@ public void onChannelUpdatePosition(@Nonnull ChannelUpdatePositionEvent event) { 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 onChannelUpdateTopic(@Nonnull ChannelUpdateTopicEvent event) {} public void onChannelUpdateType(@Nonnull ChannelUpdateTypeEvent event) {} public void onChannelUpdateUserLimit(@Nonnull ChannelUpdateUserLimitEvent event) {} 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 dc4df1238f..201b8488d4 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 @@ -86,6 +86,8 @@ public interface ChannelManager{@link #APPLIED_TAGS} *

  • {@link #PINNED}
  • *
  • {@link #REQUIRE_TAG}
  • + *
  • {@link #DEFAULT_REACTION}
  • * * * @param fields @@ -148,6 +151,7 @@ public interface ChannelManager{@link #APPLIED_TAGS} *
  • {@link #PINNED}
  • *
  • {@link #REQUIRE_TAG}
  • + *
  • {@link #DEFAULT_REACTION}
  • * * * @param fields 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 197545c5de..91723e79c4 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 @@ -21,11 +21,13 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; 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.middleman.StandardGuildChannelManager; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.List; /** @@ -116,4 +118,19 @@ public interface ForumChannelManager extends @Nonnull @CheckReturnValue ForumChannelManager setAvailableTags(@Nonnull List 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); } 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 79f2a294c7..31fd7a5965 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1292,6 +1292,7 @@ public ForumChannel createForumChannel(GuildImpl guild, DataObject json, long gu channel .setParentCategory(json.getLong("parent_id", 0)) .setFlags(json.getInt("flags", 0)) + .setDefaultReaction(json.optObject("default_reaction_emoji").orElse(null)) .setName(json.getString("name")) .setTopic(json.getString("topic", null)) .setPosition(json.getInt("position")) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index c723f136b4..79edfaa2a4 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -26,17 +26,21 @@ import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; 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.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.channel.middleman.AbstractGuildChannelImpl; import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IThreadContainerMixin; import net.dv8tion.jda.internal.entities.channel.mixin.attribute.IWebhookContainerMixin; 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; @@ -59,6 +63,7 @@ public class ForumChannelImpl extends AbstractGuildChannelImpl 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; @@ -161,6 +166,12 @@ public String getTopic() return topic; } + @Override + public EmojiUnion getDefaultReaction() + { + return (EmojiUnion) defaultReaction; + } + @Override public int getDefaultThreadSlowmode() { @@ -240,4 +251,15 @@ public ForumChannelImpl setFlags(int flags) this.flags = flags; return this; } + + public ForumChannelImpl 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; + } } 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 a825707ec5..ddaabce394 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -34,6 +34,7 @@ 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.GuildChannel; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.events.guild.override.PermissionOverrideCreateEvent; import net.dv8tion.jda.api.events.guild.override.PermissionOverrideDeleteEvent; @@ -178,6 +179,13 @@ protected Long handleInternally(DataObject content) case FORUM: { final String topic = content.getString("topic", null); + final EmojiUnion defaultReaction = content.optObject("default_reaction_emoji") + .map(json -> { + json.opt("emoji_id").ifPresent(id -> json.put("id", id)); + json.opt("emoji_name").ifPresent(n -> json.put("name", n)); + return EntityBuilder.createEmoji(json); + }) + .orElse(null); ForumChannelImpl forumChannel = (ForumChannelImpl) channel; content.optArray("available_tags").ifPresent(array -> handleTagsUpdate(forumChannel, array)); @@ -191,6 +199,7 @@ protected Long handleInternally(DataObject content) final int oldSlowmode = forumChannel.getSlowmode(); final int oldDefaultThreadSlowmode = forumChannel.getDefaultThreadSlowmode(); final int oldFlags = forumChannel.getRawFlags(); + final EmojiUnion oldDefaultReaction = forumChannel.getDefaultReaction(); if (!Objects.equals(oldName, name)) { @@ -257,6 +266,14 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, forumChannel, ChannelFlag.fromRaw(oldFlags), ChannelFlag.fromRaw(flags))); } + 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 NEWS: 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 a67b9c2655..199a5f23f8 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 @@ -33,6 +33,9 @@ import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion; +import net.dv8tion.jda.api.entities.emoji.CustomEmoji; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.managers.channel.ChannelManager; import net.dv8tion.jda.api.utils.data.DataArray; @@ -67,6 +70,7 @@ public class ChannelManagerImpl availableTags; protected List appliedTags; + protected Emoji defaultReactionEmoji; protected ChannelType type; protected String name; protected String parent; @@ -128,6 +132,8 @@ public M reset(long fields) this.availableTags = null; if ((fields & APPLIED_TAGS) == APPLIED_TAGS) this.appliedTags = null; + if ((fields & DEFAULT_REACTION) == DEFAULT_REACTION) + this.defaultReactionEmoji = null; if ((fields & PERMISSION) == PERMISSION) { withLock(lock, (lock) -> @@ -178,6 +184,7 @@ public M reset() this.region = null; this.availableTags = null; this.appliedTags = null; + this.defaultReactionEmoji = null; this.flags.clear(); this.flags.addAll(channel.getFlags()); withLock(lock, (lock) -> @@ -612,6 +619,15 @@ public M setAppliedTags(Collection tags) return (M) this; } + public M setDefaultReaction(Emoji emoji) + { + if (type != ChannelType.FORUM) + throw new IllegalStateException("Can only set default reaction on forum channels."); + this.defaultReactionEmoji = emoji; + set |= DEFAULT_REACTION; + return (M) this; + } + @Override protected RequestBody finalizeData() { @@ -650,6 +666,15 @@ protected RequestBody finalizeData() frame.put("applied_tags", DataArray.fromCollection(appliedTags)); if (shouldUpdate(PINNED | REQUIRE_TAG)) frame.put("flags", ChannelFlag.getRaw(flags)); + if (shouldUpdate(DEFAULT_REACTION)) + { + if (defaultReactionEmoji instanceof CustomEmoji) + frame.put("default_reaction_emoji", DataObject.empty().put("emoji_id", ((CustomEmoji) defaultReactionEmoji).getId())); + else if (defaultReactionEmoji instanceof UnicodeEmoji) + frame.put("default_reaction_emoji", DataObject.empty().put("emoji_name", defaultReactionEmoji.getName())); + else + frame.put("default_reaction_emoji", null); + } withLock(lock, (lock) -> { From 47ac2c19e25fe0cb09d06c0fe35dd6559fdee8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 15:44:47 +0200 Subject: [PATCH 47/75] Add missing docs --- .../jda/api/entities/channel/ChannelField.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) 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 1e74adf0f2..2a32925803 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 @@ -18,6 +18,7 @@ import net.dv8tion.jda.api.audit.AuditLogKey; import net.dv8tion.jda.api.entities.Guild; +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.StandardGuildMessageChannel; @@ -81,7 +82,18 @@ public enum ChannelField */ POSITION("position", null), //Discord doesn't track Channel position changes in AuditLog. + /** + * The default slowmode applied to threads in a {@link net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer ThreadContainer}. + * + * @see IThreadContainer#getDefaultThreadSlowmode() + */ DEFAULT_THREAD_SLOWMODE("default_thread_slowmode", AuditLogKey.CHANNEL_DEFAULT_THREAD_SLOWMODE), + + /** + * The default reaction emoji used in a {@link ForumChannel}. + * + * @see ForumChannel#getDefaultReaction() + */ DEFAULT_REACTION_EMOJI("default_reaction_emoji", AuditLogKey.CHANNEL_DEFAULT_REACTION_EMOJI), //Text Specific From 935116cca1fca5d80b12f4b22477875978327ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 15:46:09 +0200 Subject: [PATCH 48/75] Fix some docs --- .../channel/attribute/IGuildChannelContainer.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 ea8094d38f..25de06aef9 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 @@ -983,7 +983,7 @@ default List getVoiceChannels() /** - * {@link net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} of {@link ForumChannel}. + * {@link SnowflakeCacheView SnowflakeCacheView} of {@link ForumChannel}. * *

    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}, @@ -992,13 +992,13 @@ default List getVoiceChannels() *
    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 net.dv8tion.jda.api.utils.cache.SnowflakeCacheView SnowflakeCacheView} + * @return {@link SnowflakeCacheView SnowflakeCacheView} */ @Nonnull SnowflakeCacheView getForumChannelCache(); /** - * Gets a list of all {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels} + * Gets a list of all {@link ForumChannel ForumChannels} * 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. * @@ -1010,11 +1010,11 @@ default List getVoiceChannels() * 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 ThreadChannel ThreadChannels}. + * The name used to filter the returned {@link ForumChannel ForumChannels}. * @param ignoreCase * Determines if the comparison ignores case when comparing. True - case insensitive. * - * @return Possibly-empty immutable list of all ThreadChannel names that match the provided name. + * @return Possibly-empty immutable list of all ForumChannel names that match the provided name. */ @Nonnull default List getForumChannelsByName(@Nonnull String name, boolean ignoreCase) From 2f6b4e4d3a9c113c78f94c110e2e3c7309275653 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 15:48:36 +0200 Subject: [PATCH 49/75] Remove todo and update exception message --- .../jda/api/entities/channel/concrete/ThreadChannel.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java index 3d678c4406..6026e12fef 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java @@ -176,7 +176,7 @@ default GuildMessageChannelUnion getParentMessageChannel() if (getParentChannel() instanceof GuildMessageChannel) return (GuildMessageChannelUnion) getParentChannel(); - throw new UnsupportedOperationException("Parent of this thread is not a MessageChannel. Parent is type: " + getParentChannel().getType().getId()); + throw new UnsupportedOperationException("Parent of this thread is not a MessageChannel. Parent: " + getParentChannel()); } /** @@ -964,7 +964,6 @@ default void formatTo(Formatter formatter, int flags, int width, int precision) */ enum AutoArchiveDuration { - //TODO: I dislike this naming scheme. Need to come up with something better. TIME_1_HOUR(60), TIME_24_HOURS(1440), TIME_3_DAYS(4320), From 854a75924d6f0dd798b9a87be7d2526a7c7ad5de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 15:49:53 +0200 Subject: [PATCH 50/75] Add missing docs to BaseForumTag --- .../jda/api/entities/channel/forums/BaseForumTag.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/forums/BaseForumTag.java b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/BaseForumTag.java index 96d01665d6..13c6d48fc6 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/forums/BaseForumTag.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/BaseForumTag.java @@ -25,6 +25,14 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +/** + * Information describing a forum tag. + *
    This is an abstraction used to simplify managing tags. + * + * @see ForumTag + * @see ForumTagData + * @see ForumTagSnowflake + */ public interface BaseForumTag extends SerializableData { /** From f324cb1e9ff6d154be0e8f9fc3cd2aaa918cc025 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 15:50:15 +0200 Subject: [PATCH 51/75] Fix annotation --- .../dv8tion/jda/api/entities/channel/forums/ForumTagData.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java index 78d20a28f1..d2fd24efd2 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/forums/ForumTagData.java @@ -21,7 +21,6 @@ import net.dv8tion.jda.api.managers.channel.concrete.ForumChannelManager; import net.dv8tion.jda.api.utils.data.DataObject; import net.dv8tion.jda.internal.utils.Checks; -import org.jetbrains.annotations.NotNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -150,7 +149,7 @@ public EmojiUnion getEmoji() return (EmojiUnion) emoji; } - @NotNull + @Nonnull @Override public DataObject toData() { From 30edf9656ed85ef6ca9ece56f43cfb0c0b95ae18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 15:52:31 +0200 Subject: [PATCH 52/75] Use FluentRestAction interface --- .../AbstractThreadCreateAction.java | 3 ++- .../restaction/ForumPostActionImpl.java | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java index e558ae6d24..64ecc80af0 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.requests.FluentRestAction; import net.dv8tion.jda.api.requests.RestAction; import javax.annotation.CheckReturnValue; @@ -35,7 +36,7 @@ * @param * The common return type of setters, allowing for fluid interface design */ -public interface AbstractThreadCreateAction> extends RestAction +public interface AbstractThreadCreateAction> extends FluentRestAction { /** * The guild to create this {@link GuildChannel} in 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 5bc199e976..7ba4329fdb 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 @@ -41,6 +41,7 @@ import javax.annotation.Nonnull; import java.util.Collection; +import java.util.function.BooleanSupplier; public class ForumPostActionImpl extends RestActionImpl implements ForumPostAction, MessageCreateBuilderMixin { @@ -58,6 +59,27 @@ public ForumPostActionImpl(ForumChannel channel, String name, MessageCreateBuild setName(name); } + @Nonnull + @Override + public ForumPostAction setCheck(BooleanSupplier checks) + { + return (ForumPostAction) super.setCheck(checks); + } + + @Nonnull + @Override + public ForumPostAction addCheck(@Nonnull BooleanSupplier checks) + { + return (ForumPostAction) super.addCheck(checks); + } + + @Nonnull + @Override + public ForumPostAction deadline(long timestamp) + { + return (ForumPostAction) super.deadline(timestamp); + } + @Nonnull @Override public Guild getGuild() From 4ea02aa31f6b2512c6b1ccb9eb69ff148d6efe9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 16:14:42 +0200 Subject: [PATCH 53/75] Make ChannelUpdateAppliedTagsEvent cache independent --- .../update/ChannelUpdateAppliedTagsEvent.java | 61 ++++++++++++++++--- .../channel/concrete/ThreadChannelImpl.java | 7 ++- .../internal/handle/ThreadUpdateHandler.java | 21 +++---- 3 files changed, 66 insertions(+), 23 deletions(-) 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 9cc255279f..7fbaaa5a0a 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 @@ -20,57 +20,100 @@ import net.dv8tion.jda.api.entities.channel.ChannelField; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.forums.ForumTag; +import net.dv8tion.jda.api.utils.cache.SortedSnowflakeCacheView; +import net.dv8tion.jda.internal.utils.Helpers; import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** * Indicates that the tags applied to a {@link ThreadChannel} forum post have been updated. */ -public class ChannelUpdateAppliedTagsEvent extends GenericChannelUpdateEvent> +public class ChannelUpdateAppliedTagsEvent extends GenericChannelUpdateEvent> { - public ChannelUpdateAppliedTagsEvent(@Nonnull JDA api, long responseNumber, @Nonnull ThreadChannel channel, @Nonnull List oldValue) + public ChannelUpdateAppliedTagsEvent(@Nonnull JDA api, long responseNumber, @Nonnull ThreadChannel channel, @Nonnull List oldValue, @Nonnull List newValue) { - super(api, responseNumber, channel, ChannelField.APPLIED_TAGS, oldValue, channel.getAppliedTags()); + super(api, responseNumber, channel, ChannelField.APPLIED_TAGS, oldValue, newValue); } /** * The newly added tags. * + *

    This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * * @return The tags that were added to the post */ @Nonnull public List getAddedTags() { - List newTags = new ArrayList<>(getNewValue()); - newTags.removeAll(getOldValue()); + List newTags = new ArrayList<>(getNewTags()); + newTags.removeAll(getOldTags()); return newTags; } /** * The removed tags. * + *

    This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * * @return The tags that were removed from the post */ @Nonnull public List getRemovedTags() { - List oldTags = new ArrayList<>(getOldValue()); - oldTags.removeAll(getNewValue()); + List oldTags = new ArrayList<>(getOldTags()); + oldTags.removeAll(getNewTags()); return oldTags; } + /** + * The new list of applied tags. + * + *

    This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * + * @return The updated list of applied tags + */ + @Nonnull + public List getNewTags() + { + SortedSnowflakeCacheView cache = getChannel().asThreadChannel().getParentChannel().asForumChannel().getAvailableTagCache(); + return getNewValue().stream() + .map(cache::getElementById) + .filter(Objects::nonNull) + .sorted() + .collect(Helpers.toUnmodifiableList()); + } + + /** + * The old list of applied tags. + * + *

    This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * + * @return The previous list of applied tags + */ + @Nonnull + public List getOldTags() + { + SortedSnowflakeCacheView cache = getChannel().asThreadChannel().getParentChannel().asForumChannel().getAvailableTagCache(); + return getOldValue().stream() + .map(cache::getElementById) + .filter(Objects::nonNull) + .sorted() + .collect(Helpers.toUnmodifiableList()); + } + @Nonnull @Override - public List getOldValue() + public List getOldValue() { return super.getOldValue(); } @Nonnull @Override - public List getNewValue() + public List getNewValue() { return super.getNewValue(); } 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 c4f508a3d7..468f937a24 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 @@ -64,8 +64,8 @@ public class ThreadChannelImpl extends AbstractGuildChannelImpl threadMembers = new CacheView.SimpleCacheView<>(ThreadMember.class, null); - private final TLongSet appliedTags = new TLongHashSet(ForumChannel.MAX_POST_TAGS); + private TLongSet appliedTags = new TLongHashSet(ForumChannel.MAX_POST_TAGS); private AutoArchiveDuration autoArchiveDuration; private IThreadContainerUnion parentChannel; private boolean locked; @@ -421,8 +421,9 @@ public ThreadChannelImpl setSlowmode(int slowmode) public ThreadChannelImpl setAppliedTags(LongStream tags) { - this.appliedTags.clear(); - tags.forEach(this.appliedTags::add); + TLongSet set = new TLongHashSet(ForumChannel.MAX_POST_TAGS); + tags.forEach(set::add); + this.appliedTags = set; return this; } 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 778e6690e4..da024291c8 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ThreadUpdateHandler.java @@ -17,12 +17,11 @@ package net.dv8tion.jda.internal.handle; import gnu.trove.set.TLongSet; -import gnu.trove.set.hash.TLongHashSet; import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; -import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.utils.cache.CacheFlag; +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.channel.concrete.ThreadChannelImpl; @@ -30,7 +29,7 @@ import java.util.List; import java.util.Objects; -import java.util.stream.IntStream; +import java.util.stream.LongStream; public class ThreadUpdateHandler extends SocketHandler { @@ -153,22 +152,22 @@ protected Long handleInternally(DataObject content) thread, oldInvitable, invitable)); } - if (api.isCacheFlagSet(CacheFlag.FORUM_TAGS)) + if (api.isCacheFlagSet(CacheFlag.FORUM_TAGS) && !content.isNull("applied_tags")) { final TLongSet oldTags = thread.getAppliedTagsSet(); - final TLongSet tags = content.optArray("applied_tags").map(array -> - new TLongHashSet(IntStream.range(0, array.length()) - .mapToLong(array::getUnsignedLong) - .toArray()) - ).orElseGet(TLongHashSet::new); + thread.setAppliedTags(content.getArray("applied_tags") + .stream(DataArray::getUnsignedLong) + .mapToLong(Long::longValue)); + final TLongSet tags = thread.getAppliedTagsSet(); if (!oldTags.equals(tags)) { - List oldTagList = thread.getAppliedTags(); + List oldTagList = LongStream.of(oldTags.toArray()).boxed().collect(Helpers.toUnmodifiableList()); + List newTagList = LongStream.of(tags.toArray()).boxed().collect(Helpers.toUnmodifiableList()); api.handleEvent( new ChannelUpdateAppliedTagsEvent( api, responseNumber, - thread, oldTagList)); + thread, oldTagList, newTagList)); } } From 35a60c7cf7c11dab19b0fe511517148e7669ce7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 16:21:36 +0200 Subject: [PATCH 54/75] Update ChannelManager#setTopic --- .../channel/middleman/StandardGuildMessageChannel.java | 7 +++++++ .../middleman/StandardGuildMessageChannelManager.java | 6 +++--- .../dv8tion/jda/api/requests/restaction/ChannelAction.java | 7 +++++-- .../jda/internal/managers/channel/ChannelManagerImpl.java | 6 +++--- .../internal/requests/restaction/ChannelActionImpl.java | 3 ++- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/StandardGuildMessageChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/StandardGuildMessageChannel.java index 9521f92df3..c0826c8d4c 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/StandardGuildMessageChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/middleman/StandardGuildMessageChannel.java @@ -20,6 +20,7 @@ import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel; 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.concrete.ForumChannel; 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.concrete.ThreadChannel; @@ -44,6 +45,12 @@ */ public interface StandardGuildMessageChannel extends StandardGuildChannel, GuildMessageChannel, IThreadContainer, IWebhookContainer, IAgeRestrictedChannel { + /** + * The maximum length a channel topic can be ({@value #MAX_TOPIC_LENGTH}) + *
    Forum channels have a higher limit, defined by {@link ForumChannel#MAX_FORUM_TOPIC_LENGTH} + */ + int MAX_TOPIC_LENGTH = 1024; + @Nonnull @Override StandardGuildMessageChannelManager getManager(); 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 94b792a86f..4c283e357a 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 @@ -45,14 +45,14 @@ public interface StandardGuildMessageChannelManagertopic of the selected {@link StandardGuildMessageChannel channel}. * - *

    A channel topic must not be more than {@code 1024} characters long! - * * @param topic * The new topic for the selected channel, * {@code null} or empty String to reset * * @throws IllegalArgumentException - * If the provided topic is greater than {@code 1024} in length + * 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. * * @return ChannelManager for chaining convenience */ 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 f2d869679c..8d9a6d682b 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 @@ -26,6 +26,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.Category; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.utils.MiscUtil; import net.dv8tion.jda.internal.utils.Checks; @@ -149,12 +150,14 @@ public interface ChannelAction extends AuditableRestActi * Sets the topic for the new TextChannel * * @param topic - * The topic for the new GuildChannel (max 1024 chars) + * The topic for the new GuildChannel * * @throws UnsupportedOperationException * If this ChannelAction is not for a TextChannel * @throws IllegalArgumentException - * If the provided topic is longer than 1024 chars + * 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. * * @return The current ChannelAction, for chaining convenience */ 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 199a5f23f8..f8c25df884 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 @@ -32,6 +32,7 @@ import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag; import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.entities.channel.unions.IThreadContainerUnion; import net.dv8tion.jda.api.entities.emoji.CustomEmoji; import net.dv8tion.jda.api.entities.emoji.Emoji; @@ -449,14 +450,13 @@ public M setPosition(int position) @CheckReturnValue public M setTopic(String topic) { - if (TOPIC_SUPPORTED.contains(type)) - throw new IllegalStateException("Can only set topic on text, forum, and news channels"); + checkTypes(TOPIC_SUPPORTED, "topic"); if (topic != null) { if (type == ChannelType.FORUM) Checks.notLonger(topic, ForumChannel.MAX_FORUM_TOPIC_LENGTH, "Topic"); else - Checks.notLonger(topic, 1024, "Topic"); + Checks.notLonger(topic, StandardGuildMessageChannel.MAX_TOPIC_LENGTH, "Topic"); } this.topic = topic; set |= TOPIC; 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 bb0722904e..8b5dafb426 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 @@ -27,6 +27,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; +import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.requests.Request; import net.dv8tion.jda.api.requests.Response; @@ -166,7 +167,7 @@ public ChannelActionImpl setTopic(String topic) if (type == ChannelType.FORUM) Checks.notLonger(topic, ForumChannel.MAX_FORUM_TOPIC_LENGTH, "Topic"); else - Checks.notLonger(topic, 1024, "Topic"); + Checks.notLonger(topic, StandardGuildMessageChannel.MAX_TOPIC_LENGTH, "Topic"); } this.topic = topic; return this; From a3a4ddd1d3f441ee7e6b380feb21a8be25d2983a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 16:23:55 +0200 Subject: [PATCH 55/75] Update exception message for setAppliedTags --- .../jda/internal/managers/channel/ChannelManagerImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 f8c25df884..deb7ddd90a 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 @@ -605,7 +605,7 @@ public M setAvailableTags(List tags) public M setAppliedTags(Collection tags) { if (type != ChannelType.GUILD_PUBLIC_THREAD) - throw new IllegalStateException("Can only set applied tags on public thread channels."); + 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); ThreadChannel thread = (ThreadChannel) getChannel(); From 31ecfa0a7803f1cabbd80f9747c020e170b40dd7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 16:25:14 +0200 Subject: [PATCH 56/75] Move checkTypes into Checks class --- .../managers/channel/ChannelManagerImpl.java | 13 +++---------- .../requests/restaction/ChannelActionImpl.java | 14 +++----------- .../net/dv8tion/jda/internal/utils/Checks.java | 9 +++++++++ 3 files changed, 15 insertions(+), 21 deletions(-) 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 deb7ddd90a..d7b16337d6 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 @@ -450,7 +450,7 @@ public M setPosition(int position) @CheckReturnValue public M setTopic(String topic) { - checkTypes(TOPIC_SUPPORTED, "topic"); + Checks.checkSupportedChannelTypes(TOPIC_SUPPORTED, type, "topic"); if (topic != null) { if (type == ChannelType.FORUM) @@ -467,7 +467,7 @@ public M setTopic(String topic) @CheckReturnValue public M setNSFW(boolean nsfw) { - checkTypes(NSFW_SUPPORTED, "NSFW (age-restriction)"); + Checks.checkSupportedChannelTypes(NSFW_SUPPORTED, type, "NSFW (age-restriction)"); this.nsfw = nsfw; set |= NSFW; return (M) this; @@ -477,7 +477,7 @@ public M setNSFW(boolean nsfw) @CheckReturnValue public M setSlowmode(int slowmode) { - checkTypes(SLOWMODE_SUPPORTED, "slowmode"); + Checks.checkSupportedChannelTypes(SLOWMODE_SUPPORTED, type, "slowmode"); Checks.check(slowmode <= TextChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode per user must be between 0 and %d (seconds)!", TextChannel.MAX_SLOWMODE); this.slowmode = slowmode; set |= SLOWMODE; @@ -719,11 +719,4 @@ protected Collection getOverrides() }); return data.valueCollection(); } - - protected void checkTypes(EnumSet supported, String what) - { - if (!supported.contains(type)) - throw new IllegalArgumentException("Can only configure " + what + " for channels of types " + - supported.stream().map(ChannelType::name).collect(Collectors.joining(", "))); - } } 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 8b5dafb426..7eac5ae6e5 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 @@ -46,7 +46,6 @@ import java.util.EnumSet; import java.util.concurrent.TimeUnit; import java.util.function.BooleanSupplier; -import java.util.stream.Collectors; public class ChannelActionImpl extends AuditableRestActionImpl implements ChannelAction { @@ -161,7 +160,7 @@ public ChannelActionImpl setPosition(Integer position) @CheckReturnValue public ChannelActionImpl setTopic(String topic) { - checkTypes(TOPIC_SUPPORTED, "Topic"); + Checks.checkSupportedChannelTypes(TOPIC_SUPPORTED, type, "Topic"); if (topic != null) { if (type == ChannelType.FORUM) @@ -178,7 +177,7 @@ public ChannelActionImpl setTopic(String topic) @CheckReturnValue public ChannelActionImpl setNSFW(boolean nsfw) { - checkTypes(NSFW_SUPPORTED, "NSFW (age-restricted)"); + Checks.checkSupportedChannelTypes(NSFW_SUPPORTED, type, "NSFW (age-restricted)"); this.nsfw = nsfw; return this; } @@ -188,7 +187,7 @@ public ChannelActionImpl setNSFW(boolean nsfw) @CheckReturnValue public ChannelActionImpl setSlowmode(int slowmode) { - checkTypes(SLOWMODE_SUPPORTED, "Slowmode"); + Checks.checkSupportedChannelTypes(SLOWMODE_SUPPORTED, type, "Slowmode"); Checks.check(slowmode <= TextChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode must be between 0 and %d (seconds)!", TextChannel.MAX_SLOWMODE); this.slowmode = slowmode; return this; @@ -400,11 +399,4 @@ protected void handleSuccess(Response response, Request request) } request.onSuccess(clazz.cast(channel)); } - - protected void checkTypes(EnumSet supported, String what) - { - if (!supported.contains(type)) - throw new IllegalArgumentException("Can only configure " + what + " for channels of types " + - supported.stream().map(ChannelType::name).collect(Collectors.joining(", "))); - } } diff --git a/src/main/java/net/dv8tion/jda/internal/utils/Checks.java b/src/main/java/net/dv8tion/jda/internal/utils/Checks.java index b1fb73d3e6..e20c2d3407 100644 --- a/src/main/java/net/dv8tion/jda/internal/utils/Checks.java +++ b/src/main/java/net/dv8tion/jda/internal/utils/Checks.java @@ -18,6 +18,7 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.IPermissionHolder; +import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.middleman.AudioChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.exceptions.MissingAccessException; @@ -286,4 +287,12 @@ public static void checkAccess(IPermissionHolder issuer, GuildChannel channel) throw new MissingAccessException(channel, Permission.VOICE_CONNECT); throw new MissingAccessException(channel, Permission.VIEW_CHANNEL); } + + // Type checks + + public static void checkSupportedChannelTypes(EnumSet supported, ChannelType type, String what) + { + Checks.check(supported.contains(type), "Can only configure %s for channels of types %s", what, + JDALogger.getLazyString(() -> supported.stream().map(ChannelType::name).collect(Collectors.joining(", ")))); + } } From be4b40ca3e29b908e426b0240ed07292b8bc8a74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 16:32:56 +0200 Subject: [PATCH 57/75] Rename create thread routes --- src/main/java/net/dv8tion/jda/internal/requests/Route.java | 4 ++-- .../jda/internal/requests/restaction/ForumPostActionImpl.java | 2 +- .../internal/requests/restaction/ThreadChannelActionImpl.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/internal/requests/Route.java b/src/main/java/net/dv8tion/jda/internal/requests/Route.java index 41a70939c7..f3e4013e72 100644 --- a/src/main/java/net/dv8tion/jda/internal/requests/Route.java +++ b/src/main/java/net/dv8tion/jda/internal/requests/Route.java @@ -232,8 +232,8 @@ public static class Channels public static final Route GET_PERM_OVERRIDE = new Route(GET, "channels/{channel_id}/permissions/{permoverride_id}"); public static final Route FOLLOW_CHANNEL = new Route(POST, "channels/{channel_id}/followers"); - public static final Route CREATE_THREAD_WITH_MESSAGE = new Route(POST, "channels/{channel_id}/messages/{message_id}/threads"); - public static final Route CREATE_THREAD_WITHOUT_MESSAGE = new Route(POST, "channels/{channel_id}/threads"); + public static final Route CREATE_THREAD_FROM_MESSAGE = new Route(POST, "channels/{channel_id}/messages/{message_id}/threads"); + public static final Route CREATE_THREAD = new Route(POST, "channels/{channel_id}/threads"); public static final Route JOIN_THREAD = new Route(PUT, "channels/{channel_id}/thread-members/@me"); public static final Route ADD_THREAD_MEMBER = new Route(PUT, "channels/{channel_id}/thread-members/{user_id}"); public static final Route LEAVE_THREAD = new Route(DELETE, "channels/{channel_id}/thread-members/@me"); 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 7ba4329fdb..3c1ed42c1f 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 @@ -53,7 +53,7 @@ public class ForumPostActionImpl extends RestActionImpl implements Fo public ForumPostActionImpl(ForumChannel channel, String name, MessageCreateBuilder builder) { - super(channel.getJDA(), Route.Channels.CREATE_THREAD_WITHOUT_MESSAGE.compile(channel.getId())); + super(channel.getJDA(), Route.Channels.CREATE_THREAD.compile(channel.getId())); this.builder = builder; this.channel = channel; setName(name); diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java index ae66e44bcf..bd0fe2a5e0 100644 --- a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java @@ -45,7 +45,7 @@ public class ThreadChannelActionImpl extends AuditableRestActionImpl Date: Thu, 15 Sep 2022 16:35:26 +0200 Subject: [PATCH 58/75] Update src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateAppliedTagsEvent.java Co-authored-by: Austin Keener --- .../events/channel/update/ChannelUpdateAppliedTagsEvent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7fbaaa5a0a..9693010514 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 @@ -29,7 +29,7 @@ import java.util.Objects; /** - * Indicates that the tags applied to a {@link ThreadChannel} forum post have been updated. + * Indicates that the tags applied to a {@link ThreadChannel forum post} have been updated. */ public class ChannelUpdateAppliedTagsEvent extends GenericChannelUpdateEvent> { From 1f9c5777f5eb5ba966d20c8bb93c52a1c1a7a00e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Thu, 15 Sep 2022 16:35:44 +0200 Subject: [PATCH 59/75] Update src/main/java/net/dv8tion/jda/internal/handle/MessageDeleteHandler.java Co-authored-by: Austin Keener --- .../net/dv8tion/jda/internal/handle/MessageDeleteHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/dv8tion/jda/internal/handle/MessageDeleteHandler.java b/src/main/java/net/dv8tion/jda/internal/handle/MessageDeleteHandler.java index 42bf892b9d..663e120366 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/MessageDeleteHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/MessageDeleteHandler.java @@ -78,7 +78,7 @@ protected Long handleInternally(DataObject content) ThreadChannelImpl gThread = (ThreadChannelImpl) channel; gThread.setMessageCount(Math.max(0, gThread.getMessageCount() - 1)); - // Not decrementing total since that should include deleted as well + // Not decrementing totalMessageCount since that should include deleted as well } getJDA().handleEvent(new MessageDeleteEvent(getJDA(), responseNumber, messageId, channel)); From 9c777e432e825f3f0d173ac11088221769aae49b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Fri, 16 Sep 2022 19:55:28 +0200 Subject: [PATCH 60/75] Add forum tag events --- .../channel/forum/ForumTagAddEvent.java | 31 ++++++++ .../channel/forum/ForumTagRemoveEvent.java | 31 ++++++++ .../channel/forum/GenericForumTagEvent.java | 54 ++++++++++++++ .../update/ForumTagUpdateEmojiEvent.java | 57 +++++++++++++++ .../update/ForumTagUpdateModeratedEvent.java | 48 ++++++++++++ .../forum/update/ForumTagUpdateNameEvent.java | 60 +++++++++++++++ .../update/GenericForumTagUpdateEvent.java | 73 +++++++++++++++++++ .../jda/api/hooks/ListenerAdapter.java | 16 ++++ .../AbstractThreadCreateAction.java | 6 +- .../internal/handle/ChannelUpdateHandler.java | 23 +++++- 10 files changed, 392 insertions(+), 7 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagAddEvent.java create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagRemoveEvent.java create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/forum/GenericForumTagEvent.java create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateEmojiEvent.java create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.java create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/forum/update/GenericForumTagUpdateEvent.java 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 new file mode 100644 index 0000000000..38ee195a1d --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagAddEvent.java @@ -0,0 +1,31 @@ +/* + * 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.forum; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.Channel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; + +import javax.annotation.Nonnull; + +public class ForumTagAddEvent extends GenericForumTagEvent +{ + public ForumTagAddEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel 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 new file mode 100644 index 0000000000..c037230271 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/ForumTagRemoveEvent.java @@ -0,0 +1,31 @@ +/* + * 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.forum; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.Channel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; + +import javax.annotation.Nonnull; + +public class ForumTagRemoveEvent extends GenericForumTagEvent +{ + public ForumTagRemoveEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel 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 new file mode 100644 index 0000000000..3a5aa5fa2a --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/GenericForumTagEvent.java @@ -0,0 +1,54 @@ +/* + * 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.forum; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; +import net.dv8tion.jda.api.events.Event; + +import javax.annotation.Nonnull; + +public abstract class GenericForumTagEvent extends Event +{ + protected final ForumChannel channel; + protected final ForumTag tag; + + public GenericForumTagEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag) + { + super(api, responseNumber); + this.channel = channel; + this.tag = tag; + } + + @Nonnull + public ForumChannel getChannel() + { + return channel; + } + + /** + * The {@link ForumTag} that was affected by this event + * + * @return The {@link ForumTag} + */ + @Nonnull + public ForumTag getTag() + { + return tag; + } +} 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 new file mode 100644 index 0000000000..8e3e00f2f6 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateEmojiEvent.java @@ -0,0 +1,57 @@ +/* + * 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.forum.update; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; +import net.dv8tion.jda.api.entities.emoji.EmojiUnion; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class ForumTagUpdateEmojiEvent extends GenericForumTagUpdateEvent +{ + public static final String IDENTIFIER = "emoji"; + + public ForumTagUpdateEmojiEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag, @Nullable EmojiUnion previous) + { + super(api, responseNumber, channel, tag, previous, tag.getEmoji(), IDENTIFIER); + } + + /** + * The old {@link EmojiUnion} for the {@link ForumTag} + * + * @return The old {@link EmojiUnion} + */ + @Nullable + public EmojiUnion getOldEmoji() + { + return getOldValue(); + } + + /** + * The new {@link EmojiUnion} for the {@link ForumTag} + * + * @return The new {@link EmojiUnion} + */ + @Nullable + public EmojiUnion getNewEmoji() + { + return getNewValue(); + } +} diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.java new file mode 100644 index 0000000000..7cfe084920 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.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.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.forums.ForumTag; + +import javax.annotation.Nonnull; + +@SuppressWarnings("ConstantConditions") +public class ForumTagUpdateModeratedEvent extends GenericForumTagUpdateEvent +{ + public static final String IDENTIFIER = "moderated"; + + public ForumTagUpdateModeratedEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag, boolean previous) + { + super(api, responseNumber, channel, tag, previous, tag.isModerated(), IDENTIFIER); + } + + @Nonnull + @Override + public Boolean getOldValue() + { + return super.getOldValue(); + } + + @Nonnull + @Override + public Boolean getNewValue() + { + return super.getNewValue(); + } +} diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java new file mode 100644 index 0000000000..d147c2e84d --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java @@ -0,0 +1,60 @@ +/* + * 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.forum.update; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +import net.dv8tion.jda.api.entities.channel.forums.ForumTag; + +import javax.annotation.Nonnull; + +@SuppressWarnings("ConstantConditions") +public class ForumTagUpdateNameEvent extends GenericForumTagUpdateEvent +{ + public static final String IDENTIFIER = "name"; + + public ForumTagUpdateNameEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag, @Nonnull String previous) + { + super(api, responseNumber, channel, tag, previous, tag.getName(), IDENTIFIER); + } + + @Nonnull + public String getOldName() + { + return getOldValue(); + } + + @Nonnull + public String getNewName() + { + return getNewValue(); + } + + @Nonnull + @Override + public String getOldValue() + { + return super.getOldValue(); + } + + @Nonnull + @Override + public String getNewValue() + { + return super.getNewValue(); + } +} 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 new file mode 100644 index 0000000000..261919634d --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/GenericForumTagUpdateEvent.java @@ -0,0 +1,73 @@ +/* + * 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.forum.update; + +import net.dv8tion.jda.api.JDA; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; +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; + +import javax.annotation.Nonnull; + +public abstract class GenericForumTagUpdateEvent extends GenericForumTagEvent implements UpdateEvent +{ + private final T previous; + private final T next; + private final String identifier; + + public GenericForumTagUpdateEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag, + T previous, T next, @Nonnull String identifier) + { + super(api, responseNumber, channel, tag); + this.previous = previous; + this.next = next; + this.identifier = identifier; + } + + @Nonnull + @Override + public ForumTag getEntity() + { + return getTag(); + } + + @Override + public T getOldValue() + { + return previous; + } + + @Override + public T getNewValue() + { + return next; + } + + @Nonnull + @Override + public String getPropertyIdentifier() + { + return identifier; + } + + @Override + public String toString() + { + return "ForumTagUpdate[" + getPropertyIdentifier() + "](" + getOldValue() + "->" + getNewValue() + ')'; + } +} 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 fe5787e9d6..3988f0d9c5 100644 --- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java +++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java @@ -19,6 +19,13 @@ import net.dv8tion.jda.api.events.channel.ChannelCreateEvent; import net.dv8tion.jda.api.events.channel.ChannelDeleteEvent; import net.dv8tion.jda.api.events.channel.GenericChannelEvent; +import net.dv8tion.jda.api.events.channel.forum.ForumTagAddEvent; +import net.dv8tion.jda.api.events.channel.forum.ForumTagRemoveEvent; +import net.dv8tion.jda.api.events.channel.forum.GenericForumTagEvent; +import net.dv8tion.jda.api.events.channel.forum.update.ForumTagUpdateEmojiEvent; +import net.dv8tion.jda.api.events.channel.forum.update.ForumTagUpdateModeratedEvent; +import net.dv8tion.jda.api.events.channel.forum.update.ForumTagUpdateNameEvent; +import net.dv8tion.jda.api.events.channel.forum.update.GenericForumTagUpdateEvent; import net.dv8tion.jda.api.events.channel.update.*; import net.dv8tion.jda.api.events.emoji.EmojiAddedEvent; import net.dv8tion.jda.api.events.emoji.EmojiRemovedEvent; @@ -200,6 +207,13 @@ public void onChannelUpdateLocked(@Nonnull ChannelUpdateLockedEvent event) {} public void onChannelUpdateInvitable(@Nonnull ChannelUpdateInvitableEvent event) {} public void onChannelUpdateAppliedTags(@Nonnull ChannelUpdateAppliedTagsEvent event) {} + //Forum Tag Events + public void onForumTagAdd(@Nonnull ForumTagAddEvent event) {} + public void onForumTagRemove(@Nonnull ForumTagRemoveEvent event) {} + public void onForumTagUpdateName(@Nonnull ForumTagUpdateNameEvent event) {} + public void onForumTagUpdateEmoji(@Nonnull ForumTagUpdateEmojiEvent event) {} + public void onForumTagUpdateModerated(@Nonnull ForumTagUpdateModeratedEvent event) {} + //Thread Events public void onThreadRevealed(@Nonnull ThreadRevealedEvent event) {} public void onThreadHidden(@Nonnull ThreadHiddenEvent event) {} @@ -348,6 +362,8 @@ public void onGenericEmojiUpdate(@Nonnull GenericEmojiUpdateEvent event) {} public void onGenericGuildSticker(@Nonnull GenericGuildStickerEvent event) {} public void onGenericGuildStickerUpdate(@Nonnull GenericGuildStickerUpdateEvent event) {} public void onGenericPermissionOverride(@Nonnull GenericPermissionOverrideEvent event) {} + public void onGenericForumTag(@Nonnull GenericForumTagEvent event) {} + public void onGenericForumTagUpdate(@Nonnull GenericForumTagUpdateEvent event) {} private static final MethodHandles.Lookup lookup = MethodHandles.lookup(); private static final ConcurrentMap, MethodHandle> methods = new ConcurrentHashMap<>(); diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java index 64ecc80af0..6530ec254c 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java @@ -39,7 +39,7 @@ public interface AbstractThreadCreateAction> extends FluentRestAction { /** - * The guild to create this {@link GuildChannel} in + * The guild to create this {@link GuildChannel} for. * * @return The guild */ @@ -47,7 +47,7 @@ public interface AbstractThreadCreateAction { ForumTag tag = cache.remove(id); + if (tag != null) + api.handleEvent(new ForumTagRemoveEvent(api, responseNumber, channel, tag)); return true; }); } From 7d09a1454c5fa604fcbc994f514a10f631649bbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Fri, 16 Sep 2022 19:59:35 +0200 Subject: [PATCH 61/75] Fix constructors --- .../jda/api/events/channel/forum/ForumTagAddEvent.java | 4 ++-- .../jda/api/events/channel/forum/ForumTagRemoveEvent.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 38ee195a1d..274abf2673 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.Channel; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import javax.annotation.Nonnull; public class ForumTagAddEvent extends GenericForumTagEvent { - public ForumTagAddEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nonnull ForumTag tag) + public ForumTagAddEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel 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 c037230271..1ac6185655 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.Channel; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import javax.annotation.Nonnull; public class ForumTagRemoveEvent extends GenericForumTagEvent { - public ForumTagRemoveEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nonnull ForumTag tag) + public ForumTagRemoveEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag tag) { super(api, responseNumber, channel, tag); } From f8c3cbc3cfd537fccf73362f3f61ff95718675d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 15:04:30 +0200 Subject: [PATCH 62/75] Introduce ISlowmodeChannel attribute interface --- .../dv8tion/jda/api/audit/AuditLogKey.java | 15 ++++- .../api/entities/channel/ChannelField.java | 13 +++-- .../channel/attribute/ISlowmodeChannel.java | 48 +++++++++++++++ .../channel/attribute/IThreadContainer.java | 2 +- .../channel/concrete/ForumChannel.java | 21 +------ .../channel/concrete/TextChannel.java | 22 +------ .../channel/concrete/ThreadChannel.java | 12 +--- .../attribute/ISlowmodeChannelManager.java | 58 +++++++++++++++++++ .../channel/concrete/ForumChannelManager.java | 31 +--------- .../channel/concrete/TextChannelManager.java | 29 +--------- .../concrete/ThreadChannelManager.java | 28 +-------- 11 files changed, 140 insertions(+), 139 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/api/entities/channel/attribute/ISlowmodeChannel.java create mode 100644 src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java 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 07f11cae87..9016e5a8d9 100644 --- a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java +++ b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java @@ -16,10 +16,14 @@ package net.dv8tion.jda.api.audit; +import net.dv8tion.jda.annotations.DeprecatedSince; +import net.dv8tion.jda.annotations.ForRemoval; +import net.dv8tion.jda.annotations.ReplaceWith; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.channel.Channel; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.attribute.ICategorizableChannel; +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.entities.channel.concrete.TextChannel; @@ -234,8 +238,7 @@ public enum AuditLogKey CHANNEL_TOPIC("topic"), /** - * Change of the {@link TextChannel#getSlowmode() TextChannel.getSlowmode()} value. - *
    Only for {@link ChannelType#TEXT ChannelType.TEXT} + * Change of the {@link ISlowmodeChannel#getSlowmode()} value. * *

    Expected type: Integer */ @@ -318,10 +321,16 @@ public enum AuditLogKey THREAD_NAME("name"), /** - * Change of the {@link ThreadChannel#getSlowmode() ThreadChannel.getSlowmode()} value. + * Change of the {@link ISlowmodeChannel#getSlowmode()} value. * *

    Expected type: Integer + * + * @deprecated Use {@link #CHANNEL_SLOWMODE} instead */ + @Deprecated + @ForRemoval + @DeprecatedSince("5.0.0") + @ReplaceWith("CHANNEL_SLOWMODE") THREAD_SLOWMODE("rate_limit_per_user"), /** 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 2a32925803..6908db41ab 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 @@ -18,6 +18,8 @@ import net.dv8tion.jda.api.audit.AuditLogKey; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.channel.attribute.IAgeRestrictedChannel; +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.middleman.AudioChannel; @@ -110,18 +112,19 @@ public enum ChannelField /** * The NSFW state of the channel. * - *

    Limited to {@link StandardGuildMessageChannel StandardGuildMessageChannels} (and implementations). + *

    Limited to {@link IAgeRestrictedChannel IAgeRestrictedChannels} (and implementations). * - * @see StandardGuildMessageChannel#isNSFW() + * @see IAgeRestrictedChannel#isNSFW() */ NSFW("nsfw", AuditLogKey.CHANNEL_NSFW), /** - * The state of slow mode in the channel. This defines the minimum time between message sends. + * The state of slow mode in the channel. + *
    This defines the minimum time between message sends. * - *

    Limited to {@link TextChannel Text Channels}. + *

    Limited to {@link ISlowmodeChannel ISlowmodeChannels} (and implementations). * - * @see TextChannel#getSlowmode() + * @see ISlowmodeChannel#getSlowmode() */ SLOWMODE("slowmode", AuditLogKey.CHANNEL_SLOWMODE), diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/ISlowmodeChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/ISlowmodeChannel.java new file mode 100644 index 0000000000..25d9248284 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/attribute/ISlowmodeChannel.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.api.entities.channel.attribute; + +import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; + +/** + * Channels which support slowmode. + */ +public interface ISlowmodeChannel extends GuildChannel +{ + /** + * The maximum duration of slowmode in seconds + */ + int MAX_SLOWMODE = 21600; + + /** + * The slowmode set for this channel. + *
    If slowmode is set, this returns an {@code int} between 1 and {@value #MAX_SLOWMODE}. + *
    Otherwise, if no slowmode is set, this returns {@code 0}. + * + *

    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. + * + *

    Special case
    + * {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels} use this to limit how many posts a user can create. + * The client refers to this as the post slowmode. + * + * @return The slowmode for this channel, between 1 and {@value #MAX_SLOWMODE}, or {@code 0} if no slowmode is set. + */ + int getSlowmode(); +} 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 55275378d2..98003a8a94 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 @@ -42,7 +42,7 @@ public interface IThreadContainer extends GuildChannel, IPermissionContainer { /** - * The default {@link ThreadChannel#getSlowmode() slowmode} for thread channels that is copied on thread creation. + * The default {@link ISlowmodeChannel#getSlowmode() slowmode} for thread channels that is copied on thread creation. *
    Users have to wait this amount of seconds before sending another message to the same thread. * * @return The default slowmode seconds for new threads, or {@code 0} if unset 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 e84b058e59..c5c3ecad97 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 @@ -22,6 +22,7 @@ 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.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; @@ -49,7 +50,7 @@ * @see Guild#createForumChannel(String, Category) * @see #createForumPost(String, MessageCreateData) */ -public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IWebhookContainer, IAgeRestrictedChannel +public interface ForumChannel extends StandardGuildChannel, IThreadContainer, IWebhookContainer, IAgeRestrictedChannel, ISlowmodeChannel { /** * The maximum length of a forum topic ({@value #MAX_FORUM_TOPIC_LENGTH}) @@ -91,24 +92,6 @@ default List getAvailableTags() return getAvailableTagCache().asList(); } - // TODO: Should this be in StandardGuildMessageChannel? - - /** - * The slowmode set for this ForumChannel. - *
    If slowmode is set this returns an {@code int} between 1 and {@link net.dv8tion.jda.api.entities.channel.concrete.TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}. - *
    If not set this returns {@code 0}. - * - *

    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. - * - * @return The slowmode for this ForumChannel, between 1 and {@link net.dv8tion.jda.api.entities.channel.concrete.TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}, or {@code 0} if no slowmode is set. - */ - int getSlowmode(); - - // TODO: Should this be in StandardGuildChannel? - /** * 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. diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/TextChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/TextChannel.java index 6cd02880f0..a821fa5515 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/TextChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/TextChannel.java @@ -17,6 +17,7 @@ import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.managers.channel.concrete.TextChannelManager; import net.dv8tion.jda.api.requests.restaction.ChannelAction; @@ -44,27 +45,8 @@ * @see JDA#getTextChannelsByName(String, boolean) * @see JDA#getTextChannelById(long) */ -public interface TextChannel extends StandardGuildMessageChannel +public interface TextChannel extends StandardGuildMessageChannel, ISlowmodeChannel { - /** - * The maximum duration of slowmode in seconds - */ - int MAX_SLOWMODE = 21600; - - /** - * The slowmode set for this TextChannel. - *
    If slowmode is set this returns an {@code int} between 1 and {@link TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}. - *
    If not set this returns {@code 0}. - * - *

    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. - * - * @return The slowmode for this TextChannel, between 1 and {@link TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}, or {@code 0} if no slowmode is set. - */ - int getSlowmode(); - @Nonnull @Override ChannelAction createCopy(@Nonnull Guild guild); diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java index 6026e12fef..7efb1a4b35 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelFlag; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.attribute.IMemberContainer; +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.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel; @@ -56,7 +57,7 @@ * @see Guild#getThreadChannelById(long) * @see Guild#getThreadChannelCache() */ -public interface ThreadChannel extends GuildMessageChannel, IMemberContainer +public interface ThreadChannel extends GuildMessageChannel, IMemberContainer, ISlowmodeChannel { //TODO fields that need to be researched: // - rate_limit_per_user @@ -574,15 +575,6 @@ default ThreadMember getOwnerThreadMember() @Nonnull OffsetDateTime getTimeCreated(); - /** - * The slowmode time of this thread. This determines the time each non-moderator must wait before sending another message. - * - * @return The amount of time in seconds a ThreadMember must wait between sending messages. - * - * @see net.dv8tion.jda.api.managers.channel.concrete.ThreadChannelManager#setSlowmode(int) - */ - int getSlowmode(); - /** * Joins this thread, adding the current account to the member list of this thread. * diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java new file mode 100644 index 0000000000..0cf1685726 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java @@ -0,0 +1,58 @@ +/* + * 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.managers.channel.ChannelManager; + +import javax.annotation.CheckReturnValue; +import javax.annotation.Nonnull; + +public interface ISlowmodeChannelManager> + extends ChannelManager +{ + /** + * Sets the slowmode of the selected channel. + *
    Provide {@code 0} to disable slowmode. + * + *

    A channel 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. + * + *

    Special case
    + * {@link net.dv8tion.jda.api.entities.channel.concrete.ForumChannel ForumChannels} use this to limit how many posts a user can create. + * The client refers to this as the post slowmode. + * + * + * @param slowmode + * The new slowmode + * + * @throws IllegalArgumentException + * If the provided slowmode is negative or greater than {@value ISlowmodeChannel#MAX_SLOWMODE} + * + * @return ChannelManager for chaining convenience + * + * @see net.dv8tion.jda.api.entities.channel.attribute.ISlowmodeChannel#getSlowmode() + */ + @Nonnull + @CheckReturnValue + M setSlowmode(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 91723e79c4..172942b289 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 @@ -16,13 +16,12 @@ package net.dv8tion.jda.api.managers.channel.concrete; -import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; 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.ISlowmodeChannelManager; import net.dv8tion.jda.api.managers.channel.middleman.StandardGuildChannelManager; import javax.annotation.CheckReturnValue; @@ -47,7 +46,8 @@ */ public interface ForumChannelManager extends StandardGuildChannelManager, - IAgeRestrictedChannelManager + IAgeRestrictedChannelManager, + ISlowmodeChannelManager { /** * Sets the tag requirement state of this {@link ForumChannel}. @@ -64,31 +64,6 @@ public interface ForumChannelManager extends @CheckReturnValue ForumChannelManager setRequireTag(boolean requireTag); - /** - * Sets the slowmode of the selected {@link ForumChannel}. - *
    Provide {@code 0} to reset the slowmode of the {@link ForumChannel} - * - *

    A channel slowmode must not be negative nor greater than {@link TextChannel#MAX_SLOWMODE TextChannel.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 slowmode for the selected {@link ForumChannel} - * - * @throws IllegalArgumentException - * If the provided slowmode is negative or greater than {@link TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE} - * - * @return ChannelManager for chaining convenience - * - * @see ForumChannel#getSlowmode() - */ - @Nonnull - @CheckReturnValue - ForumChannelManager setSlowmode(int slowmode); - /** * Sets the available tags of the selected {@link ForumChannel}. *
    Tags will be ordered based on the provided list order. diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/TextChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/TextChannelManager.java index 2ff48e0796..48205f16e2 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/TextChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/TextChannelManager.java @@ -16,10 +16,10 @@ package net.dv8tion.jda.api.managers.channel.concrete; -import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; +import net.dv8tion.jda.api.managers.channel.attribute.ISlowmodeChannelManager; import net.dv8tion.jda.api.managers.channel.middleman.StandardGuildMessageChannelManager; import javax.annotation.CheckReturnValue; @@ -40,33 +40,8 @@ * * @see net.dv8tion.jda.api.entities.channel.concrete.TextChannel#getManager() */ -public interface TextChannelManager extends StandardGuildMessageChannelManager +public interface TextChannelManager extends StandardGuildMessageChannelManager, ISlowmodeChannelManager { - /** - * Sets the slowmode of the selected {@link TextChannel TextChannel}. - *
    Provide {@code 0} to reset the slowmode of the {@link TextChannel TextChannel} - * - *

    A channel slowmode must not be negative nor greater than {@link TextChannel#MAX_SLOWMODE TextChannel.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. - * - * @see net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel#getSlowmode() - * - * @param slowmode - * The new slowmode for the selected {@link TextChannel TextChannel} - * - * @throws IllegalArgumentException - * If the provided slowmode is negative or greater than {@link TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE} - * - * @return ChannelManager for chaining convenience - */ - @Nonnull - @CheckReturnValue - TextChannelManager setSlowmode(int slowmode); - /** * Converts the selected channel to a different {@link ChannelType}. * diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java index 274bafdf31..a9f0932a16 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java @@ -20,6 +20,7 @@ import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; import net.dv8tion.jda.api.managers.channel.ChannelManager; +import net.dv8tion.jda.api.managers.channel.attribute.ISlowmodeChannelManager; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; @@ -43,33 +44,8 @@ * @see ThreadChannel#getManager() * @see ThreadChannel */ -public interface ThreadChannelManager extends ChannelManager +public interface ThreadChannelManager extends ChannelManager, ISlowmodeChannelManager { - /** - * Sets the slowmode of the selected {@link ThreadChannel}. - *
    Provide {@code 0} to reset the slowmode of the {@link ThreadChannel}. - * - *

    A channel slowmode must not be negative nor greater than {@link net.dv8tion.jda.api.entities.channel.concrete.TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}! - * - *

    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 new slowmode, in seconds, for the selected {@link ThreadChannel} - * - * @return this ThreadChannelManager for chaining convenience - * - * @throws IllegalArgumentException - * If the provided slowmode is negative or greater than {@link net.dv8tion.jda.api.entities.channel.concrete.TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE} - * - * @see ThreadChannel#getSlowmode() - */ - @Nonnull - @CheckReturnValue - ThreadChannelManager setSlowmode(int slowmode); - /** * Sets the inactive time before autoarchiving of this ThreadChannel. * From af699762906c62ecae7bad6ba60701a84211cc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 15:06:00 +0200 Subject: [PATCH 63/75] Add varargs version of setAppliedTags --- .../concrete/ThreadChannelManager.java | 29 +++++++++++++++++++ .../requests/restaction/ForumPostAction.java | 2 ++ 2 files changed, 31 insertions(+) diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java index a9f0932a16..31e10c9e31 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java @@ -21,9 +21,11 @@ import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; import net.dv8tion.jda.api.managers.channel.ChannelManager; import net.dv8tion.jda.api.managers.channel.attribute.ISlowmodeChannelManager; +import net.dv8tion.jda.internal.utils.Checks; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +import java.util.Arrays; import java.util.Collection; /** @@ -165,4 +167,31 @@ public interface ThreadChannelManager extends ChannelManager tags); + + /** + * Sets the applied {@link net.dv8tion.jda.api.entities.channel.forums.ForumTag ForumTags} for this forum post thread. + *
    This is only applicable to public threads inside forum channels. The tags must be from the forum channel. + * You can get the list of available tags with {@link ForumChannel#getAvailableTags()}. + * + * @param tags + * The new tags for the thread + * + * @throws IllegalStateException + * If the thread is not a forum post + * @throws IllegalArgumentException + *

      + *
    • If null is provided
    • + *
    • If more than {@value ForumChannel#MAX_POST_TAGS} tags are provided
    • + *
    • If at least one tag is {@link ForumChannel#isRequireTag() required} and none were provided
    • + *
    + * + * @return this ThreadChannelManager for chaining convenience. + */ + @Nonnull + @CheckReturnValue + default ThreadChannelManager setAppliedTags(@Nonnull ForumTagSnowflake... tags) + { + Checks.noneNull(tags, "Tags"); + return setAppliedTags(Arrays.asList(tags)); + } } 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 93983f9262..828c7d1c15 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 @@ -21,6 +21,7 @@ import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageCreateRequest; +import net.dv8tion.jda.internal.utils.Checks; import javax.annotation.Nonnull; import java.util.Arrays; @@ -81,6 +82,7 @@ public interface ForumPostAction extends AbstractThreadCreateAction Date: Sat, 17 Sep 2022 15:15:18 +0200 Subject: [PATCH 64/75] Add FluentAuditableRestAction --- .../AbstractThreadCreateAction.java | 3 +- .../restaction/AuditableRestAction.java | 10 ++- .../restaction/FluentAuditableRestAction.java | 64 +++++++++++++++++++ .../requests/restaction/ForumPostAction.java | 3 +- .../restaction/ThreadChannelAction.java | 17 +---- .../restaction/ThreadChannelActionImpl.java | 7 ++ 6 files changed, 83 insertions(+), 21 deletions(-) create mode 100644 src/main/java/net/dv8tion/jda/api/requests/restaction/FluentAuditableRestAction.java diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java index 6530ec254c..6c45d16fa1 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/AbstractThreadCreateAction.java @@ -21,7 +21,6 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; -import net.dv8tion.jda.api.requests.FluentRestAction; import net.dv8tion.jda.api.requests.RestAction; import javax.annotation.CheckReturnValue; @@ -36,7 +35,7 @@ * @param * The common return type of setters, allowing for fluid interface design */ -public interface AbstractThreadCreateAction> extends FluentRestAction +public interface AbstractThreadCreateAction> extends RestAction { /** * The guild to create this {@link GuildChannel} for. diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java index ba6d7b8b37..56861c48dc 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/AuditableRestAction.java @@ -80,12 +80,18 @@ public interface AuditableRestAction extends RestAction */ @Nonnull @Override - AuditableRestAction timeout(long timeout, @Nonnull TimeUnit unit); + default AuditableRestAction timeout(long timeout, @Nonnull TimeUnit unit) + { + return (AuditableRestAction) RestAction.super.timeout(timeout, unit); + } /** * {@inheritDoc} */ @Nonnull @Override - AuditableRestAction deadline(long timestamp); + default AuditableRestAction deadline(long timestamp) + { + return (AuditableRestAction) RestAction.super.deadline(timestamp); + } } diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/FluentAuditableRestAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/FluentAuditableRestAction.java new file mode 100644 index 0000000000..be209b8c9d --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/FluentAuditableRestAction.java @@ -0,0 +1,64 @@ +/* + * 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.requests.restaction; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; + +/** + * Interface used to mixin the customization parameters for {@link AuditableRestAction AuditableRestActions}. + *
    This simply fixes the return types to be the concrete implementation instead of the base interface. + * + * @param + * The result type of the AuditableRestAction + * @param + * The concrete AuditableRestAction type used for chaining (fluent interface) + */ +@SuppressWarnings("unchecked") +public interface FluentAuditableRestAction> extends AuditableRestAction +{ + @Nonnull + @Override + R reason(@Nullable String reason); + + @Nonnull + @Override + R setCheck(@Nullable BooleanSupplier checks); + + @Nonnull + @Override + default R addCheck(@Nonnull BooleanSupplier checks) + { + return (R) AuditableRestAction.super.addCheck(checks); + } + + @Nonnull + @Override + default R timeout(long timeout, @Nonnull TimeUnit unit) + { + return (R) AuditableRestAction.super.timeout(timeout, unit); + } + + @Nonnull + @Override + default R deadline(long timestamp) + { + return (R) AuditableRestAction.super.deadline(timestamp); + } +} 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 828c7d1c15..3ca5647bad 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 @@ -19,6 +19,7 @@ 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; +import net.dv8tion.jda.api.requests.FluentRestAction; import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageCreateRequest; import net.dv8tion.jda.internal.utils.Checks; @@ -36,7 +37,7 @@ * * @see net.dv8tion.jda.api.entities.channel.concrete.ForumChannel#createForumPost(String, MessageCreateData) */ -public interface ForumPostAction extends AbstractThreadCreateAction, MessageCreateRequest +public interface ForumPostAction extends AbstractThreadCreateAction, MessageCreateRequest, FluentRestAction { /** * The {@link ForumChannel} to create the post in diff --git a/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java b/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java index 80a2563ab5..8c35b00a95 100644 --- a/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java +++ b/src/main/java/net/dv8tion/jda/api/requests/restaction/ThreadChannelAction.java @@ -21,9 +21,6 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.concurrent.TimeUnit; -import java.util.function.BooleanSupplier; /** * Extension of {@link net.dv8tion.jda.api.requests.RestAction RestAction} specifically @@ -36,20 +33,8 @@ * @see net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer#createThreadChannel(String, long) * @see net.dv8tion.jda.api.entities.channel.attribute.IThreadContainer#createThreadChannel(String, String) */ -public interface ThreadChannelAction extends AbstractThreadCreateAction, AuditableRestAction +public interface ThreadChannelAction extends AbstractThreadCreateAction, FluentAuditableRestAction { - @Nonnull - @Override - ThreadChannelAction setCheck(@Nullable BooleanSupplier checks); - - @Nonnull - @Override - ThreadChannelAction timeout(long timeout, @Nonnull TimeUnit unit); - - @Nonnull - @Override - ThreadChannelAction deadline(long timestamp); - //TODO-v5: Docs @Nonnull @CheckReturnValue diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java index bd0fe2a5e0..bc88723d46 100644 --- a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java @@ -63,6 +63,13 @@ public ThreadChannelActionImpl(GuildChannel channel, String name, String parentM this.name = name; } + @Nonnull + @Override + public ThreadChannelActionImpl reason(String reason) + { + return (ThreadChannelActionImpl) super.reason(reason); + } + @Nonnull @Override public ThreadChannelActionImpl setCheck(BooleanSupplier checks) From bab29479bcb79cbed4e91a83ac07188d06bfef73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 15:18:15 +0200 Subject: [PATCH 65/75] Rename isRequireTag to isTagRequired --- .../jda/api/entities/channel/concrete/ForumChannel.java | 2 +- .../api/managers/channel/concrete/ForumChannelManager.java | 4 ++-- .../api/managers/channel/concrete/ThreadChannelManager.java | 4 ++-- .../dv8tion/jda/api/requests/restaction/ForumPostAction.java | 4 ++-- .../jda/internal/managers/channel/ChannelManagerImpl.java | 4 ++-- .../jda/internal/requests/restaction/ForumPostActionImpl.java | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) 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 c5c3ecad97..e50c6b5d98 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 @@ -106,7 +106,7 @@ default List getAvailableTags() * * @return True, if all new posts must have a tag. */ - default boolean isRequireTag() + default boolean isTagRequired() { return getFlags().contains(ChannelFlag.REQUIRE_TAG); } 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 172942b289..2ae1348633 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 @@ -58,11 +58,11 @@ public interface ForumChannelManager extends * * @return ChannelManager for chaining convenience. * - * @see ForumChannel#isRequireTag() + * @see ForumChannel#isTagRequired() */ @Nonnull @CheckReturnValue - ForumChannelManager setRequireTag(boolean requireTag); + ForumChannelManager setTagRequired(boolean requireTag); /** * Sets the available tags of the selected {@link ForumChannel}. diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java index 31e10c9e31..ed309ee3d3 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/concrete/ThreadChannelManager.java @@ -159,7 +159,7 @@ public interface ThreadChannelManager extends ChannelManager *
  • If null is provided
  • *
  • If more than {@value ForumChannel#MAX_POST_TAGS} tags are provided
  • - *
  • If at least one tag is {@link ForumChannel#isRequireTag() required} and none were provided
  • + *
  • If at least one tag is {@link ForumChannel#isTagRequired() required} and none were provided
  • * * * @return this ThreadChannelManager for chaining convenience. @@ -182,7 +182,7 @@ public interface ThreadChannelManager extends ChannelManager *
  • If null is provided
  • *
  • If more than {@value ForumChannel#MAX_POST_TAGS} tags are provided
  • - *
  • If at least one tag is {@link ForumChannel#isRequireTag() required} and none were provided
  • + *
  • If at least one tag is {@link ForumChannel#isTagRequired() required} and none were provided
  • * * * @return this ThreadChannelManager for chaining convenience. 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 3ca5647bad..e381812d36 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 @@ -56,7 +56,7 @@ public interface ForumPostAction extends AbstractThreadCreateAction tags) IThreadContainerUnion parentChannel = thread.getParentChannel(); if (!(parentChannel instanceof ForumChannel)) throw new IllegalStateException("Cannot apply tags to threads outside of forum channels."); - if (tags.isEmpty() && parentChannel.asForumChannel().isRequireTag()) + 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()"); this.appliedTags = tags.stream().map(ISnowflake::getId).collect(Collectors.toList()); set |= APPLIED_TAGS; 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 3c1ed42c1f..79f34ef327 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 @@ -100,7 +100,7 @@ public ForumPostAction setTags(@Nonnull Collection { Checks.noneNull(tags, "Tags"); Checks.check(tags.size() <= ForumChannel.MAX_POST_TAGS, "Provided more than %d tags.", ForumChannel.MAX_POST_TAGS); - Checks.check(!channel.isRequireTag() || !tags.isEmpty(), "This forum requires at least one tag per post! See ForumChannel#isRequireTag()"); + Checks.check(!channel.isTagRequired() || !tags.isEmpty(), "This forum requires at least one tag per post! See ForumChannel#isRequireTag()"); this.appliedTags.clear(); tags.forEach(t -> this.appliedTags.add(t.getIdLong())); return this; @@ -150,7 +150,7 @@ protected RequestBody finalizeData() json.put("auto_archive_duration", autoArchiveDuration.getMinutes()); if (!appliedTags.isEmpty()) json.put("applied_tags", appliedTags.toArray()); - else if (getChannel().isRequireTag()) + else if (getChannel().isTagRequired()) throw new IllegalStateException("Cannot create posts without a tag in this forum. Apply at least one tag!"); return getMultipartBody(message.getFiles(), json); } From e02dea159b8383d9f66a9d8360c181e5aa6991f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 15:27:13 +0200 Subject: [PATCH 66/75] Add more accessors for forum tags --- .../channel/concrete/ForumChannel.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) 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 e50c6b5d98..b242399ffb 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 @@ -83,15 +83,98 @@ 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. + * + * @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. From 50f23a0598c8aa2c9745adfdac8d144e31a2b836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 15:35:46 +0200 Subject: [PATCH 67/75] Add event docs --- .../api/events/channel/forum/ForumTagAddEvent.java | 8 ++++++++ .../events/channel/forum/ForumTagRemoveEvent.java | 8 ++++++++ .../events/channel/forum/GenericForumTagEvent.java | 14 ++++++++++++++ .../forum/update/ForumTagUpdateEmojiEvent.java | 10 ++++++++++ .../forum/update/ForumTagUpdateModeratedEvent.java | 10 ++++++++++ .../forum/update/ForumTagUpdateNameEvent.java | 10 ++++++++++ .../forum/update/GenericForumTagUpdateEvent.java | 11 +++++++++++ .../update/ChannelUpdateAppliedTagsEvent.java | 4 +++- .../update/ChannelUpdateDefaultReactionEvent.java | 8 ++++++++ .../ChannelUpdateDefaultThreadSlowmodeEvent.java | 8 ++++++++ .../channel/update/ChannelUpdateFlagsEvent.java | 7 +++++++ 11 files changed, 97 insertions(+), 1 deletion(-) 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 274abf2673..d171be2f0e 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 @@ -21,7 +21,15 @@ 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}. + * + *

    Requirements
    + * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * {@link net.dv8tion.jda.api.JDABuilder#createLight(String, Collection) JDABuilder.createLight(...)} disables this by default. + */ public class ForumTagAddEvent extends GenericForumTagEvent { public ForumTagAddEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag 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 1ac6185655..10f49db772 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 @@ -21,7 +21,15 @@ 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}. + * + *

    Requirements
    + * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * {@link net.dv8tion.jda.api.JDABuilder#createLight(String, Collection) JDABuilder.createLight(...)} disables this by default. + */ public class ForumTagRemoveEvent extends GenericForumTagEvent { public ForumTagRemoveEvent(@Nonnull JDA api, long responseNumber, @Nonnull ForumChannel channel, @Nonnull ForumTag 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 3a5aa5fa2a..64f3ff4cba 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 @@ -18,11 +18,20 @@ import net.dv8tion.jda.api.JDA; 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.events.Event; import javax.annotation.Nonnull; +import java.util.Collection; +/** + * Abstraction of all tags relating to {@link ForumTag} changes (excluding {@link ThreadChannel#getAppliedTags()}). + * + *

    Requirements
    + * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * {@link net.dv8tion.jda.api.JDABuilder#createLight(String, Collection) JDABuilder.createLight(...)} disables this by default. + */ public abstract class GenericForumTagEvent extends Event { protected final ForumChannel channel; @@ -35,6 +44,11 @@ public GenericForumTagEvent(@Nonnull JDA api, long responseNumber, @Nonnull Foru this.tag = tag; } + /** + * The {@link ForumChannel} which has been updated. + * + * @return The {@link ForumChannel} + */ @Nonnull public ForumChannel getChannel() { 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 8e3e00f2f6..26b77296cf 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 @@ -23,7 +23,17 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collection; +/** + * Indicates that the {@link ForumTag#getEmoji() emoji} of a {@link ForumTag} changed. + * + *

    Requirements
    + * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * {@link net.dv8tion.jda.api.JDABuilder#createLight(String, Collection) JDABuilder.createLight(...)} disables this by default. + * + *

    Identifier: {@code emoji} + */ public class ForumTagUpdateEmojiEvent extends GenericForumTagUpdateEvent { public static final String IDENTIFIER = "emoji"; diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.java index 7cfe084920..8bffa3fa0f 100644 --- a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.java +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateModeratedEvent.java @@ -21,7 +21,17 @@ import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import javax.annotation.Nonnull; +import java.util.Collection; +/** + * Indicates that the {@link ForumTag#isModerated() moderated status} of a {@link ForumTag} changed. + * + *

    Requirements
    + * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * {@link net.dv8tion.jda.api.JDABuilder#createLight(String, Collection) JDABuilder.createLight(...)} disables this by default. + * + *

    Identifier: {@code moderated} + */ @SuppressWarnings("ConstantConditions") public class ForumTagUpdateModeratedEvent extends GenericForumTagUpdateEvent { diff --git a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java index d147c2e84d..3ca2270282 100644 --- a/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java +++ b/src/main/java/net/dv8tion/jda/api/events/channel/forum/update/ForumTagUpdateNameEvent.java @@ -21,7 +21,17 @@ import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import javax.annotation.Nonnull; +import java.util.Collection; +/** + * Indicates that the {@link ForumTag#getName() name} of a {@link ForumTag} changed. + * + *

    Requirements
    + * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * {@link net.dv8tion.jda.api.JDABuilder#createLight(String, Collection) JDABuilder.createLight(...)} disables this by default. + * + *

    Identifier: {@code name} + */ @SuppressWarnings("ConstantConditions") public class ForumTagUpdateNameEvent extends GenericForumTagUpdateEvent { 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 261919634d..0c78285a28 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 @@ -23,7 +23,18 @@ import net.dv8tion.jda.api.events.channel.forum.GenericForumTagEvent; import javax.annotation.Nonnull; +import java.util.Collection; +/** + * Abstraction of all {@link ForumTag} updates. + * + *

    Requirements
    + * This requires {@link net.dv8tion.jda.api.utils.cache.CacheFlag#FORUM_TAGS CacheFlag.FORUM_TAGS} to be enabled. + * {@link net.dv8tion.jda.api.JDABuilder#createLight(String, Collection) JDABuilder.createLight(...)} disables this by default. + * + * @param + * The type of the updated field + */ public abstract class GenericForumTagUpdateEvent extends GenericForumTagEvent implements UpdateEvent { private final T previous; 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 9693010514..0d778fabc3 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 @@ -29,7 +29,9 @@ import java.util.Objects; /** - * Indicates that the tags applied to a {@link ThreadChannel forum post} have been updated. + * Indicates that the tags applied to a {@link ThreadChannel forum post thread} have been updated. + * + * @see ChannelField#APPLIED_TAGS */ public class ChannelUpdateAppliedTagsEvent extends GenericChannelUpdateEvent> { 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 f3a8e3dc1e..36ec2733d2 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 @@ -19,11 +19,19 @@ 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.concrete.ForumChannel; import net.dv8tion.jda.api.entities.emoji.EmojiUnion; import javax.annotation.Nonnull; import javax.annotation.Nullable; +/** + * Indicates that the {@link ForumChannel#getDefaultReaction() default reaction emoji} of a {@link ForumChannel} changed. + * + *

    Can be used to retrieve the old default reaction and the new one. + * + * @see ChannelField#DEFAULT_REACTION_EMOJI + */ public class ChannelUpdateDefaultReactionEvent extends GenericChannelUpdateEvent { public ChannelUpdateDefaultReactionEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nullable EmojiUnion oldValue, @Nullable EmojiUnion newValue) 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 0a97f14053..0d3a55b5a0 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 @@ -19,9 +19,17 @@ 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.IThreadContainer; import javax.annotation.Nonnull; +/** + * Indicates that the {@link IThreadContainer#getDefaultThreadSlowmode() default thread slowmode} of a {@link IThreadContainer thread container channel} changed. + * + *

    Can be used to retrieve the old default thread slowmode and the new one. + * + * @see ChannelField#DEFAULT_THREAD_SLOWMODE + */ public class ChannelUpdateDefaultThreadSlowmodeEvent extends GenericChannelUpdateEvent { public ChannelUpdateDefaultThreadSlowmodeEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, int oldValue, int newValue) 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 af908c07f0..9a61976482 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 @@ -24,6 +24,13 @@ import javax.annotation.Nonnull; import java.util.EnumSet; +/** + * Indicates that the {@link Channel#getFlags() flags} of a {@link Channel} changed. + * + *

    Can be used to retrieve the old flags and the new ones. + * + * @see ChannelField#FLAGS + */ public class ChannelUpdateFlagsEvent extends GenericChannelUpdateEvent> { public ChannelUpdateFlagsEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nonnull EnumSet oldValue, @Nonnull EnumSet newValue) From 8a90838a3b09a927c0ca238b38831ca7ccb1f6b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 15:44:58 +0200 Subject: [PATCH 68/75] Use constants more --- .../jda/api/managers/channel/ChannelManager.java | 5 +++-- .../jda/api/requests/restaction/ChannelAction.java | 13 +++++++------ .../managers/channel/ChannelManagerImpl.java | 7 ++++--- .../requests/restaction/ChannelActionImpl.java | 9 +++++---- .../restaction/ThreadChannelActionImpl.java | 3 ++- 5 files changed, 21 insertions(+), 16 deletions(-) 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 201b8488d4..4ddc5493ac 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 @@ -17,6 +17,7 @@ package net.dv8tion.jda.api.managers.channel; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.channel.Channel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.managers.Manager; @@ -188,7 +189,7 @@ default Guild getGuild() /** * Sets the name of the selected {@link GuildChannel GuildChannel}. * - *

    A channel name must not be {@code null} nor empty or more than 100 characters long! + *

    A channel name must not be {@code null} nor empty or more than {@value Channel#MAX_NAME_LENGTH} characters long! *
    TextChannel names may only be populated with alphanumeric (with underscore and dash). * *

    Example: {@code mod-only} or {@code generic_name} @@ -198,7 +199,7 @@ default Guild getGuild() * The new name for the selected {@link GuildChannel GuildChannel} * * @throws IllegalArgumentException - * If the provided name is {@code null} or not between 1-100 characters long + * If the provided name is {@code null} or not between 1-{@value Channel#MAX_NAME_LENGTH} characters long * * @return ChannelManager for chaining convenience */ 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 8d9a6d682b..528e42a57c 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 @@ -22,9 +22,10 @@ import net.dv8tion.jda.api.entities.IPermissionHolder; import net.dv8tion.jda.api.entities.Member; 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.ISlowmodeChannel; import net.dv8tion.jda.api.entities.channel.concrete.Category; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.utils.MiscUtil; @@ -90,10 +91,10 @@ public interface ChannelAction extends AuditableRestActi * Sets the name for the new GuildChannel * * @param name - * The not-null name for the new GuildChannel (1-100 chars long) + * The not-null name for the new GuildChannel (1-{@value Channel#MAX_NAME_LENGTH} characters long) * * @throws java.lang.IllegalArgumentException - * If the provided name is null or not between 1-100 chars long + * If the provided name is null or not between 1-{@value Channel#MAX_NAME_LENGTH} characters long * * @return The current ChannelAction, for chaining convenience */ @@ -182,7 +183,7 @@ public interface ChannelAction extends AuditableRestActi /** * Sets the slowmode value, which limits the amount of time that individual users must wait - * between sending messages in the new TextChannel. This is measured in seconds. + * between sending messages in the new channel. This is measured in seconds. * *

    Note: Bots are unaffected by this. *
    Having {@link net.dv8tion.jda.api.Permission#MESSAGE_MANAGE MESSAGE_MANAGE} or @@ -193,9 +194,9 @@ public interface ChannelAction extends AuditableRestActi * The number of seconds required to wait between sending messages in the channel. * * @throws UnsupportedOperationException - * If this ChannelAction is not for a TextChannel + * If this ChannelAction is not for a {@link ISlowmodeChannel} * @throws IllegalArgumentException - * If the {@code slowmode} is greater than {@link TextChannel#MAX_SLOWMODE TextChannel.MAX_SLOWMODE}, or less than 0 + * 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 */ 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 4035a5b4fb..89eaaf974a 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 @@ -22,12 +22,13 @@ import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.*; +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.IPermissionContainer; +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; -import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag; import net.dv8tion.jda.api.entities.channel.forums.ForumTagSnowflake; @@ -378,7 +379,7 @@ public M setName(@Nonnull String name) Checks.notBlank(name, "Name"); name = name.trim(); Checks.notEmpty(name, "Name"); - Checks.notLonger(name, 100, "Name"); + Checks.notLonger(name, Channel.MAX_NAME_LENGTH, "Name"); this.name = name; set |= NAME; return (M) this; @@ -478,7 +479,7 @@ public M setNSFW(boolean nsfw) public M setSlowmode(int slowmode) { Checks.checkSupportedChannelTypes(SLOWMODE_SUPPORTED, type, "slowmode"); - Checks.check(slowmode <= TextChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode per user must be between 0 and %d (seconds)!", TextChannel.MAX_SLOWMODE); + Checks.check(slowmode <= ISlowmodeChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode per user must be between 0 and %d (seconds)!", ISlowmodeChannel.MAX_SLOWMODE); this.slowmode = slowmode; set |= SLOWMODE; return (M) this; 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 7eac5ae6e5..59b1a6308f 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 @@ -22,10 +22,11 @@ import net.dv8tion.jda.api.Region; import net.dv8tion.jda.api.entities.Guild; 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.ISlowmodeChannel; 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.TextChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; @@ -127,7 +128,7 @@ public ChannelType getType() public ChannelActionImpl setName(@Nonnull String name) { Checks.notEmpty(name, "Name"); - Checks.notLonger(name, 100, "Name"); + Checks.notLonger(name, Channel.MAX_NAME_LENGTH, "Name"); this.name = name; return this; } @@ -188,7 +189,7 @@ public ChannelActionImpl setNSFW(boolean nsfw) public ChannelActionImpl setSlowmode(int slowmode) { Checks.checkSupportedChannelTypes(SLOWMODE_SUPPORTED, type, "Slowmode"); - Checks.check(slowmode <= TextChannel.MAX_SLOWMODE && slowmode >= 0, "Slowmode must be between 0 and %d (seconds)!", TextChannel.MAX_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; } @@ -345,7 +346,7 @@ protected RequestBody finalizeData() if (parent != null) object.put("parent_id", parent.getId()); - //Text only + //Text and Forum if (slowmode != null) object.put("rate_limit_per_user", slowmode); diff --git a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java index bc88723d46..a977717527 100644 --- a/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/requests/restaction/ThreadChannelActionImpl.java @@ -17,6 +17,7 @@ package net.dv8tion.jda.internal.requests.restaction; import net.dv8tion.jda.api.entities.Guild; +import net.dv8tion.jda.api.entities.channel.Channel; import net.dv8tion.jda.api.entities.channel.ChannelType; import net.dv8tion.jda.api.entities.channel.concrete.ThreadChannel; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; @@ -111,7 +112,7 @@ public ChannelType getType() public ThreadChannelActionImpl setName(@Nonnull String name) { Checks.notEmpty(name, "Name"); - Checks.notLonger(name, 100, "Name"); + Checks.notLonger(name, Channel.MAX_NAME_LENGTH, "Name"); this.name = name; return this; } From 0d0fb2bedb897c70055130dbf0f747a45d3066f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 15:47:33 +0200 Subject: [PATCH 69/75] Update the slowmode supported types and remove outdated todo comment --- .../jda/api/entities/channel/concrete/ThreadChannel.java | 4 ---- .../jda/internal/managers/channel/ChannelManagerImpl.java | 3 ++- .../jda/internal/requests/restaction/ChannelActionImpl.java | 3 ++- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java index 7efb1a4b35..4f3c712b9c 100644 --- a/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java +++ b/src/main/java/net/dv8tion/jda/api/entities/channel/concrete/ThreadChannel.java @@ -59,10 +59,6 @@ */ public interface ThreadChannel extends GuildMessageChannel, IMemberContainer, ISlowmodeChannel { - //TODO fields that need to be researched: - // - rate_limit_per_user - // - last_pin_timestamp (do we even use this for Text/News channels?) - /** * Whether this thread is public or not. * 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 89eaaf974a..6924f5abb2 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 @@ -62,7 +62,8 @@ @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.VOICE, ChannelType.FORUM); + private static final EnumSet SLOWMODE_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, + ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_NEWS_THREAD, ChannelType.GUILD_PRIVATE_THREAD); private static final EnumSet NSFW_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM, ChannelType.NEWS); private static final EnumSet TOPIC_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, ChannelType.NEWS); 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 59b1a6308f..e2b65e41e7 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 @@ -50,7 +50,8 @@ public class ChannelActionImpl extends AuditableRestActionImpl implements ChannelAction { - private static final EnumSet SLOWMODE_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM); + private static final EnumSet SLOWMODE_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, + ChannelType.GUILD_PUBLIC_THREAD, ChannelType.GUILD_NEWS_THREAD, ChannelType.GUILD_PRIVATE_THREAD); private static final EnumSet NSFW_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.VOICE, ChannelType.FORUM, ChannelType.NEWS); private static final EnumSet TOPIC_SUPPORTED = EnumSet.of(ChannelType.TEXT, ChannelType.FORUM, ChannelType.NEWS); From a22fb789e5ca1829ca712e8ade9ca85bceeafdb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Sat, 17 Sep 2022 16:16:09 +0200 Subject: [PATCH 70/75] Add missing setters to ChannelAction --- .../requests/restaction/ChannelAction.java | 56 ++++++++++++++----- .../internal/entities/ForumChannelImpl.java | 10 +++- .../restaction/ChannelActionImpl.java | 45 ++++++++++++++- 3 files changed, 94 insertions(+), 17 deletions(-) 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 528e42a57c..727d46b4e6 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 @@ -26,8 +26,12 @@ import net.dv8tion.jda.api.entities.channel.ChannelType; 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; +import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag; +import net.dv8tion.jda.api.entities.channel.forums.ForumTagData; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; +import net.dv8tion.jda.api.entities.emoji.Emoji; import net.dv8tion.jda.api.utils.MiscUtil; import net.dv8tion.jda.internal.utils.Checks; @@ -35,8 +39,7 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.Collection; -import java.util.concurrent.TimeUnit; -import java.util.function.BooleanSupplier; +import java.util.List; /** * Extension of {@link net.dv8tion.jda.api.requests.RestAction RestAction} specifically @@ -57,20 +60,8 @@ * @param * The type of channel to create */ -public interface ChannelAction extends AuditableRestAction +public interface ChannelAction extends FluentAuditableRestAction> { - @Nonnull - @Override - ChannelAction setCheck(@Nullable BooleanSupplier checks); - - @Nonnull - @Override - ChannelAction timeout(long timeout, @Nonnull TimeUnit unit); - - @Nonnull - @Override - ChannelAction deadline(long timestamp); - /** * The guild to create this {@link GuildChannel} in * @@ -204,6 +195,41 @@ public interface ChannelAction extends AuditableRestActi @CheckReturnValue ChannelAction setSlowmode(int slowmode); + /** + * Sets the default reaction emoji of the new {@link ForumChannel}. + *
    This does not support custom emoji from other guilds. + * + * @param emoji + * The new default reaction emoji, or null to unset. + * + * @return The current ChannelAction, for chaining convenience + * + * @see ForumChannel#getDefaultReaction() + */ + @Nonnull + @CheckReturnValue + ChannelAction setDefaultReaction(@Nullable Emoji emoji); + + /** + * Sets the available tags of the new {@link ForumChannel}. + *
    Tags will be ordered based on the provided list order. + * + *

    You can use {@link ForumTagData} to create new tags. + * + * @param tags + * The new available tags in the desired order. + * + * @throws IllegalArgumentException + * If the provided list is null or contains null elements + * + * @return The current ChannelAction, for chaining convenience + * + * @see ForumChannel#getAvailableTags() + */ + @Nonnull + @CheckReturnValue + ChannelAction setAvailableTags(@Nonnull List tags); + /** * Adds a new Role or Member {@link net.dv8tion.jda.api.entities.PermissionOverride PermissionOverride} * for the new GuildChannel. diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index 79edfaa2a4..7f32b41b63 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -28,6 +28,7 @@ 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.ForumChannelManager; import net.dv8tion.jda.api.requests.restaction.ChannelAction; import net.dv8tion.jda.api.requests.restaction.ForumPostAction; @@ -99,10 +100,17 @@ public List getMembers() public ChannelAction createCopy(@Nonnull Guild guild) { Checks.notNull(guild, "Guild"); - ChannelAction action = guild.createForumChannel(name).setNSFW(nsfw).setTopic(topic).setSlowmode(slowmode); + ChannelAction action = guild.createForumChannel(name) + .setNSFW(nsfw) + .setTopic(topic) + .setSlowmode(slowmode) + .setAvailableTags(getAvailableTags()); + 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()) 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 e2b65e41e7..3209db218f 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 @@ -27,8 +27,12 @@ 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; +import net.dv8tion.jda.api.entities.channel.forums.BaseForumTag; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.channel.middleman.StandardGuildMessageChannel; +import net.dv8tion.jda.api.entities.emoji.CustomEmoji; +import net.dv8tion.jda.api.entities.emoji.Emoji; +import net.dv8tion.jda.api.entities.emoji.UnicodeEmoji; import net.dv8tion.jda.api.exceptions.InsufficientPermissionException; import net.dv8tion.jda.api.requests.Request; import net.dv8tion.jda.api.requests.Response; @@ -40,11 +44,14 @@ import net.dv8tion.jda.internal.utils.Checks; import net.dv8tion.jda.internal.utils.PermissionUtil; import okhttp3.RequestBody; +import org.jetbrains.annotations.NotNull; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.ArrayList; import java.util.EnumSet; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.BooleanSupplier; @@ -65,6 +72,10 @@ public class ChannelActionImpl extends AuditableRestActi protected Category parent; protected Integer position; + // --forum only-- + protected List availableTags; + protected Emoji defaultReactionEmoji; + // --text/forum/voice only-- protected Integer slowmode = null; @@ -88,6 +99,13 @@ public ChannelActionImpl(Class clazz, String name, Guild guild, ChannelType t this.name = name; } + @Nonnull + @Override + public ChannelActionImpl reason(@Nullable String reason) + { + return (ChannelActionImpl) super.reason(reason); + } + @Nonnull @Override public ChannelActionImpl setCheck(BooleanSupplier checks) @@ -195,6 +213,23 @@ public ChannelActionImpl setSlowmode(int slowmode) return this; } + @Nonnull + @Override + public ChannelAction setDefaultReaction(@Nullable Emoji emoji) + { + this.defaultReactionEmoji = emoji; + return this; + } + + @NotNull + @Override + public ChannelAction setAvailableTags(@NotNull List tags) + { + Checks.noneNull(tags, "Tags"); + this.availableTags = new ArrayList<>(tags); + return this; + } + @Nonnull @Override @CheckReturnValue @@ -351,12 +386,20 @@ protected RequestBody finalizeData() if (slowmode != null) object.put("rate_limit_per_user", slowmode); - //Text and News + //Text, Forum, and News if (topic != null && !topic.isEmpty()) object.put("topic", topic); if (nsfw != null) object.put("nsfw", nsfw); + //Forum 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)); + //Voice only if (userlimit != null) object.put("user_limit", userlimit); From fce8eaad083751088ee8f2c0e3cb1f4d4466e9fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 19 Sep 2022 13:33:06 +0200 Subject: [PATCH 71/75] Add docs for ISlowmodeChannelManager --- .../channel/attribute/ISlowmodeChannelManager.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java index 0cf1685726..137d1553e3 100644 --- a/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java +++ b/src/main/java/net/dv8tion/jda/api/managers/channel/attribute/ISlowmodeChannelManager.java @@ -23,6 +23,14 @@ import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; +/** + * Manager which supports setting slowmode of a channel. + * + * @param + * The concrete {@link ISlowmodeChannel} type + * @param + * The concrete manager type + */ public interface ISlowmodeChannelManager> extends ChannelManager { From 99510477ac9e0c4a9d22bb9796bc2825cce15311 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 19 Sep 2022 13:36:21 +0200 Subject: [PATCH 72/75] Mention CacheFlag in getAvailableTagCache --- .../dv8tion/jda/api/entities/channel/concrete/ForumChannel.java | 2 ++ 1 file changed, 2 insertions(+) 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 b242399ffb..5d9cae8de6 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 @@ -87,6 +87,8 @@ default ChannelAction createCopy() * 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 From f7c97f9514589b5025c761ac06c4161a5f9673f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 19 Sep 2022 13:38:33 +0200 Subject: [PATCH 73/75] Add type checks to ChannelAction --- .../internal/requests/restaction/ChannelActionImpl.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) 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 3209db218f..0154b9c6d8 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 @@ -44,7 +44,6 @@ import net.dv8tion.jda.internal.utils.Checks; import net.dv8tion.jda.internal.utils.PermissionUtil; import okhttp3.RequestBody; -import org.jetbrains.annotations.NotNull; import javax.annotation.CheckReturnValue; import javax.annotation.Nonnull; @@ -217,14 +216,18 @@ public ChannelActionImpl setSlowmode(int slowmode) @Override public ChannelAction setDefaultReaction(@Nullable Emoji emoji) { + if (type != ChannelType.FORUM) + throw new UnsupportedOperationException("Can only set default reaction emoji on a ForumChannel!"); this.defaultReactionEmoji = emoji; return this; } - @NotNull + @Nonnull @Override - public ChannelAction setAvailableTags(@NotNull List tags) + public ChannelAction setAvailableTags(@Nonnull List tags) { + if (type != ChannelType.FORUM) + throw new UnsupportedOperationException("Can only set available tags on a ForumChannel!"); Checks.noneNull(tags, "Tags"); this.availableTags = new ArrayList<>(tags); return this; From 0aa796b6d076390ec4154d04c01e290470193f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 19 Sep 2022 20:01:27 +0200 Subject: [PATCH 74/75] Add default sort oder --- .../dv8tion/jda/api/audit/AuditLogKey.java | 8 +++ .../api/entities/channel/ChannelField.java | 9 ++- .../channel/concrete/ForumChannel.java | 65 +++++++++++++++++++ .../ChannelUpdateDefaultSortOrderEvent.java | 54 +++++++++++++++ .../jda/api/hooks/ListenerAdapter.java | 1 + .../jda/internal/entities/EntityBuilder.java | 1 + .../internal/entities/ForumChannelImpl.java | 19 ++++++ .../internal/handle/ChannelUpdateHandler.java | 7 ++ 8 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultSortOrderEvent.java 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 9016e5a8d9..c124412d32 100644 --- a/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java +++ b/src/main/java/net/dv8tion/jda/api/audit/AuditLogKey.java @@ -311,6 +311,14 @@ public enum AuditLogKey */ CHANNEL_AVAILABLE_TAGS("available_tags"), + /** + * The {@link ForumChannel#getDefaultSortOrder()} value. + *
    Only for {@link ChannelType#FORUM}. + * + *

    Expected type: Integer + */ + CHANNEL_DEFAULT_SORT_ORDER("default_sort_order"), + // THREADS /** 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 6908db41ab..f9e6ab031b 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 @@ -245,7 +245,14 @@ public enum ChannelField */ APPLIED_TAGS("applied_tags", AuditLogKey.THREAD_APPLIED_TAGS), - ; + /** + * 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); private final String fieldName; private final AuditLogKey auditLogKey; 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 5d9cae8de6..ff3e7f3656 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 @@ -204,6 +204,14 @@ default boolean isTagRequired() @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 post (thread) in this forum. * @@ -234,4 +242,61 @@ default boolean isTagRequired() @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/events/channel/update/ChannelUpdateDefaultSortOrderEvent.java b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultSortOrderEvent.java new file mode 100644 index 0000000000..35a0457dd7 --- /dev/null +++ b/src/main/java/net/dv8tion/jda/api/events/channel/update/ChannelUpdateDefaultSortOrderEvent.java @@ -0,0 +1,54 @@ +/* + * 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.Channel; +import net.dv8tion.jda.api.entities.channel.ChannelField; +import net.dv8tion.jda.api.entities.channel.concrete.ForumChannel; + +import javax.annotation.Nonnull; + +/** + * Indicates that the {@link ForumChannel#getDefaultSortOrder() default sort order} of a {@link ForumChannel} 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 ChannelUpdateDefaultSortOrderEvent(@Nonnull JDA api, long responseNumber, @Nonnull Channel channel, @Nonnull ForumChannel.SortOrder oldValue, @Nonnull ForumChannel.SortOrder newValue) + { + super(api, responseNumber, channel, ChannelField.DEFAULT_SORT_ORDER, oldValue, newValue); + } + + @Nonnull + @Override + public ForumChannel.SortOrder getOldValue() + { + return super.getOldValue(); + } + + @Nonnull + @Override + public ForumChannel.SortOrder getNewValue() + { + return super.getNewValue(); + } +} 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 3988f0d9c5..6d8c362982 100644 --- a/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java +++ b/src/main/java/net/dv8tion/jda/api/hooks/ListenerAdapter.java @@ -197,6 +197,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 onChannelUpdateTopic(@Nonnull ChannelUpdateTopicEvent event) {} public void onChannelUpdateType(@Nonnull ChannelUpdateTypeEvent event) {} public void onChannelUpdateUserLimit(@Nonnull ChannelUpdateUserLimitEvent event) {} 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 31fd7a5965..94a21e5841 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/EntityBuilder.java @@ -1293,6 +1293,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)) .setName(json.getString("name")) .setTopic(json.getString("topic", null)) .setPosition(json.getInt("position")) diff --git a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java index 7f32b41b63..5a6281d79e 100644 --- a/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java +++ b/src/main/java/net/dv8tion/jda/internal/entities/ForumChannelImpl.java @@ -71,6 +71,7 @@ public class ForumChannelImpl extends AbstractGuildChannelImpl private int position; private int flags; private int slowmode; + private int defaultSortOrder; protected int defaultThreadSlowmode; public ForumChannelImpl(long id, GuildImpl guild) @@ -186,6 +187,13 @@ public int getDefaultThreadSlowmode() return defaultThreadSlowmode; } + @Nonnull + @Override + public SortOrder getDefaultSortOrder() + { + return SortOrder.fromKey(defaultSortOrder); + } + @Nonnull @Override public ForumPostAction createForumPost(@Nonnull String name, @Nonnull MessageCreateData message) @@ -213,6 +221,11 @@ public int getRawFlags() return flags; } + public int getRawSortOrder() + { + return defaultSortOrder; + } + // Setters @Override @@ -270,4 +283,10 @@ else if (emoji != null && !emoji.isNull("emoji_name")) this.defaultReaction = null; return this; } + + public ForumChannelImpl setDefaultSortOrder(int defaultSortOrder) + { + this.defaultSortOrder = defaultSortOrder; + return this; + } } 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 726e2cd3c7..e75d485460 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -194,6 +194,7 @@ protected Long handleInternally(DataObject content) ForumChannelImpl forumChannel = (ForumChannelImpl) channel; content.optArray("available_tags").ifPresent(array -> handleTagsUpdate(forumChannel, array)); + int sortOrder = content.getInt("default_sort_order", ((ForumChannelImpl) channel).getRawSortOrder()); //If any properties changed, update the values and fire the proper events. final long oldParentId = forumChannel.getParentCategoryIdLong(); @@ -204,6 +205,7 @@ protected Long handleInternally(DataObject content) final int oldSlowmode = forumChannel.getSlowmode(); final int oldDefaultThreadSlowmode = forumChannel.getDefaultThreadSlowmode(); final int oldFlags = forumChannel.getRawFlags(); + final int oldSortOrder = forumChannel.getRawSortOrder(); final EmojiUnion oldDefaultReaction = forumChannel.getDefaultReaction(); if (!Objects.equals(oldName, name)) @@ -279,6 +281,11 @@ protected Long handleInternally(DataObject content) getJDA(), responseNumber, forumChannel, oldDefaultReaction, defaultReaction)); } + if (oldSortOrder != sortOrder) + { + forumChannel.setDefaultSortOrder(sortOrder); + + } break; } case NEWS: From 051ee545f1fd67d9970de3669cf1a75c9c85a72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Spie=C3=9F?= Date: Mon, 19 Sep 2022 20:03:56 +0200 Subject: [PATCH 75/75] Missed event --- .../jda/internal/handle/ChannelUpdateHandler.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) 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 e75d485460..ab9ce6520e 100644 --- a/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java +++ b/src/main/java/net/dv8tion/jda/internal/handle/ChannelUpdateHandler.java @@ -28,10 +28,7 @@ import net.dv8tion.jda.api.entities.channel.ChannelFlag; 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.Category; -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.concrete.ThreadChannel; +import net.dv8tion.jda.api.entities.channel.concrete.*; import net.dv8tion.jda.api.entities.channel.forums.ForumTag; import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel; import net.dv8tion.jda.api.entities.emoji.EmojiUnion; @@ -284,7 +281,10 @@ protected Long handleInternally(DataObject content) if (oldSortOrder != sortOrder) { forumChannel.setDefaultSortOrder(sortOrder); - + getJDA().handleEvent( + new ChannelUpdateDefaultSortOrderEvent( + getJDA(), responseNumber, + forumChannel, ForumChannel.SortOrder.fromKey(oldSortOrder), ForumChannel.SortOrder.fromKey(sortOrder))); } break; }