diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index 34a08f1e7..d1ff7b99c 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -761,6 +761,18 @@ namespace Discord /// Task CreateCategoryAsync(string name, Action func = null, RequestOptions options = null); + /// + /// Creates a new channel forum in this guild. + /// + /// The new name for the forum. + /// The delegate containing the properties to be applied to the channel upon its creation. + /// The options to be used when sending the request. + /// + /// A task that represents the asynchronous creation operation. The task result contains the newly created + /// forum channel. + /// + Task CreateForumChannelAsync(string name, Action func = null, RequestOptions options = null); + /// /// Gets a collection of all the voice regions this guild can access. /// diff --git a/src/Discord.Net.Rest/API/Rest/CreateGuildChannelParams.cs b/src/Discord.Net.Rest/API/Rest/CreateGuildChannelParams.cs index 57816e448..4a8a2ebea 100644 --- a/src/Discord.Net.Rest/API/Rest/CreateGuildChannelParams.cs +++ b/src/Discord.Net.Rest/API/Rest/CreateGuildChannelParams.cs @@ -23,6 +23,8 @@ namespace Discord.API.Rest public Optional IsNsfw { get; set; } [JsonProperty("rate_limit_per_user")] public Optional SlowModeInterval { get; set; } + [JsonProperty("default_auto_archive_duration")] + public Optional DefaultAutoArchiveDuration { get; set; } //Voice channels [JsonProperty("bitrate")] @@ -30,6 +32,14 @@ namespace Discord.API.Rest [JsonProperty("user_limit")] public Optional UserLimit { get; set; } + //Forum channels + [JsonProperty("default_reaction_emoji")] + public Optional DefaultReactionEmoji { get; set; } + [JsonProperty("default_thread_rate_limit_per_user")] + public Optional ThreadRateLimitPerUser { get; set; } + [JsonProperty("available_tags")] + public Optional AvailableTags { get; set; } + public CreateGuildChannelParams(string name, ChannelType type) { Name = name; diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index c4e3764d1..6ed0678e2 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -1,3 +1,4 @@ +using Discord.API; using Discord.API.Rest; using System; using System.Collections.Generic; @@ -252,6 +253,7 @@ namespace Discord.Rest Deny = overwrite.Permissions.DenyValue.ToString() }).ToArray() : Optional.Create(), + DefaultAutoArchiveDuration = props.AutoArchiveDuration }; var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false); return RestTextChannel.Create(client, guild, model); @@ -338,6 +340,62 @@ namespace Discord.Rest var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false); return RestCategoryChannel.Create(client, guild, model); } + + /// is null. + public static async Task CreateForumChannelAsync(IGuild guild, BaseDiscordClient client, + string name, RequestOptions options, Action func = null) + { + if (name == null) + throw new ArgumentNullException(paramName: nameof(name)); + + var props = new ForumChannelProperties(); + func?.Invoke(props); + + var args = new CreateGuildChannelParams(name, ChannelType.Forum) + { + Position = props.Position, + Overwrites = props.PermissionOverwrites.IsSpecified + ? props.PermissionOverwrites.Value.Select(overwrite => new API.Overwrite + { + TargetId = overwrite.TargetId, + TargetType = overwrite.TargetType, + Allow = overwrite.Permissions.AllowValue.ToString(), + Deny = overwrite.Permissions.DenyValue.ToString() + }).ToArray() + : Optional.Create(), + SlowModeInterval = props.ThreadCreationInterval, + AvailableTags = props.Tags.GetValueOrDefault().Select( + x => new ModifyForumTagParams + { + Id = x.Id, + Name = x.Name, + EmojiId = x.Emoji is Emote emote + ? emote.Id + : Optional.Unspecified, + EmojiName = x.Emoji is Emoji emoji + ? emoji.Name + : Optional.Unspecified, + Moderated = x.IsModerated + }).ToArray(), + DefaultReactionEmoji = props.DefaultReactionEmoji.IsSpecified + ? new API.ModifyForumReactionEmojiParams + { + EmojiId = props.DefaultReactionEmoji.Value is Emote emote ? + emote.Id : Optional.Unspecified, + EmojiName = props.DefaultReactionEmoji.Value is Emoji emoji ? + emoji.Name : Optional.Unspecified + } + : Optional.Unspecified, + ThreadRateLimitPerUser = props.DefaultSlowModeInterval, + CategoryId = props.CategoryId, + IsNsfw = props.IsNsfw, + Topic = props.Topic, + DefaultAutoArchiveDuration = props.AutoArchiveDuration + }; + + var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false); + return RestForumChannel.Create(client, guild, model); + } #endregion #region Voice Regions diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index eb3254619..24f6ae28d 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -710,6 +710,19 @@ namespace Discord.Rest public Task CreateCategoryChannelAsync(string name, Action func = null, RequestOptions options = null) => GuildHelper.CreateCategoryChannelAsync(this, Discord, name, options, func); + /// + /// Creates a category channel with the provided name. + /// + /// The name of the new channel. + /// The delegate containing the properties to be applied to the channel upon its creation. + /// The options to be used when sending the request. + /// is . + /// + /// The created category channel. + /// + public Task CreateForumChannelAsync(string name, Action func = null, RequestOptions options = null) + => GuildHelper.CreateForumChannelAsync(this, Discord, name, options, func); + /// /// Gets a collection of all the voice regions this guild can access. /// @@ -1370,6 +1383,9 @@ namespace Discord.Rest /// async Task IGuild.CreateCategoryAsync(string name, Action func, RequestOptions options) => await CreateCategoryChannelAsync(name, func, options).ConfigureAwait(false); + /// + async Task IGuild.CreateForumChannelAsync(string name, Action func, RequestOptions options) + => await CreateForumChannelAsync(name, func, options).ConfigureAwait(false); /// async Task> IGuild.GetVoiceRegionsAsync(RequestOptions options) diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index 55f098b2f..324a287d5 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -790,6 +790,7 @@ namespace Discord.WebSocket /// public Task CreateStageChannelAsync(string name, Action func = null, RequestOptions options = null) => GuildHelper.CreateStageChannelAsync(this, Discord, name, options, func); + /// /// Creates a new channel category in this guild. /// @@ -801,9 +802,24 @@ namespace Discord.WebSocket /// A task that represents the asynchronous creation operation. The task result contains the newly created /// category channel. /// - public Task CreateCategoryChannelAsync(string name, Action func = null, RequestOptions options = null) + public Task CreateCategoryChannelAsync(string name, + Action func = null, RequestOptions options = null) => GuildHelper.CreateCategoryChannelAsync(this, Discord, name, options, func); + /// + /// Creates a new channel forum in this guild. + /// + /// The new name for the forum. + /// The delegate containing the properties to be applied to the channel upon its creation. + /// The options to be used when sending the request. + /// is . + /// + /// A task that represents the asynchronous creation operation. The task result contains the newly created + /// forum channel. + /// + public Task CreateForumChannelAsync(string name, Action func = null, RequestOptions options = null) + => GuildHelper.CreateForumChannelAsync(this, Discord, name, options, func); + internal SocketGuildChannel AddChannel(ClientState state, ChannelModel model) { var channel = SocketGuildChannel.Create(this, state, model); @@ -1897,6 +1913,9 @@ namespace Discord.WebSocket /// async Task IGuild.CreateCategoryAsync(string name, Action func, RequestOptions options) => await CreateCategoryChannelAsync(name, func, options).ConfigureAwait(false); + /// + async Task IGuild.CreateForumChannelAsync(string name, Action func, RequestOptions options) + => await CreateForumChannelAsync(name, func, options).ConfigureAwait(false); /// async Task> IGuild.GetVoiceRegionsAsync(RequestOptions options)