diff --git a/src/Discord.Net.Core/Entities/Channels/ChannelFlags.cs b/src/Discord.Net.Core/Entities/Channels/ChannelFlags.cs
index 37f34a90ed..13d0db9878 100644
--- a/src/Discord.Net.Core/Entities/Channels/ChannelFlags.cs
+++ b/src/Discord.Net.Core/Entities/Channels/ChannelFlags.cs
@@ -16,7 +16,12 @@ public enum ChannelFlags
Pinned = 1 << 1,
///
- /// Flag given to a forum channel that requires people to select tags when posting.
+ /// Flag given to a forum or media channel that requires people to select tags when posting.
///
- RequireTag = 1 << 4
+ RequireTag = 1 << 4,
+
+ ///
+ /// Flag given to a media channel that hides the embedded media download options.
+ ///
+ HideMediaDownloadOption = 1 << 15,
}
diff --git a/src/Discord.Net.Core/Entities/Channels/ChannelType.cs b/src/Discord.Net.Core/Entities/Channels/ChannelType.cs
index 15965abc31..bc39a564a9 100644
--- a/src/Discord.Net.Core/Entities/Channels/ChannelType.cs
+++ b/src/Discord.Net.Core/Entities/Channels/ChannelType.cs
@@ -1,33 +1,75 @@
-namespace Discord
+namespace Discord;
+
+/// Defines the types of channels.
+public enum ChannelType
{
- /// Defines the types of channels.
- public enum ChannelType
- {
- /// The channel is a text channel.
- Text = 0,
- /// The channel is a Direct Message channel.
- DM = 1,
- /// The channel is a voice channel.
- Voice = 2,
- /// The channel is a group channel.
- Group = 3,
- /// The channel is a category channel.
- Category = 4,
- /// The channel is a news channel.
- News = 5,
- /// The channel is a store channel.
- Store = 6,
- /// The channel is a temporary thread channel under a news channel.
- NewsThread = 10,
- /// The channel is a temporary thread channel under a text channel.
- PublicThread = 11,
- /// The channel is a private temporary thread channel under a text channel.
- PrivateThread = 12,
- /// The channel is a stage voice channel.
- Stage = 13,
- /// The channel is a guild directory used in hub servers. (Unreleased)
- GuildDirectory = 14,
- /// The channel is a forum channel containing multiple threads.
- Forum = 15
- }
+ ///
+ /// The channel is a text channel.
+ ///
+ Text = 0,
+
+ ///
+ /// The channel is a Direct Message channel.
+ ///
+ DM = 1,
+
+ ///
+ /// The channel is a voice channel.
+ ///
+ Voice = 2,
+
+ ///
+ /// The channel is a group channel.
+ ///
+ Group = 3,
+
+ ///
+ /// The channel is a category channel.
+ ///
+ Category = 4,
+
+ ///
+ /// The channel is a news channel.
+ ///
+ News = 5,
+
+ ///
+ /// The channel is a store channel.
+ ///
+ Store = 6,
+
+ ///
+ /// The channel is a temporary thread channel under a news channel.
+ ///
+ NewsThread = 10,
+
+ ///
+ /// The channel is a temporary thread channel under a text channel.
+ ///
+ PublicThread = 11,
+
+ ///
+ /// The channel is a private temporary thread channel under a text channel.
+ ///
+ PrivateThread = 12,
+
+ ///
+ /// The channel is a stage voice channel.
+ ///
+ Stage = 13,
+
+ ///
+ /// The channel is a guild directory used in hub servers. (Unreleased)
+ ///
+ GuildDirectory = 14,
+
+ ///
+ /// The channel is a forum channel containing multiple threads.
+ ///
+ Forum = 15,
+
+ ///
+ /// The channel is a media channel containing multiple threads.
+ ///
+ Media = 16,
}
diff --git a/src/Discord.Net.Core/Entities/Channels/ForumChannelProperties.cs b/src/Discord.Net.Core/Entities/Channels/ForumChannelProperties.cs
index eb18d392c6..336e17eb0b 100644
--- a/src/Discord.Net.Core/Entities/Channels/ForumChannelProperties.cs
+++ b/src/Discord.Net.Core/Entities/Channels/ForumChannelProperties.cs
@@ -29,22 +29,25 @@ public class ForumChannelProperties : TextChannelProperties
public Optional ThreadCreationInterval { get; set; }
///
- /// Gets or sets a collection of tags inside of this forum channel.
+ /// Gets or sets a collection of tags inside of this forum channel.
///
public Optional> Tags { get; set; }
///
- /// Gets or sets a new default reaction emoji in this forum channel.
+ /// Gets or sets a new default reaction emoji in this forum channel.
///
public Optional DefaultReactionEmoji { get; set; }
///
- /// Gets or sets the rule used to order posts in forum channels.
+ /// Gets or sets the rule used to order posts in forum channels.
///
public Optional DefaultSortOrder { get; set; }
///
- /// Gets or sets the rule used to display posts in a forum channel.
+ /// Gets or sets the rule used to display posts in a forum channel.
///
+ ///
+ /// This property cannot be changed in media channels.
+ ///
public Optional DefaultLayout { get; set; }
}
diff --git a/src/Discord.Net.Core/Entities/Channels/IMediaChannel.cs b/src/Discord.Net.Core/Entities/Channels/IMediaChannel.cs
new file mode 100644
index 0000000000..93cd65aab9
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Channels/IMediaChannel.cs
@@ -0,0 +1,9 @@
+namespace Discord;
+
+///
+/// Represents a media channel in a guild that can create posts.
+///
+public interface IMediaChannel : IForumChannel
+{
+
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
index 086a92d3dc..6e62e59cd2 100644
--- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
@@ -733,6 +733,52 @@ public interface IGuild : IDeletable, ISnowflakeEntity
///
Task> GetThreadChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
+ ///
+ /// Gets a forum channel in this guild.
+ ///
+ /// The snowflake identifier for the stage channel.
+ /// The that determines whether the object should be fetched from cache.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains the stage channel associated
+ /// with the specified ; if none is found.
+ ///
+ Task GetForumChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
+
+ ///
+ /// Gets a collection of all forum channels in this guild.
+ ///
+ /// The that determines whether the object should be fetched from cache.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains a read-only collection of
+ /// forum channels found within this guild.
+ ///
+ Task> GetForumChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
+
+ ///
+ /// Gets a forum channel in this guild.
+ ///
+ /// The snowflake identifier for the stage channel.
+ /// The that determines whether the object should be fetched from cache.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains the stage channel associated
+ /// with the specified ; if none is found.
+ ///
+ Task GetMediaChannelAsync(ulong id, CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
+
+ ///
+ /// Gets a collection of all forum channels in this guild.
+ ///
+ /// The that determines whether the object should be fetched from cache.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains a read-only collection of
+ /// media channels found within this guild.
+ ///
+ Task> GetMediaChannelsAsync(CacheMode mode = CacheMode.AllowDownload, RequestOptions options = null);
+
///
/// Creates a new text channel in this guild.
///
@@ -795,6 +841,18 @@ public interface IGuild : IDeletable, ISnowflakeEntity
///
Task CreateForumChannelAsync(string name, Action func = null, RequestOptions options = null);
+ ///
+ /// Creates a new media channel in this guild.
+ ///
+ /// The new name for the media channel.
+ /// 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 CreateMediaChannelAsync(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.Core/Entities/Messages/FileAttachment.cs b/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
index b7b1cb36a4..7d7f6a4630 100644
--- a/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
+++ b/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
@@ -1,9 +1,5 @@
using System;
-using System.Collections.Generic;
using System.IO;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Discord
{
@@ -26,6 +22,11 @@ public struct FileAttachment : IDisposable
///
public bool IsSpoiler { get; set; }
+ ///
+ /// Gets or sets if this file should be a thumbnail for a media channel post.
+ ///
+ public bool IsThumbnail { get; set; }
+
#pragma warning disable IDISP008
///
/// Gets the stream containing the file content.
@@ -42,12 +43,14 @@ public struct FileAttachment : IDisposable
/// The name of the attachment.
/// The description of the attachment.
/// Whether or not the attachment is a spoiler.
- public FileAttachment(Stream stream, string fileName, string description = null, bool isSpoiler = false)
+ /// Whether or not this attachment should be a thumbnail for a media channel post.
+ public FileAttachment(Stream stream, string fileName, string description = null, bool isSpoiler = false, bool isThumbnail = false)
{
_isDisposed = false;
FileName = fileName;
Description = description;
Stream = stream;
+ IsThumbnail = isThumbnail;
try
{
Stream.Position = 0;
@@ -67,6 +70,7 @@ public FileAttachment(Stream stream, string fileName, string description = null,
/// The name of the attachment.
/// The description of the attachment.
/// Whether or not the attachment is a spoiler.
+ /// Whether or not this attachment should be a thumbnail for a media channel post.
///
/// is a zero-length string, contains only white space, or contains one or more invalid
/// characters as defined by .
@@ -87,13 +91,14 @@ public FileAttachment(Stream stream, string fileName, string description = null,
/// The file specified in was not found.
///
/// An I/O error occurred while opening the file.
- public FileAttachment(string path, string fileName = null, string description = null, bool isSpoiler = false)
+ public FileAttachment(string path, string fileName = null, string description = null, bool isSpoiler = false, bool isThumbnail = false)
{
_isDisposed = false;
Stream = File.OpenRead(path);
FileName = fileName ?? Path.GetFileName(path);
Description = description;
IsSpoiler = isSpoiler;
+ IsThumbnail = isThumbnail;
}
public void Dispose()
diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs
index d33d5a4471..e317401853 100644
--- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs
+++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs
@@ -50,6 +50,11 @@ public struct ChannelPermissions
///
public static readonly ChannelPermissions Forum = new(0b01_001110_010010_110011_111101_111111_111101_010001);
+ ///
+ /// Gets a that grants all permissions for media channels.
+ ///
+ public static readonly ChannelPermissions Media = new(0b01_001110_010010_110011_111101_111111_111101_010001);
+
///
/// Gets a that grants all permissions for a given channel type.
///
@@ -64,6 +69,7 @@ public static ChannelPermissions All(IChannel channel)
ICategoryChannel _ => Category,
IDMChannel _ => DM,
IGroupChannel _ => Group,
+ IMediaChannel _ => Media,
IForumChannel => Forum,
_ => throw new ArgumentException(message: "Unknown channel type.", paramName: nameof(channel)),
};
diff --git a/src/Discord.Net.Core/Extensions/ChannelExtensions.cs b/src/Discord.Net.Core/Extensions/ChannelExtensions.cs
index a24588792c..ff9fc507c9 100644
--- a/src/Discord.Net.Core/Extensions/ChannelExtensions.cs
+++ b/src/Discord.Net.Core/Extensions/ChannelExtensions.cs
@@ -47,6 +47,9 @@ public static class ChannelExtensions
case ITextChannel:
return ChannelType.Text;
+ case IMediaChannel:
+ return ChannelType.Media;
+
case IForumChannel:
return ChannelType.Forum;
}
diff --git a/src/Discord.Net.Core/Utils/ChannelTypeUtils.cs b/src/Discord.Net.Core/Utils/ChannelTypeUtils.cs
index 4dd7645080..331d5be86d 100644
--- a/src/Discord.Net.Core/Utils/ChannelTypeUtils.cs
+++ b/src/Discord.Net.Core/Utils/ChannelTypeUtils.cs
@@ -9,6 +9,6 @@ public static List AllChannelTypes()
{
ChannelType.Forum, ChannelType.Category, ChannelType.DM, ChannelType.Group, ChannelType.GuildDirectory,
ChannelType.News, ChannelType.NewsThread, ChannelType.PrivateThread, ChannelType.PublicThread,
- ChannelType.Stage, ChannelType.Store, ChannelType.Text, ChannelType.Voice
+ ChannelType.Stage, ChannelType.Store, ChannelType.Text, ChannelType.Voice, ChannelType.Media
};
}
diff --git a/src/Discord.Net.Interactions/TypeConverters/SlashCommands/DefaultEntityTypeConverter.cs b/src/Discord.Net.Interactions/TypeConverters/SlashCommands/DefaultEntityTypeConverter.cs
index 76f135a98c..facf151bf3 100644
--- a/src/Discord.Net.Interactions/TypeConverters/SlashCommands/DefaultEntityTypeConverter.cs
+++ b/src/Discord.Net.Interactions/TypeConverters/SlashCommands/DefaultEntityTypeConverter.cs
@@ -69,6 +69,12 @@ _ when typeof(IThreadChannel).IsAssignableFrom(type)
_ when typeof(ITextChannel).IsAssignableFrom(type)
=> new List { ChannelType.Text },
+ _ when typeof(IMediaChannel).IsAssignableFrom(type)
+ => new List { ChannelType.Media },
+
+ _ when typeof(IForumChannel).IsAssignableFrom(type)
+ => new List { ChannelType.Forum },
+
_ => null
};
}
diff --git a/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs b/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs
index 14e5f5383f..e1cd383a50 100644
--- a/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs
+++ b/src/Discord.Net.Rest/API/Rest/CreateMultipartPostAsync.cs
@@ -78,7 +78,8 @@ public IReadOnlyDictionary ToDictionary()
{
id = (ulong)n,
filename = filename,
- description = attachment.Description ?? Optional.Unspecified
+ description = attachment.Description ?? Optional.Unspecified,
+ is_thumbnail = attachment.IsThumbnail,
});
}
diff --git a/src/Discord.Net.Rest/Entities/Channels/ForumHelper.cs b/src/Discord.Net.Rest/Entities/Channels/ForumHelper.cs
index 5f239890cb..9a6c0aebbf 100644
--- a/src/Discord.Net.Rest/Entities/Channels/ForumHelper.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/ForumHelper.cs
@@ -57,8 +57,7 @@ public static async Task ModifyAsync(IForumChannel channel, BaseDiscordCl
emoji.Name : Optional.Unspecified
}
: Optional.Unspecified,
- DefaultSortOrder = args.DefaultSortOrder,
- DefaultLayout = args.DefaultLayout,
+ DefaultSortOrder = args.DefaultSortOrder
};
return await client.ApiClient.ModifyGuildChannelAsync(channel.Id, apiArgs, options).ConfigureAwait(false);
}
diff --git a/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs
index 3f472c74ea..bbf52a44ef 100644
--- a/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/RestChannel.cs
@@ -50,7 +50,8 @@ ChannelType.Stage or
ChannelType.NewsThread or
ChannelType.PrivateThread or
ChannelType.PublicThread or
- ChannelType.Forum
+ ChannelType.Forum or
+ ChannelType.Media
=> RestGuildChannel.Create(discord, guild, model),
ChannelType.DM or ChannelType.Group => CreatePrivate(discord, model) as RestChannel,
ChannelType.Category => RestCategoryChannel.Create(discord, guild, model),
diff --git a/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
index 30b058476b..0f2f6e2396 100644
--- a/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
+++ b/src/Discord.Net.Rest/Entities/Channels/RestGuildChannel.cs
@@ -42,6 +42,7 @@ internal static RestGuildChannel Create(BaseDiscordClient discord, IGuild guild,
ChannelType.Text => RestTextChannel.Create(discord, guild, model),
ChannelType.Voice => RestVoiceChannel.Create(discord, guild, model),
ChannelType.Stage => RestStageChannel.Create(discord, guild, model),
+ ChannelType.Media => RestMediaChannel.Create(discord, guild, model),
ChannelType.Forum => RestForumChannel.Create(discord, guild, model),
ChannelType.Category => RestCategoryChannel.Create(discord, guild, model),
ChannelType.PublicThread or ChannelType.PrivateThread or ChannelType.NewsThread => RestThreadChannel.Create(discord, guild, model),
diff --git a/src/Discord.Net.Rest/Entities/Channels/RestMediaChannel.cs b/src/Discord.Net.Rest/Entities/Channels/RestMediaChannel.cs
new file mode 100644
index 0000000000..6126329412
--- /dev/null
+++ b/src/Discord.Net.Rest/Entities/Channels/RestMediaChannel.cs
@@ -0,0 +1,24 @@
+using Model = Discord.API.Channel;
+
+namespace Discord.Rest;
+
+public class RestMediaChannel : RestForumChannel, IMediaChannel
+{
+ internal RestMediaChannel(BaseDiscordClient client, IGuild guild, ulong id)
+ : base(client, guild, id)
+ {
+
+ }
+
+ internal new static RestMediaChannel Create(BaseDiscordClient discord, IGuild guild, Model model)
+ {
+ var entity = new RestMediaChannel(discord, guild, model.Id);
+ entity.Update(model);
+ return entity;
+ }
+
+ internal override void Update(Model model)
+ {
+ base.Update(model);
+ }
+}
diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
index b88ef5adf3..65774f057c 100644
--- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
+++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs
@@ -428,6 +428,66 @@ public static async Task CreateForumChannelAsync(IGuild guild,
var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false);
return RestForumChannel.Create(client, guild, model);
}
+
+ /// is .
+ public static async Task CreateMediaChannelAsync(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);
+
+ Preconditions.AtMost(props.Tags.IsSpecified ? props.Tags.Value.Count() : 0, 20, nameof(props.Tags), "Media channel can have max 20 tags.");
+
+ var args = new CreateGuildChannelParams(name, ChannelType.Media)
+ {
+ 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(Array.Empty()).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,
+ DefaultSortOrder = props.DefaultSortOrder.GetValueOrDefault(ForumSortOrder.LatestActivity),
+ };
+
+ var model = await client.ApiClient.CreateGuildChannelAsync(guild.Id, args, options).ConfigureAwait(false);
+ return RestMediaChannel.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 82a0fe8029..3981814359 100644
--- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
+++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
@@ -462,6 +462,64 @@ public async Task> GetTextChannelsAsync(Req
return channels.OfType().ToImmutableArray();
}
+ ///
+ /// Gets a forum channel in this guild.
+ ///
+ /// The snowflake identifier for the forum channel.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains the text channel
+ /// associated with the specified ; if none is found.
+ ///
+ public async Task GetForumChannelAsync(ulong id, RequestOptions options = null)
+ {
+ var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false);
+ return channel as RestForumChannel;
+ }
+
+ ///
+ /// Gets a collection of all forum channels in this guild.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains a read-only collection of
+ /// forum channels found within this guild.
+ ///
+ public async Task> GetForumChannelsAsync(RequestOptions options = null)
+ {
+ var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false);
+ return channels.OfType().ToImmutableArray();
+ }
+
+ ///
+ /// Gets a media channel in this guild.
+ ///
+ /// The snowflake identifier for the text channel.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains the media channel
+ /// associated with the specified ; if none is found.
+ ///
+ public async Task GetMediaChannelAsync(ulong id, RequestOptions options = null)
+ {
+ var channel = await GuildHelper.GetChannelAsync(this, Discord, id, options).ConfigureAwait(false);
+ return channel as RestMediaChannel;
+ }
+
+ ///
+ /// Gets a collection of all media channels in this guild.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation. The task result contains a read-only collection of
+ /// media channels found within this guild.
+ ///
+ public async Task> GetMediaChannelsAsync(RequestOptions options = null)
+ {
+ var channels = await GuildHelper.GetChannelsAsync(this, Discord, options).ConfigureAwait(false);
+ return channels.OfType().ToImmutableArray();
+ }
+
///
/// Gets a thread channel in this guild.
///
@@ -735,18 +793,31 @@ public Task CreateCategoryChannelAsync(string name, Action<
=> GuildHelper.CreateCategoryChannelAsync(this, Discord, name, options, func);
///
- /// Creates a category channel with the provided name.
+ /// Creates a new forum 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.
+ /// The created forum channel.
///
public Task CreateForumChannelAsync(string name, Action func = null, RequestOptions options = null)
=> GuildHelper.CreateForumChannelAsync(this, Discord, name, options, func);
+ ///
+ /// Creates a new media channel in this guild.
+ ///
+ /// The new name for the media channel.
+ /// 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
+ /// media channel.
+ ///
+ public Task CreateMediaChannelAsync(string name, Action func = null, RequestOptions options = null)
+ => GuildHelper.CreateMediaChannelAsync(this, Discord, name, options, func);
+
///
/// Gets a collection of all the voice regions this guild can access.
///
@@ -1342,6 +1413,43 @@ async Task IGuild.GetTextChannelAsync(ulong id, CacheMode mode, Re
else
return null;
}
+
+ ///
+ async Task IGuild.GetForumChannelAsync(ulong id, CacheMode mode, RequestOptions options)
+ {
+ if (mode == CacheMode.AllowDownload)
+ return await GetForumChannelAsync(id, options).ConfigureAwait(false);
+ else
+ return null;
+ }
+
+ ///
+ async Task> IGuild.GetForumChannelsAsync(CacheMode mode, RequestOptions options)
+ {
+ if (mode == CacheMode.AllowDownload)
+ return await GetForumChannelsAsync(options).ConfigureAwait(false);
+ else
+ return null;
+ }
+
+ ///
+ async Task IGuild.GetMediaChannelAsync(ulong id, CacheMode mode, RequestOptions options)
+ {
+ if (mode == CacheMode.AllowDownload)
+ return await GetMediaChannelAsync(id, options).ConfigureAwait(false);
+ else
+ return null;
+ }
+
+ ///
+ async Task> IGuild.GetMediaChannelsAsync(CacheMode mode, RequestOptions options)
+ {
+ if (mode == CacheMode.AllowDownload)
+ return await GetMediaChannelsAsync(options).ConfigureAwait(false);
+ else
+ return null;
+ }
+
///
async Task IGuild.GetThreadChannelAsync(ulong id, CacheMode mode, RequestOptions options)
{
@@ -1462,6 +1570,10 @@ async Task IGuild.CreateCategoryAsync(string name, Action IGuild.CreateForumChannelAsync(string name, Action func, RequestOptions options)
=> await CreateForumChannelAsync(name, func, options).ConfigureAwait(false);
+ ///
+ async Task IGuild.CreateMediaChannelAsync(string name, Action func, RequestOptions options)
+ => await CreateMediaChannelAsync(name, func, options).ConfigureAwait(false);
+
///
async Task> IGuild.GetVoiceRegionsAsync(RequestOptions options)
=> await GetVoiceRegionsAsync(options).ConfigureAwait(false);
diff --git a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs
index 4860f60e58..52fb67262b 100644
--- a/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs
+++ b/src/Discord.Net.Rest/Entities/Interactions/RestInteraction.cs
@@ -201,7 +201,9 @@ ChannelType.Voice or
ChannelType.Stage or
ChannelType.NewsThread or
ChannelType.PrivateThread or
- ChannelType.PublicThread
+ ChannelType.PublicThread or
+ ChannelType.Media or
+ ChannelType.Forum
=> RestGuildChannel.Create(discord, Guild, model.Channel.Value) as IRestMessageChannel,
ChannelType.DM => RestDMChannel.Create(discord, model.Channel.Value),
ChannelType.Group => RestGroupChannel.Create(discord, model.Channel.Value),
diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
index bb4e461383..027b217db2 100644
--- a/src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
+++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketGuildChannel.cs
@@ -63,6 +63,7 @@ internal static SocketGuildChannel Create(SocketGuild guild, ClientState state,
ChannelType.PrivateThread or ChannelType.PublicThread or ChannelType.NewsThread => SocketThreadChannel.Create(guild, state, model),
ChannelType.Stage => SocketStageChannel.Create(guild, state, model),
ChannelType.Forum => SocketForumChannel.Create(guild, state, model),
+ ChannelType.Media => SocketMediaChannel.Create(guild, state, model),
_ => new SocketGuildChannel(guild.Discord, model.Id, guild),
};
}
diff --git a/src/Discord.Net.WebSocket/Entities/Channels/SocketMediaChannel.cs b/src/Discord.Net.WebSocket/Entities/Channels/SocketMediaChannel.cs
new file mode 100644
index 0000000000..ca03f1d638
--- /dev/null
+++ b/src/Discord.Net.WebSocket/Entities/Channels/SocketMediaChannel.cs
@@ -0,0 +1,24 @@
+using Model = Discord.API.Channel;
+
+namespace Discord.WebSocket;
+
+public class SocketMediaChannel : SocketForumChannel, IMediaChannel
+{
+ internal SocketMediaChannel(DiscordSocketClient discord, ulong id, SocketGuild guild)
+ : base(discord, id, guild)
+ {
+
+ }
+
+ internal new static SocketMediaChannel Create(SocketGuild guild, ClientState state, Model model)
+ {
+ var entity = new SocketMediaChannel(guild?.Discord, model.Id, guild);
+ entity.Update(state, model);
+ return entity;
+ }
+
+ internal override void Update(ClientState state, Model model)
+ {
+ base.Update(state, model);
+ }
+}
diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
index 53c5c93ee9..1740e37233 100644
--- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
+++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs
@@ -339,6 +339,15 @@ public IReadOnlyCollection ThreadChannels
public IReadOnlyCollection ForumChannels
=> Channels.OfType().ToImmutableArray();
+ ///
+ /// Gets a collection of all media channels in this guild.
+ ///
+ ///
+ /// A read-only collection of forum channels found within this guild.
+ ///
+ public IReadOnlyCollection MediaChannels
+ => Channels.OfType().ToImmutableArray();
+
///
/// Gets the current logged-in user.
///
@@ -790,6 +799,16 @@ public SocketStageChannel GetStageChannel(ulong id)
public SocketCategoryChannel GetCategoryChannel(ulong id)
=> GetChannel(id) as SocketCategoryChannel;
+ ///
+ /// Gets a media channel in this guild.
+ ///
+ /// The snowflake identifier for the stage channel.
+ ///
+ /// A stage channel associated with the specified ; if none is found.
+ ///
+ public SocketMediaChannel GetMediaChannel(ulong id)
+ => GetChannel(id) as SocketMediaChannel;
+
///
/// Creates a new text channel in this guild.
///
@@ -857,7 +876,7 @@ public Task CreateCategoryChannelAsync(string name, Action<
=> GuildHelper.CreateCategoryChannelAsync(this, Discord, name, options, func);
///
- /// Creates a new channel forum in this guild.
+ /// Creates a new forum channel in this guild.
///
/// The new name for the forum.
/// The delegate containing the properties to be applied to the channel upon its creation.
@@ -870,6 +889,20 @@ public Task CreateCategoryChannelAsync(string name, Action<
public Task CreateForumChannelAsync(string name, Action func = null, RequestOptions options = null)
=> GuildHelper.CreateForumChannelAsync(this, Discord, name, options, func);
+ ///
+ /// Creates a new media channel in this guild.
+ ///
+ /// The new name for the media 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 .
+ ///
+ /// A task that represents the asynchronous creation operation. The task result contains the newly created
+ /// media channel.
+ ///
+ public Task CreateMediaChannelAsync(string name, Action func = null, RequestOptions options = null)
+ => GuildHelper.CreateMediaChannelAsync(this, Discord, name, options, func);
+
internal SocketGuildChannel AddChannel(ClientState state, ChannelModel model)
{
var channel = SocketGuildChannel.Create(this, state, model);
@@ -2075,6 +2108,21 @@ Task IGuild.GetRulesChannelAsync(CacheMode mode, RequestOptions op
///
Task IGuild.GetPublicUpdatesChannelAsync(CacheMode mode, RequestOptions options)
=> Task.FromResult(PublicUpdatesChannel);
+
+ ///
+ Task IGuild.GetForumChannelAsync(ulong id, CacheMode mode, RequestOptions options)
+ => Task.FromResult(GetForumChannel(id));
+ ///
+ Task> IGuild.GetForumChannelsAsync(CacheMode mode, RequestOptions options)
+ => Task.FromResult>(ForumChannels);
+
+ ///
+ Task IGuild.GetMediaChannelAsync(ulong id, CacheMode mode, RequestOptions options)
+ => Task.FromResult(GetMediaChannel(id));
+ ///
+ Task> IGuild.GetMediaChannelsAsync(CacheMode mode, RequestOptions options)
+ => Task.FromResult>(MediaChannels);
+
///
async Task IGuild.CreateTextChannelAsync(string name, Action func, RequestOptions options)
=> await CreateTextChannelAsync(name, func, options).ConfigureAwait(false);
@@ -2091,6 +2139,10 @@ async Task IGuild.CreateCategoryAsync(string name, Action IGuild.CreateForumChannelAsync(string name, Action func, RequestOptions options)
=> await CreateForumChannelAsync(name, func, options).ConfigureAwait(false);
+ ///
+ async Task IGuild.CreateMediaChannelAsync(string name, Action func, RequestOptions options)
+ => await CreateMediaChannelAsync(name, func, options).ConfigureAwait(false);
+
///
async Task> IGuild.GetVoiceRegionsAsync(RequestOptions options)
=> await GetVoiceRegionsAsync(options).ConfigureAwait(false);
diff --git a/src/Discord.Net.WebSocket/Entities/Invites/SocketInvite.cs b/src/Discord.Net.WebSocket/Entities/Invites/SocketInvite.cs
index 3d54c62877..c659b7badc 100644
--- a/src/Discord.Net.WebSocket/Entities/Invites/SocketInvite.cs
+++ b/src/Discord.Net.WebSocket/Entities/Invites/SocketInvite.cs
@@ -39,6 +39,8 @@ ChannelType IInvite.ChannelType
IGroupChannel groupChannel => ChannelType.Group,
INewsChannel newsChannel => ChannelType.News,
ITextChannel textChannel => ChannelType.Text,
+ IMediaChannel mediaChannel => ChannelType.Media,
+ IForumChannel forumChannel => ChannelType.Forum,
_ => throw new InvalidOperationException("Invalid channel type."),
};
}