[Feature] Add missing properties in forum & thread channels (#2469)
* 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
This commit is contained in:
@@ -27,9 +27,33 @@ namespace Discord.WebSocket
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyCollection<ForumTag> Tags { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int ThreadCreationInterval { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public int DefaultSlowModeInterval { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string Mention => MentionUtils.MentionChannel(Id);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ulong? CategoryId { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IEmote DefaultReactionEmoji { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ForumSortOrder? DefaultSortOrder { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the parent (category) of this channel in the guild's channel list.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An <see cref="ICategoryChannel"/> representing the parent of this channel; <c>null</c> if none is set.
|
||||
/// </returns>
|
||||
public ICategoryChannel Category
|
||||
=> CategoryId.HasValue ? Guild.GetChannel(CategoryId.Value) as ICategoryChannel : null;
|
||||
|
||||
internal SocketForumChannel(DiscordSocketClient discord, ulong id, SocketGuild guild) : base(discord, id, guild) { }
|
||||
|
||||
internal new static SocketForumChannel Create(SocketGuild guild, ClientState state, Model model)
|
||||
@@ -46,46 +70,70 @@ namespace Discord.WebSocket
|
||||
Topic = model.Topic.GetValueOrDefault();
|
||||
DefaultAutoArchiveDuration = model.AutoArchiveDuration.GetValueOrDefault(ThreadArchiveDuration.OneDay);
|
||||
|
||||
if (model.ThreadRateLimitPerUser.IsSpecified)
|
||||
DefaultSlowModeInterval = model.ThreadRateLimitPerUser.Value;
|
||||
|
||||
if (model.SlowMode.IsSpecified)
|
||||
ThreadCreationInterval = model.SlowMode.Value;
|
||||
|
||||
DefaultSortOrder = model.DefaultSortOrder.GetValueOrDefault();
|
||||
|
||||
Tags = model.ForumTags.GetValueOrDefault(Array.Empty<API.ForumTags>()).Select(
|
||||
x => new ForumTag(x.Id, x.Name, x.EmojiId.GetValueOrDefault(null), x.EmojiName.GetValueOrDefault())
|
||||
x => new ForumTag(x.Id, x.Name, x.EmojiId.GetValueOrDefault(null), x.EmojiName.GetValueOrDefault(), x.Moderated)
|
||||
).ToImmutableArray();
|
||||
|
||||
if (model.DefaultReactionEmoji.IsSpecified && model.DefaultReactionEmoji.Value is not null)
|
||||
{
|
||||
if (model.DefaultReactionEmoji.Value.EmojiId.HasValue && model.DefaultReactionEmoji.Value.EmojiId.Value != 0)
|
||||
DefaultReactionEmoji = new Emote(model.DefaultReactionEmoji.Value.EmojiId.GetValueOrDefault(), null, false);
|
||||
else if (model.DefaultReactionEmoji.Value.EmojiName.IsSpecified)
|
||||
DefaultReactionEmoji = new Emoji(model.DefaultReactionEmoji.Value.EmojiName.Value);
|
||||
else
|
||||
DefaultReactionEmoji = null;
|
||||
}
|
||||
|
||||
CategoryId = model.CategoryId.GetValueOrDefault();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostAsync(string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
public Task<RestThreadChannel> 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)
|
||||
=> ThreadHelper.CreatePostAsync(this, Discord, title, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||
/// <inheritdoc />
|
||||
public virtual Task ModifyAsync(Action<ForumChannelProperties> func, RequestOptions options = null)
|
||||
=> ForumHelper.ModifyAsync(this, Discord, func, options);
|
||||
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostAsync(string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags, ForumTag[])"/>
|
||||
public Task<RestThreadChannel> 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, ForumTag[] tags = null)
|
||||
=> ThreadHelper.CreatePostAsync(this, Discord, title, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags, tags?.Select(tag => tag.Id).ToArray());
|
||||
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags, ForumTag[])"/>
|
||||
public async Task<RestThreadChannel> 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)
|
||||
{
|
||||
using var file = new FileAttachment(filePath, isSpoiler: isSpoiler);
|
||||
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags, tags?.Select(tag => tag.Id).ToArray()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, Stream, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, Stream, string, ThreadArchiveDuration, int?, string, Embed, RequestOptions, bool, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags, ForumTag[])"/>
|
||||
public async Task<RestThreadChannel> 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)
|
||||
{
|
||||
using var file = new FileAttachment(stream, filename, isSpoiler: isSpoiler);
|
||||
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||
return await ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { file }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags, tags?.Select(tag => tag.Id).ToArray()).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, FileAttachment, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFileAsync(string, FileAttachment, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags, ForumTag[])"/>
|
||||
public Task<RestThreadChannel> 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)
|
||||
=> ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { attachment }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, ForumTag[] tags = null)
|
||||
=> ThreadHelper.CreatePostAsync(this, Discord, title, new FileAttachment[] { attachment }, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags, tags?.Select(tag => tag.Id).ToArray());
|
||||
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFilesAsync(string, IEnumerable{FileAttachment}, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags)"/>
|
||||
/// <inheritdoc cref="IForumChannel.CreatePostWithFilesAsync(string, IEnumerable{FileAttachment}, ThreadArchiveDuration, int?, string, Embed, RequestOptions, AllowedMentions, MessageComponent, ISticker[], Embed[], MessageFlags, ForumTag[])"/>
|
||||
public Task<RestThreadChannel> 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)
|
||||
=> ThreadHelper.CreatePostAsync(this, Discord, title, attachments, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||
MessageComponent components = null, ISticker[] stickers = null, Embed[] embeds = null, MessageFlags flags = MessageFlags.None, ForumTag[] tags = null)
|
||||
=> ThreadHelper.CreatePostAsync(this, Discord, title, attachments, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags, tags?.Select(tag => tag.Id).ToArray());
|
||||
|
||||
/// <inheritdoc cref="IForumChannel.GetActiveThreadsAsync(RequestOptions)"/>
|
||||
public Task<IReadOnlyCollection<RestThreadChannel>> GetActiveThreadsAsync(RequestOptions options = null)
|
||||
@@ -112,17 +160,41 @@ namespace Discord.WebSocket
|
||||
=> await GetPrivateArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||
async Task<IReadOnlyCollection<IThreadChannel>> IForumChannel.GetJoinedPrivateArchivedThreadsAsync(int? limit, DateTimeOffset? before, RequestOptions options)
|
||||
=> await GetJoinedPrivateArchivedThreadsAsync(limit, before, options).ConfigureAwait(false);
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostAsync(string title, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostAsync(string title, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, ForumTag[] tags)
|
||||
=> await CreatePostAsync(title, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, string filePath, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, ForumTag[] tags)
|
||||
=> await CreatePostWithFileAsync(title, filePath, archiveDuration, slowmode, text, embed, options, isSpoiler, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, Stream stream, string filename, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, bool isSpoiler, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, ForumTag[] tags)
|
||||
=> await CreatePostWithFileAsync(title, stream, filename, archiveDuration, slowmode, text, embed, options, isSpoiler, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFileAsync(string title, FileAttachment attachment, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, ForumTag[] tags)
|
||||
=> await CreatePostWithFileAsync(title, attachment, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags).ConfigureAwait(false);
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags)
|
||||
async Task<IThreadChannel> IForumChannel.CreatePostWithFilesAsync(string title, IEnumerable<FileAttachment> attachments, ThreadArchiveDuration archiveDuration, int? slowmode, string text, Embed embed, RequestOptions options, AllowedMentions allowedMentions, MessageComponent components, ISticker[] stickers, Embed[] embeds, MessageFlags flags, ForumTag[] tags)
|
||||
=> await CreatePostWithFilesAsync(title, attachments, archiveDuration, slowmode, text, embed, options, allowedMentions, components, stickers, embeds, flags);
|
||||
|
||||
#endregion
|
||||
|
||||
#region INestedChannel
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<IInviteMetadata> CreateInviteAsync(int? maxAge = 86400, int? maxUses = null, bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
|
||||
=> await ChannelHelper.CreateInviteAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, options).ConfigureAwait(false);
|
||||
public virtual async Task<IInviteMetadata> CreateInviteToApplicationAsync(ulong applicationId, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
|
||||
=> await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, applicationId, options);
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<IInviteMetadata> CreateInviteToApplicationAsync(DefaultApplications application, int? maxAge = 86400, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
|
||||
=> await ChannelHelper.CreateInviteToApplicationAsync(this, Discord, maxAge, maxUses, isTemporary, isUnique, (ulong)application, options);
|
||||
public virtual Task<IInviteMetadata> CreateInviteToStreamAsync(IUser user, int? maxAge, int? maxUses = default(int?), bool isTemporary = false, bool isUnique = false, RequestOptions options = null)
|
||||
=> throw new NotImplementedException();
|
||||
/// <inheritdoc />
|
||||
public virtual async Task<IReadOnlyCollection<IInviteMetadata>> GetInvitesAsync(RequestOptions options = null)
|
||||
=> await ChannelHelper.GetInvitesAsync(this, Discord, options).ConfigureAwait(false);
|
||||
|
||||
/// <inheritdoc />
|
||||
Task<ICategoryChannel> INestedChannel.GetCategoryAsync(CacheMode mode, RequestOptions options)
|
||||
=> Task.FromResult(Category);
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual Task SyncPermissionsAsync(RequestOptions options = null)
|
||||
=> ChannelHelper.SyncPermissionsAsync(this, Discord, options);
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,9 @@ namespace Discord.WebSocket
|
||||
/// <inheritdoc />
|
||||
public int Position { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ChannelFlags Flags { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IReadOnlyCollection<Overwrite> PermissionOverwrites => _overwrites;
|
||||
/// <summary>
|
||||
@@ -74,6 +77,8 @@ namespace Discord.WebSocket
|
||||
for (int i = 0; i < overwrites.Length; i++)
|
||||
newOverwrites.Add(overwrites[i].ToEntity());
|
||||
_overwrites = newOverwrites.ToImmutable();
|
||||
|
||||
Flags = model.Flags.GetValueOrDefault(ChannelFlags.None);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
@@ -89,6 +89,9 @@ namespace Discord.WebSocket
|
||||
/// <inheritdoc/>
|
||||
public bool? IsInvitable { get; private set; }
|
||||
|
||||
/// <inheritdoc/>
|
||||
public IReadOnlyCollection<ulong> AppliedTags { get; private set; }
|
||||
|
||||
/// <inheritdoc cref="IThreadChannel.CreatedAt"/>
|
||||
public override DateTimeOffset CreatedAt { get; }
|
||||
|
||||
@@ -149,6 +152,8 @@ namespace Discord.WebSocket
|
||||
}
|
||||
|
||||
HasJoined = model.ThreadMember.IsSpecified;
|
||||
|
||||
AppliedTags = model.AppliedTags.GetValueOrDefault(Array.Empty<ulong>()).ToImmutableArray();
|
||||
}
|
||||
|
||||
internal IReadOnlyCollection<SocketThreadUser> RemoveUsers(ulong[] users)
|
||||
@@ -334,12 +339,13 @@ namespace Discord.WebSocket
|
||||
=> throw new NotSupportedException("This method is not supported in threads.");
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>
|
||||
/// <b>This method is not supported in threads.</b>
|
||||
/// </remarks>
|
||||
public override Task ModifyAsync(Action<TextChannelProperties> func, RequestOptions options = null)
|
||||
=> ThreadHelper.ModifyAsync(this, Discord, func, options);
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task ModifyAsync(Action<ThreadChannelProperties> func, RequestOptions options = null)
|
||||
=> ThreadHelper.ModifyAsync(this, Discord, func, options);
|
||||
|
||||
/// <inheritdoc/>
|
||||
/// <remarks>
|
||||
/// <b>This method is not supported in threads.</b>
|
||||
|
||||
Reference in New Issue
Block a user