Skip to content

Commit

Permalink
[Feature] Add missing properties in forum & thread channels (#2469)
Browse files Browse the repository at this point in the history
* add `AppliedTags` property

* convert collections into immutable arrays

* remove "not supported" remark

* implement `ThreadChannelProperties`

* Add `DefaultSlowModeInterval` and `DefaultSlowModeInterval` properties to forum channels

* add `Moderated` property to `ForumTag``

* `ForumTag` inherits `ISnowflakeEntity`

* Fix `DiscordRestClient.GetChannelAsync` not getting forum channel

* a lot of changes

added:
- channel flags
- `ForumTagBuilder`
- imroved channel modification

* fixed a bug in forum tag emoji parsing

* inherit forum channel from `INesteeChannel`

* implement `INestedChannel` in forum channels

* Add `Flags` property to channels

* add iteraface for forum tags & add equality operators

* Add default reaction emoji property

* add support for modifing default reaction & some renaming

* add createForumChannelAsync to guild

* *fix resharper being a d... and moving code to next line*

* add a `ForumChannels` property

* Some fixes & add support for `default_sort_order`

* fix misleading comment

* fix #2502

* support creating post with applied tags

* fix xmldoc

* set category id on model update

* add limit checks for tag count
  • Loading branch information
Misha-133 committed Nov 7, 2022
1 parent 6712ef4 commit 01ae904
Show file tree
Hide file tree
Showing 45 changed files with 1,132 additions and 119 deletions.
22 changes: 22 additions & 0 deletions src/Discord.Net.Core/Entities/Channels/ChannelFlags.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace Discord;

/// <summary>
/// Represents public flags for a channel.
/// </summary>
public enum ChannelFlags
{
/// <summary>
/// Default value for flags, when none are given to a channel.
/// </summary>
None = 0,

/// <summary>
/// Flag given to a thread channel pinned on top of parent forum channel.
/// </summary>
Pinned = 1 << 1,

/// <summary>
/// Flag given to a forum channel that requires people to select tags when posting.
/// </summary>
RequireTag = 1 << 4
}
60 changes: 60 additions & 0 deletions src/Discord.Net.Core/Entities/Channels/ForumChannelProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;

namespace Discord;

public class ForumChannelProperties : TextChannelProperties
{

/// <summary>
/// Gets or sets the topic of the channel.
/// </summary>
/// <remarks>
/// Not available in forum channels.
/// </remarks>
public new Optional<int> SlowModeInterval { get; }

/// <summary>
/// Gets or sets rate limit on creating posts in this forum channel.
/// </summary>
/// <remarks>
/// Setting this value to anything above zero will require each user to wait X seconds before
/// creating another thread; setting this value to <c>0</c> will disable rate limits for this channel.
/// <note>
/// Users with <see cref="Discord.ChannelPermission.ManageMessages"/> or
/// <see cref="ChannelPermission.ManageChannels"/> will be exempt from rate limits.
/// </note>
/// </remarks>
/// <exception cref="ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception>
public Optional<int> ThreadCreationInterval { get; set; }


/// <summary>
/// Gets or sets the default slow-mode for threads in this channel.
/// </summary>
/// <remarks>
/// Setting this value to anything above zero will require each user to wait X seconds before
/// sending another message; setting this value to <c>0</c> will disable slow-mode for child threads.
/// <note>
/// Users with <see cref="Discord.ChannelPermission.ManageMessages"/> or
/// <see cref="ChannelPermission.ManageChannels"/> will be exempt from slow-mode.
/// </note>
/// </remarks>
/// <exception cref="ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception>
public Optional<int> DefaultSlowModeInterval { get; set; }

/// <summary>
/// Gets or sets a collection of tags inside of this forum channel.
/// </summary>
public Optional<IEnumerable<ForumTagProperties>> Tags { get; set; }

/// <summary>
/// Gets or sets a new default reaction emoji in this forum channel.
/// </summary>
public Optional<IEmote> DefaultReactionEmoji { get; set; }

/// <summary>
/// Gets or sets the rule used to order posts in forum channels.
/// </summary>
public Optional<ForumSortOrder> DefaultSortOrder { get; set; }
}
17 changes: 17 additions & 0 deletions src/Discord.Net.Core/Entities/Channels/ForumSortOrder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
namespace Discord;

/// <summary>
/// Defines the rule used to order posts in forum channels.
/// </summary>
public enum ForumSortOrder
{
/// <summary>
/// Sort forum posts by activity.
/// </summary>
LatestActivity = 0,

/// <summary>
/// Sort forum posts by creation time (from most recent to oldest).
/// </summary>
CreationDate = 1
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,10 @@ public class GuildChannelProperties
/// Gets or sets the permission overwrites for this channel.
/// </summary>
public Optional<IEnumerable<Overwrite>> PermissionOverwrites { get; set; }

/// <summary>
/// Gets or sets the flags of the channel.
/// </summary>
public Optional<ChannelFlags> Flags { get; set; }
}
}
68 changes: 61 additions & 7 deletions src/Discord.Net.Core/Entities/Channels/IForumChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

namespace Discord
{
public interface IForumChannel : IGuildChannel, IMentionable
public interface IForumChannel : IGuildChannel, IMentionable, INestedChannel
{
/// <summary>
/// Gets a value that indicates whether the channel is NSFW.
Expand Down Expand Up @@ -35,6 +35,55 @@ public interface IForumChannel : IGuildChannel, IMentionable
/// </summary>
IReadOnlyCollection<ForumTag> Tags { get; }

/// <summary>
/// Gets the current rate limit on creating posts in this forum channel.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// </returns>
int ThreadCreationInterval { get; }

/// <summary>
/// Gets the current default slow-mode delay for threads in this forum channel.
/// </summary>
/// <returns>
/// An <see cref="int"/> representing the time in seconds required before the user can send another
/// message; <c>0</c> if disabled.
/// </returns>
int DefaultSlowModeInterval { get; }

/// <summary>
/// Gets the emoji to show in the add reaction button on a thread in a forum channel
/// </summary>
/// <remarks>
/// If the emoji is <see cref="Emote"/> only the <see cref="Emote.Id"/> will be populated.
/// Use <see cref="IGuild.GetEmoteAsync"/> to get the emoji.
/// </remarks>
IEmote DefaultReactionEmoji { get; }

/// <summary>
/// Gets or sets the rule used to order posts in forum channels.
/// </summary>
/// <remarks>
/// Defaults to null, which indicates a preferred sort order hasn't been set
/// </remarks>
ForumSortOrder? DefaultSortOrder { get; }

/// <summary>
/// Modifies this forum channel.
/// </summary>
/// <remarks>
/// This method modifies the current forum channel with the specified properties. To see an example of this
/// method and what properties are available, please refer to <see cref="ForumChannelProperties"/>.
/// </remarks>
/// <param name="func">The delegate containing the properties to modify the channel with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
Task ModifyAsync(Action<ForumChannelProperties> func, RequestOptions options = null);

/// <summary>
/// Creates a new post (thread) within the forum.
/// </summary>
Expand All @@ -52,12 +101,13 @@ public interface IForumChannel : IGuildChannel, IMentionable
/// <param name="stickers">A collection of stickers to send with the message.</param>
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
/// <param name="tags">An array of <see cref="ForumTag"/> to be applied to the post.</param>
/// <returns>
/// A task that represents the asynchronous creation operation.
/// </returns>
Task<IThreadChannel> CreatePostAsync(string title, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay, int? slowmode = null,
string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, ForumTag[] tags = null);

/// <summary>
/// Creates a new post (thread) within the forum.
Expand All @@ -78,13 +128,14 @@ public interface IForumChannel : IGuildChannel, IMentionable
/// <param name="stickers">A collection of stickers to send with the file.</param>
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
/// <param name="tags">An array of <see cref="ForumTag"/> to be applied to the post.</param>
/// <returns>
/// A task that represents the asynchronous creation operation.
/// </returns>
Task<IThreadChannel> CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
AllowedMentions allowedMentions = null, MessageComponent components = null,
ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, ForumTag[] tags = null);

/// <summary>
/// Creates a new post (thread) within the forum.
Expand All @@ -106,13 +157,14 @@ public interface IForumChannel : IGuildChannel, IMentionable
/// <param name="stickers">A collection of stickers to send with the file.</param>
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
/// <param name="tags">An array of <see cref="ForumTag"/> to be applied to the post.</param>
/// <returns>
/// A task that represents the asynchronous creation operation.
/// </returns>
public Task<IThreadChannel> CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, bool isSpoiler = false,
AllowedMentions allowedMentions = null, MessageComponent components = null,
ISticker[] stickers = null, Embed[] embeds = null,MessageFlags flags = MessageFlags.None);
ISticker[] stickers = null, Embed[] embeds = null,MessageFlags flags = MessageFlags.None, ForumTag[] tags = null);

/// <summary>
/// Creates a new post (thread) within the forum.
Expand All @@ -132,12 +184,13 @@ public interface IForumChannel : IGuildChannel, IMentionable
/// <param name="stickers">A collection of stickers to send with the file.</param>
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
/// <param name="tags">An array of <see cref="ForumTag"/> to be applied to the post.</param>
/// <returns>
/// A task that represents the asynchronous creation operation.
/// </returns>
public Task<IThreadChannel> CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, ForumTag[] tags = null);

/// <summary>
/// Creates a new post (thread) within the forum.
Expand All @@ -155,14 +208,15 @@ public interface IForumChannel : IGuildChannel, IMentionable
/// </param>
/// <param name="components">The message components to be included with this message. Used for interactions.</param>
/// <param name="stickers">A collection of stickers to send with the file.</param>
/// <param name="embeds">A array of <see cref="Embed"/>s to send with this response. Max 10.</param>
/// <param name="embeds">An array of <see cref="Embed"/>s to send with this response. Max 10.</param>
/// <param name="flags">A message flag to be applied to the sent message, only <see cref="MessageFlags.SuppressEmbeds"/> is permitted.</param>
/// <param name="tags">An array of <see cref="ForumTag"/> to be applied to the post.</param>
/// <returns>
/// A task that represents the asynchronous creation operation.
/// </returns>
public Task<IThreadChannel> CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration = ThreadArchiveDuration.OneDay,
int? slowmode = null, string text = null, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null,
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None);
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, ForumTag[] tags = null);

/// <summary>
/// Gets a collection of active threads within this forum channel.
Expand Down
11 changes: 11 additions & 0 deletions src/Discord.Net.Core/Entities/Channels/IGuildChannel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@ public interface IGuildChannel : IChannel, IDeletable
/// </returns>
int Position { get; }

/// <summary>
/// Gets the flags related to this channel.
/// </summary>
/// <remarks>
/// This value is determined by bitwise OR-ing <see cref="ChannelFlags"/> values together.
/// </remarks>
/// <returns>
/// A channel's flags, if any is associated.
/// </returns>
ChannelFlags Flags { get; }

/// <summary>
/// Gets the guild associated with this channel.
/// </summary>
Expand Down
20 changes: 20 additions & 0 deletions src/Discord.Net.Core/Entities/Channels/IThreadChannel.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Discord
Expand Down Expand Up @@ -56,6 +57,14 @@ public interface IThreadChannel : ITextChannel
/// </remarks>
bool? IsInvitable { get; }

/// <summary>
/// Gets ids of tags applied to a forum thread
/// </summary>
/// <remarks>
/// This property is only available on forum threads.
/// </remarks>
IReadOnlyCollection<ulong> AppliedTags { get; }

/// <summary>
/// Gets when the thread was created.
/// </summary>
Expand Down Expand Up @@ -102,5 +111,16 @@ public interface IThreadChannel : ITextChannel
/// A task that represents the asynchronous operation of removing a user from this thread.
/// </returns>
Task RemoveUserAsync(IGuildUser user, RequestOptions options = null);

/// <summary>
/// Modifies this thread channel.
/// </summary>
/// <param name="func">The delegate containing the properties to modify the channel with.</param>
/// <param name="options">The options to be used when sending the request.</param>
/// <returns>
/// A task that represents the asynchronous modification operation.
/// </returns>
/// <seealso cref="ThreadChannelProperties"/>
Task ModifyAsync(Action<ThreadChannelProperties> func, RequestOptions options = null);
}
}
13 changes: 2 additions & 11 deletions src/Discord.Net.Core/Entities/Channels/TextChannelProperties.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;

namespace Discord
{
Expand Down Expand Up @@ -39,20 +40,10 @@ public class TextChannelProperties : GuildChannelProperties
/// <exception cref="ArgumentOutOfRangeException">Thrown if the value does not fall within [0, 21600].</exception>
public Optional<int> SlowModeInterval { get; set; }

/// <summary>
/// Gets or sets whether or not the thread is archived.
/// </summary>
public Optional<bool> Archived { get; set; }

/// <summary>
/// Gets or sets whether or not the thread is locked.
/// </summary>
public Optional<bool> Locked { get; set; }

/// <summary>
/// Gets or sets the auto archive duration.
/// </summary>
public Optional<ThreadArchiveDuration> AutoArchiveDuration { get; set; }

}
}
26 changes: 26 additions & 0 deletions src/Discord.Net.Core/Entities/Channels/ThreadChannelProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;

namespace Discord;


/// <summary>
/// Provides properties that are used to modify an <see cref="IThreadChannel"/> with the specified changes.
/// </summary>
/// <seealso cref="IThreadChannel.ModifyAsync(System.Action{ThreadChannelProperties}, RequestOptions)"/>
public class ThreadChannelProperties : TextChannelProperties
{
/// <summary>
/// Gets or sets the tags applied to a forum thread
/// </summary>
public Optional<IEnumerable<ulong>> AppliedTags { get; set; }

/// <summary>
/// Gets or sets whether or not the thread is locked.
/// </summary>
public Optional<bool> Locked { get; set; }

/// <summary>
/// Gets or sets whether or not the thread is archived.
/// </summary>
public Optional<bool> Archived { get; set; }
}
Loading

0 comments on commit 01ae904

Please sign in to comment.