| @@ -147,17 +147,17 @@ namespace Discord.Net.Models | |||
| // | |||
| /// <summary> | |||
| /// Text or voice <see cref="Channel"/> position changed. | |||
| /// <see cref="GuildTextChannel"/> or <see cref="VoiceChannel"/> position changed. | |||
| /// </summary> | |||
| Position, | |||
| /// <summary> | |||
| /// Text <see cref="Channel"/> topic changed. | |||
| /// <see cref="GuildTextChannel"/> topic changed. | |||
| /// </summary> | |||
| Topic, | |||
| /// <summary> | |||
| /// Voice <see cref="Channel"/> bitrate changed. | |||
| /// <see cref="VoiceChannel"/> bitrate changed. | |||
| /// </summary> | |||
| Bitrate, | |||
| @@ -297,7 +297,7 @@ namespace Discord.Net.Models | |||
| // | |||
| /// <summary> | |||
| /// New user limit in a voice <see cref="Channel"/>. | |||
| /// New user limit in a <see cref="VoiceChannel"/>. | |||
| /// </summary> | |||
| UserLimit, | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record CategoryChannel : GuildChannel | |||
| { | |||
| } | |||
| } | |||
| @@ -11,6 +11,76 @@ namespace Discord.Net.Models | |||
| /// </remarks> | |||
| public record Channel | |||
| { | |||
| /// <summary> | |||
| /// Minimum langth of a channel name. | |||
| /// </summary> | |||
| public const int MinChannelNameLength = 1; | |||
| /// <summary> | |||
| /// Maximum langth of a channel name. | |||
| /// </summary> | |||
| public const int MaxChannelNameLength = 100; | |||
| /// <summary> | |||
| /// Minimum langth of a channel topic. | |||
| /// </summary> | |||
| public const int MinChannelTopicLength = 0; | |||
| /// <summary> | |||
| /// Maximum langth of a channel topic. | |||
| /// </summary> | |||
| public const int MaxChannelTopicLength = 1024; | |||
| /// <summary> | |||
| /// Minimum langth of a channel topic. | |||
| /// </summary> | |||
| public const int MinRateLimitPerUserDuration = 0; | |||
| /// <summary> | |||
| /// Maximum langth of a channel topic. | |||
| /// </summary> | |||
| public const int MaxRateLimitPerUserDuration = 1024; | |||
| /// <summary> | |||
| /// Minimum amount of users in channel. | |||
| /// </summary> | |||
| public const int MinUserLimit = 0; | |||
| /// <summary> | |||
| /// Maximum amount of users in channel. | |||
| /// </summary> | |||
| public const int MaxUserLimit = 99; | |||
| /// <summary> | |||
| /// Minimum bitrate for a channel. | |||
| /// </summary> | |||
| public const int MinBitrate = 8000; | |||
| /// <summary> | |||
| /// Maximum bitrate for a channel. | |||
| /// </summary> | |||
| public const int MaxBitrate = 128000; | |||
| /// <summary> | |||
| /// Minimum afk timeout duration for a channel. | |||
| /// </summary> | |||
| public const int MinAfkTimeoutDuration = 60; | |||
| /// <summary> | |||
| /// Maximum afk timeout duration for a channel. | |||
| /// </summary> | |||
| public const int MaxAFkTimeoutDuration = 3600; | |||
| /// <summary> | |||
| /// Minimum amount of messages to requests in a channel. | |||
| /// </summary> | |||
| public const int MinGetMessagesAmount = 1; | |||
| /// <summary> | |||
| /// Maximum amount of messages to requests in a channel. | |||
| /// </summary> | |||
| public const int MaxGetMessagesAmount = 100; | |||
| /// <summary> | |||
| /// The id of this <see cref="Channel"/>. | |||
| /// </summary> | |||
| @@ -73,13 +143,13 @@ namespace Discord.Net.Models | |||
| public Optional<Snowflake?> LastMessageId { get; init; } | |||
| /// <summary> | |||
| /// The bitrate (in bits) of the voice <see cref="Channel"/>. | |||
| /// The bitrate (in bits) of the <see cref="VoiceChannel"/>. | |||
| /// </summary> | |||
| [JsonPropertyName("bitrate")] | |||
| public Optional<int> Bitrate { get; init; } | |||
| /// <summary> | |||
| /// The <see cref="User"/> limit of the voice <see cref="Channel"/>. | |||
| /// The <see cref="User"/> limit of the <see cref="VoiceChannel"/>. | |||
| /// </summary> | |||
| [JsonPropertyName("user_limit")] | |||
| public Optional<int> UserLimit { get; init; } | |||
| @@ -135,13 +205,13 @@ namespace Discord.Net.Models | |||
| public Optional<DateTimeOffset?> LastPinTimestamp { get; init; } | |||
| /// <summary> | |||
| /// Voice region id for the voice <see cref="Channel"/>, automatic when set to null. | |||
| /// Voice region id for the <see cref="VoiceChannel"/>, automatic when set to null. | |||
| /// </summary> | |||
| [JsonPropertyName("rtc_region")] | |||
| public Optional<string?> RtcRegion { get; init; } | |||
| /// <summary> | |||
| /// The camera video quality mode of the voice channel, 1 when not present. | |||
| /// The camera video quality mode of the <see cref="VoiceChannel"/>, 1 when not present. | |||
| /// </summary> | |||
| [JsonPropertyName("video_quality_mode")] | |||
| public Optional<VideoQualityMode> VideoQualityMode { get; init; } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record DMChannel : PrivateChannel | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record GroupChannel : Channel | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record GuildChannel : Channel | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record GuildTextChannel : GuildChannel | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record PrivateChannel : Channel | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record StageChannel : GuildChannel | |||
| { | |||
| } | |||
| } | |||
| @@ -17,13 +17,13 @@ namespace Discord.Net.Models | |||
| public Snowflake Id { get; } | |||
| /// <summary> | |||
| /// The <see cref="Guild"/> id of the associated Stage <see cref="Channel"/>. | |||
| /// The <see cref="Guild"/> id of the associated <see cref="StageChannel"/>. | |||
| /// </summary> | |||
| [JsonPropertyName("guild_id")] | |||
| public Snowflake GuildId { get; } | |||
| /// <summary> | |||
| /// The id of the associated Stage <see cref="Channel"/>. | |||
| /// The id of the associated <see cref="StageChannel"/>. | |||
| /// </summary> | |||
| [JsonPropertyName("channel_id")] | |||
| public Snowflake ChannelId { get; } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record ThreadChannel : GuildChannel | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,9 @@ | |||
| namespace Discord.Net.Models | |||
| { | |||
| /// <summary> | |||
| /// To be written - just a filler for xml docs for now | |||
| /// </summary> | |||
| public record VoiceChannel : GuildChannel | |||
| { | |||
| } | |||
| } | |||
| @@ -159,7 +159,7 @@ namespace Discord.Net.Models | |||
| public int SystemChannelFlags { get; init; } | |||
| /// <summary> | |||
| /// The id of the <see cref="Channel"/> where Community <see cref="Guild"/>s | |||
| /// The id of the <see cref="Channel"/> where Community <see cref="Guild"/>s. | |||
| /// can display rules and/or guidelines. | |||
| /// </summary> | |||
| [JsonPropertyName("rules_channel_id")] | |||
| @@ -190,7 +190,7 @@ namespace Discord.Net.Models | |||
| public Optional<int> MemberCount { get; init; } | |||
| /// <summary> | |||
| /// States of <see cref="GuildMember"/>s currently in voice <see cref="Channel"/>s. | |||
| /// States of <see cref="GuildMember"/>s currently in <see cref="VoiceChannel"/>s. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Lacks the <see cref="VoiceState.GuildId"/>. | |||
| @@ -211,8 +211,8 @@ namespace Discord.Net.Models | |||
| public Optional<Channel[]> Channels { get; init; } | |||
| /// <summary> | |||
| /// All active thread <see cref="Channel"/>s in the <see cref="Guild"/> that current <see cref="User"/> | |||
| /// has permission to view. | |||
| /// All active <see cref="ThreadChannel"/>s in the <see cref="Guild"/> that the | |||
| /// current <see cref="User"/> has permission to view. | |||
| /// </summary> | |||
| [JsonPropertyName("threads")] | |||
| public Optional<Channel[]> Threads { get; init; } | |||
| @@ -42,13 +42,13 @@ namespace Discord.Net.Models | |||
| public Optional<DateTimeOffset?> PremiumSince { get; init; } | |||
| /// <summary> | |||
| /// Whether the user is deafened in voice <see cref="Channel"/>s. | |||
| /// Whether the user is deafened in <see cref="VoiceChannel"/>s. | |||
| /// </summary> | |||
| [JsonPropertyName("deaf")] | |||
| public bool Deaf { get; init; } | |||
| /// <summary> | |||
| /// Whether the user is muted in voice <see cref="Channel"/>s. | |||
| /// Whether the user is muted in <see cref="VoiceChannel"/>s. | |||
| /// </summary> | |||
| [JsonPropertyName("mute")] | |||
| public bool Mute { get; init; } | |||
| @@ -9,8 +9,28 @@ namespace Discord.Net.Models | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/invite#invite-metadata-object-invite-metadata-structure"/> | |||
| /// </remarks> | |||
| public record InviteMetadata : Invite | |||
| public record InviteWithMetadata : Invite | |||
| { | |||
| /// <summary> | |||
| /// Minimum age for an invite in seconds. | |||
| /// </summary> | |||
| public const int MinAgeTime = 0; | |||
| /// <summary> | |||
| /// Maximum age for an invite in seconds. | |||
| /// </summary> | |||
| public const int MaxAgeTime = 604800; | |||
| /// <summary> | |||
| /// Minimum amount of uses for an invite. | |||
| /// </summary> | |||
| public const int MinUseCount = 0; | |||
| /// <summary> | |||
| /// Maximum amount of uses for an invite. | |||
| /// </summary> | |||
| public const int MaxUseCount = 100; | |||
| /// <summary> | |||
| /// Number of times this <see cref="Invite"/> has been used. | |||
| /// </summary> | |||
| @@ -18,7 +38,7 @@ namespace Discord.Net.Models | |||
| public int Uses { get; init; } | |||
| /// <summary> | |||
| /// Max number of times this <see cref="Invite"/> can be used. | |||
| /// Maximum number of times this <see cref="Invite"/> can be used. | |||
| /// </summary> | |||
| [JsonPropertyName("max_uses")] | |||
| public int MaxUses { get; init; } | |||
| @@ -11,6 +11,26 @@ namespace Discord.Net.Models | |||
| /// </remarks> | |||
| public record Message | |||
| { | |||
| /// <summary> | |||
| /// Maximum length of the message content. | |||
| /// </summary> | |||
| public const int MaxContentLength = 2000; | |||
| /// <summary> | |||
| /// Maximum amount of embeds. | |||
| /// </summary> | |||
| public const int MaxEmbeds = 10; | |||
| /// <summary> | |||
| /// Minimum amount of messages to bulk delete. | |||
| /// </summary> | |||
| public const int MinBulkDeleteAmount = 2; | |||
| /// <summary> | |||
| /// Maximum amount of messages to bulk delete. | |||
| /// </summary> | |||
| public const int MaxBulkDeleteAmount = 100; | |||
| /// <summary> | |||
| /// Id of the <see cref="Message"/>. | |||
| /// </summary> | |||
| @@ -182,7 +202,7 @@ namespace Discord.Net.Models | |||
| public Optional<MessageInteraction> Interaction { get; init; } | |||
| /// <summary> | |||
| /// The thread <see cref="Channel"/> that was started from this <see cref="Message"/>, | |||
| /// The <see cref="ThreadChannel"/> that was started from this <see cref="Message"/>, | |||
| /// includes <see cref="ThreadMember"/>s. | |||
| /// </summary> | |||
| [JsonPropertyName("thread")] | |||
| @@ -14,12 +14,12 @@ namespace Discord.Net.Models | |||
| Default = 0, | |||
| /// <summary> | |||
| /// Recipient was added to a group <see cref="Channel"/>. | |||
| /// Recipient was added to a <see cref="GroupChannel"/>. | |||
| /// </summary> | |||
| RecipientAdd = 1, | |||
| /// <summary> | |||
| /// Recipient was removed from a group <see cref="Channel"/>. | |||
| /// Recipient was removed from a <see cref="GroupChannel"/>. | |||
| /// </summary> | |||
| RecipientRemove = 2, | |||
| @@ -29,12 +29,12 @@ namespace Discord.Net.Models | |||
| Call = 3, | |||
| /// <summary> | |||
| /// Group <see cref="Channel"/> name was changed. | |||
| /// <see cref="GroupChannel"/> name was changed. | |||
| /// </summary> | |||
| ChannelNameChange = 4, | |||
| /// <summary> | |||
| /// Group <see cref="Channel"/> icon was changed. | |||
| /// <see cref="GroupChannel"/> icon was changed. | |||
| /// </summary> | |||
| ChannelIconChange = 5, | |||
| @@ -96,7 +96,7 @@ namespace Discord.Net.Models | |||
| GuildDiscoveryGracePeriodFinalWarning = 17, | |||
| /// <summary> | |||
| /// A thread <see cref="Channel"/> was created. | |||
| /// A <see cref="ThreadChannel"/> was created. | |||
| /// </summary> | |||
| ThreadCreated = 18, | |||
| @@ -111,7 +111,7 @@ namespace Discord.Net.Models | |||
| ApplicationCommand = 20, | |||
| /// <summary> | |||
| /// Starter message for a thread <see cref="Channel"/>. | |||
| /// Starter message for a <see cref="ThreadChannel"/>. | |||
| /// </summary> | |||
| ThreadStarterMessage = 21, | |||
| @@ -10,6 +10,16 @@ namespace Discord.Net.Models | |||
| /// </remarks> | |||
| public record Reaction | |||
| { | |||
| /// <summary> | |||
| /// Minimum amount of users that reacted in a message. | |||
| /// </summary> | |||
| public const int MinGetReactionsAmount = 1; | |||
| /// <summary> | |||
| /// Maximum amount of users that reacted in a message. | |||
| /// </summary> | |||
| public const int MaxGetReactionsAmount = 100; | |||
| /// <summary> | |||
| /// Times this <see cref="Models.Emoji"/> has been used to react. | |||
| /// </summary> | |||
| @@ -28,16 +28,357 @@ namespace Discord.Net | |||
| #region Audit Log | |||
| /// <inheritdoc/> | |||
| public Task<AuditLog> GetGuildAuditLogAsync(Snowflake guildId, GetGuildAuditLogParams? args = null, CancellationToken cancellationToken = default) | |||
| public Task<AuditLog> GetGuildAuditLogAsync(Snowflake guildId, GetGuildAuditLogParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(guildId, nameof(guildId)); | |||
| if (args == null) | |||
| args = new(); | |||
| else | |||
| args.Validate(); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.GetGuildAuditLogAsync(guildId, args, cancellationToken); | |||
| } | |||
| #endregion | |||
| #region Channel | |||
| /// <inheritdoc/> | |||
| public Task<Channel> GetChannelAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.GetChannelAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<GroupChannel> ModifyChannelAsync(Snowflake channelId, ModifyGroupChannelParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.ModifyChannelAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<GuildChannel> ModifyChannelAsync(Snowflake channelId, ModifyGuildChannelParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.ModifyChannelAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadChannel> ModifyChannelAsync(Snowflake channelId, ModifyThreadChannelParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.ModifyChannelAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Channel> DeleteChannelAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.DeleteChannelAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Message[]> GetChannelMessagesAsync(Snowflake channelId, GetChannelMessagesParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.GetChannelMessagesAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Message> GetChannelMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| return _api.GetChannelMessageAsync(channelId, messageId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Message> CreateMessageAsync(Snowflake channelId, CreateMessageParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.CreateMessageAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Message> CrosspostMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| return _api.CrosspostMessageAsync(channelId, messageId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task CreateReactionAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotNull(emoji, nameof(emoji)); | |||
| return _api.CreateReactionAsync(channelId, messageId, emoji, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task DeleteOwnReactionAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotNull(emoji, nameof(emoji)); | |||
| return _api.DeleteOwnReactionAsync(channelId, messageId, emoji, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task DeleteUserReactionAsync(Snowflake channelId, Snowflake messageId, Snowflake userId, Emoji emoji, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(userId, nameof(userId)); | |||
| Preconditions.NotNull(emoji, nameof(emoji)); | |||
| return _api.DeleteUserReactionAsync(channelId, messageId, userId, emoji, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<User[]> GetReactionsAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, GetReactionsParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotNull(emoji, nameof(emoji)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.GetReactionsAsync(channelId, messageId, emoji, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task DeleteAllReactionsAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.DeleteAllReactionsAsync(messageId, channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task DeleteAllReactionsforEmojiAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotNull(emoji, nameof(emoji)); | |||
| return _api.DeleteAllReactionsforEmojiAsync(channelId, messageId, emoji, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Message> EditMessageAsync(Snowflake channelId, Snowflake messageId, EditMessageParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.EditMessageAsync(channelId, messageId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task DeleteMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| return _api.DeleteMessageAsync(channelId, messageId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task BulkDeleteMessagesAsync(Snowflake channelId, BulkDeleteMessagesParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.BulkDeleteMessagesAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task EditChannelPermissionsAsync(Snowflake channelId, Snowflake overwriteId, EditChannelPermissionsParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(overwriteId, nameof(overwriteId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.EditChannelPermissionsAsync(channelId, overwriteId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<InviteWithMetadata[]> GetChannelInvitesAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.GetChannelInvitesAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Invite> CreateChannelInviteAsync(Snowflake channelId, CreateChannelInviteParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.CreateChannelInviteAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task DeleteChannelPermissionAsync(Snowflake channelId, Snowflake overwriteId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(overwriteId, nameof(overwriteId)); | |||
| return _api.DeleteChannelPermissionAsync(channelId, overwriteId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<FollowedChannel> FollowNewsChannelAsync(Snowflake channelId, FollowNewsChannelParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.FollowNewsChannelAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task TriggerTypingIndicatorAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.TriggerTypingIndicatorAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<Message[]> GetPinnedMessagesAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.GetPinnedMessagesAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task PinMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| return _api.PinMessageAsync(channelId, messageId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task UnpinMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| return _api.UnpinMessageAsync(channelId, messageId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task GroupDMAddRecipientAsync(Snowflake channelId, Snowflake userId, GroupDMAddRecipientParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(userId, nameof(userId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.GroupDMAddRecipientAsync(channelId, userId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task GroupDMRemoveRecipientAsync(Snowflake channelId, Snowflake userId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(userId, nameof(userId)); | |||
| return _api.GroupDMRemoveRecipientAsync(channelId, userId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadChannel> StartThreadAsync(Snowflake channelId, Snowflake messageId, StartThreadWithMessageParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(messageId, nameof(messageId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.StartThreadAsync(channelId, messageId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadChannel> StartThreadAsync(Snowflake channelId, StartThreadWithoutMessageParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.StartThreadAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task JoinThreadAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.JoinThreadAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task AddThreadMemberAsync(Snowflake channelId, Snowflake userId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(userId, nameof(userId)); | |||
| return _api.AddThreadMemberAsync(channelId, userId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task LeaveThreadAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.LeaveThreadAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task RemoveThreadMemberAsync(Snowflake channelId, Snowflake userId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotZero(userId, nameof(userId)); | |||
| return _api.RemoveThreadMemberAsync(channelId, userId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadMember[]> ListThreadMembersAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.ListThreadMembersAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadList> ListActiveThreadsAsync(Snowflake channelId, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| return _api.ListActiveThreadsAsync(channelId, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadList> ListPublicArchivedThreadsAsync(Snowflake channelId, ListPublicArchivedThreadsParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.ListPublicArchivedThreadsAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadList> ListPrivateArchivedThreadsAsync(Snowflake channelId, ListPrivateArchivedThreadsParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.ListPrivateArchivedThreadsAsync(channelId, args, cancellationToken); | |||
| } | |||
| /// <inheritdoc/> | |||
| public Task<ThreadList> ListJoinedPrivateArchivedThreadsAsync(Snowflake channelId, ListJoinedPrivateArchivedThreadsParams args, CancellationToken cancellationToken = default) | |||
| { | |||
| Preconditions.NotZero(channelId, nameof(channelId)); | |||
| Preconditions.NotNull(args, nameof(args)); | |||
| args.Validate(); | |||
| return _api.ListJoinedPrivateArchivedThreadsAsync(channelId, args, cancellationToken); | |||
| } | |||
| #endregion Channel | |||
| } | |||
| } | |||
| @@ -0,0 +1,57 @@ | |||
| using System; | |||
| using System.Net; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Represents errors received in response to rest requests. | |||
| /// </summary> | |||
| public class DiscordRestException : Exception | |||
| { | |||
| /// <summary> | |||
| /// HTTP status code returned. | |||
| /// </summary> | |||
| public HttpStatusCode HttpCode { get; } | |||
| /// <summary> | |||
| /// Discord JSON error code. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/topics/opcodes-and-status-codes#json-json-error-codes"/> | |||
| /// </remarks> | |||
| public int? DiscordCode { get; } | |||
| /// <summary> | |||
| /// Reason of this error. | |||
| /// </summary> | |||
| public string? Reason { get; } | |||
| /// <summary> | |||
| /// Creates a <see cref="DiscordRestException"/> with the provided error data. | |||
| /// </summary> | |||
| /// <param name="httpCode"> | |||
| /// HTTP status code. | |||
| /// </param> | |||
| /// <param name="discordCode"> | |||
| /// Discord JSON error code. | |||
| /// </param> | |||
| /// <param name="reason"> | |||
| /// Reason of this error. | |||
| /// </param> | |||
| public DiscordRestException(HttpStatusCode httpCode, int? discordCode = null, string? reason = null) | |||
| : base(CreateMessage(httpCode, discordCode, reason)) | |||
| { | |||
| HttpCode = httpCode; | |||
| DiscordCode = discordCode; | |||
| Reason = reason; | |||
| } | |||
| private static string CreateMessage(HttpStatusCode httpCode, int? discordCode = null, string? reason = null) | |||
| { | |||
| if (!string.IsNullOrEmpty(reason)) | |||
| return $"The server responded with error {discordCode ?? (int)httpCode}: {reason}"; | |||
| else | |||
| return $"The server responded with error {discordCode ?? (int)httpCode}: {httpCode}"; | |||
| } | |||
| } | |||
| } | |||
| @@ -13,13 +13,13 @@ namespace Discord.Net.Rest | |||
| #region Audit Log | |||
| /// <summary> | |||
| /// Returns an audit log object for the guild. | |||
| /// Gets an <see cref="AuditLog"/> for the <see cref="Guild"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Requires the <see cref="Permissions.ViewAuditLog"/> permission. | |||
| /// <see href="https://discord.com/developers/docs/resources/audit-log#get-guild-audit-log"/> | |||
| /// </remarks> | |||
| /// <param name="guildId"> | |||
| /// The guild identifier. | |||
| /// The <see cref="Guild"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| @@ -27,8 +27,843 @@ namespace Discord.Net.Rest | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| Task<AuditLog> GetGuildAuditLogAsync(Snowflake guildId, GetGuildAuditLogParams? args = null, CancellationToken cancellationToken = default); | |||
| /// <returns> | |||
| /// A task that contains an <see cref="AuditLog"/>. | |||
| /// </returns> | |||
| Task<AuditLog> GetGuildAuditLogAsync(Snowflake guildId, GetGuildAuditLogParams args, CancellationToken cancellationToken = default); | |||
| #endregion | |||
| #region Channel | |||
| /// <summary> | |||
| /// Gets a <see cref="Channel"/> by their identifier. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#get-channel"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains a <see cref="Channel"/> if it exists; | |||
| /// otherwise, <see langword="null"/>. | |||
| /// </returns> | |||
| Task<Channel> GetChannelAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Updates a <see cref="GroupChannel"/>'s settings. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#modify-channel"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="GroupChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the updated <see cref="GroupChannel"/>. | |||
| /// </returns> | |||
| /// <exception cref="DiscordRestException"> | |||
| /// Thrown when invalid parameters are supplied in <paramref name="args"/>. | |||
| /// </exception> | |||
| Task<GroupChannel> ModifyChannelAsync(Snowflake channelId, ModifyGroupChannelParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Updates a <see cref="GuildChannel"/>'s settings. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#modify-channel"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="GuildChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the updated <see cref="GuildChannel"/>. | |||
| /// </returns> | |||
| /// <exception cref="DiscordRestException"> | |||
| /// Thrown when invalid parameters are supplied in <paramref name="args"/>. | |||
| /// </exception> | |||
| Task<GuildChannel> ModifyChannelAsync(Snowflake channelId, ModifyGuildChannelParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Updates a <see cref="ThreadChannel"/>'s settings. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#modify-channel"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="ThreadChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the updated <see cref="ThreadChannel"/>. | |||
| /// </returns> | |||
| /// <exception cref="DiscordRestException"> | |||
| /// Thrown when invalid parameters are supplied in <paramref name="args"/>. | |||
| /// </exception> | |||
| Task<ThreadChannel> ModifyChannelAsync(Snowflake channelId, ModifyThreadChannelParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes a <see cref="Channel"/>, or closes a <see cref="PrivateChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#deleteclose-channel"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the deleted <see cref="Channel"/>. | |||
| /// </returns> | |||
| Task<Channel> DeleteChannelAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets an array of <see cref="Message"/>s from a <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#get-channel-messages"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains an array of <see cref="Message"/>s from the <see cref="Channel"/>. | |||
| /// </returns> | |||
| Task<Message[]> GetChannelMessagesAsync(Snowflake channelId, GetChannelMessagesParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets a specific <see cref="Message"/> from a <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#get-channel-message"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the specified <see cref="Message"/> or <see langword="null"/>. | |||
| /// </returns> | |||
| Task<Message> GetChannelMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Sends a <see cref="Message"/> to a <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#create-message"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the <see cref="Message"/> created. | |||
| /// </returns> | |||
| Task<Message> CreateMessageAsync(Snowflake channelId, CreateMessageParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Crossposts a <see cref="Message"/> in a News <see cref="Channel"/> to following channels. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#crosspost-message"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the crossposted <see cref="Message"/>. | |||
| /// </returns> | |||
| Task<Message> CrosspostMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Creates a <see cref="Reaction"/> for a <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#create-reaction"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="emoji"> | |||
| /// An <see cref="Emoji"/>. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task CreateReactionAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes a <see cref="Reaction"/> the current user has made for the <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#delete-own-reaction"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="emoji"> | |||
| /// An <see cref="Emoji"/>. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task DeleteOwnReactionAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes another <see cref="User"/>'s <see cref="Reaction"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#delete-user-reaction"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="userId"> | |||
| /// The <see cref="User"/> identifier. | |||
| /// </param> | |||
| /// <param name="emoji"> | |||
| /// An <see cref="Emoji"/>. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task DeleteUserReactionAsync(Snowflake channelId, Snowflake messageId, Snowflake userId, Emoji emoji, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets an array of <see cref="User"/>s that reacted with this <see cref="Emoji"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#get-reactions"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="emoji"> | |||
| /// An <see cref="Emoji"/>. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains an array of <see cref="User"/>s that reacted with | |||
| /// the provided <see cref="Emoji"/>. | |||
| /// </returns> | |||
| Task<User[]> GetReactionsAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, GetReactionsParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes all <see cref="Reaction"/>s on a <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#delete-all-reactions"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task DeleteAllReactionsAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes all the <see cref="Reaction"/>s for a given <see cref="Emoji"/> | |||
| /// on a <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#delete-all-reactions-for-emoji"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="emoji"> | |||
| /// An <see cref="Emoji"/>. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task DeleteAllReactionsforEmojiAsync(Snowflake channelId, Snowflake messageId, Emoji emoji, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Edits a previously sent <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#edit-message"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the updated <see cref="Message"/>. | |||
| /// </returns> | |||
| Task<Message> EditMessageAsync(Snowflake channelId, Snowflake messageId, EditMessageParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes a message. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#delete-message"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task DeleteMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes multiple <see cref="Message"/>s in a single request. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#bulk-delete-messages"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| /// <exception cref="DiscordRestException"> | |||
| /// Thrown when invalid parameters are supplied in <paramref name="args"/>. | |||
| /// </exception> | |||
| Task BulkDeleteMessagesAsync(Snowflake channelId, BulkDeleteMessagesParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Edits the <see cref="Channel"/> permission <see cref="Overwrite"/>s for a <see cref="User"/> or <see cref="Role"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#edit-channel-permissions"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="overwriteId"> | |||
| /// The <see cref="Overwrite"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task EditChannelPermissionsAsync(Snowflake channelId, Snowflake overwriteId, EditChannelPermissionsParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets an array of <see cref="Invite"/>s for a <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#get-channel-invites"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains an array of <see cref="InviteWithMetadata"/>s. | |||
| /// </returns> | |||
| Task<InviteWithMetadata[]> GetChannelInvitesAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Creates a new <see cref="Invite"/> for the <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#create-channel-invite"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the created <see cref="Invite"/>. | |||
| /// </returns> | |||
| Task<Invite> CreateChannelInviteAsync(Snowflake channelId, CreateChannelInviteParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Deletes a <see cref="Channel"/> permission <see cref="Overwrite"/> for a <see cref="User"/> or <see cref="Role"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#delete-channel-permission"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="overwriteId"> | |||
| /// The <see cref="Overwrite"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task DeleteChannelPermissionAsync(Snowflake channelId, Snowflake overwriteId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Follow a News <see cref="Channel"/> to send <see cref="Message"/>s to a target <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#follow-news-channel"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the <see cref="FollowedChannel"/>. | |||
| /// </returns> | |||
| Task<FollowedChannel> FollowNewsChannelAsync(Snowflake channelId, FollowNewsChannelParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Posts a typing indicator for the specified <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task TriggerTypingIndicatorAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets all pinned <see cref="Message"/>s in the <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#get-pinned-messages"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains an array of all pinned <see cref="Message"/>s. | |||
| /// </returns> | |||
| Task<Message[]> GetPinnedMessagesAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Pins a <see cref="Message"/> in a <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#pin-message"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task PinMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Unpins a <see cref="Message"/> in a <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#unpin-message"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task UnpinMessageAsync(Snowflake channelId, Snowflake messageId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Adds a recipient to a <see cref="GroupChannel"/> using their access token. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#group-dm-add-recipient"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="userId"> | |||
| /// The <see cref="User"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task GroupDMAddRecipientAsync(Snowflake channelId, Snowflake userId, GroupDMAddRecipientParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Removes a recipient from a <see cref="GroupChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#group-dm-remove-recipient"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="userId"> | |||
| /// The <see cref="User"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task GroupDMRemoveRecipientAsync(Snowflake channelId, Snowflake userId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Creates a new <see cref="ThreadChannel"/> from an existing <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#start-thread-with-message"/> | |||
| /// </remarks> | |||
| /// <param name="messageId"> | |||
| /// The <see cref="Message"/> identifier. | |||
| /// </param> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the created <see cref="ThreadChannel"/>. | |||
| /// </returns> | |||
| /// <exception cref="DiscordRestException"> | |||
| /// Thrown when invalid parameters are supplied in <paramref name="args"/>. | |||
| /// </exception> | |||
| Task<ThreadChannel> StartThreadAsync(Snowflake channelId, Snowflake messageId, StartThreadWithMessageParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Creates a new private <see cref="ThreadChannel"/> that is not connected to an existing <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#start-thread-without-message"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains the created <see cref="ThreadChannel"/>. | |||
| /// </returns> | |||
| /// <exception cref="DiscordRestException"> | |||
| /// Thrown when invalid parameters are supplied in <paramref name="args"/>. | |||
| /// </exception> | |||
| Task<ThreadChannel> StartThreadAsync(Snowflake channelId, StartThreadWithoutMessageParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Adds the current user to a <see cref="ThreadChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#join-thread"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="ThreadChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task JoinThreadAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Adds another <see cref="GuildMember"/> to a <see cref="ThreadChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#add-thread-member"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="ThreadChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="userId"> | |||
| /// The <see cref="GuildMember"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task AddThreadMemberAsync(Snowflake channelId, Snowflake userId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Removes the current user from a <see cref="ThreadChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#leave-thread"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="ThreadChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task LeaveThreadAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Removes another <see cref="GuildMember"/> from a <see cref="ThreadChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#remove-thread-member"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="ThreadChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="userId"> | |||
| /// The <see cref="GuildMember"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that represents this asynchronous operation. | |||
| /// </returns> | |||
| Task RemoveThreadMemberAsync(Snowflake channelId, Snowflake userId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets an array of <see cref="ThreadMember"/>s that are part of the <see cref="ThreadChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#list-thread-members"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="ThreadChannel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains an array of <see cref="ThreadMember"/>s that are part of the | |||
| /// specified <see cref="ThreadChannel"/>. | |||
| /// </returns> | |||
| Task<ThreadMember[]> ListThreadMembersAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets all active <see cref="ThreadChannel"/>s in the <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#list-active-threads"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains a <see cref="ThreadList"/>. | |||
| /// </returns> | |||
| Task<ThreadList> ListActiveThreadsAsync(Snowflake channelId, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets archived <see cref="ThreadChannel"/>s in the <see cref="Channel"/> that are public. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#list-public-archived-threads"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains a <see cref="ThreadList"/>. | |||
| /// </returns> | |||
| Task<ThreadList> ListPublicArchivedThreadsAsync(Snowflake channelId, ListPublicArchivedThreadsParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets archived <see cref="ThreadChannel"/>s in the <see cref="Channel"/> that are private. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#list-private-archived-threads"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains a <see cref="ThreadList"/>. | |||
| /// </returns> | |||
| Task<ThreadList> ListPrivateArchivedThreadsAsync(Snowflake channelId, ListPrivateArchivedThreadsParams args, CancellationToken cancellationToken = default); | |||
| /// <summary> | |||
| /// Gets archived <see cref="ThreadChannel"/>s in the <see cref="Channel"/> that are | |||
| /// private and the current user has joined. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#list-joined-private-archived-threads"/> | |||
| /// </remarks> | |||
| /// <param name="channelId"> | |||
| /// The <see cref="Channel"/> identifier. | |||
| /// </param> | |||
| /// <param name="args"> | |||
| /// Parameters to include in the request. | |||
| /// </param> | |||
| /// <param name="cancellationToken"> | |||
| /// Cancellation token for the request. | |||
| /// </param> | |||
| /// <returns> | |||
| /// A task that contains a <see cref="ThreadList"/>. | |||
| /// </returns> | |||
| Task<ThreadList> ListJoinedPrivateArchivedThreadsAsync(Snowflake channelId, ListJoinedPrivateArchivedThreadsParams args, CancellationToken cancellationToken = default); | |||
| #endregion Channel | |||
| } | |||
| } | |||
| @@ -8,7 +8,7 @@ namespace Discord.Net.Rest | |||
| public record GetGuildAuditLogParams | |||
| { | |||
| /// <summary> | |||
| /// Filter the log for actions made by a user. | |||
| /// Filter the log for actions made by a <see cref="User"/>. | |||
| /// </summary> | |||
| public Optional<Snowflake> UserId { get; set; } | |||
| @@ -36,6 +36,7 @@ namespace Discord.Net.Rest | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotZero(UserId, nameof(UserId)); | |||
| Preconditions.NotZero(Before, nameof(Before)); | |||
| Preconditions.AtLeast(Limit, AuditLog.MinimumGetEntryAmount, nameof(Limit)); | |||
| Preconditions.AtMost(Limit, AuditLog.MaximumGetEntryAmount, nameof(Limit)); | |||
| } | |||
| @@ -0,0 +1,32 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record EditChannelPermissionsParams | |||
| { | |||
| /// <summary> | |||
| /// The bitwise value of all allowed permissions. | |||
| /// </summary> | |||
| public Permissions Allow { get; set; } | |||
| /// <summary> | |||
| /// The bitwise value of all disallowed permissions. | |||
| /// </summary> | |||
| public Permissions Deny { get; set; } | |||
| /// <summary> | |||
| /// Type of overwrite. | |||
| /// </summary> | |||
| public OverwriteType Type { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,23 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record FollowNewsChannelParams | |||
| { | |||
| /// <summary> | |||
| /// Id of target <see cref="Channel"/>. | |||
| /// </summary> | |||
| public Snowflake WebhookChannelId { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotZero(WebhookChannelId, nameof(WebhookChannelId)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record GroupDMAddRecipientParams | |||
| { | |||
| /// <summary> | |||
| /// Access token of a <see cref="User"/> that has granted your app the gdm.join scope. | |||
| /// </summary> | |||
| public string? AccessToken { get; set; } // Required property candidate | |||
| /// <summary> | |||
| /// Nickname of the <see cref="User"/> being added. | |||
| /// </summary> | |||
| public string? Nick { get; set; } // Required property candidate | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotNullOrEmpty(AccessToken, nameof(AccessToken)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,27 @@ | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record ListJoinedPrivateArchivedThreadsParams | |||
| { | |||
| /// <summary> | |||
| /// Returns threads before this id. | |||
| /// </summary> | |||
| public Optional<Snowflake> Before { get; set; } | |||
| /// <summary> | |||
| /// Maximum number of threads to return. | |||
| /// </summary> | |||
| public Optional<int> Limit { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotZero(Before, nameof(Before)); | |||
| Preconditions.NotZero(Limit, nameof(Limit)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| using System; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record ListPrivateArchivedThreadsParams | |||
| { | |||
| /// <summary> | |||
| /// Returns threads before this timestamp. | |||
| /// </summary> | |||
| public Optional<DateTimeOffset> Before { get; set; } | |||
| /// <summary> | |||
| /// Maximum number of threads to return. | |||
| /// </summary> | |||
| public Optional<int> Limit { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotZero(Limit, nameof(Limit)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,28 @@ | |||
| using System; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record ListPublicArchivedThreadsParams | |||
| { | |||
| /// <summary> | |||
| /// Returns threads before this timestamp. | |||
| /// </summary> | |||
| public Optional<DateTimeOffset> Before { get; set; } | |||
| /// <summary> | |||
| /// Maximum number of threads to return. | |||
| /// </summary> | |||
| public Optional<int> Limit { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotZero(Limit, nameof(Limit)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to include in a request to modify a <see cref="GroupChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#modify-channel-json-params-group-dm"/> | |||
| /// </remarks> | |||
| public record ModifyGroupChannelParams | |||
| { | |||
| /// <summary> | |||
| /// <see cref="Channel"/> name. | |||
| /// </summary> | |||
| public Optional<string> Name { get; set; } | |||
| /// <summary> | |||
| /// Base64 encoded icon. | |||
| /// </summary> | |||
| public Optional<string> Icon { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotNullOrWhitespace(Name!, nameof(Name)); | |||
| Preconditions.LengthAtLeast(Name!, Channel.MinChannelNameLength, nameof(Name)); | |||
| Preconditions.LengthAtMost(Name!, Channel.MaxChannelNameLength, nameof(Name)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,101 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to include in a request to modify a <see cref="GuildChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#modify-channel-json-params-guild-channel"/> | |||
| /// </remarks> | |||
| public record ModifyGuildChannelParams | |||
| { | |||
| /// <summary> | |||
| /// <see cref="Channel"/> name. | |||
| /// </summary> | |||
| public Optional<string> Name { get; set; } | |||
| /// <summary> | |||
| /// The type of <see cref="Channel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Only conversion between text and news is supported and only in guilds with the "NEWS" feature. | |||
| /// </remarks> | |||
| public Optional<ChannelType> Type { get; set; } | |||
| /// <summary> | |||
| /// The position of the <see cref="Channel"/> in the left-hand listing. | |||
| /// </summary> | |||
| public Optional<int?> Position { get; set; } | |||
| /// <summary> | |||
| /// <see cref="Channel"/> topic. | |||
| /// </summary> | |||
| public Optional<string?> Topic { get; set; } | |||
| /// <summary> | |||
| /// Whether the <see cref="Channel"/> is nsfw. | |||
| /// </summary> | |||
| public Optional<bool?> Nsfw { get; set; } | |||
| /// <summary> | |||
| /// Amount of seconds a <see cref="User"/> has to wait before sending another message; | |||
| /// bots, as well as <see cref="User"/>s with the permission <see cref="Permissions.ManageMessages"/> | |||
| /// or <see cref="Permissions.ManageChannels"/>, are unaffected. | |||
| /// </summary> | |||
| public Optional<int?> RateLimitPerUser { get; set; } | |||
| /// <summary> | |||
| /// The bitrate (in bits) of the <see cref="VoiceChannel"/>. | |||
| /// </summary> | |||
| public Optional<int?> Bitrate { get; set; } | |||
| /// <summary> | |||
| /// The <see cref="User"/> limit of the <see cref="VoiceChannel"/>; 0 refers to no limit, | |||
| /// 1 to 99 refers to a <see cref="User"/> limit. | |||
| /// </summary> | |||
| public Optional<int?> UserLimit { get; set; } | |||
| /// <summary> | |||
| /// <see cref="Channel"/> or category-specific permissions. | |||
| /// </summary> | |||
| public Optional<Overwrite[]?> PermissionOverwrites { get; set; } | |||
| /// <summary> | |||
| /// Id of the new parent <see cref="CategoryChannel"/> for a <see cref="Channel"/>. | |||
| /// </summary> | |||
| public Optional<Snowflake?> ParentId { get; set; } | |||
| /// <summary> | |||
| /// <see cref="Channel"/> voice region id, automatic when set to <see langword="null"/>. | |||
| /// </summary> | |||
| public Optional<string?> RtcRegion { get; set; } | |||
| /// <summary> | |||
| /// The camera video quality mode of the <see cref="VoiceChannel"/>. | |||
| /// </summary> | |||
| public Optional<int?> VideoQualityMode { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotNullOrWhitespace(Name!, nameof(Name)); | |||
| Preconditions.LengthAtLeast(Name!, Channel.MinChannelNameLength, nameof(Name)); | |||
| Preconditions.LengthAtMost(Name!, Channel.MaxChannelNameLength, nameof(Name)); | |||
| Preconditions.MustBeOneOf(Type, new[] { ChannelType.GuildText, ChannelType.GuildNews }, nameof(Type)); | |||
| Preconditions.NotNegative(Position, nameof(Position)); | |||
| Preconditions.NotNull(Topic, nameof(Topic)); | |||
| Preconditions.LengthAtLeast(Topic, Channel.MinChannelTopicLength, nameof(Topic)); | |||
| Preconditions.LengthAtMost(Topic, Channel.MaxChannelTopicLength, nameof(Topic)); | |||
| Preconditions.AtLeast(RateLimitPerUser, Channel.MinRateLimitPerUserDuration, nameof(RateLimitPerUser)); | |||
| Preconditions.AtMost(RateLimitPerUser, Channel.MaxRateLimitPerUserDuration, nameof(RateLimitPerUser)); | |||
| Preconditions.AtLeast(Bitrate, Channel.MinBitrate, nameof(Bitrate)); | |||
| Preconditions.AtMost(Bitrate, Channel.MaxBitrate, nameof(Bitrate)); | |||
| Preconditions.AtLeast(UserLimit, Channel.MinUserLimit, nameof(UserLimit)); | |||
| Preconditions.AtMost(UserLimit, Channel.MaxUserLimit, nameof(UserLimit)); | |||
| Preconditions.NotNull(PermissionOverwrites, nameof(PermissionOverwrites)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,57 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to include in a request to modify a <see cref="ThreadChannel"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#modify-channel-json-params-guild-channel"/> | |||
| /// </remarks> | |||
| public record ModifyThreadChannelParams | |||
| { | |||
| /// <summary> | |||
| /// <see cref="ThreadChannel"/> name. | |||
| /// </summary> | |||
| public Optional<string> Name { get; set; } | |||
| /// <summary> | |||
| /// Whether the <see cref="ThreadChannel"/> is archived. | |||
| /// </summary> | |||
| public Optional<bool> Archived { get; set; } | |||
| /// <summary> | |||
| /// Duration in minutes to automatically archive the <see cref="ThreadChannel"/> after recent activity. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Can be set to 60, 1440, 4320, or 10080. | |||
| /// </remarks> | |||
| public Optional<int> AutoArchiveDuration { get; set; } | |||
| /// <summary> | |||
| /// When a <see cref="ThreadChannel"/> is locked, only <see cref="User"/>s with | |||
| /// <see cref="Permissions.ManageThreads"/> can unarchive it. | |||
| /// </summary> | |||
| public Optional<bool> Locked { get; set; } | |||
| /// <summary> | |||
| /// Amount of seconds a <see cref="User"/> has to wait before sending another message; | |||
| /// bots, as well as <see cref="User"/>s with the permission <see cref="Permissions.ManageMessages"/>, | |||
| /// <see cref="Permissions.ManageThreads"/>, or <see cref="Permissions.ManageChannels"/>, are unaffected. | |||
| /// </summary> | |||
| public Optional<int?> RateLimitPerUser { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotNullOrWhitespace(Name!, nameof(Name)); | |||
| Preconditions.LengthAtLeast(Name!, Channel.MinChannelNameLength, nameof(Name)); | |||
| Preconditions.LengthAtMost(Name!, Channel.MaxChannelNameLength, nameof(Name)); | |||
| Preconditions.MustBeOneOf(AutoArchiveDuration, new[] { 60, 1440, 4320, 10080 }, nameof(AutoArchiveDuration)); | |||
| Preconditions.AtLeast(RateLimitPerUser, Channel.MinRateLimitPerUserDuration, nameof(RateLimitPerUser)); | |||
| Preconditions.AtMost(RateLimitPerUser, Channel.MaxRateLimitPerUserDuration, nameof(RateLimitPerUser)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record StartThreadWithMessageParams | |||
| { | |||
| /// <summary> | |||
| /// <see cref="ThreadChannel"/> name. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Must be between 1-100, inclusive. | |||
| /// </remarks> | |||
| public string? Name { get; set; } // Required property candidate | |||
| /// <summary> | |||
| /// Duration in minutes to automatically archive the thread after recent activity. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Can be set to: 60, 1440, 4320, 10080. | |||
| /// </remarks> | |||
| public int AutoArchiveDuration { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotNullOrWhitespace(Name!, nameof(Name)); | |||
| Preconditions.LengthAtLeast(Name!, Channel.MinChannelNameLength, nameof(Name)); | |||
| Preconditions.LengthAtMost(Name!, Channel.MaxChannelNameLength, nameof(Name)); | |||
| Preconditions.MustBeOneOf(AutoArchiveDuration, new[] { 60, 1440, 4320, 10080 }, nameof(AutoArchiveDuration)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,37 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record StartThreadWithoutMessageParams | |||
| { | |||
| /// <summary> | |||
| /// <see cref="ThreadChannel"/> name. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Must be between 1-100, inclusive. | |||
| /// </remarks> | |||
| public string? Name { get; set; } // Required property candidate | |||
| /// <summary> | |||
| /// Duration in minutes to automatically archive the thread after recent activity. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Can be set to: 60, 1440, 4320, 10080. | |||
| /// </remarks> | |||
| public int AutoArchiveDuration { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotNullOrWhitespace(Name!, nameof(Name)); | |||
| Preconditions.LengthAtLeast(Name!, Channel.MinChannelNameLength, nameof(Name)); | |||
| Preconditions.LengthAtMost(Name!, Channel.MaxChannelNameLength, nameof(Name)); | |||
| Preconditions.MustBeOneOf(AutoArchiveDuration, new[] { 60, 1440, 4320, 10080 }, nameof(AutoArchiveDuration)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,73 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record CreateChannelInviteParams | |||
| { | |||
| /// <summary> | |||
| /// Duration of <see cref="Invite"/> in seconds before expiry. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Must be between 0 and 604800 (7 days), inclusive. Zero means never. | |||
| /// </remarks> | |||
| public Optional<int> MaxAge { get; set; } | |||
| /// <summary> | |||
| /// Maximum number of uses. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Must be between 0 and 100, inclusive. Zero means unlimited. | |||
| /// </remarks> | |||
| public Optional<int> MaxUses { get; set; } | |||
| /// <summary> | |||
| /// Whether this <see cref="Invite"/> only grants temporary membership. | |||
| /// </summary> | |||
| public Optional<bool> Temporary { get; set; } | |||
| /// <summary> | |||
| /// If true, don't try to reuse a similar <see cref="Invite"/> (useful for | |||
| /// creating many unique one time use invites). | |||
| /// </summary> | |||
| public Optional<bool> Unique { get; set; } | |||
| /// <summary> | |||
| /// The type of target for this <see cref="VoiceChannel"/> <see cref="Invite"/>. | |||
| /// </summary> | |||
| public Optional<InviteTargetType> TargetType { get; set; } | |||
| /// <summary> | |||
| /// The id of the <see cref="User"/> whose stream to display for this <see cref="Invite"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Required if <see cref="TargetType"/> is <see cref="InviteTargetType.Stream"/>, | |||
| /// the <see cref="User"/> must be streaming in the <see cref="Channel"/>. | |||
| /// </remarks> | |||
| public Optional<Snowflake> TargetUserId { get; set; } | |||
| /// <summary> | |||
| /// The id of the embedded application to open for this <see cref="Invite"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Required if <see cref="TargetType"/> is <see cref="InviteTargetType.EmbeddedApplication"/>, | |||
| /// the application must have the <see cref="ApplicationFlags.Embedded"/> flag. | |||
| /// </remarks> | |||
| public Optional<Snowflake> TargetApplicationId { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.AtLeast(MaxAge, InviteWithMetadata.MinAgeTime, nameof(MaxAge)); | |||
| Preconditions.AtMost(MaxAge, InviteWithMetadata.MaxAgeTime, nameof(MaxAge)); | |||
| Preconditions.AtLeast(MaxUses, InviteWithMetadata.MinUseCount, nameof(MaxUses)); | |||
| Preconditions.AtMost(MaxUses, InviteWithMetadata.MaxUseCount, nameof(MaxUses)); | |||
| Preconditions.NotZero(TargetUserId, nameof(TargetUserId)); | |||
| Preconditions.NotZero(TargetApplicationId, nameof(TargetApplicationId)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,27 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record BulkDeleteMessagesParams | |||
| { | |||
| /// <summary> | |||
| /// An array of <see cref="Message"/> ids to delete. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Length must be between 2 and 100, inclusive. | |||
| /// </remarks> | |||
| public Snowflake[]? Messages { get; set; } // Required property candidate | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.LengthAtLeast(Messages!, Message.MinBulkDeleteAmount, nameof(Messages)); | |||
| Preconditions.LengthAtMost(Messages!, Message.MaxBulkDeleteAmount, nameof(Messages)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,71 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to include in a request to create a <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#create-message-jsonform-params"/> | |||
| /// </remarks> | |||
| public record CreateMessageParams | |||
| { | |||
| /// <summary> | |||
| /// The <see cref="Message"/> content. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Up to 2000 characters. | |||
| /// </remarks> | |||
| public Optional<string> Content { get; set; } | |||
| /// <summary> | |||
| /// Set the <see cref="Message"/> as a TTS one. | |||
| /// </summary> | |||
| public Optional<bool> Tts { get; set; } | |||
| /// <summary> | |||
| /// The contents of the file being sent. | |||
| /// </summary> | |||
| public Optional<MultipartFile> File { get; set; } | |||
| /// <summary> | |||
| /// Array of <see cref="Embed"/>s to include with the <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Up to 10 <see cref="Embed"/>s. | |||
| /// </remarks> | |||
| public Optional<Embed[]> Embeds { get; set; } | |||
| /// <summary> | |||
| /// JSON encoded body of non-file params. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Multipart/form-data only. | |||
| /// </remarks> | |||
| public Optional<CreateMessageParams> PayloadJson { get; set; } // TODO: Should change this to an easy way to convert to form data. | |||
| /// <summary> | |||
| /// Allowed mentions for the <see cref="Message"/>. | |||
| /// </summary> | |||
| public Optional<AllowedMentions> AlloweMentions { get; set; } | |||
| /// <summary> | |||
| /// Include to make your <see cref="Message"/> a reply. | |||
| /// </summary> | |||
| public Optional<MessageReference> MessageReference { get; set; } | |||
| /// <summary> | |||
| /// The <see cref="Component"/>s to include with the <see cref="Message"/>. | |||
| /// </summary> | |||
| public Optional<Component[]> Components { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.LengthAtMost(Content!, Message.MaxContentLength, nameof(Content)); | |||
| Preconditions.LengthAtMost(Embeds!, Message.MaxEmbeds, nameof(Embeds)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,74 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to include in a request to edit a <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#edit-message-jsonform-params"/> | |||
| /// </remarks> | |||
| public record EditMessageParams | |||
| { | |||
| /// <summary> | |||
| /// The <see cref="Message"/> content. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Up to 2000 characters. | |||
| /// </remarks> | |||
| public Optional<string?> Content { get; set; } | |||
| /// <summary> | |||
| /// Array of <see cref="Embed"/>s to include with the <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Up to 10 <see cref="Embed"/>s. | |||
| /// </remarks> | |||
| public Optional<Embed[]?> Embeds { get; set; } | |||
| /// <summary> | |||
| /// Edit the <see cref="MessageFlags"/> of a <see cref="Message"/>. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Only <see cref="MessageFlags.SuppressEmbeds"/> can currently be set/unset. | |||
| /// </remarks> | |||
| public Optional<MessageFlags?> Flags { get; set; } | |||
| /// <summary> | |||
| /// The contents of the file being sent. | |||
| /// </summary> | |||
| public Optional<MultipartFile?> File { get; set; } | |||
| /// <summary> | |||
| /// JSON encoded body of non-file params. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Multipart/form-data only. | |||
| /// </remarks> | |||
| public Optional<CreateMessageParams?> PayloadJson { get; set; } // TODO: Should change this to an easy way to convert to form data. | |||
| /// <summary> | |||
| /// Attached files to keep. | |||
| /// </summary> | |||
| public Optional<Attachment[]?> Attachments { get; set; } | |||
| /// <summary> | |||
| /// Allowed mentions for the <see cref="Message"/>. | |||
| /// </summary> | |||
| public Optional<AllowedMentions?> AlloweMentions { get; set; } | |||
| /// <summary> | |||
| /// The <see cref="Component"/>s to include with the <see cref="Message"/>. | |||
| /// </summary> | |||
| public Optional<Component[]?> Components { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.LengthAtMost(Content!, Message.MaxContentLength, nameof(Content)); | |||
| Preconditions.LengthAtMost(Embeds, Message.MaxEmbeds, nameof(Embeds)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,44 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record GetChannelMessagesParams | |||
| { | |||
| /// <summary> | |||
| /// Get <see cref="Message"/>s around this <see cref="Message"/> ID. | |||
| /// </summary> | |||
| public Optional<Snowflake> Around { get; set; } | |||
| /// <summary> | |||
| /// Get <see cref="Message"/>s before this <see cref="Message"/> ID. | |||
| /// </summary> | |||
| public Optional<Snowflake> Before { get; set; } | |||
| /// <summary> | |||
| /// Get <see cref="Message"/>s after this <see cref="Message"/> ID. | |||
| /// </summary> | |||
| public Optional<Snowflake> After { get; set; } | |||
| /// <summary> | |||
| /// Maximum number of <see cref="Message"/>s to return. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Default: 50. Acceptable range: 1-100, inclusive. | |||
| /// </remarks> | |||
| public Optional<int> Limit { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotZero(Before, nameof(Before)); | |||
| Preconditions.Exclusive(new[] { Around, Before, After }, new[] { nameof(Around), nameof(Before), nameof(After) }); | |||
| Preconditions.AtLeast(Limit, Channel.MinGetMessagesAmount, nameof(Limit)); | |||
| Preconditions.AtMost(Limit, Channel.MaxGetMessagesAmount, nameof(Limit)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,33 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Parameters to add to the request. | |||
| /// </summary> | |||
| public record GetReactionsParams | |||
| { | |||
| /// <summary> | |||
| /// Get <see cref="User"/>s after this <see cref="User"/> ID. | |||
| /// </summary> | |||
| public Optional<Snowflake> After { get; set; } | |||
| /// <summary> | |||
| /// Maximum number of <see cref="User"/>s to return. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// Default: 25. Acceptable range: 1-100, inclusive. | |||
| /// </remarks> | |||
| public Optional<int> Limit { get; set; } | |||
| /// <summary> | |||
| /// Validates the data. | |||
| /// </summary> | |||
| public void Validate() | |||
| { | |||
| Preconditions.NotZero(After, nameof(After)); | |||
| Preconditions.AtLeast(Limit, Reaction.MinGetReactionsAmount, nameof(Limit)); | |||
| Preconditions.AtMost(Limit, Reaction.MaxGetReactionsAmount, nameof(Limit)); | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,20 @@ | |||
| using System.IO; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Represents a multipart file to send in a request. | |||
| /// </summary> | |||
| public record MultipartFile | |||
| { | |||
| /// <summary> | |||
| /// The file stream. | |||
| /// </summary> | |||
| public Stream? Stream { get; set; } // Required property candidate | |||
| /// <summary> | |||
| /// The file name. | |||
| /// </summary> | |||
| public string? Filename { get; set; } // Required property candidate | |||
| } | |||
| } | |||
| @@ -0,0 +1,30 @@ | |||
| using Discord.Net.Models; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| /// <summary> | |||
| /// Represents a response to list <see cref="ThreadChannel"/>s. | |||
| /// </summary> | |||
| /// <remarks> | |||
| /// <see href="https://discord.com/developers/docs/resources/channel#list-active-threads-response-body"/> | |||
| /// </remarks> | |||
| public record ThreadList | |||
| { | |||
| /// <summary> | |||
| /// Array of <see cref="ThreadChannel"/>s returned. | |||
| /// </summary> | |||
| public ThreadChannel[]? Threads { get; init; } // Required property candidate | |||
| /// <summary> | |||
| /// Array of <see cref="ThreadMember"/>s for each returned thread the current | |||
| /// user has joined. | |||
| /// </summary> | |||
| public ThreadMember[]? Members { get; init; } // Required property candidate | |||
| /// <summary> | |||
| /// Whether there are potentially additional <see cref="ThreadChannel"/>s that | |||
| /// could be returned on a subsequent call. | |||
| /// </summary> | |||
| public bool HasMore { get; init; } | |||
| } | |||
| } | |||
| @@ -1,4 +1,6 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| namespace Discord.Net.Rest | |||
| { | |||
| @@ -6,8 +8,8 @@ namespace Discord.Net.Rest | |||
| { | |||
| // Objects | |||
| public static void NotNull<T>(T obj, string name, string? msg = null) where T : class { if (obj == null) throw CreateNotNullException(name, msg); } | |||
| public static void NotNull<T>(Optional<T> obj, string name, string? msg = null) where T : class { if (obj.IsSpecified && obj.Value == null) throw CreateNotNullException(name, msg); } | |||
| public static void NotNull<T>(T? obj, string name, string? msg = null) where T : class { if (obj == null) throw CreateNotNullException(name, msg); } | |||
| public static void NotNull<T>(Optional<T?> obj, string name, string? msg = null) where T : class { if (obj.IsSpecified && obj.Value == null) throw CreateNotNullException(name, msg); } | |||
| private static ArgumentNullException CreateNotNullException(string name, string? msg) | |||
| { | |||
| @@ -17,6 +19,27 @@ namespace Discord.Net.Rest | |||
| return new ArgumentNullException(name, msg); | |||
| } | |||
| public static void LengthAtLeast<T>(T[]? obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj?.Length < value) | |||
| { | |||
| if (msg == null) | |||
| throw new ArgumentException($"Length must be at least {value}", name); | |||
| else | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| public static void LengthAtMost<T>(T[]? obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj?.Length > value) | |||
| { | |||
| if (msg == null) | |||
| throw new ArgumentException($"Length must be at most {value}", name); | |||
| else | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| // Optionals | |||
| public static void Exclusive<T>(Optional<T>[] objs, string[] names, string? msg = null) | |||
| @@ -36,18 +59,39 @@ namespace Discord.Net.Rest | |||
| } | |||
| } | |||
| public static void LengthAtLeast<T>(Optional<T[]?> obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj.IsSpecified && obj.Value?.Length < value) | |||
| { | |||
| if (msg == null) | |||
| throw new ArgumentException($"Length must be at least {value}", name); | |||
| else | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| public static void LengthAtMost<T>(Optional<T[]?> obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj.IsSpecified && obj.Value?.Length > value) | |||
| { | |||
| if (msg == null) | |||
| throw new ArgumentException($"Length must be at most {value}", name); | |||
| else | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| // Strings | |||
| public static void NotEmpty(string obj, string name, string? msg = null) { if (obj != null && obj.Length == 0) throw CreateNotEmptyException(name, msg); } | |||
| public static void NotEmpty(Optional<string> obj, string name, string? msg = null) { if (obj.IsSpecified && obj.Value != null && obj.Value.Length == 0) throw CreateNotEmptyException(name, msg); } | |||
| public static void NotNullOrEmpty(string obj, string name, string? msg = null) | |||
| public static void NotEmpty(string? obj, string name, string? msg = null) { if (obj != null && obj.Length == 0) throw CreateNotEmptyException(name, msg); } | |||
| public static void NotEmpty(Optional<string?> obj, string name, string? msg = null) { if (obj.IsSpecified && obj.Value != null && obj.Value.Length == 0) throw CreateNotEmptyException(name, msg); } | |||
| public static void NotNullOrEmpty(string? obj, string name, string? msg = null) | |||
| { | |||
| if (obj == null) | |||
| throw CreateNotNullException(name, msg); | |||
| if (obj.Length == 0) | |||
| throw CreateNotEmptyException(name, msg); | |||
| } | |||
| public static void NotNullOrEmpty(Optional<string> obj, string name, string? msg = null) | |||
| public static void NotNullOrEmpty(Optional<string?> obj, string name, string? msg = null) | |||
| { | |||
| if (obj.IsSpecified) | |||
| { | |||
| @@ -57,14 +101,14 @@ namespace Discord.Net.Rest | |||
| throw CreateNotEmptyException(name, msg); | |||
| } | |||
| } | |||
| public static void NotNullOrWhitespace(string obj, string name, string? msg = null) | |||
| public static void NotNullOrWhitespace(string? obj, string name, string? msg = null) | |||
| { | |||
| if (obj == null) | |||
| throw CreateNotNullException(name, msg); | |||
| if (obj.Trim().Length == 0) | |||
| throw CreateNotEmptyException(name, msg); | |||
| } | |||
| public static void NotNullOrWhitespace(Optional<string> obj, string name, string? msg = null) | |||
| public static void NotNullOrWhitespace(Optional<string?> obj, string name, string? msg = null) | |||
| { | |||
| if (obj.IsSpecified) | |||
| { | |||
| @@ -75,7 +119,7 @@ namespace Discord.Net.Rest | |||
| } | |||
| } | |||
| public static void LengthAtLeast(string obj, int value, string name, string? msg = null) | |||
| public static void LengthAtLeast(string? obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj?.Length < value) | |||
| { | |||
| @@ -85,7 +129,7 @@ namespace Discord.Net.Rest | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| public static void LengthAtMost(string obj, int value, string name, string? msg = null) | |||
| public static void LengthAtMost(string? obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj?.Length > value) | |||
| { | |||
| @@ -95,7 +139,7 @@ namespace Discord.Net.Rest | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| public static void LengthGreaterThan(string obj, int value, string name, string? msg = null) | |||
| public static void LengthGreaterThan(string? obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj?.Length <= value) | |||
| { | |||
| @@ -105,7 +149,7 @@ namespace Discord.Net.Rest | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| public static void LengthLessThan(string obj, int value, string name, string? msg = null) | |||
| public static void LengthLessThan(string? obj, int value, string name, string? msg = null) | |||
| { | |||
| if (obj?.Length >= value) | |||
| { | |||
| @@ -115,25 +159,25 @@ namespace Discord.Net.Rest | |||
| throw new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| public static void LengthAtLeast(Optional<string> obj, int value, string name, string? msg = null) | |||
| public static void LengthAtLeast(Optional<string?> obj, int value, string name, string? msg = null) | |||
| { | |||
| if (!obj.IsSpecified) | |||
| return; | |||
| LengthAtLeast(obj.Value, value, name, msg); | |||
| } | |||
| public static void LengthAtMost(Optional<string> obj, int value, string name, string? msg = null) | |||
| public static void LengthAtMost(Optional<string?> obj, int value, string name, string? msg = null) | |||
| { | |||
| if (!obj.IsSpecified) | |||
| return; | |||
| LengthAtMost(obj.Value, value, name, msg); | |||
| } | |||
| public static void LengthGreaterThan(Optional<string> obj, int value, string name, string? msg = null) | |||
| public static void LengthGreaterThan(Optional<string?> obj, int value, string name, string? msg = null) | |||
| { | |||
| if (!obj.IsSpecified) | |||
| return; | |||
| LengthGreaterThan(obj.Value, value, name, msg); | |||
| } | |||
| public static void LengthLessThan(Optional<string> obj, int value, string name, string? msg = null) | |||
| public static void LengthLessThan(Optional<string?> obj, int value, string name, string? msg = null) | |||
| { | |||
| if (!obj.IsSpecified) | |||
| return; | |||
| @@ -558,5 +602,31 @@ namespace Discord.Net.Rest | |||
| throw new ArgumentOutOfRangeException(name, msg); | |||
| } | |||
| } | |||
| // Structs | |||
| public static void MustBeOneOf<T>(T value, IEnumerable<T> allowed, string name, string? msg = null) | |||
| where T : struct | |||
| { | |||
| if (!allowed.Contains(value)) | |||
| throw CreateMustBeOneOfException(name, msg, allowed); | |||
| } | |||
| public static void MustBeOneOf<T>(Optional<T> value, IEnumerable<T> allowed, string name, string? msg = null) | |||
| where T : struct | |||
| { | |||
| if (value.IsSpecified && !allowed.Contains(value.Value)) | |||
| throw CreateMustBeOneOfException(name, msg, allowed); | |||
| } | |||
| private static ArgumentException CreateMustBeOneOfException<T>(string name, string? msg, IEnumerable<T> value) | |||
| where T : struct | |||
| { | |||
| if (msg == null) | |||
| { | |||
| var options = typeof(T).IsEnum ? string.Join(", ", value.Select(x => Enum.GetName(typeof(T), x))) : string.Join(", ", value); | |||
| return new ArgumentException($"Value must be one of the following: {options}", name); | |||
| } | |||
| else | |||
| return new ArgumentException(msg, name); | |||
| } | |||
| } | |||
| } | |||