From cf047995fa349fb035c6cd2dd97a4a8336f9804f Mon Sep 17 00:00:00 2001 From: Andrzej Bansleben Date: Sun, 13 Sep 2026 12:10:13 +0200 Subject: [PATCH 1/5] Introduce channel capability interfaces --- NetCord/Channels/ICategoryGuildChannel.cs | 6 ++ NetCord/Channels/IChannel.cs | 21 ++++ NetCord/Channels/IGuildChannel.cs | 97 +++++++++++++------ NetCord/Channels/IInteractionChannel.cs | 11 --- NetCord/Channels/IInviteChannel.cs | 8 ++ NetCord/Channels/INamedChannel.cs | 14 --- .../Guild/IAnnouncementGuildChannel.cs | 17 ++++ .../Guild/IDirectoryGuildChannel.cs | 5 + .../TextChannels/Guild/ITextGuildChannel.cs | 18 ++++ .../Guild/IThreadOnlyGuildChannel.cs | 34 +++++++ .../Guild/Threads/IGuildThread.cs | 48 +++++++++ .../Guild/Threads/IUnknownGuildThread.cs | 8 -- NetCord/Channels/TextChannels/IDMChannel.cs | 6 ++ .../Channels/TextChannels/IGroupDMChannel.cs | 28 ++++++ NetCord/Channels/TextChannels/ITextChannel.cs | 28 ++++++ ...IVoiceGuildChannel.cs => IVoiceChannel.cs} | 28 ++++-- 16 files changed, 310 insertions(+), 67 deletions(-) create mode 100644 NetCord/Channels/ICategoryGuildChannel.cs create mode 100644 NetCord/Channels/IChannel.cs delete mode 100644 NetCord/Channels/IInteractionChannel.cs create mode 100644 NetCord/Channels/IInviteChannel.cs delete mode 100644 NetCord/Channels/INamedChannel.cs create mode 100644 NetCord/Channels/TextChannels/Guild/IAnnouncementGuildChannel.cs create mode 100644 NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs create mode 100644 NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs create mode 100644 NetCord/Channels/TextChannels/Guild/IThreadOnlyGuildChannel.cs create mode 100644 NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs delete mode 100644 NetCord/Channels/TextChannels/Guild/Threads/IUnknownGuildThread.cs create mode 100644 NetCord/Channels/TextChannels/IDMChannel.cs create mode 100644 NetCord/Channels/TextChannels/IGroupDMChannel.cs create mode 100644 NetCord/Channels/TextChannels/ITextChannel.cs rename NetCord/Channels/VoiceChannels/Guild/{IVoiceGuildChannel.cs => IVoiceChannel.cs} (64%) diff --git a/NetCord/Channels/ICategoryGuildChannel.cs b/NetCord/Channels/ICategoryGuildChannel.cs new file mode 100644 index 000000000..6ecefdc02 --- /dev/null +++ b/NetCord/Channels/ICategoryGuildChannel.cs @@ -0,0 +1,6 @@ +namespace NetCord; + +public interface ICategoryGuildChannel : + IGuildChannel, IPermissionOverwriteChannel, INamedChannel, IPositionedGuildChannel +{ +} diff --git a/NetCord/Channels/IChannel.cs b/NetCord/Channels/IChannel.cs new file mode 100644 index 000000000..daa2ba026 --- /dev/null +++ b/NetCord/Channels/IChannel.cs @@ -0,0 +1,21 @@ +namespace NetCord; + +public interface IChannel : IEntity, ISpanFormattable +{ + ChannelType Type { get; } + + // Null means Discord did not provide flags. + ChannelFlags? Flags { get; } + + public string ToString(); +} + +public interface INamedChannel : IChannel +{ + string Name { get; } +} + +public interface IInteractionChannel : IChannel +{ + Permissions Permissions { get; } +} diff --git a/NetCord/Channels/IGuildChannel.cs b/NetCord/Channels/IGuildChannel.cs index ae016567b..74a1529e2 100644 --- a/NetCord/Channels/IGuildChannel.cs +++ b/NetCord/Channels/IGuildChannel.cs @@ -1,44 +1,87 @@ -using NetCord.JsonModels; -using NetCord.Rest; - namespace NetCord; +public interface IGuildChannel : IChannel +{ + ulong GuildId { get; } +} + /// -/// Represents a channel within a guild. +/// Represents a guild channel which directly contains Discord messages. /// -public partial interface IGuildChannel : INamedChannel +/// +/// This includes: +/// +/// GUILD_TEXT +/// GUILD_ANNOUNCEMENT +/// GUILD_VOICE +/// GUILD_STAGE_VOICE +/// ANNOUNCEMENT_THREAD +/// PUBLIC_THREAD +/// PRIVATE_THREAD +/// +/// +public interface IGuildMessageChannel : ITextChannel, IGuildChannel { - /// - /// The ID corresponding to the channel's parent guild. - /// - public ulong GuildId { get; } +} +/// +/// Represents a guild channel that has a position and can have a parent category. +/// +public interface IPositionedGuildChannel : IGuildChannel +{ /// /// The channel's position within the guild channel list. /// /// /// If two or more channels share a position, they are instead sorted by their ID. /// - public int? Position { get; } + int Position { get; } /// - /// A list of explicit permission overwrites for specified members and roles. + /// The ID of the channel's parent category, if it has one. /// - public IReadOnlyDictionary PermissionOverwrites { get; } + ulong? ParentId { get; } +} + +/// +/// Represents a guild channel that has permission overwrites. +/// +public interface IPermissionOverwriteChannel : IGuildChannel +{ + IReadOnlyDictionary PermissionOverwrites { get; } +} + +/// +/// Represents a guild channel that can have webhooks. +/// +/// +/// This includes: +/// +/// GUILD_TEXT +/// GUILD_ANNOUNCEMENT +/// GUILD_FORUM +/// GUILD_MEDIA +/// +/// For threads, use the parent channel's webhooks. +/// +public interface IWebhookChannel : IGuildChannel +{ +} - public static IGuildChannel CreateFromJson(JsonChannel jsonChannel, ulong guildId, RestClient client) - { - return jsonChannel.Type switch - { - ChannelType.TextGuildChannel => new TextGuildChannel(jsonChannel, guildId, client), - ChannelType.VoiceGuildChannel => new VoiceGuildChannel(jsonChannel, guildId, client), - ChannelType.CategoryChannel => new CategoryGuildChannel(jsonChannel, guildId, client), - ChannelType.AnnouncementGuildChannel => new AnnouncementGuildChannel(jsonChannel, guildId, client), - ChannelType.StageGuildChannel => new StageGuildChannel(jsonChannel, guildId, client), - ChannelType.DirectoryGuildChannel => new DirectoryGuildChannel(jsonChannel, guildId, client), - ChannelType.ForumGuildChannel => new ForumGuildChannel(jsonChannel, guildId, client), - ChannelType.MediaForumGuildChannel => new MediaForumGuildChannel(jsonChannel, guildId, client), - _ => new UnknownGuildChannel(jsonChannel, guildId, client), - }; - } +/// +/// Represents a guild channel that can be invited to. +/// +/// +/// This includes: +/// +/// GUILD_TEXT +/// GUILD_ANNOUNCEMENT +/// GUILD_VOICE +/// GUILD_STAGE_VOICE +/// GUILD_FORUM +/// GUILD_MEDIA +/// +/// +public interface IInvitableGuildChannel : IGuildChannel +{ } diff --git a/NetCord/Channels/IInteractionChannel.cs b/NetCord/Channels/IInteractionChannel.cs deleted file mode 100644 index f91658736..000000000 --- a/NetCord/Channels/IInteractionChannel.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace NetCord; - -/// -/// An optional interface for acquiring channel permissions. -/// -public interface IInteractionChannel : IEntity, ISpanFormattable -{ - public Permissions Permissions { get; } - - public string ToString(); -} diff --git a/NetCord/Channels/IInviteChannel.cs b/NetCord/Channels/IInviteChannel.cs new file mode 100644 index 000000000..19759e2af --- /dev/null +++ b/NetCord/Channels/IInviteChannel.cs @@ -0,0 +1,8 @@ +namespace NetCord; + +public interface IInviteChannel : IChannel +{ + string? Name { get; } + string? Icon { get; } + IReadOnlyList? RecipientUsernames { get; } +} diff --git a/NetCord/Channels/INamedChannel.cs b/NetCord/Channels/INamedChannel.cs deleted file mode 100644 index 35ec24ba4..000000000 --- a/NetCord/Channels/INamedChannel.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace NetCord; - -/// -/// Represents a named channel. -/// -public interface INamedChannel : IEntity, ISpanFormattable -{ - /// - /// The name of the channel object, between 1 and 100 characters. - /// - public string Name { get; } - - public string ToString(); -} diff --git a/NetCord/Channels/TextChannels/Guild/IAnnouncementGuildChannel.cs b/NetCord/Channels/TextChannels/Guild/IAnnouncementGuildChannel.cs new file mode 100644 index 000000000..e227a1389 --- /dev/null +++ b/NetCord/Channels/TextChannels/Guild/IAnnouncementGuildChannel.cs @@ -0,0 +1,17 @@ +namespace NetCord; + +public interface IAnnouncementGuildChannel : + IGuildMessageChannel, + INamedChannel, + IPositionedGuildChannel, + IPermissionOverwriteChannel, + IPinnableChannel, + IWebhookChannel, + IInvitableGuildChannel +{ + string? Topic { get; } + bool? Nsfw { get; } + int? Slowmode { get; } + + ThreadArchiveDuration? DefaultAutoArchiveDuration { get; } +} diff --git a/NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs b/NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs new file mode 100644 index 000000000..14b29684c --- /dev/null +++ b/NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs @@ -0,0 +1,5 @@ +namespace NetCord; + +public interface IDirectoryGuildChannel : IGuildChannel, IPermissionOverwriteChannel, INamedChannel, IPositionedGuildChannel +{ +} \ No newline at end of file diff --git a/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs b/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs new file mode 100644 index 000000000..80b34f007 --- /dev/null +++ b/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs @@ -0,0 +1,18 @@ +namespace NetCord; + +public interface ITextGuildChannel : + IGuildMessageChannel, + INamedChannel, + IPositionedGuildChannel, + IPermissionOverwriteChannel, + IPinnableChannel, + IWebhookChannel, + IInvitableGuildChannel +{ + string? Topic { get; } + bool? Nsfw { get; } + int? Slowmode { get; } + + ThreadArchiveDuration? DefaultAutoArchiveDuration { get; } + int? DefaultThreadSlowmode { get; } +} diff --git a/NetCord/Channels/TextChannels/Guild/IThreadOnlyGuildChannel.cs b/NetCord/Channels/TextChannels/Guild/IThreadOnlyGuildChannel.cs new file mode 100644 index 000000000..09a369488 --- /dev/null +++ b/NetCord/Channels/TextChannels/Guild/IThreadOnlyGuildChannel.cs @@ -0,0 +1,34 @@ +namespace NetCord; + +public interface IThreadOnlyGuildChannel : + IGuildChannel, + INamedChannel, + IPositionedGuildChannel, + IPermissionOverwriteChannel, + IWebhookChannel, + IInvitableGuildChannel +{ + string? Topic { get; } + bool? Nsfw { get; } + + ulong? LastThreadId { get; } + + int? Slowmode { get; } + DateTimeOffset? LastPin { get; } + + ThreadArchiveDuration? DefaultAutoArchiveDuration { get; } + int? DefaultThreadSlowmode { get; } + + IReadOnlyList AvailableTags { get; } + Emoji? DefaultReactionEmoji { get; } + SortOrderType? DefaultSortOrder { get; } +} + +public interface IForumGuildChannel : IThreadOnlyGuildChannel +{ + ForumLayoutType DefaultForumLayout { get; } +} + +public interface IMediaGuildChannel : IThreadOnlyGuildChannel +{ +} diff --git a/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs b/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs new file mode 100644 index 000000000..f5b9c83f9 --- /dev/null +++ b/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs @@ -0,0 +1,48 @@ +using NetCord.Rest; + +namespace NetCord; + +public interface IGuildThread : + IGuildMessageChannel, + INamedChannel, + IPinnableChannel +{ + ulong ParentId { get; } + ulong OwnerId { get; } + int MessageCount { get; } + int UserCount { get; } + GuildThreadMetadata Metadata { get; } + ThreadCurrentUser? CurrentUser { get; } + int TotalMessageSent { get; } +} + +public interface IAnnouncementGuildThread : IGuildThread +{ +} + +public interface IUnknownGuildThread : + IUnknownGuildChannel, + IGuildThread +{ +} + +public interface IPrivateGuildThread : IGuildThread +{ +} + +/// +/// Represents a public guild thread channel, which is a specialized . +/// +/// +/// This also includes threads in forum and media channels. +/// +public interface IPublicGuildThread : IGuildThread +{ + IReadOnlyList? AppliedTags { get; } +} + +public sealed class CreateGuildThreadResult +{ + public required IPublicGuildThread Thread { get; init; } + public required RestMessage Message { get; init; } +} diff --git a/NetCord/Channels/TextChannels/Guild/Threads/IUnknownGuildThread.cs b/NetCord/Channels/TextChannels/Guild/Threads/IUnknownGuildThread.cs deleted file mode 100644 index 800b264be..000000000 --- a/NetCord/Channels/TextChannels/Guild/Threads/IUnknownGuildThread.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace NetCord; - -/// -/// Represents a guild thread of an unresolved type. -/// -public partial interface IUnknownGuildThread : IUnknownGuildChannel -{ -} diff --git a/NetCord/Channels/TextChannels/IDMChannel.cs b/NetCord/Channels/TextChannels/IDMChannel.cs new file mode 100644 index 000000000..084f4beac --- /dev/null +++ b/NetCord/Channels/TextChannels/IDMChannel.cs @@ -0,0 +1,6 @@ +namespace NetCord; + +public interface IDMChannel : ITextChannel, IPinnableChannel +{ + ulong? RecipientId { get; } +} diff --git a/NetCord/Channels/TextChannels/IGroupDMChannel.cs b/NetCord/Channels/TextChannels/IGroupDMChannel.cs new file mode 100644 index 000000000..b4b8a0e05 --- /dev/null +++ b/NetCord/Channels/TextChannels/IGroupDMChannel.cs @@ -0,0 +1,28 @@ +namespace NetCord; + +public interface IGroupDMChannel : + ITextChannel, + IPinnableChannel, + INamedChannel, + IInteractionChannel +{ + /// + /// The group channel's icon hash. + /// + string? IconHash { get; } + + /// + /// The ID corresponding to the group channel's owner. + /// + ulong OwnerId { get; } + + /// + /// The ID corresponding to the application managing the group channel, if any, otherwise . + /// + ulong? ApplicationId { get; } + + /// + /// Whether the group channel is managed by an application with set. + /// + bool Managed { get; } +} diff --git a/NetCord/Channels/TextChannels/ITextChannel.cs b/NetCord/Channels/TextChannels/ITextChannel.cs new file mode 100644 index 000000000..6e67bd760 --- /dev/null +++ b/NetCord/Channels/TextChannels/ITextChannel.cs @@ -0,0 +1,28 @@ +namespace NetCord; + +public interface ITextChannel : IChannel +{ + ulong? LastMessageId { get; } +} + +/// +/// Represents a text channel that can have pins. +/// +/// +/// This includes: +/// +/// GUILD_TEXT +/// GUILD_ANNOUNCEMENT +/// GUILD_VOICE +/// GUILD_STAGE_VOICE +/// ANNOUNCEMENT_THREAD +/// PUBLIC_THREAD +/// PRIVATE_THREAD +/// DM +/// GROUP_DM +/// +/// +public interface IPinnableChannel : ITextChannel +{ + DateTimeOffset? LastPin { get; } +} \ No newline at end of file diff --git a/NetCord/Channels/VoiceChannels/Guild/IVoiceGuildChannel.cs b/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs similarity index 64% rename from NetCord/Channels/VoiceChannels/Guild/IVoiceGuildChannel.cs rename to NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs index 7448d0eae..f73a262f8 100644 --- a/NetCord/Channels/VoiceChannels/Guild/IVoiceGuildChannel.cs +++ b/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs @@ -1,13 +1,7 @@ namespace NetCord; -/// -/// Represents a generic voice channel within a guild. -/// -public partial interface IVoiceGuildChannel : IGuildChannel +public interface IVoiceChannel : IGuildMessageChannel { - /// - public bool Nsfw { get; } - /// /// The voice channel's bitrate (in bits per second). /// @@ -34,3 +28,23 @@ public partial interface IVoiceGuildChannel : IGuildChannel /// public VideoQualityMode VideoQualityMode { get; } } + +public interface IVoiceGuildChannel : + IVoiceChannel, + INamedChannel, + IPositionedGuildChannel, + IPermissionOverwriteChannel, + IWebhookChannel, + IInvitableGuildChannel +{ +} + +public interface IStageGuildChannel : + IVoiceChannel, + INamedChannel, + IPositionedGuildChannel, + IPermissionOverwriteChannel, + IWebhookChannel, + IInvitableGuildChannel +{ +} From 32289908478c7cd62064af1f55fb24496dcd3ffb Mon Sep 17 00:00:00 2001 From: Andrzej Bansleben Date: Sun, 13 Sep 2026 12:34:06 +0200 Subject: [PATCH 2/5] Decouple channel implementation inheritance --- NetCord/Channels/ICategoryGuildChannel.cs | 3 +++ NetCord/Channels/IChannel.cs | 14 ++++++++++++++ .../TextChannels/Guild/Threads/IGuildThread.cs | 3 +++ NetCord/Channels/TextChannels/IGroupDMChannel.cs | 3 +-- NetCord/Channels/TextChannels/ITextChannel.cs | 2 -- .../Channels/VoiceChannels/Guild/IVoiceChannel.cs | 2 -- 6 files changed, 21 insertions(+), 6 deletions(-) diff --git a/NetCord/Channels/ICategoryGuildChannel.cs b/NetCord/Channels/ICategoryGuildChannel.cs index 6ecefdc02..0e6eb30e4 100644 --- a/NetCord/Channels/ICategoryGuildChannel.cs +++ b/NetCord/Channels/ICategoryGuildChannel.cs @@ -1,5 +1,8 @@ namespace NetCord; +/// +/// Represents an organizational category that contains up to 50 channels. +/// public interface ICategoryGuildChannel : IGuildChannel, IPermissionOverwriteChannel, INamedChannel, IPositionedGuildChannel { diff --git a/NetCord/Channels/IChannel.cs b/NetCord/Channels/IChannel.cs index daa2ba026..2620e588a 100644 --- a/NetCord/Channels/IChannel.cs +++ b/NetCord/Channels/IChannel.cs @@ -1,5 +1,12 @@ namespace NetCord; +/// +/// Represents any channel. +/// +/// +/// This includes all text and voice channels, threads, +/// DMs, group DMs, categories and directory channels. +/// public interface IChannel : IEntity, ISpanFormattable { ChannelType Type { get; } @@ -10,11 +17,18 @@ public interface IChannel : IEntity, ISpanFormattable public string ToString(); } +/// +/// Represents a channel that has a name. +/// public interface INamedChannel : IChannel { string Name { get; } } + +/// +/// Represents a channel representation which came with resolved interaction permissions. +/// public interface IInteractionChannel : IChannel { Permissions Permissions { get; } diff --git a/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs b/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs index f5b9c83f9..d6889121d 100644 --- a/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs +++ b/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs @@ -26,6 +26,9 @@ public interface IUnknownGuildThread : { } +/// +/// Represents a private thread channel that is only viewale by those invited and those with the MANAGE_THREADS permission. +/// public interface IPrivateGuildThread : IGuildThread { } diff --git a/NetCord/Channels/TextChannels/IGroupDMChannel.cs b/NetCord/Channels/TextChannels/IGroupDMChannel.cs index b4b8a0e05..e65fbe97c 100644 --- a/NetCord/Channels/TextChannels/IGroupDMChannel.cs +++ b/NetCord/Channels/TextChannels/IGroupDMChannel.cs @@ -3,8 +3,7 @@ namespace NetCord; public interface IGroupDMChannel : ITextChannel, IPinnableChannel, - INamedChannel, - IInteractionChannel + INamedChannel { /// /// The group channel's icon hash. diff --git a/NetCord/Channels/TextChannels/ITextChannel.cs b/NetCord/Channels/TextChannels/ITextChannel.cs index 6e67bd760..4b9b9eee8 100644 --- a/NetCord/Channels/TextChannels/ITextChannel.cs +++ b/NetCord/Channels/TextChannels/ITextChannel.cs @@ -13,8 +13,6 @@ public interface ITextChannel : IChannel /// /// GUILD_TEXT /// GUILD_ANNOUNCEMENT -/// GUILD_VOICE -/// GUILD_STAGE_VOICE /// ANNOUNCEMENT_THREAD /// PUBLIC_THREAD /// PRIVATE_THREAD diff --git a/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs b/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs index f73a262f8..9db08ceaf 100644 --- a/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs +++ b/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs @@ -34,7 +34,6 @@ public interface IVoiceGuildChannel : INamedChannel, IPositionedGuildChannel, IPermissionOverwriteChannel, - IWebhookChannel, IInvitableGuildChannel { } @@ -44,7 +43,6 @@ public interface IStageGuildChannel : INamedChannel, IPositionedGuildChannel, IPermissionOverwriteChannel, - IWebhookChannel, IInvitableGuildChannel { } From 6328d3cb286593f8c34590b0280453636f7da6f5 Mon Sep 17 00:00:00 2001 From: Andrzej Bansleben Date: Sun, 13 Sep 2026 13:40:35 +0200 Subject: [PATCH 3/5] Target channel REST aliases by capabilities --- NetCord/Rest/RestClient.Channel.cs | 93 ++++++++++++------------ NetCord/Rest/RestClient.Poll.cs | 4 +- NetCord/Rest/RestClient.StageInstance.cs | 6 +- NetCord/Rest/RestClient.Undocumented.cs | 2 +- NetCord/Rest/RestClient.Webhook.cs | 6 +- 5 files changed, 55 insertions(+), 56 deletions(-) diff --git a/NetCord/Rest/RestClient.Channel.cs b/NetCord/Rest/RestClient.Channel.cs index ef8b636c5..55aabe6d7 100644 --- a/NetCord/Rest/RestClient.Channel.cs +++ b/NetCord/Rest/RestClient.Channel.cs @@ -15,7 +15,7 @@ public partial class RestClient /// The ID of the channel to retrieve. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(Channel)], nameof(Channel.Id), Cast = true)] + [GenerateAlias([typeof(IChannel)], nameof(IChannel.Id), Cast = true)] public async Task GetChannelAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => Channel.CreateFromJson(await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); @@ -26,7 +26,7 @@ public async Task GetChannelAsync(ulong channelId, RestRequestPropertie /// An action delegate used to configure the channel's updated properties. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GroupDMChannel)], nameof(GroupDMChannel.Id), Cast = true)] + [GenerateAlias([typeof(IGroupDMChannel)], nameof(IGroupDMChannel.Id), Cast = true)] public async Task ModifyGroupDMChannelAsync(ulong channelId, Action action, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { GroupDMChannelOptions groupDMChannelOptions = new(); @@ -58,7 +58,7 @@ public async Task ModifyGuildChannelAsync(ulong channelId, ActionThe status to apply to the channel. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(VoiceGuildChannel)], nameof(VoiceGuildChannel.Id))] + [GenerateAlias([typeof(IVoiceGuildChannel)], nameof(IVoiceGuildChannel.Id))] public async Task SetVoiceGuildChannelStatusAsync(ulong channelId, VoiceGuildChannelStatusProperties statusProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(statusProperties, Serialization.Default.VoiceGuildChannelStatusProperties)) @@ -71,7 +71,7 @@ public async Task SetVoiceGuildChannelStatusAsync(ulong channelId, VoiceGuildCha /// The ID of the channel to delete. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(Channel)], nameof(Channel.Id), Cast = true)] + [GenerateAlias([typeof(IChannel)], nameof(IChannel.Id), Cast = true)] public async Task DeleteChannelAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => Channel.CreateFromJson(await (await SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); @@ -81,7 +81,7 @@ public async Task DeleteChannelAsync(ulong channelId, RestRequestProper /// The ID of the channel to retrieve messages from. /// Optional properties to customize result pagination, can be . /// Optional properties to customize each request, can be . - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] public IAsyncEnumerable GetMessagesAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.Prepare(paginationProperties, 0, long.MaxValue, PaginationDirection.Before, 100); @@ -111,7 +111,7 @@ public IAsyncEnumerable GetMessagesAsync(ulong channelId, Paginatio /// The maximum number of messages to retrieve, or to use the default. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] public async Task> GetMessagesAroundAsync(ulong channelId, ulong messageId, int? limit = null, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => (await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}/messages", $"?limit={limit.GetValueOrDefault(100)}&around={messageId}", new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonMessageArray).ConfigureAwait(false)).Select(m => new RestMessage(m, this)).ToArray(); @@ -361,7 +361,7 @@ static string InvalidEnum(string propertyName) /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. /// - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public async Task GetMessageAsync(ulong channelId, ulong messageId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => new(await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}/messages/{messageId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonMessage).ConfigureAwait(false), this); @@ -373,7 +373,7 @@ public async Task GetMessageAsync(ulong channelId, ulong messageId, /// The content and properties of the message to send. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), TypeNameOverride = "Message")] public async Task SendMessageAsync(ulong channelId, MessageProperties message, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { @@ -388,8 +388,7 @@ public async Task SendMessageAsync(ulong channelId, MessageProperti /// The ID of the message to crosspost. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(AnnouncementGuildChannel)], nameof(AnnouncementGuildChannel.Id))] - [GenerateAlias([typeof(AnnouncementGuildThread)], nameof(AnnouncementGuildThread.Id))] + [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public async Task CrosspostMessageAsync(ulong channelId, ulong messageId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => new(await (await SendRequestAsync(HttpMethod.Post, $"/channels/{channelId}/messages/{messageId}/crosspost", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonMessage).ConfigureAwait(false), this); @@ -402,7 +401,7 @@ public async Task CrosspostMessageAsync(ulong channelId, ulong mess /// The emoji to use as the reaction. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task AddMessageReactionAsync(ulong channelId, ulong messageId, ReactionEmojiProperties emoji, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Put, $"/channels/{channelId}/messages/{messageId}/reactions/{ReactionEmojiToString(emoji)}/@me", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -415,7 +414,7 @@ public Task AddMessageReactionAsync(ulong channelId, ulong messageId, ReactionEm /// The emoji to remove as a reaction. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task DeleteCurrentUserMessageReactionAsync(ulong channelId, ulong messageId, ReactionEmojiProperties emoji, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/messages/{messageId}/reactions/{ReactionEmojiToString(emoji)}/@me", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -429,7 +428,7 @@ public Task DeleteCurrentUserMessageReactionAsync(ulong channelId, ulong message /// The ID of the user whose reaction will be removed. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task DeleteUserMessageReactionAsync(ulong channelId, ulong messageId, ReactionEmojiProperties emoji, ulong userId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/messages/{messageId}/reactions/{ReactionEmojiToString(emoji)}/{userId}", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -442,7 +441,7 @@ public Task DeleteUserMessageReactionAsync(ulong channelId, ulong messageId, Rea /// The emoji to filter reactions by. /// Pagination options for fetching users, or to use defaults. /// Optional properties to customize each request, can be . - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public IAsyncEnumerable GetMessageReactionsAsync(ulong channelId, ulong messageId, ReactionEmojiProperties emoji, MessageReactionsPaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { @@ -469,7 +468,7 @@ public IAsyncEnumerable GetMessageReactionsAsync(ulong channelId, ulong me /// The ID of the message to clear reactions from. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task DeleteAllMessageReactionsAsync(ulong channelId, ulong messageId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/messages/{messageId}/reactions", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -482,7 +481,7 @@ public Task DeleteAllMessageReactionsAsync(ulong channelId, ulong messageId, Res /// The emoji to remove from all users. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task DeleteAllMessageReactionsForEmojiAsync(ulong channelId, ulong messageId, ReactionEmojiProperties emoji, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/messages/{messageId}/reactions/{ReactionEmojiToString(emoji)}", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -501,7 +500,7 @@ private static string ReactionEmojiToString(ReactionEmojiProperties emoji) /// An action that sets the new message properties. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public async Task ModifyMessageAsync(ulong channelId, ulong messageId, Action action, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { @@ -518,7 +517,7 @@ public async Task ModifyMessageAsync(ulong channelId, ulong message /// The ID of the message to delete. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task DeleteMessageAsync(ulong channelId, ulong messageId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/messages/{messageId}", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -530,7 +529,7 @@ public Task DeleteMessageAsync(ulong channelId, ulong messageId, RestRequestProp /// The list of message IDs to delete. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(IGuildMessageChannel)], nameof(IGuildMessageChannel.Id))] public async Task DeleteMessagesAsync(ulong channelId, IEnumerable messageIds, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { var ids = ArrayPool.Shared.Rent(100); @@ -574,7 +573,7 @@ private async Task BulkDeleteMessagesAsync(ulong channelId, ReadOnlyMemoryThe permission overwrite to apply. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(IGuildChannel)], nameof(IGuildChannel.Id))] + [GenerateAlias([typeof(IPermissionOverwriteChannel)], nameof(IPermissionOverwriteChannel.Id))] public async Task ModifyGuildChannelPermissionsAsync(ulong channelId, PermissionOverwriteProperties permissionOverwrite, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(permissionOverwrite, Serialization.Default.PermissionOverwriteProperties)) @@ -587,7 +586,7 @@ public async Task ModifyGuildChannelPermissionsAsync(ulong channelId, Permission /// The ID of the channel to retrieve invites for. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(IGuildChannel)], nameof(IGuildChannel.Id))] + [GenerateAlias([typeof(IInvitableGuildChannel)], nameof(IInvitableGuildChannel.Id))] public async Task> GetGuildChannelInvitesAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => (await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}/invites", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonRestInviteArray).ConfigureAwait(false)).Select(r => new RestInvite(r, this)).ToArray(); @@ -598,7 +597,7 @@ public async Task> GetGuildChannelInvitesAsync(ulong c /// The properties to configure the new invite. Can be for defaults. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(IGuildChannel)], nameof(IGuildChannel.Id))] + [GenerateAlias([typeof(IInvitableGuildChannel)], nameof(IInvitableGuildChannel.Id))] public async Task CreateGuildChannelInviteAsync(ulong channelId, InviteProperties? inviteProperties = null, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { if (inviteProperties is null) @@ -615,7 +614,7 @@ public async Task CreateGuildChannelInviteAsync(ulong channelId, Inv /// The ID of the role or user whose permission overwrite is to be deleted. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(IGuildChannel)], nameof(IGuildChannel.Id))] + [GenerateAlias([typeof(IPermissionOverwriteChannel)], nameof(IPermissionOverwriteChannel.Id))] public Task DeleteGuildChannelPermissionAsync(ulong channelId, ulong overwriteId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/permissions/{overwriteId}", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -626,8 +625,7 @@ public Task DeleteGuildChannelPermissionAsync(ulong channelId, ulong overwriteId /// The ID of the channel to receive crossposted messages. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(AnnouncementGuildChannel)], nameof(AnnouncementGuildChannel.Id))] - [GenerateAlias([typeof(AnnouncementGuildThread)], nameof(AnnouncementGuildThread.Id), TypeNameOverride = nameof(AnnouncementGuildChannel))] + [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] public async Task FollowAnnouncementGuildChannelAsync(ulong channelId, ulong webhookChannelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(new(webhookChannelId), Serialization.Default.FollowAnnouncementGuildChannelProperties)) @@ -640,7 +638,7 @@ public async Task FollowAnnouncementGuildChannelAsync(ulong cha /// The ID of the channel to trigger typing in. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] public Task TriggerTypingAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Post, $"/channels/{channelId}/typing", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -651,7 +649,7 @@ public Task TriggerTypingAsync(ulong channelId, RestRequestProperties? propertie /// Optional properties to customize the typing interval, can be . /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] public ValueTask EnterTypingScopeAsync(ulong channelId, TypingScopeProperties? scopeProperties = null, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { AsyncTypingScope scope = new(this, channelId, scopeProperties, properties, cancellationToken); @@ -665,7 +663,7 @@ public ValueTask EnterTypingScopeAsync(ulong channelId, TypingScope /// The ID of the channel to type in. /// Optional properties to customize the typing interval, can be . /// Optional properties to customize the request, can be . - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] public IDisposable EnterTypingScope(ulong channelId, TypingScopeProperties? scopeProperties = null, RestRequestProperties? properties = null) { return new TypingScope(this, channelId, scopeProperties, properties); @@ -677,7 +675,7 @@ public IDisposable EnterTypingScope(ulong channelId, TypingScopeProperties? scop /// The ID of the channel to get pinned messages from. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(IPinnableChannel)], nameof(IPinnableChannel.Id))] public async Task> GetPinnedMessagesAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => (await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}/pins", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonMessageArray).ConfigureAwait(false)).Select(m => new RestMessage(m, this)).ToArray(); @@ -688,7 +686,7 @@ public async Task> GetPinnedMessagesAsync(ulong chann /// The ID of the message to pin. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(IPinnableChannel)], nameof(IPinnableChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task PinMessageAsync(ulong channelId, ulong messageId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Put, $"/channels/{channelId}/pins/{messageId}", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -700,7 +698,7 @@ public Task PinMessageAsync(ulong channelId, ulong messageId, RestRequestPropert /// The ID of the message to unpin. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(IPinnableChannel)], nameof(IPinnableChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public Task UnpinMessageAsync(ulong channelId, ulong messageId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/pins/{messageId}", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -713,7 +711,7 @@ public Task UnpinMessageAsync(ulong channelId, ulong messageId, RestRequestPrope /// Properties for adding the user, such as access tokens. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GroupDMChannel)], nameof(GroupDMChannel.Id))] + [GenerateAlias([typeof(IGroupDMChannel)], nameof(IGroupDMChannel.Id))] public async Task GroupDMChannelAddUserAsync(ulong channelId, ulong userId, GroupDMChannelUserAddProperties groupDMChannelUserAddProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(groupDMChannelUserAddProperties, Serialization.Default.GroupDMChannelUserAddProperties)) @@ -727,7 +725,7 @@ public async Task GroupDMChannelAddUserAsync(ulong channelId, ulong userId, Grou /// The ID of the user to remove. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GroupDMChannel)], nameof(GroupDMChannel.Id))] + [GenerateAlias([typeof(IGroupDMChannel)], nameof(IGroupDMChannel.Id))] public Task GroupDMChannelDeleteUserAsync(ulong channelId, ulong userId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}/recipients/{userId}", null, new(channelId), properties, cancellationToken: cancellationToken); @@ -739,7 +737,8 @@ public Task GroupDMChannelDeleteUserAsync(ulong channelId, ulong userId, RestReq /// The properties of the thread to create. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextGuildChannel)], nameof(TextGuildChannel.Id))] + [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] + [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] public async Task CreateGuildThreadAsync(ulong channelId, ulong messageId, GuildThreadFromMessageProperties threadFromMessageProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { @@ -754,7 +753,8 @@ public async Task CreateGuildThreadAsync(ulong channelId, ulong mes /// The properties of the thread to create. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(TextGuildChannel)], nameof(TextGuildChannel.Id))] + [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] + [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] public async Task CreateGuildThreadAsync(ulong channelId, GuildThreadProperties threadProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(threadProperties, Serialization.Default.GuildThreadProperties)) @@ -762,13 +762,13 @@ public async Task CreateGuildThreadAsync(ulong channelId, GuildThre } /// - /// Creates a new thread in a forum channel. + /// Creates a new thread in a thread-only channel (forum and media channels). /// /// The ID of the forum channel. /// The properties of the forum thread to create. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(ForumGuildChannel)], nameof(ForumGuildChannel.Id))] + [GenerateAlias([typeof(IThreadOnlyGuildChannel)], nameof(IThreadOnlyGuildChannel.Id))] public async Task CreateForumGuildThreadAsync(ulong channelId, ForumGuildThreadProperties threadProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = threadProperties.Serialize()) @@ -781,7 +781,7 @@ public async Task CreateForumGuildThreadAsync(ulong channelId, /// The ID of the thread to join. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GuildThread)], nameof(GuildThread.Id))] + [GenerateAlias([typeof(IGuildThread)], nameof(IGuildThread.Id))] public Task JoinGuildThreadAsync(ulong threadId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Put, $"/channels/{threadId}/thread-members/@me", null, new(threadId), properties, cancellationToken: cancellationToken); @@ -792,7 +792,7 @@ public Task JoinGuildThreadAsync(ulong threadId, RestRequestProperties? properti /// The ID of the user to add to the thread. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GuildThread)], nameof(GuildThread.Id))] + [GenerateAlias([typeof(IGuildThread)], nameof(IGuildThread.Id))] public Task AddGuildThreadUserAsync(ulong threadId, ulong userId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Put, $"/channels/{threadId}/thread-members/{userId}", null, new(threadId), properties, cancellationToken: cancellationToken); @@ -802,7 +802,7 @@ public Task AddGuildThreadUserAsync(ulong threadId, ulong userId, RestRequestPro /// The ID of the thread to leave. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GuildThread)], nameof(GuildThread.Id))] + [GenerateAlias([typeof(IGuildThread)], nameof(IGuildThread.Id))] public Task LeaveGuildThreadAsync(ulong threadId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{threadId}/thread-members/@me", null, new(threadId), properties, cancellationToken: cancellationToken); @@ -813,7 +813,7 @@ public Task LeaveGuildThreadAsync(ulong threadId, RestRequestProperties? propert /// The ID of the user to remove from the thread. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GuildThread)], nameof(GuildThread.Id))] + [GenerateAlias([typeof(IGuildThread)], nameof(IGuildThread.Id))] [GenerateAlias([typeof(GuildThreadUser)], nameof(GuildThreadUser.ThreadId), nameof(GuildThreadUser.Id))] public Task DeleteGuildThreadUserAsync(ulong threadId, ulong userId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/channels/{threadId}/thread-members/{userId}", null, new(threadId), properties, cancellationToken: cancellationToken); @@ -826,7 +826,7 @@ public Task DeleteGuildThreadUserAsync(ulong threadId, ulong userId, RestRequest /// Whether to include full guild member info in the response. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(GuildThread)], nameof(GuildThread.Id))] + [GenerateAlias([typeof(IGuildThread)], nameof(IGuildThread.Id))] public async Task GetGuildThreadUserAsync(ulong threadId, ulong userId, bool withGuildUser = false, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { var user = await (await SendRequestAsync(HttpMethod.Get, $"/channels/{threadId}/thread-members/{userId}", $"?with_member={withGuildUser}", new(threadId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonThreadUser).ConfigureAwait(false); @@ -839,7 +839,7 @@ public async Task GetGuildThreadUserAsync(ulong threadId, ulong user /// The ID of the thread. /// Pagination options for fetching users, or to use defaults. /// Optional properties to customize each request, can be . - [GenerateAlias([typeof(GuildThread)], nameof(GuildThread.Id))] + [GenerateAlias([typeof(IGuildThread)], nameof(IGuildThread.Id))] public IAsyncEnumerable GetGuildThreadUsersAsync(ulong threadId, OptionalGuildUsersPaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.PrepareWithDirectionValidation(paginationProperties, PaginationDirection.After, 100); @@ -866,7 +866,8 @@ public IAsyncEnumerable GetGuildThreadUsersAsync(ulong threadId, Opt /// The ID of the text channel. /// Pagination options for archived threads, or to use defaults. /// Optional properties to customize each request, can be . - [GenerateAlias([typeof(TextGuildChannel)], nameof(TextGuildChannel.Id))] + [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] + [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] public IAsyncEnumerable GetPublicArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.PrepareWithDirectionValidation(paginationProperties, PaginationDirection.Before, 100); @@ -893,7 +894,7 @@ public IAsyncEnumerable GetPublicArchivedGuildThreadsAsync(ulong ch /// The ID of the text channel. /// Pagination options for archived threads, or to use defaults. /// Optional properties to customize each request, can be . - [GenerateAlias([typeof(TextGuildChannel)], nameof(TextGuildChannel.Id))] + [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] public IAsyncEnumerable GetPrivateArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.PrepareWithDirectionValidation(paginationProperties, PaginationDirection.Before, 100); @@ -920,7 +921,7 @@ public IAsyncEnumerable GetPrivateArchivedGuildThreadsAsync(ulong c /// The ID of the text channel. /// Pagination options for archived threads, or to use defaults. /// Optional properties to customize each request, can be . - [GenerateAlias([typeof(TextGuildChannel)], nameof(TextGuildChannel.Id))] + [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] public IAsyncEnumerable GetJoinedPrivateArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.PrepareWithDirectionValidation(paginationProperties, PaginationDirection.Before, 100); diff --git a/NetCord/Rest/RestClient.Poll.cs b/NetCord/Rest/RestClient.Poll.cs index c5ac5ad48..8ad2e0263 100644 --- a/NetCord/Rest/RestClient.Poll.cs +++ b/NetCord/Rest/RestClient.Poll.cs @@ -4,7 +4,7 @@ namespace NetCord.Rest; public partial class RestClient { - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = nameof(Message))] public IAsyncEnumerable GetMessagePollAnswerVotersAsync(ulong channelId, ulong messageId, int answerId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { @@ -22,7 +22,7 @@ public IAsyncEnumerable GetMessagePollAnswerVotersAsync(ulong channelId, u properties); } - [GenerateAlias([typeof(TextChannel)], nameof(TextChannel.Id))] + [GenerateAlias([typeof(ITextChannel)], nameof(ITextChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = nameof(Message))] public async Task EndMessagePollAsync(ulong channelId, ulong messageId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => new(await (await SendRequestAsync(HttpMethod.Post, $"/channels/{channelId}/polls/{messageId}/expire", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonMessage).ConfigureAwait(false), this); diff --git a/NetCord/Rest/RestClient.StageInstance.cs b/NetCord/Rest/RestClient.StageInstance.cs index 27c68f95c..9b8c5de04 100644 --- a/NetCord/Rest/RestClient.StageInstance.cs +++ b/NetCord/Rest/RestClient.StageInstance.cs @@ -8,12 +8,12 @@ public async Task CreateStageInstanceAsync(StageInstancePropertie return new(await (await SendRequestAsync(HttpMethod.Post, content, $"/stage-instances", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonStageInstance).ConfigureAwait(false), this); } - [GenerateAlias([typeof(StageGuildChannel)], nameof(StageGuildChannel.Id))] + [GenerateAlias([typeof(IStageGuildChannel)], nameof(IStageGuildChannel.Id))] [GenerateAlias([typeof(StageInstance)], nameof(StageInstance.ChannelId))] public async Task GetStageInstanceAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => new(await (await SendRequestAsync(HttpMethod.Get, $"/stage-instances/{channelId}", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonStageInstance).ConfigureAwait(false), this); - [GenerateAlias([typeof(StageGuildChannel)], nameof(StageGuildChannel.Id))] + [GenerateAlias([typeof(IStageGuildChannel)], nameof(IStageGuildChannel.Id))] [GenerateAlias([typeof(StageInstance)], nameof(StageInstance.ChannelId))] public async Task ModifyStageInstanceAsync(ulong channelId, Action action, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { @@ -23,7 +23,7 @@ public async Task ModifyStageInstanceAsync(ulong channelId, Actio return new(await (await SendRequestAsync(HttpMethod.Patch, content, $"/stage-instances/{channelId}", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonStageInstance).ConfigureAwait(false), this); } - [GenerateAlias([typeof(StageGuildChannel)], nameof(StageGuildChannel.Id))] + [GenerateAlias([typeof(IStageGuildChannel)], nameof(IStageGuildChannel.Id))] [GenerateAlias([typeof(StageInstance)], nameof(StageInstance.ChannelId))] public Task DeleteStageInstanceAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => SendRequestAsync(HttpMethod.Delete, $"/stage-instances/{channelId}", null, null, properties, cancellationToken: cancellationToken); diff --git a/NetCord/Rest/RestClient.Undocumented.cs b/NetCord/Rest/RestClient.Undocumented.cs index d023c0d78..df0d7d9c3 100644 --- a/NetCord/Rest/RestClient.Undocumented.cs +++ b/NetCord/Rest/RestClient.Undocumented.cs @@ -8,7 +8,7 @@ public partial class RestClient public async Task GetApplicationAsync(ulong applicationId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => new(await (await SendRequestAsync(HttpMethod.Get, $"/applications/{applicationId}/rpc", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonApplication).ConfigureAwait(false), this); - [GenerateAlias([typeof(Channel)], nameof(Channel.Id))] + [GenerateAlias([typeof(IChannel)], nameof(IChannel.Id))] public async Task> CreateGoogleCloudPlatformStorageBucketsAsync(ulong channelId, IEnumerable buckets, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(new(buckets), Serialization.Default.GoogleCloudPlatformStorageBucketsProperties)) diff --git a/NetCord/Rest/RestClient.Webhook.cs b/NetCord/Rest/RestClient.Webhook.cs index 96859e0e1..5b745c297 100644 --- a/NetCord/Rest/RestClient.Webhook.cs +++ b/NetCord/Rest/RestClient.Webhook.cs @@ -14,8 +14,7 @@ public partial class RestClient /// Properties to customize the webhook's appearance. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(ForumGuildChannel)], nameof(ForumGuildChannel.Id))] - [GenerateAlias([typeof(TextGuildChannel)], nameof(TextGuildChannel.Id))] + [GenerateAlias([typeof(IWebhookChannel)], nameof(IWebhookChannel.Id))] public async Task CreateWebhookAsync(ulong channelId, WebhookProperties webhookProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(webhookProperties, Serialization.Default.WebhookProperties)) @@ -28,8 +27,7 @@ public async Task CreateWebhookAsync(ulong channelId, WebhookPr /// The ID of the channel to retrieve webhooks for. /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. - [GenerateAlias([typeof(ForumGuildChannel)], nameof(ForumGuildChannel.Id))] - [GenerateAlias([typeof(TextGuildChannel)], nameof(TextGuildChannel.Id))] + [GenerateAlias([typeof(IWebhookChannel)], nameof(IWebhookChannel.Id))] public async Task> GetChannelWebhooksAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => (await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}/webhooks", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonWebhookArray).ConfigureAwait(false)).Select(w => Webhook.CreateFromJson(w, this)).ToArray(); From 5647136aba0d48a4b826c42cfe74ad644e93a10a Mon Sep 17 00:00:00 2001 From: Andrzej Bansleben Date: Sun, 13 Sep 2026 13:41:01 +0200 Subject: [PATCH 4/5] Document ITextGuildChannel semantics --- NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs b/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs index 80b34f007..fa0479d64 100644 --- a/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs +++ b/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs @@ -1,5 +1,13 @@ namespace NetCord; +/// +/// Represents a regular text channel in a guild. +/// +/// +/// This only includes the GUILD_TEXT channel type +/// and excludes DMs and group DMs, annoucement channels, +/// voice and stage channels, and threads. +/// public interface ITextGuildChannel : IGuildMessageChannel, INamedChannel, From 00d7043524c17791acb0ad075dfcfcbf66af8736 Mon Sep 17 00:00:00 2001 From: Andrzej Bansleben Date: Sun, 13 Sep 2026 17:25:09 +0200 Subject: [PATCH 5/5] Introduce the first slice of the channels interfaces refactor This includes: - Replace classes with interfaces and make classes internal - Reorganise file structure for channels - Create a ChannelFactory to replace the old `*Channel.CreateFromJson` methods - Introduce a `TextChannelBase` abstraction This change now crossess the core assembly boundary and produces 93 errors on build. It is experimental and is a proof of concept for the proposed huge refactor --- .../basic-concepts/SendingMessages/Program.cs | 1 + .../ApplicationCommandContexts.cs | 20 +++--- .../AutocompleteInteractionContexts.cs | 4 +- NetCord.Services/Commands/CommandContexts.cs | 2 +- .../TypeReaders/Channels/ChannelTypeReader.cs | 4 +- .../Commands/TypeReaders/UserTypeReader.cs | 2 +- .../ComponentInteractionContexts.cs | 44 ++++++------ NetCord.Services/Contexts/IChannelContext.cs | 2 +- NetCord/ChannelMenuInteraction.cs | 2 +- NetCord/Channels/Channel.cs | 27 ++------ NetCord/Channels/ChannelFactory.cs | 69 +++++++++++++++++++ NetCord/Channels/DMChannel.cs | 17 +++++ .../{TextChannels => }/GroupDMChannel.cs | 2 +- .../Guild/AnnouncementGuildChannel.cs | 25 +++++++ .../{ => Guild}/CategoryGuildChannel.cs | 2 +- .../Guild/DirectoryGuildChannel.cs | 4 +- .../Guild/ForumGuildChannel.cs | 2 +- .../Channels/Guild/GuildMessageChannelBase.cs | 9 +++ .../Guild/IAnnouncementGuildChannel.cs | 2 +- .../{ => Guild}/ICategoryGuildChannel.cs | 2 +- .../Channels/Guild/IDirectoryGuildChannel.cs | 5 ++ NetCord/Channels/{ => Guild}/IGuildChannel.cs | 12 ++-- .../Guild/ITextGuildChannel.cs | 2 +- .../Guild/IThreadOnlyGuildChannel.cs | 6 +- .../{ => Guild}/IUnknownGuildChannel.cs | 0 .../Guild/IVoiceChannel.cs | 6 +- .../Guild/MediaForumGuildChannel.cs | 2 +- NetCord/Channels/Guild/StageGuildChannel.cs | 10 +++ .../Guild/TextGuildChannel.cs | 4 +- .../Guild/Threads/AnnouncementGuildThread.cs | 2 +- .../Guild/Threads/ForumGuildThread.cs | 2 +- .../Guild/Threads/GuildThread.cs | 37 +++++----- .../Guild/Threads/GuildThreadMetadata.cs | 0 .../Guild/Threads/IGuildThread.cs | 10 +-- .../Guild/Threads/PrivateGuildThread.cs | 2 +- .../Guild/Threads/PublicGuildThread.cs | 2 +- .../Guild/Threads/UnknownGuildThread.cs | 0 .../{ => Guild}/UnknownGuildChannel.cs | 0 NetCord/Channels/Guild/VoiceGuildChannel.cs | 27 ++++++++ NetCord/Channels/IChannel.cs | 15 ++-- NetCord/Channels/IDMChannel.cs | 6 ++ .../{TextChannels => }/IGroupDMChannel.cs | 2 +- NetCord/Channels/IInviteChannel.cs | 2 +- .../{TextChannels => }/ITextChannel.cs | 10 ++- NetCord/Channels/IUnknownChannel.cs | 4 +- .../{TextChannels => }/IUnknownDMChannel.cs | 2 +- .../{TextChannels => }/IUnknownTextChannel.cs | 2 +- NetCord/Channels/TextChannel.cs | 13 ++++ NetCord/Channels/TextChannelBase.cs | 10 +++ NetCord/Channels/TextChannels/DMChannel.cs | 24 ------- .../Guild/AnnouncementGuildChannel.cs | 10 --- .../Guild/IDirectoryGuildChannel.cs | 5 -- NetCord/Channels/TextChannels/IDMChannel.cs | 6 -- NetCord/Channels/TextChannels/TextChannel.cs | 38 ---------- .../{TextChannels => }/UnknownDMChannel.cs | 0 .../{TextChannels => }/UnknownTextChannel.cs | 2 +- .../VoiceChannels/Guild/StageGuildChannel.cs | 17 ----- .../VoiceChannels/Guild/VoiceGuildChannel.cs | 17 ----- NetCord/Components/ChannelMenu.cs | 2 +- NetCord/Components/EntityMenu.cs | 2 +- NetCord/Components/EntityMenuHelper.cs | 2 +- NetCord/EntityArrayWrapper.cs | 2 +- NetCord/EntityMenuInteraction.cs | 2 +- .../Gateway/ConcurrentGatewayClientCache.cs | 4 +- .../EventArgs/GuildThreadCreateEventArgs.cs | 4 +- .../EventArgs/GuildThreadListSyncEventArgs.cs | 2 +- NetCord/Gateway/GatewayClient.cs | 12 ++-- NetCord/Gateway/Guild.cs | 6 +- NetCord/Gateway/IGatewayClientCache.cs | 4 +- .../Gateway/ImmutableGatewayClientCache.cs | 4 +- NetCord/Gateway/Message.cs | 10 +-- NetCord/Interaction.cs | 4 +- NetCord/InteractionResolvedData.cs | 4 +- NetCord/MessageComponentInteraction.cs | 2 +- NetCord/ModalInteraction.cs | 2 +- NetCord/PartialGuildUserExtensions.cs | 20 +++--- NetCord/Rest/GuildMessageSearchResult.cs | 2 +- NetCord/Rest/GuildTemplatePreview.cs | 2 +- NetCord/Rest/GuildThreadGenerator.cs | 4 +- NetCord/Rest/RestAuditLogEntryData.cs | 2 +- NetCord/Rest/RestClient.Channel.cs | 49 +++++++------ NetCord/Rest/RestClient.Guild.cs | 6 +- NetCord/Rest/RestClient.User.cs | 8 +-- NetCord/Rest/RestInvite.cs | 4 +- NetCord/Rest/RestMessage.cs | 4 +- NetCord/Rest/Webhook.cs | 4 +- 86 files changed, 400 insertions(+), 329 deletions(-) create mode 100644 NetCord/Channels/ChannelFactory.cs create mode 100644 NetCord/Channels/DMChannel.cs rename NetCord/Channels/{TextChannels => }/GroupDMChannel.cs (87%) create mode 100644 NetCord/Channels/Guild/AnnouncementGuildChannel.cs rename NetCord/Channels/{ => Guild}/CategoryGuildChannel.cs (74%) rename NetCord/Channels/{TextChannels => }/Guild/DirectoryGuildChannel.cs (56%) rename NetCord/Channels/{TextChannels => }/Guild/ForumGuildChannel.cs (97%) create mode 100644 NetCord/Channels/Guild/GuildMessageChannelBase.cs rename NetCord/Channels/{TextChannels => }/Guild/IAnnouncementGuildChannel.cs (86%) rename NetCord/Channels/{ => Guild}/ICategoryGuildChannel.cs (81%) create mode 100644 NetCord/Channels/Guild/IDirectoryGuildChannel.cs rename NetCord/Channels/{ => Guild}/IGuildChannel.cs (82%) rename NetCord/Channels/{TextChannels => }/Guild/ITextGuildChannel.cs (93%) rename NetCord/Channels/{TextChannels => }/Guild/IThreadOnlyGuildChannel.cs (76%) rename NetCord/Channels/{ => Guild}/IUnknownGuildChannel.cs (100%) rename NetCord/Channels/{VoiceChannels => }/Guild/IVoiceChannel.cs (87%) rename NetCord/Channels/{TextChannels => }/Guild/MediaForumGuildChannel.cs (55%) create mode 100644 NetCord/Channels/Guild/StageGuildChannel.cs rename NetCord/Channels/{TextChannels => }/Guild/TextGuildChannel.cs (89%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/AnnouncementGuildThread.cs (52%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/ForumGuildThread.cs (83%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/GuildThread.cs (68%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/GuildThreadMetadata.cs (100%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/IGuildThread.cs (78%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/PrivateGuildThread.cs (50%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/PublicGuildThread.cs (75%) rename NetCord/Channels/{TextChannels => }/Guild/Threads/UnknownGuildThread.cs (100%) rename NetCord/Channels/{ => Guild}/UnknownGuildChannel.cs (100%) create mode 100644 NetCord/Channels/Guild/VoiceGuildChannel.cs create mode 100644 NetCord/Channels/IDMChannel.cs rename NetCord/Channels/{TextChannels => }/IGroupDMChannel.cs (94%) rename NetCord/Channels/{TextChannels => }/ITextChannel.cs (54%) rename NetCord/Channels/{TextChannels => }/IUnknownDMChannel.cs (65%) rename NetCord/Channels/{TextChannels => }/IUnknownTextChannel.cs (62%) create mode 100644 NetCord/Channels/TextChannel.cs create mode 100644 NetCord/Channels/TextChannelBase.cs delete mode 100644 NetCord/Channels/TextChannels/DMChannel.cs delete mode 100644 NetCord/Channels/TextChannels/Guild/AnnouncementGuildChannel.cs delete mode 100644 NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs delete mode 100644 NetCord/Channels/TextChannels/IDMChannel.cs delete mode 100644 NetCord/Channels/TextChannels/TextChannel.cs rename NetCord/Channels/{TextChannels => }/UnknownDMChannel.cs (100%) rename NetCord/Channels/{TextChannels => }/UnknownTextChannel.cs (70%) delete mode 100644 NetCord/Channels/VoiceChannels/Guild/StageGuildChannel.cs delete mode 100644 NetCord/Channels/VoiceChannels/Guild/VoiceGuildChannel.cs diff --git a/Documentation/guides/basic-concepts/SendingMessages/Program.cs b/Documentation/guides/basic-concepts/SendingMessages/Program.cs index 463110921..2aef74e3a 100644 --- a/Documentation/guides/basic-concepts/SendingMessages/Program.cs +++ b/Documentation/guides/basic-concepts/SendingMessages/Program.cs @@ -128,6 +128,7 @@ async static Task PropertiesAsync() attachment = new QuotedPrintableAttachmentProperties("polish.txt", new MemoryStream("R=C3=B3=C5=BCowy means pink"u8.ToArray())); + // TODO: This guide is outdated for the new channels interface representation. TextChannel textChannel = null!; HttpClient httpClient = null!; diff --git a/NetCord.Services/ApplicationCommands/ApplicationCommandContexts.cs b/NetCord.Services/ApplicationCommands/ApplicationCommandContexts.cs index c908d7067..3f6242ccc 100644 --- a/NetCord.Services/ApplicationCommands/ApplicationCommandContexts.cs +++ b/NetCord.Services/ApplicationCommands/ApplicationCommandContexts.cs @@ -29,7 +29,7 @@ public class ApplicationCommandContext(ApplicationCommandInteraction interaction public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; @@ -50,7 +50,7 @@ public class HttpApplicationCommandContext(ApplicationCommandInteraction interac public RestClient Client => client; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => (ITextChannel)Interaction.Channel; public User User => Interaction.User; } @@ -84,7 +84,7 @@ public class SlashCommandContext(SlashCommandInteraction interaction, GatewayCli public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; @@ -105,7 +105,7 @@ public class HttpSlashCommandContext(SlashCommandInteraction interaction, RestCl public RestClient Client => client; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; } @@ -139,7 +139,7 @@ public class UserCommandContext(UserCommandInteraction interaction, GatewayClien public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; @@ -165,7 +165,7 @@ public class HttpUserCommandContext(UserCommandInteraction interaction, RestClie public RestClient Client => client; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; @@ -204,7 +204,7 @@ public class MessageCommandContext(MessageCommandInteraction interaction, Gatewa public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; @@ -230,7 +230,7 @@ public class HttpMessageCommandContext(MessageCommandInteraction interaction, Re public RestClient Client => client; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; @@ -269,7 +269,7 @@ public class EntryPointCommandContext(EntryPointCommandInteraction interaction, public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; @@ -290,7 +290,7 @@ public class HttpEntryPointCommandContext(EntryPointCommandInteraction interacti public RestClient Client => client; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; public User User => Interaction.User; } diff --git a/NetCord.Services/ApplicationCommands/AutocompleteInteractionContexts.cs b/NetCord.Services/ApplicationCommands/AutocompleteInteractionContexts.cs index 56e8f1f0b..df732dfb9 100644 --- a/NetCord.Services/ApplicationCommands/AutocompleteInteractionContexts.cs +++ b/NetCord.Services/ApplicationCommands/AutocompleteInteractionContexts.cs @@ -28,7 +28,7 @@ public class AutocompleteInteractionContext(AutocompleteInteraction interaction, public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => (ITextChannel)Interaction.Channel; public User User => Interaction.User; @@ -49,7 +49,7 @@ public class HttpAutocompleteInteractionContext(AutocompleteInteraction interact public RestClient Client => client; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => (ITextChannel)Interaction.Channel; public User User => Interaction.User; } diff --git a/NetCord.Services/Commands/CommandContexts.cs b/NetCord.Services/Commands/CommandContexts.cs index 75afca73e..a7c1eec2c 100644 --- a/NetCord.Services/Commands/CommandContexts.cs +++ b/NetCord.Services/Commands/CommandContexts.cs @@ -28,7 +28,7 @@ public class CommandContext(Message message, GatewayClient client) public Guild? Guild => Message.Guild; /// - public TextChannel? Channel => Message.Channel; + public ITextChannel? Channel => Message.Channel; public User User => Message.Author; diff --git a/NetCord.Services/Commands/TypeReaders/Channels/ChannelTypeReader.cs b/NetCord.Services/Commands/TypeReaders/Channels/ChannelTypeReader.cs index 6077e9805..370b1ffef 100644 --- a/NetCord.Services/Commands/TypeReaders/Channels/ChannelTypeReader.cs +++ b/NetCord.Services/Commands/TypeReaders/Channels/ChannelTypeReader.cs @@ -14,12 +14,12 @@ public override ValueTask ParseAsync(ReadOnlyMemory(channel, input.Span)); } else - return new(GetGuildChannel(guild, input.Span)); + return new(GetGuildChannel(guild, input.Span)); return new(CommandTypeParserResult.Fail("The channel was not found.")); } - protected CommandTypeParserResult GetChannel(TextChannel channel, ReadOnlySpan input) + protected CommandTypeParserResult GetChannel(ITextChannel channel, ReadOnlySpan input) { if (Mention.TryParseChannel(input, out var id)) { diff --git a/NetCord.Services/Commands/TypeReaders/UserTypeReader.cs b/NetCord.Services/Commands/TypeReaders/UserTypeReader.cs index d471c8751..db3daba3e 100644 --- a/NetCord.Services/Commands/TypeReaders/UserTypeReader.cs +++ b/NetCord.Services/Commands/TypeReaders/UserTypeReader.cs @@ -20,7 +20,7 @@ public override ValueTask ParseAsync(ReadOnlyMemory input) + protected CommandTypeParserResult GetUser(IDMChannel dMChannel, ReadOnlySpan input) { var users = dMChannel.Users; diff --git a/NetCord.Services/ComponentInteractions/ComponentInteractionContexts.cs b/NetCord.Services/ComponentInteractions/ComponentInteractionContexts.cs index 29a4534c7..368fc59fb 100644 --- a/NetCord.Services/ComponentInteractions/ComponentInteractionContexts.cs +++ b/NetCord.Services/ComponentInteractions/ComponentInteractionContexts.cs @@ -32,7 +32,7 @@ public class ComponentInteractionContext(ComponentInteraction interaction, Gatew public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; ulong? IGuildContext.GuildId => Interaction.GuildId; } @@ -53,7 +53,7 @@ public class HttpComponentInteractionContext(ComponentInteraction interaction, R public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; } /// @@ -90,7 +90,7 @@ public class MessageComponentInteractionContext(MessageComponentInteraction inte public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; ulong? IGuildContext.GuildId => Interaction.GuildId; } @@ -114,7 +114,7 @@ public class HttpMessageComponentInteractionContext(MessageComponentInteraction public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; } /// @@ -151,7 +151,7 @@ public class ButtonInteractionContext(ButtonInteraction interaction, GatewayClie public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; ulong? IGuildContext.GuildId => Interaction.GuildId; } @@ -175,7 +175,7 @@ public class HttpButtonInteractionContext(ButtonInteraction interaction, RestCli public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; } /// @@ -212,7 +212,7 @@ public class StringMenuInteractionContext(StringMenuInteraction interaction, Gat public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected string values from the menu. @@ -241,7 +241,7 @@ public class HttpStringMenuInteractionContext(StringMenuInteraction interaction, public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected string values from the menu. @@ -283,7 +283,7 @@ public class EntityMenuInteractionContext(EntityMenuInteraction interaction, Gat public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected entity IDs from the menu. @@ -312,7 +312,7 @@ public class HttpEntityMenuInteractionContext(EntityMenuInteraction interaction, public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected entity IDs from the menu. @@ -354,7 +354,7 @@ public class UserMenuInteractionContext(UserMenuInteraction interaction, Gateway public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected users from the menu. @@ -383,7 +383,7 @@ public class HttpUserMenuInteractionContext(UserMenuInteraction interaction, Res public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected users from the menu. @@ -425,7 +425,7 @@ public class RoleMenuInteractionContext(RoleMenuInteraction interaction, Gateway public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected roles from the menu. @@ -454,7 +454,7 @@ public class HttpRoleMenuInteractionContext(RoleMenuInteraction interaction, Res public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected roles from the menu. @@ -496,7 +496,7 @@ public class MentionableMenuInteractionContext(MentionableMenuInteraction intera public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected mentionables (users or roles) from the menu. @@ -525,7 +525,7 @@ public class HttpMentionableMenuInteractionContext(MentionableMenuInteraction in public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The selected mentionables (users or roles) from the menu. @@ -567,12 +567,12 @@ public class ChannelMenuInteractionContext(ChannelMenuInteraction interaction, G public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => (ITextChannel)Interaction.Channel; /// /// The selected channels from the menu. /// - public IReadOnlyList SelectedValues => Interaction.Data.SelectedValues; + public IReadOnlyList SelectedValues => Interaction.Data.SelectedValues; ulong? IGuildContext.GuildId => Interaction.GuildId; } @@ -596,12 +596,12 @@ public class HttpChannelMenuInteractionContext(ChannelMenuInteraction interactio public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => (ITextChannel)Interaction.Channel; /// /// The selected channels from the menu. /// - public IReadOnlyList SelectedValues => Interaction.Data.SelectedValues; + public IReadOnlyList SelectedValues => Interaction.Data.SelectedValues; } /// @@ -635,7 +635,7 @@ public class ModalInteractionContext(ModalInteraction interaction, GatewayClient public Guild? Guild => Interaction.Guild; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The components submitted with the modal. @@ -661,7 +661,7 @@ public class HttpModalInteractionContext(ModalInteraction interaction, RestClien public User User => Interaction.User; /// - public TextChannel Channel => Interaction.Channel; + public ITextChannel Channel => Interaction.Channel; /// /// The components submitted with the modal. diff --git a/NetCord.Services/Contexts/IChannelContext.cs b/NetCord.Services/Contexts/IChannelContext.cs index 1d16066b3..7ddfca14d 100644 --- a/NetCord.Services/Contexts/IChannelContext.cs +++ b/NetCord.Services/Contexts/IChannelContext.cs @@ -9,5 +9,5 @@ public interface IChannelContext : IContext /// Channel in which the handled command or interaction was invoked. /// /// May be if the channel has not been cached. - public TextChannel? Channel { get; } + public ITextChannel? Channel { get; } } diff --git a/NetCord/ChannelMenuInteraction.cs b/NetCord/ChannelMenuInteraction.cs index 887900a89..eac5b4868 100644 --- a/NetCord/ChannelMenuInteraction.cs +++ b/NetCord/ChannelMenuInteraction.cs @@ -19,5 +19,5 @@ public unsafe ChannelMenuInteractionData(JsonModels.JsonInteractionData jsonMode SelectedValues = selectedValues; } - public new IReadOnlyList SelectedValues { get; } + public new IReadOnlyList SelectedValues { get; } } diff --git a/NetCord/Channels/Channel.cs b/NetCord/Channels/Channel.cs index a2f0e00cf..4f8fb2d73 100644 --- a/NetCord/Channels/Channel.cs +++ b/NetCord/Channels/Channel.cs @@ -3,38 +3,19 @@ namespace NetCord; -public abstract partial class Channel(JsonChannel jsonModel, RestClient client) : ClientEntity(client), IJsonModel, IInteractionChannel +internal abstract partial class Channel(JsonChannel jsonModel, RestClient client) : ClientEntity(client), IJsonModel, IInteractionChannel { JsonChannel IJsonModel.JsonModel => _jsonModel; + private protected JsonChannel _jsonModel = jsonModel; public override ulong Id => _jsonModel.Id; - public ChannelFlags Flags => _jsonModel.Flags.GetValueOrDefault(); + + public ChannelFlags? Flags => _jsonModel.Flags; Permissions IInteractionChannel.Permissions => _jsonModel.Permissions.GetValueOrDefault(); public override string ToString() => $"<#{Id}>"; public override bool TryFormat(Span destination, out int charsWritten, ReadOnlySpan format = default, IFormatProvider? provider = null) => Mention.TryFormatChannel(destination, out charsWritten, Id); - - public static Channel CreateFromJson(JsonChannel jsonChannel, RestClient client) - { - return jsonChannel.Type switch - { - ChannelType.TextGuildChannel => new TextGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.DMChannel => new DMChannel(jsonChannel, client), - ChannelType.VoiceGuildChannel => new VoiceGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.GroupDMChannel => new GroupDMChannel(jsonChannel, client), - ChannelType.CategoryChannel => new CategoryGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.AnnouncementGuildChannel => new AnnouncementGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.AnnouncementGuildThread => new AnnouncementGuildThread(jsonChannel, client), - ChannelType.PublicGuildThread => new PublicGuildThread(jsonChannel, client), - ChannelType.PrivateGuildThread => new PrivateGuildThread(jsonChannel, client), - ChannelType.StageGuildChannel => new StageGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.DirectoryGuildChannel => new DirectoryGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.ForumGuildChannel => new ForumGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.MediaForumGuildChannel => new MediaForumGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - _ => new UnknownChannel(jsonChannel, client), - }; - } } diff --git a/NetCord/Channels/ChannelFactory.cs b/NetCord/Channels/ChannelFactory.cs new file mode 100644 index 000000000..508b5f36f --- /dev/null +++ b/NetCord/Channels/ChannelFactory.cs @@ -0,0 +1,69 @@ +using NetCord.JsonModels; +using NetCord.Rest; + +namespace NetCord; + +internal static class ChannelFactory +{ + public static IGuildChannel CreateGuild( + JsonChannel jsonChannel, + RestClient client) + => Require(Create(jsonChannel, client)); + + public static ITextChannel CreateText( + JsonChannel jsonChannel, + RestClient client) + => Require(Create(jsonChannel, client)); + + public static IDMChannel CreateDM( + JsonChannel jsonChannel, + RestClient client) + => Require(Create(jsonChannel, client)); + + public static IGroupDMChannel CreateGroupDM( + JsonChannel jsonChannel, + RestClient client) + => Require(Create(jsonChannel, client)); + + public static IGuildThread CreateGuildThread( + JsonChannel jsonChannel, + RestClient client) + => Require(Create(jsonChannel, client)); + + public static IPublicGuildThread CreatePublicGuildThread( + JsonChannel jsonChannel, + RestClient client) + => Require(Create(jsonChannel, client)); + + public static IChannel Create( + JsonChannel jsonChannel, + RestClient client) + { + return jsonChannel.Type switch + { + ChannelType.TextGuildChannel => new TextGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + ChannelType.DMChannel => new DMChannel(jsonChannel, client), + ChannelType.VoiceGuildChannel => new VoiceGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + ChannelType.GroupDMChannel => new GroupDMChannel(jsonChannel, client), + ChannelType.CategoryChannel => new CategoryGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + ChannelType.AnnouncementGuildChannel => new AnnouncementGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + ChannelType.AnnouncementGuildThread => new AnnouncementGuildThread(jsonChannel, client), + ChannelType.PublicGuildThread => new PublicGuildThread(jsonChannel, client), + ChannelType.PrivateGuildThread => new PrivateGuildThread(jsonChannel, client), + ChannelType.StageGuildChannel => new StageGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + ChannelType.DirectoryGuildChannel => new DirectoryGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + ChannelType.ForumGuildChannel => new ForumGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + ChannelType.MediaForumGuildChannel => new MediaForumGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), + _ => new UnknownChannel(jsonChannel, client), + }; + } + + private static TChannel Require(IChannel channel) + where TChannel : IChannel + { + if (channel is TChannel result) + return result; + + throw new InvalidOperationException(); + } +} \ No newline at end of file diff --git a/NetCord/Channels/DMChannel.cs b/NetCord/Channels/DMChannel.cs new file mode 100644 index 000000000..e54d05cba --- /dev/null +++ b/NetCord/Channels/DMChannel.cs @@ -0,0 +1,17 @@ +using NetCord.Rest; + +namespace NetCord; + +/// +/// Represents a text channel for private messages between two users. +/// +internal partial class DMChannel(JsonModels.JsonChannel jsonModel, RestClient client) : TextChannelBase(jsonModel, client), IDMChannel +{ + /// + /// A list of the users present in the private channel, indexed by their IDs. + /// + public IReadOnlyDictionary Users { get; } = jsonModel.Users.ToDictionaryOrEmpty(u => u.Id, u => new User(u, client)); + + /// + public DateTimeOffset? LastPin => throw new NotImplementedException(); +} diff --git a/NetCord/Channels/TextChannels/GroupDMChannel.cs b/NetCord/Channels/GroupDMChannel.cs similarity index 87% rename from NetCord/Channels/TextChannels/GroupDMChannel.cs rename to NetCord/Channels/GroupDMChannel.cs index d0474a43d..87c2749b3 100644 --- a/NetCord/Channels/TextChannels/GroupDMChannel.cs +++ b/NetCord/Channels/GroupDMChannel.cs @@ -5,7 +5,7 @@ namespace NetCord; /// /// Represents a text channel for private messages, with up to 10 users. /// -public partial class GroupDMChannel(JsonModels.JsonChannel jsonModel, RestClient client) : DMChannel(jsonModel, client), INamedChannel +internal partial class GroupDMChannel(JsonModels.JsonChannel jsonModel, RestClient client) : DMChannel(jsonModel, client), INamedChannel { /// /// The group channel's name. diff --git a/NetCord/Channels/Guild/AnnouncementGuildChannel.cs b/NetCord/Channels/Guild/AnnouncementGuildChannel.cs new file mode 100644 index 000000000..b824026b7 --- /dev/null +++ b/NetCord/Channels/Guild/AnnouncementGuildChannel.cs @@ -0,0 +1,25 @@ +using NetCord.Rest; + +namespace NetCord; + +/// +/// Represents a channel that users can follow and crosspost from into their own servers. Formerly known as news channels. +/// +internal partial class AnnouncementGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : GuildMessageChannelBase(jsonModel, guildId, client), IAnnouncementGuildChannel +{ + public string? Topic => _jsonModel.Topic; + + public bool? Nsfw => _jsonModel.Nsfw; + + public int? Slowmode => _jsonModel.Slowmode; + + public ThreadArchiveDuration? DefaultAutoArchiveDuration => _jsonModel.DefaultAutoArchiveDuration; + + public string Name => _jsonModel.Name!; + + public int Position => _jsonModel.Position.GetValueOrDefault(); + + public ulong? ParentId => _jsonModel.ParentId; + public IReadOnlyDictionary PermissionOverwrites => _jsonModel.PermissionOverwrites.ToDictionaryOrEmpty(p => p.Id, p => new PermissionOverwrite(p)); + public DateTimeOffset? LastPin => _jsonModel.LastPin; +} diff --git a/NetCord/Channels/CategoryGuildChannel.cs b/NetCord/Channels/Guild/CategoryGuildChannel.cs similarity index 74% rename from NetCord/Channels/CategoryGuildChannel.cs rename to NetCord/Channels/Guild/CategoryGuildChannel.cs index 9d30739ec..1e953d5c2 100644 --- a/NetCord/Channels/CategoryGuildChannel.cs +++ b/NetCord/Channels/Guild/CategoryGuildChannel.cs @@ -5,7 +5,7 @@ namespace NetCord; /// /// Represents a category within a guild. /// -public partial class CategoryGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : Channel(jsonModel, client), IGuildChannel +internal partial class CategoryGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : Channel(jsonModel, client), IGuildChannel { public ulong GuildId { get; } = guildId; diff --git a/NetCord/Channels/TextChannels/Guild/DirectoryGuildChannel.cs b/NetCord/Channels/Guild/DirectoryGuildChannel.cs similarity index 56% rename from NetCord/Channels/TextChannels/Guild/DirectoryGuildChannel.cs rename to NetCord/Channels/Guild/DirectoryGuildChannel.cs index 9e149d0e1..843e5409f 100644 --- a/NetCord/Channels/TextChannels/Guild/DirectoryGuildChannel.cs +++ b/NetCord/Channels/Guild/DirectoryGuildChannel.cs @@ -6,10 +6,10 @@ namespace NetCord; /// /// Represents a hub channel, with listed guilds. /// -public partial class DirectoryGuildChannel(JsonChannel jsonModel, ulong guildId, RestClient client) : TextChannel(jsonModel, client), IGuildChannel +internal partial class DirectoryGuildChannel(JsonChannel jsonModel, ulong guildId, RestClient client) : TextChannelBase(jsonModel, client), IGuildChannel { public ulong GuildId { get; } = guildId; public int? Position => _jsonModel.Position; - public IReadOnlyDictionary PermissionOverwrites { get; } = jsonModel.PermissionOverwrites.ToDictionaryOrEmpty(p => p.Id, p => new PermissionOverwrite(p)); + public IReadOnlyDictionary PermissionOverwrites => _jsonModel.PermissionOverwrites.ToDictionaryOrEmpty(p => p.Id, p => new PermissionOverwrite(p)); public string Name => _jsonModel.Name!; } diff --git a/NetCord/Channels/TextChannels/Guild/ForumGuildChannel.cs b/NetCord/Channels/Guild/ForumGuildChannel.cs similarity index 97% rename from NetCord/Channels/TextChannels/Guild/ForumGuildChannel.cs rename to NetCord/Channels/Guild/ForumGuildChannel.cs index 75127fecf..82e473e6b 100644 --- a/NetCord/Channels/TextChannels/Guild/ForumGuildChannel.cs +++ b/NetCord/Channels/Guild/ForumGuildChannel.cs @@ -6,7 +6,7 @@ namespace NetCord; /// /// Represents a forum channel within a guild. /// -public partial class ForumGuildChannel : Channel, IGuildChannel +internal partial class ForumGuildChannel : Channel, IGuildChannel { public ForumGuildChannel(JsonChannel jsonModel, ulong guildId, RestClient client) : base(jsonModel, client) { diff --git a/NetCord/Channels/Guild/GuildMessageChannelBase.cs b/NetCord/Channels/Guild/GuildMessageChannelBase.cs new file mode 100644 index 000000000..cde17648b --- /dev/null +++ b/NetCord/Channels/Guild/GuildMessageChannelBase.cs @@ -0,0 +1,9 @@ +using NetCord.JsonModels; +using NetCord.Rest; + +namespace NetCord; + +internal abstract partial class GuildMessageChannelBase(JsonChannel jsonModel, ulong guildId, RestClient client) : TextChannelBase(jsonModel, client), IGuildMessageChannel +{ + public ulong GuildId => guildId; +} \ No newline at end of file diff --git a/NetCord/Channels/TextChannels/Guild/IAnnouncementGuildChannel.cs b/NetCord/Channels/Guild/IAnnouncementGuildChannel.cs similarity index 86% rename from NetCord/Channels/TextChannels/Guild/IAnnouncementGuildChannel.cs rename to NetCord/Channels/Guild/IAnnouncementGuildChannel.cs index e227a1389..df27ef6c7 100644 --- a/NetCord/Channels/TextChannels/Guild/IAnnouncementGuildChannel.cs +++ b/NetCord/Channels/Guild/IAnnouncementGuildChannel.cs @@ -1,6 +1,6 @@ namespace NetCord; -public interface IAnnouncementGuildChannel : +public partial interface IAnnouncementGuildChannel : IGuildMessageChannel, INamedChannel, IPositionedGuildChannel, diff --git a/NetCord/Channels/ICategoryGuildChannel.cs b/NetCord/Channels/Guild/ICategoryGuildChannel.cs similarity index 81% rename from NetCord/Channels/ICategoryGuildChannel.cs rename to NetCord/Channels/Guild/ICategoryGuildChannel.cs index 0e6eb30e4..ed46f3289 100644 --- a/NetCord/Channels/ICategoryGuildChannel.cs +++ b/NetCord/Channels/Guild/ICategoryGuildChannel.cs @@ -3,7 +3,7 @@ namespace NetCord; /// /// Represents an organizational category that contains up to 50 channels. /// -public interface ICategoryGuildChannel : +public partial interface ICategoryGuildChannel : IGuildChannel, IPermissionOverwriteChannel, INamedChannel, IPositionedGuildChannel { } diff --git a/NetCord/Channels/Guild/IDirectoryGuildChannel.cs b/NetCord/Channels/Guild/IDirectoryGuildChannel.cs new file mode 100644 index 000000000..e2b246e59 --- /dev/null +++ b/NetCord/Channels/Guild/IDirectoryGuildChannel.cs @@ -0,0 +1,5 @@ +namespace NetCord; + +public partial interface IDirectoryGuildChannel : IGuildChannel, IPermissionOverwriteChannel, INamedChannel, IPositionedGuildChannel +{ +} \ No newline at end of file diff --git a/NetCord/Channels/IGuildChannel.cs b/NetCord/Channels/Guild/IGuildChannel.cs similarity index 82% rename from NetCord/Channels/IGuildChannel.cs rename to NetCord/Channels/Guild/IGuildChannel.cs index 74a1529e2..7a447a340 100644 --- a/NetCord/Channels/IGuildChannel.cs +++ b/NetCord/Channels/Guild/IGuildChannel.cs @@ -1,6 +1,6 @@ namespace NetCord; -public interface IGuildChannel : IChannel +public partial interface IGuildChannel : IChannel { ulong GuildId { get; } } @@ -20,14 +20,14 @@ public interface IGuildChannel : IChannel /// PRIVATE_THREAD /// /// -public interface IGuildMessageChannel : ITextChannel, IGuildChannel +public partial interface IGuildMessageChannel : ITextChannel, IGuildChannel { } /// /// Represents a guild channel that has a position and can have a parent category. /// -public interface IPositionedGuildChannel : IGuildChannel +public partial interface IPositionedGuildChannel : IGuildChannel { /// /// The channel's position within the guild channel list. @@ -46,7 +46,7 @@ public interface IPositionedGuildChannel : IGuildChannel /// /// Represents a guild channel that has permission overwrites. /// -public interface IPermissionOverwriteChannel : IGuildChannel +public partial interface IPermissionOverwriteChannel : IGuildChannel { IReadOnlyDictionary PermissionOverwrites { get; } } @@ -64,7 +64,7 @@ public interface IPermissionOverwriteChannel : IGuildChannel /// /// For threads, use the parent channel's webhooks. /// -public interface IWebhookChannel : IGuildChannel +public partial interface IWebhookChannel : IGuildChannel { } @@ -82,6 +82,6 @@ public interface IWebhookChannel : IGuildChannel /// GUILD_MEDIA /// /// -public interface IInvitableGuildChannel : IGuildChannel +public partial interface IInvitableGuildChannel : IGuildChannel { } diff --git a/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs b/NetCord/Channels/Guild/ITextGuildChannel.cs similarity index 93% rename from NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs rename to NetCord/Channels/Guild/ITextGuildChannel.cs index fa0479d64..3441a0c45 100644 --- a/NetCord/Channels/TextChannels/Guild/ITextGuildChannel.cs +++ b/NetCord/Channels/Guild/ITextGuildChannel.cs @@ -8,7 +8,7 @@ namespace NetCord; /// and excludes DMs and group DMs, annoucement channels, /// voice and stage channels, and threads. /// -public interface ITextGuildChannel : +public partial interface ITextGuildChannel : IGuildMessageChannel, INamedChannel, IPositionedGuildChannel, diff --git a/NetCord/Channels/TextChannels/Guild/IThreadOnlyGuildChannel.cs b/NetCord/Channels/Guild/IThreadOnlyGuildChannel.cs similarity index 76% rename from NetCord/Channels/TextChannels/Guild/IThreadOnlyGuildChannel.cs rename to NetCord/Channels/Guild/IThreadOnlyGuildChannel.cs index 09a369488..62cfe1dd1 100644 --- a/NetCord/Channels/TextChannels/Guild/IThreadOnlyGuildChannel.cs +++ b/NetCord/Channels/Guild/IThreadOnlyGuildChannel.cs @@ -1,6 +1,6 @@ namespace NetCord; -public interface IThreadOnlyGuildChannel : +public partial interface IThreadOnlyGuildChannel : IGuildChannel, INamedChannel, IPositionedGuildChannel, @@ -24,11 +24,11 @@ public interface IThreadOnlyGuildChannel : SortOrderType? DefaultSortOrder { get; } } -public interface IForumGuildChannel : IThreadOnlyGuildChannel +public partial interface IForumGuildChannel : IThreadOnlyGuildChannel { ForumLayoutType DefaultForumLayout { get; } } -public interface IMediaGuildChannel : IThreadOnlyGuildChannel +public partial interface IMediaGuildChannel : IThreadOnlyGuildChannel { } diff --git a/NetCord/Channels/IUnknownGuildChannel.cs b/NetCord/Channels/Guild/IUnknownGuildChannel.cs similarity index 100% rename from NetCord/Channels/IUnknownGuildChannel.cs rename to NetCord/Channels/Guild/IUnknownGuildChannel.cs diff --git a/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs b/NetCord/Channels/Guild/IVoiceChannel.cs similarity index 87% rename from NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs rename to NetCord/Channels/Guild/IVoiceChannel.cs index 9db08ceaf..599cbd808 100644 --- a/NetCord/Channels/VoiceChannels/Guild/IVoiceChannel.cs +++ b/NetCord/Channels/Guild/IVoiceChannel.cs @@ -1,6 +1,6 @@ namespace NetCord; -public interface IVoiceChannel : IGuildMessageChannel +public partial interface IVoiceChannel : IGuildMessageChannel { /// /// The voice channel's bitrate (in bits per second). @@ -29,7 +29,7 @@ public interface IVoiceChannel : IGuildMessageChannel public VideoQualityMode VideoQualityMode { get; } } -public interface IVoiceGuildChannel : +public partial interface IVoiceGuildChannel : IVoiceChannel, INamedChannel, IPositionedGuildChannel, @@ -38,7 +38,7 @@ public interface IVoiceGuildChannel : { } -public interface IStageGuildChannel : +public partial interface IStageGuildChannel : IVoiceChannel, INamedChannel, IPositionedGuildChannel, diff --git a/NetCord/Channels/TextChannels/Guild/MediaForumGuildChannel.cs b/NetCord/Channels/Guild/MediaForumGuildChannel.cs similarity index 55% rename from NetCord/Channels/TextChannels/Guild/MediaForumGuildChannel.cs rename to NetCord/Channels/Guild/MediaForumGuildChannel.cs index a0d5e0a9d..e7308f390 100644 --- a/NetCord/Channels/TextChannels/Guild/MediaForumGuildChannel.cs +++ b/NetCord/Channels/Guild/MediaForumGuildChannel.cs @@ -6,6 +6,6 @@ namespace NetCord; /// /// Represents a media channel, which is a specialized . /// -public partial class MediaForumGuildChannel(JsonChannel jsonModel, ulong guildId, RestClient client) : ForumGuildChannel(jsonModel, guildId, client) +internal partial class MediaForumGuildChannel(JsonChannel jsonModel, ulong guildId, RestClient client) : ForumGuildChannel(jsonModel, guildId, client) { } diff --git a/NetCord/Channels/Guild/StageGuildChannel.cs b/NetCord/Channels/Guild/StageGuildChannel.cs new file mode 100644 index 000000000..a181f6e8d --- /dev/null +++ b/NetCord/Channels/Guild/StageGuildChannel.cs @@ -0,0 +1,10 @@ +using NetCord.Rest; + +namespace NetCord; + +/// +/// Represents a stage channel within a guild. +/// +internal partial class StageGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : VoiceGuildChannel(jsonModel, guildId, client) +{ +} diff --git a/NetCord/Channels/TextChannels/Guild/TextGuildChannel.cs b/NetCord/Channels/Guild/TextGuildChannel.cs similarity index 89% rename from NetCord/Channels/TextChannels/Guild/TextGuildChannel.cs rename to NetCord/Channels/Guild/TextGuildChannel.cs index 8cae67a03..f6520cf6f 100644 --- a/NetCord/Channels/TextChannels/Guild/TextGuildChannel.cs +++ b/NetCord/Channels/Guild/TextGuildChannel.cs @@ -5,10 +5,8 @@ namespace NetCord; /// /// Represents a text channel within a guild. /// -public partial class TextGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : TextChannel(jsonModel, client), IGuildChannel +internal partial class TextGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : GuildMessageChannelBase(jsonModel, guildId, client) { - public ulong GuildId { get; } = guildId; - public int? Position => _jsonModel.Position; public IReadOnlyDictionary PermissionOverwrites { get; } = jsonModel.PermissionOverwrites.ToDictionaryOrEmpty(p => p.Id, p => new PermissionOverwrite(p)); diff --git a/NetCord/Channels/TextChannels/Guild/Threads/AnnouncementGuildThread.cs b/NetCord/Channels/Guild/Threads/AnnouncementGuildThread.cs similarity index 52% rename from NetCord/Channels/TextChannels/Guild/Threads/AnnouncementGuildThread.cs rename to NetCord/Channels/Guild/Threads/AnnouncementGuildThread.cs index b82a54df7..65f1d43f5 100644 --- a/NetCord/Channels/TextChannels/Guild/Threads/AnnouncementGuildThread.cs +++ b/NetCord/Channels/Guild/Threads/AnnouncementGuildThread.cs @@ -5,6 +5,6 @@ namespace NetCord; /// /// Represents a thread within an . /// -public partial class AnnouncementGuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : GuildThread(jsonModel, client) +internal partial class AnnouncementGuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : GuildThread(jsonModel, client) { } diff --git a/NetCord/Channels/TextChannels/Guild/Threads/ForumGuildThread.cs b/NetCord/Channels/Guild/Threads/ForumGuildThread.cs similarity index 83% rename from NetCord/Channels/TextChannels/Guild/Threads/ForumGuildThread.cs rename to NetCord/Channels/Guild/Threads/ForumGuildThread.cs index a788737f2..67350682e 100644 --- a/NetCord/Channels/TextChannels/Guild/Threads/ForumGuildThread.cs +++ b/NetCord/Channels/Guild/Threads/ForumGuildThread.cs @@ -9,7 +9,7 @@ namespace NetCord; /// /// Threads within a forum are typically acquired as objects. /// -public partial class ForumGuildThread(JsonChannel jsonModel, RestClient client) : PublicGuildThread(jsonModel, client) +internal partial class ForumGuildThread(JsonChannel jsonModel, RestClient client) : PublicGuildThread(jsonModel, client) { /// /// The message embedded as the thread's starting point. diff --git a/NetCord/Channels/TextChannels/Guild/Threads/GuildThread.cs b/NetCord/Channels/Guild/Threads/GuildThread.cs similarity index 68% rename from NetCord/Channels/TextChannels/Guild/Threads/GuildThread.cs rename to NetCord/Channels/Guild/Threads/GuildThread.cs index b8b774df4..b68531fd1 100644 --- a/NetCord/Channels/TextChannels/Guild/Threads/GuildThread.cs +++ b/NetCord/Channels/Guild/Threads/GuildThread.cs @@ -5,17 +5,12 @@ namespace NetCord; /// /// Represents a thread within a guild. /// -public abstract partial class GuildThread : TextGuildChannel +internal abstract partial class GuildThread : GuildMessageChannelBase, IGuildThread { /// - /// The ID of the this thread was created in. + /// The ID of the parent channel of the thread. /// - public new ulong ParentId => base.ParentId.GetValueOrDefault(); - - /// - /// The ID of the thread's creator. - /// - public ulong OwnerId => _jsonModel.OwnerId.GetValueOrDefault(); + public ulong ParentId => _jsonModel.ParentId.GetValueOrDefault(); /// /// The number of messages within the thread, excluding the initial and deleted messages. @@ -45,6 +40,21 @@ public abstract partial class GuildThread : TextGuildChannel /// public int TotalMessageSent => _jsonModel.TotalMessageSent.GetValueOrDefault(); + /// + /// The name of the thread. + /// + public string Name => _jsonModel.Name!; + + /// + /// The timestamp of the last pinned message in the thread. + /// + public DateTimeOffset? LastPin => _jsonModel.LastPin; + + /// + /// The ID of the user who created the thread. + /// + public ulong OwnerId => _jsonModel.OwnerId.GetValueOrDefault(); + protected GuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : base(jsonModel, jsonModel.GuildId.GetValueOrDefault(), client) { Metadata = new(jsonModel.Metadata!); @@ -53,15 +63,4 @@ protected GuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : bas if (jsonCurrentUser is not null) CurrentUser = new(jsonCurrentUser); } - - public static new GuildThread CreateFromJson(JsonModels.JsonChannel jsonChannel, RestClient client) - { - return jsonChannel.Type switch - { - ChannelType.AnnouncementGuildThread => new AnnouncementGuildThread(jsonChannel, client), - ChannelType.PublicGuildThread => new PublicGuildThread(jsonChannel, client), - ChannelType.PrivateGuildThread => new PrivateGuildThread(jsonChannel, client), - _ => new UnknownGuildThread(jsonChannel, client), - }; - } } diff --git a/NetCord/Channels/TextChannels/Guild/Threads/GuildThreadMetadata.cs b/NetCord/Channels/Guild/Threads/GuildThreadMetadata.cs similarity index 100% rename from NetCord/Channels/TextChannels/Guild/Threads/GuildThreadMetadata.cs rename to NetCord/Channels/Guild/Threads/GuildThreadMetadata.cs diff --git a/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs b/NetCord/Channels/Guild/Threads/IGuildThread.cs similarity index 78% rename from NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs rename to NetCord/Channels/Guild/Threads/IGuildThread.cs index d6889121d..2dbab8ff2 100644 --- a/NetCord/Channels/TextChannels/Guild/Threads/IGuildThread.cs +++ b/NetCord/Channels/Guild/Threads/IGuildThread.cs @@ -2,7 +2,7 @@ namespace NetCord; -public interface IGuildThread : +public partial interface IGuildThread : IGuildMessageChannel, INamedChannel, IPinnableChannel @@ -16,11 +16,11 @@ public interface IGuildThread : int TotalMessageSent { get; } } -public interface IAnnouncementGuildThread : IGuildThread +public partial interface IAnnouncementGuildThread : IGuildThread { } -public interface IUnknownGuildThread : +public partial interface IUnknownGuildThread : IUnknownGuildChannel, IGuildThread { @@ -29,7 +29,7 @@ public interface IUnknownGuildThread : /// /// Represents a private thread channel that is only viewale by those invited and those with the MANAGE_THREADS permission. /// -public interface IPrivateGuildThread : IGuildThread +public partial interface IPrivateGuildThread : IGuildThread { } @@ -39,7 +39,7 @@ public interface IPrivateGuildThread : IGuildThread /// /// This also includes threads in forum and media channels. /// -public interface IPublicGuildThread : IGuildThread +public partial interface IPublicGuildThread : IGuildThread { IReadOnlyList? AppliedTags { get; } } diff --git a/NetCord/Channels/TextChannels/Guild/Threads/PrivateGuildThread.cs b/NetCord/Channels/Guild/Threads/PrivateGuildThread.cs similarity index 50% rename from NetCord/Channels/TextChannels/Guild/Threads/PrivateGuildThread.cs rename to NetCord/Channels/Guild/Threads/PrivateGuildThread.cs index 6fb11eddd..3166e399a 100644 --- a/NetCord/Channels/TextChannels/Guild/Threads/PrivateGuildThread.cs +++ b/NetCord/Channels/Guild/Threads/PrivateGuildThread.cs @@ -5,6 +5,6 @@ namespace NetCord; /// /// Represents a only accessible to a subset of users. /// -public partial class PrivateGuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : GuildThread(jsonModel, client) +internal partial class PrivateGuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : GuildThread(jsonModel, client), IPrivateGuildThread { } diff --git a/NetCord/Channels/TextChannels/Guild/Threads/PublicGuildThread.cs b/NetCord/Channels/Guild/Threads/PublicGuildThread.cs similarity index 75% rename from NetCord/Channels/TextChannels/Guild/Threads/PublicGuildThread.cs rename to NetCord/Channels/Guild/Threads/PublicGuildThread.cs index e14cf9079..94b94f0a8 100644 --- a/NetCord/Channels/TextChannels/Guild/Threads/PublicGuildThread.cs +++ b/NetCord/Channels/Guild/Threads/PublicGuildThread.cs @@ -5,7 +5,7 @@ namespace NetCord; /// /// Represents a accessible to all users. /// -public partial class PublicGuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : GuildThread(jsonModel, client) +internal partial class PublicGuildThread(JsonModels.JsonChannel jsonModel, RestClient client) : GuildThread(jsonModel, client), IPublicGuildThread { /// /// The set of tags applied to the thread. diff --git a/NetCord/Channels/TextChannels/Guild/Threads/UnknownGuildThread.cs b/NetCord/Channels/Guild/Threads/UnknownGuildThread.cs similarity index 100% rename from NetCord/Channels/TextChannels/Guild/Threads/UnknownGuildThread.cs rename to NetCord/Channels/Guild/Threads/UnknownGuildThread.cs diff --git a/NetCord/Channels/UnknownGuildChannel.cs b/NetCord/Channels/Guild/UnknownGuildChannel.cs similarity index 100% rename from NetCord/Channels/UnknownGuildChannel.cs rename to NetCord/Channels/Guild/UnknownGuildChannel.cs diff --git a/NetCord/Channels/Guild/VoiceGuildChannel.cs b/NetCord/Channels/Guild/VoiceGuildChannel.cs new file mode 100644 index 000000000..0ee684a62 --- /dev/null +++ b/NetCord/Channels/Guild/VoiceGuildChannel.cs @@ -0,0 +1,27 @@ +using NetCord.Rest; + +namespace NetCord; + +/// +/// Represents a standard voice channel within a guild. +/// +internal partial class VoiceGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : GuildMessageChannelBase(jsonModel, guildId, client), IVoiceGuildChannel +{ + public int Bitrate => _jsonModel.Bitrate.GetValueOrDefault(); + + public int UserLimit => _jsonModel.UserLimit.GetValueOrDefault(); + + public string? RtcRegion => _jsonModel.RtcRegion; + + public VideoQualityMode VideoQualityMode => _jsonModel.VideoQualityMode.GetValueOrDefault(VideoQualityMode.Auto); + + public int Slowmode => throw new NotImplementedException(); + + public ulong? ParentId => throw new NotImplementedException(); + + public string Name => throw new NotImplementedException(); + + public int Position => throw new NotImplementedException(); + + public IReadOnlyDictionary PermissionOverwrites => throw new NotImplementedException(); +} diff --git a/NetCord/Channels/IChannel.cs b/NetCord/Channels/IChannel.cs index 2620e588a..efeed8186 100644 --- a/NetCord/Channels/IChannel.cs +++ b/NetCord/Channels/IChannel.cs @@ -7,11 +7,11 @@ namespace NetCord; /// This includes all text and voice channels, threads, /// DMs, group DMs, categories and directory channels. /// -public interface IChannel : IEntity, ISpanFormattable +public partial interface IChannel : IEntity, ISpanFormattable { - ChannelType Type { get; } - - // Null means Discord did not provide flags. + /// + /// Additional information about the channel's state. + /// ChannelFlags? Flags { get; } public string ToString(); @@ -20,8 +20,11 @@ public interface IChannel : IEntity, ISpanFormattable /// /// Represents a channel that has a name. /// -public interface INamedChannel : IChannel +public partial interface INamedChannel : IChannel { + /// + /// The name of the channel. + /// string Name { get; } } @@ -29,7 +32,7 @@ public interface INamedChannel : IChannel /// /// Represents a channel representation which came with resolved interaction permissions. /// -public interface IInteractionChannel : IChannel +public partial interface IInteractionChannel : IChannel { Permissions Permissions { get; } } diff --git a/NetCord/Channels/IDMChannel.cs b/NetCord/Channels/IDMChannel.cs new file mode 100644 index 000000000..2918842b9 --- /dev/null +++ b/NetCord/Channels/IDMChannel.cs @@ -0,0 +1,6 @@ +namespace NetCord; + +public partial interface IDMChannel : ITextChannel, IPinnableChannel +{ + IReadOnlyDictionary Users { get; } +} diff --git a/NetCord/Channels/TextChannels/IGroupDMChannel.cs b/NetCord/Channels/IGroupDMChannel.cs similarity index 94% rename from NetCord/Channels/TextChannels/IGroupDMChannel.cs rename to NetCord/Channels/IGroupDMChannel.cs index e65fbe97c..c647cae29 100644 --- a/NetCord/Channels/TextChannels/IGroupDMChannel.cs +++ b/NetCord/Channels/IGroupDMChannel.cs @@ -1,6 +1,6 @@ namespace NetCord; -public interface IGroupDMChannel : +public partial interface IGroupDMChannel : ITextChannel, IPinnableChannel, INamedChannel diff --git a/NetCord/Channels/IInviteChannel.cs b/NetCord/Channels/IInviteChannel.cs index 19759e2af..420c79723 100644 --- a/NetCord/Channels/IInviteChannel.cs +++ b/NetCord/Channels/IInviteChannel.cs @@ -1,6 +1,6 @@ namespace NetCord; -public interface IInviteChannel : IChannel +public partial interface IInviteChannel : IChannel { string? Name { get; } string? Icon { get; } diff --git a/NetCord/Channels/TextChannels/ITextChannel.cs b/NetCord/Channels/ITextChannel.cs similarity index 54% rename from NetCord/Channels/TextChannels/ITextChannel.cs rename to NetCord/Channels/ITextChannel.cs index 4b9b9eee8..bdc177a0e 100644 --- a/NetCord/Channels/TextChannels/ITextChannel.cs +++ b/NetCord/Channels/ITextChannel.cs @@ -1,7 +1,10 @@ namespace NetCord; -public interface ITextChannel : IChannel +public partial interface ITextChannel : IChannel { + /// + /// The ID corresponding to the last message sent within the channel. Can be if the channel is empty. + /// ulong? LastMessageId { get; } } @@ -20,7 +23,10 @@ public interface ITextChannel : IChannel /// GROUP_DM /// /// -public interface IPinnableChannel : ITextChannel +public partial interface IPinnableChannel : ITextChannel { + /// + /// The timestamp of the last pinned message, if any, otherwise . + /// DateTimeOffset? LastPin { get; } } \ No newline at end of file diff --git a/NetCord/Channels/IUnknownChannel.cs b/NetCord/Channels/IUnknownChannel.cs index 98b7f1045..275838128 100644 --- a/NetCord/Channels/IUnknownChannel.cs +++ b/NetCord/Channels/IUnknownChannel.cs @@ -3,10 +3,10 @@ namespace NetCord; /// /// Represents a channel of an unresolved type. /// -public interface IUnknownChannel : IEntity, ISpanFormattable +public partial interface IUnknownChannel : IChannel { /// /// The unresolved channel's type. /// - public ChannelType Type { get; } + ChannelType Type { get; } } diff --git a/NetCord/Channels/TextChannels/IUnknownDMChannel.cs b/NetCord/Channels/IUnknownDMChannel.cs similarity index 65% rename from NetCord/Channels/TextChannels/IUnknownDMChannel.cs rename to NetCord/Channels/IUnknownDMChannel.cs index 60e5821cf..3d2dbc770 100644 --- a/NetCord/Channels/TextChannels/IUnknownDMChannel.cs +++ b/NetCord/Channels/IUnknownDMChannel.cs @@ -3,6 +3,6 @@ namespace NetCord; /// /// Represents a channel for private messages of an unresolved type. /// -public interface IUnknownDMChannel : IUnknownTextChannel +public partial interface IUnknownDMChannel : IUnknownTextChannel { } diff --git a/NetCord/Channels/TextChannels/IUnknownTextChannel.cs b/NetCord/Channels/IUnknownTextChannel.cs similarity index 62% rename from NetCord/Channels/TextChannels/IUnknownTextChannel.cs rename to NetCord/Channels/IUnknownTextChannel.cs index f96d5f338..f225f9070 100644 --- a/NetCord/Channels/TextChannels/IUnknownTextChannel.cs +++ b/NetCord/Channels/IUnknownTextChannel.cs @@ -3,6 +3,6 @@ namespace NetCord; /// /// Represents a text channel of an unresolved type. /// -public interface IUnknownTextChannel : IUnknownChannel +public partial interface IUnknownTextChannel : IUnknownChannel { } diff --git a/NetCord/Channels/TextChannel.cs b/NetCord/Channels/TextChannel.cs new file mode 100644 index 000000000..04e6aa5b6 --- /dev/null +++ b/NetCord/Channels/TextChannel.cs @@ -0,0 +1,13 @@ +using NetCord.JsonModels; +using NetCord.Rest; + +namespace NetCord; + +/// +/// Represents a text channel. +/// +internal abstract partial class TextChannel(JsonChannel jsonModel, RestClient client) : TextChannelBase(jsonModel, client), IPinnableChannel +{ + /// + public DateTimeOffset? LastPin => _jsonModel.LastPin; +} diff --git a/NetCord/Channels/TextChannelBase.cs b/NetCord/Channels/TextChannelBase.cs new file mode 100644 index 000000000..6badfcb54 --- /dev/null +++ b/NetCord/Channels/TextChannelBase.cs @@ -0,0 +1,10 @@ +using NetCord.JsonModels; +using NetCord.Rest; + +namespace NetCord; + +internal abstract partial class TextChannelBase(JsonChannel jsonModel, RestClient client) : Channel(jsonModel, client), ITextChannel +{ + /// + public ulong? LastMessageId => throw new NotImplementedException(); +} \ No newline at end of file diff --git a/NetCord/Channels/TextChannels/DMChannel.cs b/NetCord/Channels/TextChannels/DMChannel.cs deleted file mode 100644 index b759480e7..000000000 --- a/NetCord/Channels/TextChannels/DMChannel.cs +++ /dev/null @@ -1,24 +0,0 @@ -using NetCord.Rest; - -namespace NetCord; - -/// -/// Represents a text channel for private messages between two users. -/// -public partial class DMChannel(JsonModels.JsonChannel jsonModel, RestClient client) : TextChannel(jsonModel, client) -{ - /// - /// A list of the users present in the private channel, indexed by their IDs. - /// - public IReadOnlyDictionary Users { get; } = jsonModel.Users.ToDictionaryOrEmpty(u => u.Id, u => new User(u, client)); - - public static new DMChannel CreateFromJson(JsonModels.JsonChannel jsonModel, RestClient client) - { - return jsonModel.Type switch - { - ChannelType.DMChannel => new DMChannel(jsonModel, client), - ChannelType.GroupDMChannel => new GroupDMChannel(jsonModel, client), - _ => new UnknownDMChannel(jsonModel, client), - }; - } -} diff --git a/NetCord/Channels/TextChannels/Guild/AnnouncementGuildChannel.cs b/NetCord/Channels/TextChannels/Guild/AnnouncementGuildChannel.cs deleted file mode 100644 index 7bfd915fa..000000000 --- a/NetCord/Channels/TextChannels/Guild/AnnouncementGuildChannel.cs +++ /dev/null @@ -1,10 +0,0 @@ -using NetCord.Rest; - -namespace NetCord; - -/// -/// Represents a channel that users can follow and crosspost from into their own servers. Formerly known as news channels. -/// -public partial class AnnouncementGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : TextGuildChannel(jsonModel, guildId, client) -{ -} diff --git a/NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs b/NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs deleted file mode 100644 index 14b29684c..000000000 --- a/NetCord/Channels/TextChannels/Guild/IDirectoryGuildChannel.cs +++ /dev/null @@ -1,5 +0,0 @@ -namespace NetCord; - -public interface IDirectoryGuildChannel : IGuildChannel, IPermissionOverwriteChannel, INamedChannel, IPositionedGuildChannel -{ -} \ No newline at end of file diff --git a/NetCord/Channels/TextChannels/IDMChannel.cs b/NetCord/Channels/TextChannels/IDMChannel.cs deleted file mode 100644 index 084f4beac..000000000 --- a/NetCord/Channels/TextChannels/IDMChannel.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace NetCord; - -public interface IDMChannel : ITextChannel, IPinnableChannel -{ - ulong? RecipientId { get; } -} diff --git a/NetCord/Channels/TextChannels/TextChannel.cs b/NetCord/Channels/TextChannels/TextChannel.cs deleted file mode 100644 index 750825000..000000000 --- a/NetCord/Channels/TextChannels/TextChannel.cs +++ /dev/null @@ -1,38 +0,0 @@ -using NetCord.JsonModels; -using NetCord.Rest; - -namespace NetCord; - -/// -/// Represents a generic text channel. -/// -public abstract partial class TextChannel(JsonChannel jsonModel, RestClient client) : Channel(jsonModel, client) -{ - /// - /// The ID corresponding to the last message sent within the channel. Can be if the channel is empty. - /// - public ulong? LastMessageId => _jsonModel.LastMessageId; - - /// - /// The timestamp of the last pinned message, if any, otherwise . - /// - public DateTimeOffset? LastPin => _jsonModel.LastPin; - - public static new TextChannel CreateFromJson(JsonChannel jsonChannel, RestClient client) - { - return jsonChannel.Type switch - { - ChannelType.TextGuildChannel => new TextGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.DMChannel => new DMChannel(jsonChannel, client), - ChannelType.VoiceGuildChannel => new VoiceGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.GroupDMChannel => new GroupDMChannel(jsonChannel, client), - ChannelType.AnnouncementGuildChannel => new AnnouncementGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.AnnouncementGuildThread => new AnnouncementGuildThread(jsonChannel, client), - ChannelType.PublicGuildThread => new PublicGuildThread(jsonChannel, client), - ChannelType.PrivateGuildThread => new PrivateGuildThread(jsonChannel, client), - ChannelType.StageGuildChannel => new StageGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - ChannelType.DirectoryGuildChannel => new DirectoryGuildChannel(jsonChannel, jsonChannel.GuildId.GetValueOrDefault(), client), - _ => new UnknownTextChannel(jsonChannel, client), - }; - } -} diff --git a/NetCord/Channels/TextChannels/UnknownDMChannel.cs b/NetCord/Channels/UnknownDMChannel.cs similarity index 100% rename from NetCord/Channels/TextChannels/UnknownDMChannel.cs rename to NetCord/Channels/UnknownDMChannel.cs diff --git a/NetCord/Channels/TextChannels/UnknownTextChannel.cs b/NetCord/Channels/UnknownTextChannel.cs similarity index 70% rename from NetCord/Channels/TextChannels/UnknownTextChannel.cs rename to NetCord/Channels/UnknownTextChannel.cs index 6eb5744b4..3a15b4d00 100644 --- a/NetCord/Channels/TextChannels/UnknownTextChannel.cs +++ b/NetCord/Channels/UnknownTextChannel.cs @@ -3,7 +3,7 @@ namespace NetCord; -internal partial class UnknownTextChannel(JsonChannel jsonModel, RestClient client) : TextChannel(jsonModel, client), IUnknownTextChannel +internal partial class UnknownTextChannel(JsonChannel jsonModel, RestClient client) : TextChannelBase(jsonModel, client), IUnknownTextChannel { public ChannelType Type => _jsonModel.Type; } diff --git a/NetCord/Channels/VoiceChannels/Guild/StageGuildChannel.cs b/NetCord/Channels/VoiceChannels/Guild/StageGuildChannel.cs deleted file mode 100644 index 57453aef6..000000000 --- a/NetCord/Channels/VoiceChannels/Guild/StageGuildChannel.cs +++ /dev/null @@ -1,17 +0,0 @@ -using NetCord.Rest; - -namespace NetCord; - -/// -/// Represents a stage channel within a guild. -/// -public partial class StageGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : TextGuildChannel(jsonModel, guildId, client), IVoiceGuildChannel -{ - public int Bitrate => _jsonModel.Bitrate.GetValueOrDefault(); - - public int UserLimit => _jsonModel.UserLimit.GetValueOrDefault(); - - public string? RtcRegion => _jsonModel.RtcRegion; - - public VideoQualityMode VideoQualityMode => _jsonModel.VideoQualityMode.GetValueOrDefault(VideoQualityMode.Auto); -} diff --git a/NetCord/Channels/VoiceChannels/Guild/VoiceGuildChannel.cs b/NetCord/Channels/VoiceChannels/Guild/VoiceGuildChannel.cs deleted file mode 100644 index 12412e342..000000000 --- a/NetCord/Channels/VoiceChannels/Guild/VoiceGuildChannel.cs +++ /dev/null @@ -1,17 +0,0 @@ -using NetCord.Rest; - -namespace NetCord; - -/// -/// Represents a standard voice channel within a guild. -/// -public partial class VoiceGuildChannel(JsonModels.JsonChannel jsonModel, ulong guildId, RestClient client) : TextGuildChannel(jsonModel, guildId, client), IVoiceGuildChannel -{ - public int Bitrate => _jsonModel.Bitrate.GetValueOrDefault(); - - public int UserLimit => _jsonModel.UserLimit.GetValueOrDefault(); - - public string? RtcRegion => _jsonModel.RtcRegion; - - public VideoQualityMode VideoQualityMode => _jsonModel.VideoQualityMode.GetValueOrDefault(VideoQualityMode.Auto); -} diff --git a/NetCord/Components/ChannelMenu.cs b/NetCord/Components/ChannelMenu.cs index ed9e4f642..48bc11c38 100644 --- a/NetCord/Components/ChannelMenu.cs +++ b/NetCord/Components/ChannelMenu.cs @@ -24,5 +24,5 @@ public unsafe ChannelMenu(JsonChannelMenuComponent jsonModel, public IReadOnlyList ChannelTypes { get; } - public new IReadOnlyList? SelectedValues { get; } + public new IReadOnlyList? SelectedValues { get; } } diff --git a/NetCord/Components/EntityMenu.cs b/NetCord/Components/EntityMenu.cs index e9b739720..c56012675 100644 --- a/NetCord/Components/EntityMenu.cs +++ b/NetCord/Components/EntityMenu.cs @@ -30,7 +30,7 @@ private protected EntityMenu(JsonEntityMenuComponent jsonModel, IReadOnlyList
    GetSelectedValues(JsonEntityMenuComponent jsonModel, delegate*, InteractionResolvedData, T[]> getValues, out T[] values, InteractionResolvedData? resolvedData) where T : Entity + private protected static unsafe IReadOnlyList GetSelectedValues(JsonEntityMenuComponent jsonModel, delegate*, InteractionResolvedData, T[]> getValues, out T[] values, InteractionResolvedData? resolvedData) where T : IEntity { if (resolvedData is not null) return new EntityArrayWrapper(values = getValues(jsonModel.SelectedValues!, resolvedData)); diff --git a/NetCord/Components/EntityMenuHelper.cs b/NetCord/Components/EntityMenuHelper.cs index 598592812..ca91aceea 100644 --- a/NetCord/Components/EntityMenuHelper.cs +++ b/NetCord/Components/EntityMenuHelper.cs @@ -30,7 +30,7 @@ public static Mentionable[] GetMentionableValues(IEnumerable selectedValu }).ToArray(); } - public static Channel[] GetChannelValues(IEnumerable selectedValues, InteractionResolvedData resolvedData) + public static IChannel[] GetChannelValues(IEnumerable selectedValues, InteractionResolvedData resolvedData) { var channels = resolvedData.Channels; return selectedValues.Select(v => channels![v]).ToArray(); diff --git a/NetCord/EntityArrayWrapper.cs b/NetCord/EntityArrayWrapper.cs index 452083bf9..af7e5123d 100644 --- a/NetCord/EntityArrayWrapper.cs +++ b/NetCord/EntityArrayWrapper.cs @@ -2,7 +2,7 @@ namespace NetCord; -internal sealed class EntityArrayWrapper(T[] array) : IReadOnlyList where T : Entity +internal sealed class EntityArrayWrapper(T[] array) : IReadOnlyList where T : IEntity { public ulong this[int index] => array[index].Id; diff --git a/NetCord/EntityMenuInteraction.cs b/NetCord/EntityMenuInteraction.cs index 9c03cdb6e..00693b29d 100644 --- a/NetCord/EntityMenuInteraction.cs +++ b/NetCord/EntityMenuInteraction.cs @@ -28,7 +28,7 @@ private protected static unsafe IReadOnlyList GetSelectedValues(JsonMo RestClient client, delegate*, InteractionResolvedData, T[]> getSelectedValues, out T[] selectedValues, - out InteractionResolvedData? resolvedData) where T : Entity + out InteractionResolvedData? resolvedData) where T : IEntity { if (jsonModel.ResolvedData is { } jsonResolvedData) return new EntityArrayWrapper(selectedValues = getSelectedValues(jsonModel.SelectedValues!.Select(v => Snowflake.Parse(v)), resolvedData = new(jsonResolvedData, guildId, client))); diff --git a/NetCord/Gateway/ConcurrentGatewayClientCache.cs b/NetCord/Gateway/ConcurrentGatewayClientCache.cs index f4b8752fb..f67b4bb48 100644 --- a/NetCord/Gateway/ConcurrentGatewayClientCache.cs +++ b/NetCord/Gateway/ConcurrentGatewayClientCache.cs @@ -147,7 +147,7 @@ public IGatewayClientCache CacheGuildScheduledEvent(GuildScheduledEvent schedule return this; } - public IGatewayClientCache CacheGuildThread(GuildThread thread) + public IGatewayClientCache CacheGuildThread(IGuildThread thread) { if (_guilds.TryGetValue(thread.GuildId, out var guild)) { @@ -225,7 +225,7 @@ public IGatewayClientCache SyncGuildStickers(ulong guildId, IReadOnlyDictionary< return this; } - public IGatewayClientCache SyncGuildActiveThreads(ulong guildId, IReadOnlyDictionary threads) + public IGatewayClientCache SyncGuildActiveThreads(ulong guildId, IReadOnlyDictionary threads) { if (_guilds.TryGetValue(guildId, out var guild)) guild.ActiveThreads = threads; diff --git a/NetCord/Gateway/EventArgs/GuildThreadCreateEventArgs.cs b/NetCord/Gateway/EventArgs/GuildThreadCreateEventArgs.cs index 3ec5be775..c410b8454 100644 --- a/NetCord/Gateway/EventArgs/GuildThreadCreateEventArgs.cs +++ b/NetCord/Gateway/EventArgs/GuildThreadCreateEventArgs.cs @@ -1,8 +1,8 @@ namespace NetCord.Gateway; -public class GuildThreadCreateEventArgs(GuildThread thread, bool newlyCreated) +public class GuildThreadCreateEventArgs(IGuildThread thread, bool newlyCreated) { - public GuildThread Thread { get; } = thread; + public IGuildThread Thread { get; } = thread; public bool NewlyCreated { get; } = newlyCreated; } diff --git a/NetCord/Gateway/EventArgs/GuildThreadListSyncEventArgs.cs b/NetCord/Gateway/EventArgs/GuildThreadListSyncEventArgs.cs index 56d36ab20..f860cab0f 100644 --- a/NetCord/Gateway/EventArgs/GuildThreadListSyncEventArgs.cs +++ b/NetCord/Gateway/EventArgs/GuildThreadListSyncEventArgs.cs @@ -10,7 +10,7 @@ public class GuildThreadListSyncEventArgs(JsonModels.EventArgs.JsonGuildThreadLi public IReadOnlyList? ChannelIds => jsonModel.ChannelIds; - public IReadOnlyDictionary Threads { get; } = dictionaryProvider.CreateDictionary(jsonModel.Threads, t => t.Id, t => GuildThread.CreateFromJson(t, client)); + public IReadOnlyDictionary Threads { get; } = dictionaryProvider.CreateDictionary(jsonModel.Threads, t => t.Id, t => ChannelFactory.CreateGuildThread(t, client)); public IReadOnlyList Users { get; } = jsonModel.Users.Select(u => new ThreadUser(u, client)).ToArray(); } diff --git a/NetCord/Gateway/GatewayClient.cs b/NetCord/Gateway/GatewayClient.cs index bb645c897..6fa77657f 100644 --- a/NetCord/Gateway/GatewayClient.cs +++ b/NetCord/Gateway/GatewayClient.cs @@ -150,7 +150,7 @@ public sealed partial class GatewayClient : WebSocketClient, IEntity ///
    Required Intents: ///
    Optional Intents: None /// - public partial event Func? GuildThreadUpdate; + public partial event Func? GuildThreadUpdate; /// /// Sent when a thread relevant to the bot is deleted. @@ -1183,21 +1183,21 @@ await InvokeEventAsync(_ready, this, (Args: args, State: state, ConnectionState: case "CHANNEL_CREATE": { var json = data.ToObject(Serialization.Default.JsonChannel); - var channel = IGuildChannel.CreateFromJson(json, json.GuildId.GetValueOrDefault(), Rest); + var channel = ChannelFactory.CreateGuild(json, Rest); await InvokeEventAsync(_guildChannelCreate, this, channel, static (client, channel) => client.Cache = client.Cache.CacheGuildChannel(channel)).ConfigureAwait(false); } break; case "CHANNEL_UPDATE": { var json = data.ToObject(Serialization.Default.JsonChannel); - var channel = IGuildChannel.CreateFromJson(json, json.GuildId.GetValueOrDefault(), Rest); + var channel = ChannelFactory.CreateGuild(json, Rest); await InvokeEventAsync(_guildChannelUpdate, this, channel, static (client, channel) => client.Cache = client.Cache.CacheGuildChannel(channel)).ConfigureAwait(false); } break; case "CHANNEL_DELETE": { var json = data.ToObject(Serialization.Default.JsonChannel); - await InvokeEventAsync(_guildChannelDelete, this, (Json: json, RestClient: Rest), static data => IGuildChannel.CreateFromJson(data.Json, data.Json.GuildId.GetValueOrDefault(), data.RestClient), static (client, data) => client.Cache = client.Cache.RemoveGuildChannel(data.Json.GuildId.GetValueOrDefault(), data.Json.Id)).ConfigureAwait(false); + await InvokeEventAsync(_guildChannelDelete, this, (Json: json, RestClient: Rest), static data => ChannelFactory.CreateGuild(data.Json, data.RestClient), static (client, data) => client.Cache = client.Cache.RemoveGuildChannel(data.Json.GuildId.GetValueOrDefault(), data.Json.Id)).ConfigureAwait(false); } break; case "CHANNEL_PINS_UPDATE": @@ -1208,14 +1208,14 @@ await InvokeEventAsync(_ready, this, (Args: args, State: state, ConnectionState: case "THREAD_CREATE": { var json = data.ToObject(Serialization.Default.JsonChannel); - var thread = GuildThread.CreateFromJson(json, Rest); + var thread = ChannelFactory.CreateGuildThread(json, Rest); await InvokeEventAsync(_guildThreadCreate, this, (Json: json, Thread: thread), static data => new(data.Thread, data.Json.NewlyCreated.GetValueOrDefault()), static (client, data) => client.Cache = client.Cache.CacheGuildThread(data.Thread)).ConfigureAwait(false); } break; case "THREAD_UPDATE": { var json = data.ToObject(Serialization.Default.JsonChannel); - var thread = GuildThread.CreateFromJson(json, Rest); + var thread = ChannelFactory.CreateGuildThread(json, Rest); await InvokeEventAsync(_guildThreadUpdate, this, thread, static (client, thread) => client.Cache = client.Cache.CacheGuildThread(thread)).ConfigureAwait(false); } break; diff --git a/NetCord/Gateway/Guild.cs b/NetCord/Gateway/Guild.cs index fd09b9e1d..b8411b6f3 100644 --- a/NetCord/Gateway/Guild.cs +++ b/NetCord/Gateway/Guild.cs @@ -17,8 +17,8 @@ public Guild(JsonGuild jsonModel, ulong clientId, RestClient client, IDictionary VoiceStates = dictionaryProvider.CreateDictionary(jsonModel.VoiceStates ?? [], s => s.UserId, s => new VoiceState(s, guildId, client)); Users = dictionaryProvider.CreateDictionary(GetUsers(jsonModel.Users), u => u.User.Id, u => new GuildUser(u, guildId, client)); - Channels = dictionaryProvider.CreateDictionary(jsonModel.Channels ?? [], c => c.Id, c => IGuildChannel.CreateFromJson(c, guildId, client)); - ActiveThreads = dictionaryProvider.CreateDictionary(jsonModel.ActiveThreads ?? [], t => t.Id, t => GuildThread.CreateFromJson(t, client)); + Channels = dictionaryProvider.CreateDictionary(jsonModel.Channels ?? [], c => c.Id, c => ChannelFactory.CreateGuild(c, client)); + ActiveThreads = dictionaryProvider.CreateDictionary(jsonModel.ActiveThreads ?? [], t => t.Id, t => ChannelFactory.CreateGuildThread(t, client)); StageInstances = dictionaryProvider.CreateDictionary(jsonModel.StageInstances ?? [], i => i.Id, i => new StageInstance(i, client)); Presences = dictionaryProvider.CreateDictionary(jsonModel.Presences ?? [], p => p.User.Id, p => new Presence(p, guildId, client)); ScheduledEvents = dictionaryProvider.CreateDictionary(jsonModel.ScheduledEvents ?? [], e => e.Id, e => new GuildScheduledEvent(e, client)); @@ -125,7 +125,7 @@ private static JsonGuild Copy(JsonGuild jsonModel, Guild oldGuild) /// /// An array of objects, representing all active threads in the that current user has permission to view. /// - public IReadOnlyDictionary ActiveThreads { get; set; } + public IReadOnlyDictionary ActiveThreads { get; set; } /// /// A dictionary of objects, will only include offline users if is . diff --git a/NetCord/Gateway/IGatewayClientCache.cs b/NetCord/Gateway/IGatewayClientCache.cs index a95d3ecfb..81717ddbd 100644 --- a/NetCord/Gateway/IGatewayClientCache.cs +++ b/NetCord/Gateway/IGatewayClientCache.cs @@ -11,7 +11,7 @@ public interface IGatewayClientCache : IDictionaryProvider, IDisposable public IGatewayClientCache CachePresences(ulong guildId, IReadOnlyList presences); public IGatewayClientCache CacheRole(Role role); public IGatewayClientCache CacheGuildScheduledEvent(GuildScheduledEvent scheduledEvent); - public IGatewayClientCache CacheGuildThread(GuildThread thread); + public IGatewayClientCache CacheGuildThread(IGuildThread thread); public IGatewayClientCache CacheGuildChannel(IGuildChannel channel); public IGatewayClientCache CacheStageInstance(StageInstance stageInstance); public IGatewayClientCache CacheCurrentUser(CurrentUser user); @@ -20,7 +20,7 @@ public interface IGatewayClientCache : IDictionaryProvider, IDisposable public IGatewayClientCache SyncGuildEmojis(ulong guildId, IReadOnlyDictionary emojis); public IGatewayClientCache SyncGuildStickers(ulong guildId, IReadOnlyDictionary stickers); - public IGatewayClientCache SyncGuildActiveThreads(ulong guildId, IReadOnlyDictionary threads); + public IGatewayClientCache SyncGuildActiveThreads(ulong guildId, IReadOnlyDictionary threads); public IGatewayClientCache SyncGuilds(IReadOnlyList guildIds); public IGatewayClientCache RemoveGuild(ulong guildId); diff --git a/NetCord/Gateway/ImmutableGatewayClientCache.cs b/NetCord/Gateway/ImmutableGatewayClientCache.cs index 72fbfabc8..dbd5869c8 100644 --- a/NetCord/Gateway/ImmutableGatewayClientCache.cs +++ b/NetCord/Gateway/ImmutableGatewayClientCache.cs @@ -177,7 +177,7 @@ public IGatewayClientCache CacheGuildScheduledEvent(GuildScheduledEvent schedule return this; } - public IGatewayClientCache CacheGuildThread(GuildThread thread) + public IGatewayClientCache CacheGuildThread(IGuildThread thread) { var guildId = thread.GuildId; var guilds = _guilds; @@ -293,7 +293,7 @@ public IGatewayClientCache SyncGuildStickers(ulong guildId, IReadOnlyDictionary< return this; } - public IGatewayClientCache SyncGuildActiveThreads(ulong guildId, IReadOnlyDictionary threads) + public IGatewayClientCache SyncGuildActiveThreads(ulong guildId, IReadOnlyDictionary threads) { var guilds = _guilds; if (guilds.TryGetValue(guildId, out var guild)) diff --git a/NetCord/Gateway/Message.cs b/NetCord/Gateway/Message.cs index 1c556fe14..8fa9accf6 100644 --- a/NetCord/Gateway/Message.cs +++ b/NetCord/Gateway/Message.cs @@ -6,7 +6,7 @@ namespace NetCord.Gateway; /// /// Represents a complete object, with all required fields present. /// -public class Message(JsonMessage jsonModel, Guild? guild, TextChannel? channel, RestClient client) : RestMessage(jsonModel, client) +public class Message(JsonMessage jsonModel, Guild? guild, ITextChannel? channel, RestClient client) : RestMessage(jsonModel, client) { public static Message CreateFromJson(JsonMessage jsonModel, IGatewayClientCache cache, RestClient client) { @@ -14,10 +14,10 @@ public static Message CreateFromJson(JsonMessage jsonModel, IGatewayClientCache return new(jsonModel, guild, channel, client); } - private static (Guild?, TextChannel?) GetCacheData(JsonMessage jsonModel, IGatewayClientCache cache) + private static (Guild?, ITextChannel?) GetCacheData(JsonMessage jsonModel, IGatewayClientCache cache) { Guild? guild; - TextChannel? channel; + ITextChannel? channel; var guildId = jsonModel.GuildId; if (guildId.HasValue) { @@ -25,7 +25,7 @@ private static (Guild?, TextChannel?) GetCacheData(JsonMessage jsonModel, IGatew { var channelId = jsonModel.ChannelId; if (guild.Channels.TryGetValue(channelId, out var guildChannel)) - channel = (TextChannel)guildChannel; + channel = (ITextChannel)guildChannel; else if (guild.ActiveThreads.TryGetValue(channelId, out var thread)) channel = thread; else @@ -50,5 +50,5 @@ private static (Guild?, TextChannel?) GetCacheData(JsonMessage jsonModel, IGatew public Guild? Guild { get; } = guild; /// - public TextChannel? Channel { get; } = channel; + public ITextChannel? Channel { get; } = channel; } diff --git a/NetCord/Interaction.cs b/NetCord/Interaction.cs index 4f18c5439..1872d134a 100644 --- a/NetCord/Interaction.cs +++ b/NetCord/Interaction.cs @@ -25,7 +25,7 @@ private protected Interaction(JsonModels.JsonInteraction jsonModel, Guild? guild GuildReference = new(guildReference); Guild = guild; - Channel = TextChannel.CreateFromJson(jsonModel.Channel!, client); + Channel = (IInteractionChannel)ChannelFactory.CreateText(jsonModel.Channel!, client); Entitlements = jsonModel.Entitlements.Select(e => new Entitlement(e, client)).ToArray(); _sendResponseAsync = sendResponseAsync; @@ -41,7 +41,7 @@ private protected Interaction(JsonModels.JsonInteraction jsonModel, Guild? guild public Guild? Guild { get; } - public TextChannel Channel { get; } + public IInteractionChannel Channel { get; } public User User { get; } diff --git a/NetCord/InteractionResolvedData.cs b/NetCord/InteractionResolvedData.cs index f591957f4..3240086f3 100644 --- a/NetCord/InteractionResolvedData.cs +++ b/NetCord/InteractionResolvedData.cs @@ -21,7 +21,7 @@ public class InteractionResolvedData /// /// A list of channel objects, mapped to their IDs. /// - public IReadOnlyDictionary? Channels { get; } + public IReadOnlyDictionary? Channels { get; } /// /// A list of message objects, mapped to their IDs. @@ -75,7 +75,7 @@ public InteractionResolvedData(JsonInteractionResolvedData jsonModel, ulong? gui var channels = jsonModel.Channels; if (channels is not null) - Channels = channels.ToDictionary(c => c.Key, c => Channel.CreateFromJson(c.Value, client)); + Channels = channels.ToDictionary(c => c.Key, c => ChannelFactory.Create(c.Value, client)); var messages = jsonModel.Messages; if (messages is not null) diff --git a/NetCord/MessageComponentInteraction.cs b/NetCord/MessageComponentInteraction.cs index 1040a946f..3a7f0556c 100644 --- a/NetCord/MessageComponentInteraction.cs +++ b/NetCord/MessageComponentInteraction.cs @@ -10,7 +10,7 @@ private protected MessageComponentInteraction(JsonInteraction jsonModel, Guild? { var message = jsonModel.Message!; message.GuildId = jsonModel.GuildId; - Message = new(message, guild, Channel, client); + Message = new(message, guild, Channel as ITextChannel, client); } public Message Message { get; } diff --git a/NetCord/ModalInteraction.cs b/NetCord/ModalInteraction.cs index 7c46df669..241cc8a83 100644 --- a/NetCord/ModalInteraction.cs +++ b/NetCord/ModalInteraction.cs @@ -11,7 +11,7 @@ public ModalInteraction(JsonModels.JsonInteraction jsonModel, Guild? guild, Inte if (message is not null) { message.GuildId = jsonModel.GuildId; - Message = new(message, guild, Channel, client); + Message = new(message, guild, Channel as ITextChannel, client); } Data = new(jsonModel.Data!, jsonModel.GuildId, client); diff --git a/NetCord/PartialGuildUserExtensions.cs b/NetCord/PartialGuildUserExtensions.cs index 01ff4c388..decb1335d 100644 --- a/NetCord/PartialGuildUserExtensions.cs +++ b/NetCord/PartialGuildUserExtensions.cs @@ -42,39 +42,39 @@ public static Permissions GetPermissions(this PartialGuildUser user, RestGuild g } /// - /// Returns a -specific object belonging to the by acquiring it from the specificied . + /// Returns a -specific object belonging to the by acquiring it from the specificied . /// /// The to acquire permissions for. /// The to acquire the permissions from. - /// The to acquire the permissions for. - public static Permissions GetChannelPermissions(this PartialGuildUser user, RestGuild guild, IGuildChannel channel) + /// The to acquire the permissions for. + public static Permissions GetChannelPermissions(this PartialGuildUser user, RestGuild guild, IPermissionOverwriteChannel channel) { var guildPermissions = GetPermissions(user, guild); return user.GetChannelPermissions(guildPermissions, channel); } /// - /// Returns a -specific object belonging to the by acquiring it from the specificied . + /// Returns a -specific object belonging to the by acquiring it from the specificied . /// /// The to acquire permissions for. /// The to acquire the permissions from. - /// The ID of the to acquire the permissions for. + /// The ID of the to acquire the permissions for. public static Permissions GetChannelPermissions(this PartialGuildUser user, Guild guild, ulong channelId) { var guildPermissions = GetPermissions(user, guild); if (guildPermissions.HasFlag(Permissions.Administrator)) return (Permissions)ulong.MaxValue; - return user.GetChannelPermissionsCore(guildPermissions, guild.Channels[channelId]); + return user.GetChannelPermissionsCore(guildPermissions, guild.Channels[channelId] as IPermissionOverwriteChannel ?? throw new InvalidOperationException("The channel does not support permission overwrites.")); } /// - /// Returns a -specific object belonging to the by acquiring it from the specificied . + /// Returns a -specific object belonging to the by acquiring it from the specificied . /// /// The to acquire permissions for. /// The object to acquire permissions from. - /// The to acquire the permissions for. - public static Permissions GetChannelPermissions(this PartialGuildUser user, Permissions guildPermissions, IGuildChannel channel) + /// The to acquire the permissions for. + public static Permissions GetChannelPermissions(this PartialGuildUser user, Permissions guildPermissions, IPermissionOverwriteChannel channel) { if (guildPermissions.HasFlag(Permissions.Administrator)) return (Permissions)ulong.MaxValue; @@ -82,7 +82,7 @@ public static Permissions GetChannelPermissions(this PartialGuildUser user, Perm return user.GetChannelPermissionsCore(guildPermissions, channel); } - private static Permissions GetChannelPermissionsCore(this PartialGuildUser user, Permissions guildPermissions, IGuildChannel channel) + private static Permissions GetChannelPermissionsCore(this PartialGuildUser user, Permissions guildPermissions, IPermissionOverwriteChannel channel) { var permissions = guildPermissions; diff --git a/NetCord/Rest/GuildMessageSearchResult.cs b/NetCord/Rest/GuildMessageSearchResult.cs index 9aa5d2c1c..9cc4c9fe3 100644 --- a/NetCord/Rest/GuildMessageSearchResult.cs +++ b/NetCord/Rest/GuildMessageSearchResult.cs @@ -64,7 +64,7 @@ public class GuildMessagesSearchResultData(JsonGuildMessagesSearchResult jsonMod /// /// The threads associated with the search results. /// - public IReadOnlyList Threads { get; } = jsonModel.Threads.SelectOrEmpty(t => GuildThread.CreateFromJson(t, client)).ToArray(); + public IReadOnlyList Threads { get; } = jsonModel.Threads.SelectOrEmpty(t => ChannelFactory.CreateGuildThread(t, client)).ToArray(); /// /// The thread users associated with the search results. diff --git a/NetCord/Rest/GuildTemplatePreview.cs b/NetCord/Rest/GuildTemplatePreview.cs index 0db44d947..48f83b1b7 100644 --- a/NetCord/Rest/GuildTemplatePreview.cs +++ b/NetCord/Rest/GuildTemplatePreview.cs @@ -18,5 +18,5 @@ public class GuildTemplatePreview(JsonGuild jsonModel, RestClient client) : IJso public ulong? SystemChannelId => jsonModel.SystemChannelId; public SystemChannelFlags SystemChannelFlags => jsonModel.SystemChannelFlags; public IReadOnlyDictionary Roles { get; } = jsonModel.Roles.ToDictionaryOrEmpty(r => r.Id, r => new Role(r, 0, client)); - public IReadOnlyDictionary Channels { get; } = jsonModel.Channels.ToDictionaryOrEmpty(c => c.Id, c => IGuildChannel.CreateFromJson(c, 0, client)); + public IReadOnlyDictionary Channels { get; } = jsonModel.Channels.ToDictionaryOrEmpty(c => c.Id, c => ChannelFactory.CreateGuild(c, client)); } diff --git a/NetCord/Rest/GuildThreadGenerator.cs b/NetCord/Rest/GuildThreadGenerator.cs index d176c339a..b99f92eed 100644 --- a/NetCord/Rest/GuildThreadGenerator.cs +++ b/NetCord/Rest/GuildThreadGenerator.cs @@ -2,7 +2,7 @@ namespace NetCord.Rest; internal static class GuildThreadGenerator { - public static IEnumerable CreateThreads(JsonModels.JsonRestGuildThreadResult jsonThreads, RestClient client) + public static IEnumerable CreateThreads(JsonModels.JsonRestGuildThreadResult jsonThreads, RestClient client) { var users = jsonThreads.Users.ToDictionary(u => u.ThreadId); return jsonThreads.Threads.Select(t => @@ -10,7 +10,7 @@ public static IEnumerable CreateThreads(JsonModels.JsonRestGuildThr if (users.TryGetValue(t.Id, out var user)) t.CurrentUser = user; - return GuildThread.CreateFromJson(t, client); + return ChannelFactory.CreateGuildThread(t, client); }); } } diff --git a/NetCord/Rest/RestAuditLogEntryData.cs b/NetCord/Rest/RestAuditLogEntryData.cs index 2b7bb001a..c5115b219 100644 --- a/NetCord/Rest/RestAuditLogEntryData.cs +++ b/NetCord/Rest/RestAuditLogEntryData.cs @@ -25,7 +25,7 @@ public class RestAuditLogEntryData(JsonModels.JsonAuditLog jsonModel, RestClient /// /// List of threads referenced in the audit log /// - public IReadOnlyDictionary Threads { get; } = jsonModel.Threads.ToDictionary(c => c.Id, t => GuildThread.CreateFromJson(t, client)); + public IReadOnlyDictionary Threads { get; } = jsonModel.Threads.ToDictionary(c => c.Id, t => ChannelFactory.CreateGuildThread(t, client)); /// /// List of users referenced in the audit log. diff --git a/NetCord/Rest/RestClient.Channel.cs b/NetCord/Rest/RestClient.Channel.cs index 55aabe6d7..f082f64ce 100644 --- a/NetCord/Rest/RestClient.Channel.cs +++ b/NetCord/Rest/RestClient.Channel.cs @@ -16,8 +16,8 @@ public partial class RestClient /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. [GenerateAlias([typeof(IChannel)], nameof(IChannel.Id), Cast = true)] - public async Task GetChannelAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) - => Channel.CreateFromJson(await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + public async Task GetChannelAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + => ChannelFactory.Create(await (await SendRequestAsync(HttpMethod.Get, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); /// /// Modifies a group DM channel's properties. @@ -27,12 +27,12 @@ public async Task GetChannelAsync(ulong channelId, RestRequestPropertie /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. [GenerateAlias([typeof(IGroupDMChannel)], nameof(IGroupDMChannel.Id), Cast = true)] - public async Task ModifyGroupDMChannelAsync(ulong channelId, Action action, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task ModifyGroupDMChannelAsync(ulong channelId, Action action, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { GroupDMChannelOptions groupDMChannelOptions = new(); action(groupDMChannelOptions); using (HttpContent content = new JsonContent(groupDMChannelOptions, Serialization.Default.GroupDMChannelOptions)) - return Channel.CreateFromJson(await (await SendRequestAsync(HttpMethod.Patch, content, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + return ChannelFactory.CreateGroupDM(await (await SendRequestAsync(HttpMethod.Patch, content, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); } /// @@ -43,12 +43,12 @@ public async Task ModifyGroupDMChannelAsync(ulong channelId, ActionOptional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. [GenerateAlias([typeof(IGuildChannel)], nameof(IGuildChannel.Id), Cast = true)] - public async Task ModifyGuildChannelAsync(ulong channelId, Action action, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task ModifyGuildChannelAsync(ulong channelId, Action action, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { GuildChannelOptions guildChannelOptions = new(); action(guildChannelOptions); using (HttpContent content = new JsonContent(guildChannelOptions, Serialization.Default.GuildChannelOptions)) - return Channel.CreateFromJson(await (await SendRequestAsync(HttpMethod.Patch, content, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + return ChannelFactory.CreateGuild(await (await SendRequestAsync(HttpMethod.Patch, content, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); } /// @@ -72,8 +72,8 @@ public async Task SetVoiceGuildChannelStatusAsync(ulong channelId, VoiceGuildCha /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. [GenerateAlias([typeof(IChannel)], nameof(IChannel.Id), Cast = true)] - public async Task DeleteChannelAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) - => Channel.CreateFromJson(await (await SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + public async Task DeleteChannelAsync(ulong channelId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + => ChannelFactory.Create(await (await SendRequestAsync(HttpMethod.Delete, $"/channels/{channelId}", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); /// /// Retrieves an , representing the messages of a specific channel. @@ -740,10 +740,10 @@ public Task GroupDMChannelDeleteUserAsync(ulong channelId, ulong userId, RestReq [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] [GenerateAlias([typeof(RestMessage)], nameof(RestMessage.ChannelId), nameof(RestMessage.Id), TypeNameOverride = "Message")] - public async Task CreateGuildThreadAsync(ulong channelId, ulong messageId, GuildThreadFromMessageProperties threadFromMessageProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task CreateGuildThreadAsync(ulong channelId, ulong messageId, GuildThreadFromMessageProperties threadFromMessageProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(threadFromMessageProperties, Serialization.Default.GuildThreadFromMessageProperties)) - return GuildThread.CreateFromJson(await (await SendRequestAsync(HttpMethod.Post, content, $"/channels/{channelId}/messages/{messageId}/threads", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + return ChannelFactory.CreateGuildThread(await (await SendRequestAsync(HttpMethod.Post, content, $"/channels/{channelId}/messages/{messageId}/threads", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); } /// @@ -755,10 +755,10 @@ public async Task CreateGuildThreadAsync(ulong channelId, ulong mes /// A token that can be used to cancel the operation before it completes. [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] - public async Task CreateGuildThreadAsync(ulong channelId, GuildThreadProperties threadProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task CreateGuildThreadAsync(ulong channelId, GuildThreadProperties threadProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(threadProperties, Serialization.Default.GuildThreadProperties)) - return GuildThread.CreateFromJson(await (await SendRequestAsync(HttpMethod.Post, content, $"/channels/{channelId}/threads", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + return ChannelFactory.CreateGuildThread(await (await SendRequestAsync(HttpMethod.Post, content, $"/channels/{channelId}/threads", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); } /// @@ -769,10 +769,19 @@ public async Task CreateGuildThreadAsync(ulong channelId, GuildThre /// Optional properties to customize the request, can be . /// A token that can be used to cancel the operation before it completes. [GenerateAlias([typeof(IThreadOnlyGuildChannel)], nameof(IThreadOnlyGuildChannel.Id))] - public async Task CreateForumGuildThreadAsync(ulong channelId, ForumGuildThreadProperties threadProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task CreateForumGuildThreadAsync(ulong channelId, ForumGuildThreadProperties threadProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = threadProperties.Serialize()) - return new ForumGuildThread(await (await SendRequestAsync(HttpMethod.Post, content, $"/channels/{channelId}/threads", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + { + var result = await (await SendRequestAsync(HttpMethod.Post, content, $"/channels/{channelId}/threads", null, new(channelId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false); + var message = new RestMessage(result.Message!, this); + var thread = ChannelFactory.CreatePublicGuildThread(result, this); + return new CreateGuildThreadResult + { + Thread = new PublicGuildThread(result, this), + Message = message, + }; + } } /// @@ -868,11 +877,11 @@ public IAsyncEnumerable GetGuildThreadUsersAsync(ulong threadId, Opt /// Optional properties to customize each request, can be . [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] [GenerateAlias([typeof(IAnnouncementGuildChannel)], nameof(IAnnouncementGuildChannel.Id))] - public IAsyncEnumerable GetPublicArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) + public IAsyncEnumerable GetPublicArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.PrepareWithDirectionValidation(paginationProperties, PaginationDirection.Before, 100); - return new OptimizedQueryPaginationAsyncEnumerable( + return new OptimizedQueryPaginationAsyncEnumerable( this, paginationProperties, async s => @@ -895,11 +904,11 @@ public IAsyncEnumerable GetPublicArchivedGuildThreadsAsync(ulong ch /// Pagination options for archived threads, or to use defaults. /// Optional properties to customize each request, can be . [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] - public IAsyncEnumerable GetPrivateArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) + public IAsyncEnumerable GetPrivateArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.PrepareWithDirectionValidation(paginationProperties, PaginationDirection.Before, 100); - return new OptimizedQueryPaginationAsyncEnumerable( + return new OptimizedQueryPaginationAsyncEnumerable( this, paginationProperties, async s => @@ -922,11 +931,11 @@ public IAsyncEnumerable GetPrivateArchivedGuildThreadsAsync(ulong c /// Pagination options for archived threads, or to use defaults. /// Optional properties to customize each request, can be . [GenerateAlias([typeof(ITextGuildChannel)], nameof(ITextGuildChannel.Id))] - public IAsyncEnumerable GetJoinedPrivateArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) + public IAsyncEnumerable GetJoinedPrivateArchivedGuildThreadsAsync(ulong channelId, PaginationProperties? paginationProperties = null, RestRequestProperties? properties = null) { paginationProperties = PaginationProperties.PrepareWithDirectionValidation(paginationProperties, PaginationDirection.Before, 100); - return new OptimizedQueryPaginationAsyncEnumerable( + return new OptimizedQueryPaginationAsyncEnumerable( this, paginationProperties, async s => diff --git a/NetCord/Rest/RestClient.Guild.cs b/NetCord/Rest/RestClient.Guild.cs index eb62e537f..84ae25c37 100644 --- a/NetCord/Rest/RestClient.Guild.cs +++ b/NetCord/Rest/RestClient.Guild.cs @@ -35,13 +35,13 @@ public Task DeleteGuildAsync(ulong guildId, RestRequestProperties? properties = [GenerateAlias([typeof(RestGuild)], nameof(RestGuild.Id), TypeNameOverride = nameof(Guild))] public async Task> GetGuildChannelsAsync(ulong guildId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) - => (await (await SendRequestAsync(HttpMethod.Get, $"/guilds/{guildId}/channels", null, new(guildId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannelArray).ConfigureAwait(false)).Select(c => IGuildChannel.CreateFromJson(c, guildId, this)).ToArray(); + => (await (await SendRequestAsync(HttpMethod.Get, $"/guilds/{guildId}/channels", null, new(guildId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannelArray).ConfigureAwait(false)).Select(c => ChannelFactory.CreateGuild(c, this)).ToArray(); [GenerateAlias([typeof(RestGuild)], nameof(RestGuild.Id), TypeNameOverride = nameof(Guild))] public async Task CreateGuildChannelAsync(ulong guildId, GuildChannelProperties channelProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(channelProperties, Serialization.Default.GuildChannelProperties)) - return IGuildChannel.CreateFromJson(await (await SendRequestAsync(HttpMethod.Post, content, $"/guilds/{guildId}/channels", null, new(guildId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), guildId, this); + return ChannelFactory.CreateGuild(await (await SendRequestAsync(HttpMethod.Post, content, $"/guilds/{guildId}/channels", null, new(guildId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); } [GenerateAlias([typeof(RestGuild)], nameof(RestGuild.Id), TypeNameOverride = nameof(Guild))] @@ -52,7 +52,7 @@ public async Task ModifyGuildChannelPositionsAsync(ulong guildId, IEnumerable> GetActiveGuildThreadsAsync(ulong guildId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task> GetActiveGuildThreadsAsync(ulong guildId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) => GuildThreadGenerator.CreateThreads(await (await SendRequestAsync(HttpMethod.Get, $"/guilds/{guildId}/threads/active", null, new(guildId), properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonRestGuildThreadResult).ConfigureAwait(false), this).ToArray(); [GenerateAlias([typeof(RestGuild)], nameof(RestGuild.Id), TypeNameOverride = nameof(Guild))] diff --git a/NetCord/Rest/RestClient.User.cs b/NetCord/Rest/RestClient.User.cs index c5e0b5718..2d2b2d0f3 100644 --- a/NetCord/Rest/RestClient.User.cs +++ b/NetCord/Rest/RestClient.User.cs @@ -49,16 +49,16 @@ public Task LeaveGuildAsync(ulong guildId, RestRequestProperties? properties = n => SendRequestAsync(HttpMethod.Delete, $"/users/@me/guilds/{guildId}", null, null, properties, cancellationToken: cancellationToken); [GenerateAlias([typeof(User)], nameof(User.Id))] - public async Task GetDMChannelAsync(ulong userId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task GetDMChannelAsync(ulong userId, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(new(userId), Serialization.Default.DMChannelProperties)) - return new(await (await SendRequestAsync(HttpMethod.Post, content, $"/users/@me/channels", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + return ChannelFactory.CreateDM(await (await SendRequestAsync(HttpMethod.Post, content, $"/users/@me/channels", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); } - public async Task CreateGroupDMChannelAsync(GroupDMChannelProperties groupDMChannelProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) + public async Task CreateGroupDMChannelAsync(GroupDMChannelProperties groupDMChannelProperties, RestRequestProperties? properties = null, CancellationToken cancellationToken = default) { using (HttpContent content = new JsonContent(groupDMChannelProperties, Serialization.Default.GroupDMChannelProperties)) - return new(await (await SendRequestAsync(HttpMethod.Post, content, $"/users/@me/channels", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); + return ChannelFactory.CreateGroupDM(await (await SendRequestAsync(HttpMethod.Post, content, $"/users/@me/channels", null, null, properties, cancellationToken: cancellationToken).ConfigureAwait(false)).ToObjectAsync(Serialization.Default.JsonChannel).ConfigureAwait(false), this); } [GenerateAlias([typeof(CurrentUser)])] diff --git a/NetCord/Rest/RestInvite.cs b/NetCord/Rest/RestInvite.cs index 18be1a36a..701a57377 100644 --- a/NetCord/Rest/RestInvite.cs +++ b/NetCord/Rest/RestInvite.cs @@ -13,7 +13,7 @@ public partial class RestInvite : IInvite, IJsonModel public RestGuild? Guild { get; } - public Channel? Channel { get; } + public IInviteChannel? Channel { get; } public User? Inviter { get; } @@ -65,7 +65,7 @@ public RestInvite(JsonModels.JsonRestInvite jsonModel, RestClient client) } if (jsonModel.Channel is { } channel) - Channel = Channel.CreateFromJson(channel, client); + Channel = (IInviteChannel)ChannelFactory.Create(channel, client); if (jsonModel.Inviter is { } inviter) Inviter = new(inviter, client); diff --git a/NetCord/Rest/RestMessage.cs b/NetCord/Rest/RestMessage.cs index 95c2d6942..c52414c04 100644 --- a/NetCord/Rest/RestMessage.cs +++ b/NetCord/Rest/RestMessage.cs @@ -70,7 +70,7 @@ public RestMessage(NetCord.JsonModels.JsonMessage jsonModel, RestClient client) var startedThread = jsonModel.StartedThread; if (startedThread is not null) - StartedThread = GuildThread.CreateFromJson(startedThread, client); + StartedThread = ChannelFactory.CreateGuildThread(startedThread, client); Components = jsonModel.Components.SelectOrEmpty(IMessageComponent.CreateFromJson).ToArray(); Stickers = jsonModel.Stickers.SelectOrEmpty(s => new MessageSticker(s, client)).ToArray(); @@ -240,7 +240,7 @@ public RestMessage(NetCord.JsonModels.JsonMessage jsonModel, RestClient client) /// /// The that was started from this message, if any. /// - public GuildThread? StartedThread { get; } + public IGuildThread? StartedThread { get; } /// /// A list of objects, contains components like s, s, or other interactive components if any are present. diff --git a/NetCord/Rest/Webhook.cs b/NetCord/Rest/Webhook.cs index b34113203..0cb669429 100644 --- a/NetCord/Rest/Webhook.cs +++ b/NetCord/Rest/Webhook.cs @@ -24,7 +24,7 @@ public Webhook(JsonWebhook jsonModel, RestClient client) : base(client) var channel = jsonModel.Channel; if (channel is not null) - Channel = Channel.CreateFromJson(channel, client); + Channel = ChannelFactory.Create(channel, client); } /// @@ -100,7 +100,7 @@ public Webhook(JsonWebhook jsonModel, RestClient client) : base(client) /// This property is if is not , /// or if the has lost access to the guild where the resides. /// - public Channel? Channel { get; } + public IChannel? Channel { get; } /// /// The URL used for executing the webhook.