diff --git a/docs/guides/guild_events/creating-guild-events.md b/docs/guides/guild_events/creating-guild-events.md
new file mode 100644
index 000000000..64ac0de9b
--- /dev/null
+++ b/docs/guides/guild_events/creating-guild-events.md
@@ -0,0 +1,31 @@
+---
+uid: Guides.GuildEvents.Creating
+title: Creating Guild Events
+---
+
+# Creating guild events
+
+You can create new guild events by using the `CreateEventAsync` function on a guild.
+
+### Parameters
+
+| Name | Type | Summary |
+| ------------- | --------------------------------- | ---------------------------------------------------------------------------- |
+| name | `string` | Sets the name of the event. |
+| startTime | `DateTimeOffset` | Sets the start time of the event. |
+| type | `GuildScheduledEventType` | Sets the type of the event. |
+| privacyLevel? | `GuildScheduledEventPrivacyLevel` | Sets the privacy level of the event |
+| description? | `string` | Sets the description of the event. |
+| endTime? | `DateTimeOffset?` | Sets the end time of the event. |
+| channelId? | `ulong?` | Sets the channel id of the event, only valid on stage or voice channel types |
+| location? | `string` | Sets the location of the event, only valid on external types |
+
+Lets create a basic test event.
+
+```cs
+var guild = client.GetGuild(guildId);
+
+var guildEvent = await guild.CreateEventAsync("test event", DateTimeOffset.UtcNow.AddDays(1), GuildScheduledEventType.External, endTime: DateTimeOffset.UtcNow.AddDays(2), location: "Space");
+```
+
+This code will create an event that lasts a day and starts tomorrow. It will be an external event thats in space.
diff --git a/docs/guides/guild_events/getting-event-users.md b/docs/guides/guild_events/getting-event-users.md
new file mode 100644
index 000000000..f4b5388a0
--- /dev/null
+++ b/docs/guides/guild_events/getting-event-users.md
@@ -0,0 +1,16 @@
+---
+uid: Guides.GuildEvents.GettingUsers
+title: Getting Guild Event Users
+---
+
+# Getting Event Users
+
+You can get a collection of users who are currently interested in the event by calling `GetUsersAsync`. This method works like any other get users method as in it returns an async enumerable. This method also supports pagination by user id.
+
+```cs
+// get all users and flatten the result into one collection.
+var users = await event.GetUsersAsync().FlattenAsync();
+
+// get users around the 613425648685547541 id.
+var aroundUsers = await event.GetUsersAsync(613425648685547541, Direction.Around).FlattenAsync();
+```
diff --git a/docs/guides/guild_events/intro.md b/docs/guides/guild_events/intro.md
new file mode 100644
index 000000000..b60a8c70d
--- /dev/null
+++ b/docs/guides/guild_events/intro.md
@@ -0,0 +1,41 @@
+---
+uid: Guides.GuildEvents.Intro
+title: Introduction to Guild Events
+---
+
+# Guild Events
+
+Guild events are a way to host events within a guild. They offer alot of features and flexibility.
+
+## Getting started with guild events
+
+You can access any events within a guild by calling `GetEventsAsync` on a guild.
+
+```cs
+var guildEvents = await guild.GetEventsAsync();
+```
+
+If your working with socket guilds you can just use the `Events` property:
+
+```cs
+var guildEvents = guild.Events;
+```
+
+There are also new gateway events that you can hook to receive guild scheduled events on.
+
+```cs
+// Fired when a guild event is cancelled.
+client.GuildScheduledEventCancelled += ...
+
+// Fired when a guild event is completed.
+client.GuildScheduledEventCompleted += ...
+
+// Fired when a guild event is started.
+client.GuildScheduledEventStarted += ...
+
+// Fired when a guild event is created.
+client.GuildScheduledEventCreated += ...
+
+// Fired when a guild event is updated.
+client.GuildScheduledEventUpdated += ...
+```
diff --git a/docs/guides/guild_events/modifying-events.md b/docs/guides/guild_events/modifying-events.md
new file mode 100644
index 000000000..05e14ec98
--- /dev/null
+++ b/docs/guides/guild_events/modifying-events.md
@@ -0,0 +1,23 @@
+---
+uid: Guides.GuildEvents.Modifying
+title: Modifying Guild Events
+---
+
+# Modifying Events
+
+You can modify events using the `ModifyAsync` method to modify the event, heres the properties you can modify:
+
+| Name | Type | Description |
+| ------------ | --------------------------------- | -------------------------------------------- |
+| ChannelId | `ulong?` | Gets or sets the channel id of the event. |
+| string | `string` | Gets or sets the location of this event. |
+| Name | `string` | Gets or sets the name of the event. |
+| PrivacyLevel | `GuildScheduledEventPrivacyLevel` | Gets or sets the privacy level of the event. |
+| StartTime | `DateTimeOffset` | Gets or sets the start time of the event. |
+| EndTime | `DateTimeOffset` | Gets or sets the end time of the event. |
+| Description | `string` | Gets or sets the description of the event. |
+| Type | `GuildScheduledEventType` | Gets or sets the type of the event. |
+| Status | `GuildScheduledEventStatus` | Gets or sets the status of the event. |
+
+> [!NOTE]
+> All of these properties are optional.
diff --git a/docs/guides/interactions/application-commands/slash-commands/02-creating-slash-commands.md b/docs/guides/interactions/application-commands/slash-commands/02-creating-slash-commands.md
index 1abab1a25..9e35de285 100644
--- a/docs/guides/interactions/application-commands/slash-commands/02-creating-slash-commands.md
+++ b/docs/guides/interactions/application-commands/slash-commands/02-creating-slash-commands.md
@@ -79,6 +79,8 @@ public async Task Client_Ready()
// With global commands we dont need the guild.
await client.CreateGlobalApplicationCommandAsync(globalCommand.Build());
+ // Using the ready event is a simple implementation for the sake of the example. Suitable for testing and development.
+ // For a production bot, it is recommended to only run the CreateGlobalApplicationCommandAsync() once for each command.
}
catch(ApplicationCommandException exception)
{
@@ -93,4 +95,4 @@ public async Task Client_Ready()
```
> [!NOTE]
-> Slash commands only need to be created once. They do _not_ have to be 'created' on every startup or connection. The example simple shows creating them in the ready event as it's simpler than creating normal bot commands to register slash commands.
+> Slash commands only need to be created once. They do _not_ have to be 'created' on every startup or connection. The example simple shows creating them in the ready event as it's simpler than creating normal bot commands to register slash commands. The global commands take up to an hour to register every time the CreateGlobalApplicationCommandAsync() is called for a given command.
diff --git a/docs/guides/interactions/application-commands/slash-commands/05-responding-ephemerally.md b/docs/guides/interactions/application-commands/slash-commands/05-responding-ephemerally.md
index 641103df5..10b04a8d2 100644
--- a/docs/guides/interactions/application-commands/slash-commands/05-responding-ephemerally.md
+++ b/docs/guides/interactions/application-commands/slash-commands/05-responding-ephemerally.md
@@ -20,4 +20,4 @@ await command.RespondAsync(embed: embedBuiler.Build(), ephemeral: true);
Running the command now only shows the message to us!
-
+
\ No newline at end of file
diff --git a/docs/guides/toc.yml b/docs/guides/toc.yml
index 10e91760b..968468416 100644
--- a/docs/guides/toc.yml
+++ b/docs/guides/toc.yml
@@ -1,26 +1,15 @@
- name: Introduction
topicUid: Guides.Introduction
-- name: Getting Started
+- name: "Working with Guild Events"
items:
- - name: Installation
- topicUid: Guides.GettingStarted.Installation
- items:
- - name: Nightly Builds
- topicUid: Guides.GettingStarted.Installation.Nightlies
- - name: Your First Bot
- topicUid: Guides.GettingStarted.FirstBot
- - name: Terminology
- topicUid: Guides.GettingStarted.Terminology
-- name: Basic Concepts
- items:
- - name: Logging Data
- topicUid: Guides.Concepts.Logging
- - name: Working with Events
- topicUid: Guides.Concepts.Events
- - name: Managing Connections
- topicUid: Guides.Concepts.ManageConnections
- - name: Entities
- topicUid: Guides.Concepts.Entities
+ - name: Introduction
+ topicUid: Guides.GuildEvents.Intro
+ - name: Creating Events
+ topicUid: Guides.GuildEvents.Creating
+ - name: Getting Event Users
+ topicUid: Guides.GuildEvents.GettingUsers
+ - name: Modifying Events
+ topicUid: Guides.GuildEvents.Modifying
- name: Working with Commands
items:
- name: Introduction
@@ -35,7 +24,7 @@
topicUid: Guides.Commands.DI
- name: Post-execution Handling
topicUid: Guides.Commands.PostExecution
-- name: Working with Slash commands
+- name: Working with Slash Commands
items:
- name: Introduction
topicUid: Guides.SlashCommands.Intro
diff --git a/src/Discord.Net.Core/DiscordConfig.cs b/src/Discord.Net.Core/DiscordConfig.cs
index da8525644..d5951bd07 100644
--- a/src/Discord.Net.Core/DiscordConfig.cs
+++ b/src/Discord.Net.Core/DiscordConfig.cs
@@ -94,6 +94,13 @@ namespace Discord
/// The maximum number of users that can be gotten per-batch.
///
public const int MaxUsersPerBatch = 1000;
+ ///
+ /// Returns the max users allowed to be in a request for guild event users.
+ ///
+ ///
+ /// The maximum number of users that can be gotten per-batch.
+ ///
+ public const int MaxGuildEventUsersPerBatch = 100;
///
/// Returns the max guilds allowed to be in a request.
///
@@ -158,5 +165,17 @@ namespace Discord
/// clock. Your system will still need a stable clock.
///
public bool UseSystemClock { get; set; } = true;
+
+ ///
+ /// Gets or sets whether or not the internal experation check uses the system date
+ /// + snowflake date to check if an interaction can be responded to.
+ ///
+ ///
+ /// If set to then the CreatedAt property in an interaction
+ /// will be set to when it was received instead of the snowflakes date.
+ ///
+ /// This will still require a stable clock on your system.
+ ///
+ public bool UseInteractionSnowflakeDate { get; set; } = true;
}
}
diff --git a/src/Discord.Net.Core/DiscordErrorCode.cs b/src/Discord.Net.Core/DiscordErrorCode.cs
new file mode 100644
index 000000000..5a5223b93
--- /dev/null
+++ b/src/Discord.Net.Core/DiscordErrorCode.cs
@@ -0,0 +1,197 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents a set of json error codes received by discord.
+ ///
+ public enum DiscordErrorCode
+ {
+ GeneralError = 0,
+
+ #region UnknownXYZ (10XXX)
+ UnknownAccount = 10001,
+ UnknownApplication = 10002,
+ UnknownChannel = 10003,
+ UnknownGuild = 10004,
+ UnknownIntegration = 10005,
+ UnknownInvite = 10006,
+ UnknownMember = 10007,
+ UnknownMessage = 10008,
+ UnknownPermissionOverwrite = 10009,
+ UnknownProvider = 10010,
+ UnknownRole = 10011,
+ UnknownToken = 10012,
+ UnknownUser = 10013,
+ UnknownEmoji = 10014,
+ UnknownWebhook = 10015,
+ UnknownWebhookService = 10016,
+ UnknownSession = 10020,
+ UnknownBan = 10026,
+ UnknownSKU = 10027,
+ UnknownStoreListing = 10028,
+ UnknownEntitlement = 10029,
+ UnknownBuild = 10030,
+ UnknownLobby = 10031,
+ UnknownBranch = 10032,
+ UnknownStoreDirectoryLayout = 10033,
+ UnknownRedistributable = 10036,
+ UnknownGiftCode = 10038,
+ UnknownStream = 10049,
+ UnknownPremiumServerSubscribeCooldown = 10050,
+ UnknownGuildTemplate = 10057,
+ UnknownDiscoverableServerCategory = 10059,
+ UnknownSticker = 10060,
+ UnknownInteraction = 10062,
+ UnknownApplicationCommand = 10063,
+ UnknownApplicationCommandPermissions = 10066,
+ UnknownStageInstance = 10067,
+ UnknownGuildMemberVerificationForm = 10068,
+ UnknownGuildWelcomeScreen = 10069,
+ UnknownGuildScheduledEvent = 10070,
+ UnknownGuildScheduledEventUser = 10071,
+ #endregion
+
+ #region General Actions (20XXX)
+ BotsCannotUse = 20001,
+ OnlyBotsCanUse = 20002,
+ CannotSendExplicitContent = 20009,
+ ApplicationActionUnauthorized = 20012,
+ ActionSlowmode = 20016,
+ OnlyOwnerAction = 20018,
+ AnnouncementEditRatelimit = 20022,
+ ChannelWriteRatelimit = 20028,
+ WordsNotAllowed = 20031,
+ GuildPremiumTooLow = 20035,
+ #endregion
+
+ #region Numeric Limits Reached (30XXX)
+ MaximumGuildsReached = 30001,
+ MaximumFriendsReached = 30002,
+ MaximumPinsReached = 30003,
+ MaximumRecipientsReached = 30004,
+ MaximumGuildRolesReached = 30005,
+ MaximumWebhooksReached = 30007,
+ MaximumEmojisReached = 30008,
+ MaximumReactionsReached = 30010,
+ MaximumGuildChannelsReached = 30013,
+ MaximumAttachmentsReached = 30015,
+ MaximumInvitesReached = 30016,
+ MaximumAnimatedEmojisReached = 30018,
+ MaximumServerMembersReached = 30019,
+ MaximumServerCategoriesReached = 30030,
+ GuildTemplateAlreadyExists = 30031,
+ MaximumThreadMembersReached = 30033,
+ MaximumBansForNonGuildMembersReached = 30035,
+ MaximumBanFetchesReached = 30037,
+ MaximumUncompleteGuildScheduledEvents = 30038,
+ MaximumStickersReached = 30039,
+ MaximumPruneRequestReached = 30040,
+ MaximumGuildWigitsReached = 30042,
+ #endregion
+
+ #region General Request Errors (40XXX)
+ TokenUnauthorized = 40001,
+ InvalidVerification = 40002,
+ OpeningDMTooFast = 40003,
+ RequestEntityTooLarge = 40005,
+ FeatureDisabled = 40006,
+ UserBanned = 40007,
+ TargetUserNotInVoice = 40032,
+ MessageAlreadyCrossposted = 40033,
+ ApplicationNameAlreadyExists = 40041,
+ #endregion
+
+ #region Action Preconditions/Checks (50XXX)
+ MissingPermissions = 50001,
+ InvalidAccountType = 50002,
+ CannotExecuteForDM = 50003,
+ GuildWigitDisabled = 50004,
+ CannotEditOtherUsersMessage = 50005,
+ CannotSendEmptyMessage = 50006,
+ CannotSendMessageToUser = 50007,
+ CannotSendMessageToVoiceChannel = 50008,
+ ChannelVerificationTooHight = 50009,
+ OAuth2ApplicationDoesntHaveBot = 50010,
+ OAuth2ApplicationLimitReached = 50011,
+ InvalidOAuth2State = 50012,
+ InsufficientPermissions = 50013,
+ InvalidAuthenticationToken = 50014,
+ NoteTooLong = 50015,
+ ProvidedMessageDeleteCountOutOfBounds = 50016,
+ InvalidPinChannel = 50019,
+ InvalidInvite = 50020,
+ CannotExecuteOnSystemMessage = 50021,
+ CannotExecuteOnChannelType = 50024,
+ InvalidOAuth2Token = 50025,
+ MissingOAuth2Scope = 50026,
+ InvalidWebhookToken = 50027,
+ InvalidRole = 50028,
+ InvalidRecipients = 50033,
+ BulkDeleteMessageTooOld = 50034,
+ InvalidFormBody = 50035,
+ InviteAcceptedForGuildThatBotIsntIn = 50036,
+ InvalidAPIVersion = 50041,
+ FileUploadTooBig = 50045,
+ InvalidFileUpload = 50046,
+ CannotSelfRedeemGift = 50054,
+ PaymentSourceRequiredForGift = 50070,
+ CannotDeleteRequiredCommunityChannel = 50074,
+ InvalidSticker = 50081,
+ CannotExecuteOnArchivedThread = 50083,
+ InvalidThreadNotificationSettings = 50084,
+ BeforeValueEarlierThanThreadCreation = 50085,
+ ServerLocaleUnavailable = 50095,
+ ServerRequiresMonetization = 50097,
+ ServerRequiresBoosts = 50101,
+
+ #endregion
+
+ #region 2FA (60XXX)
+ Requires2FA = 60003,
+ #endregion
+
+ #region User Searches (80XXX)
+ NoUsersWithTag = 80004,
+ #endregion
+
+ #region Reactions (90XXX)
+ ReactionBlocked = 90001,
+ #endregion
+
+ #region API Status (130XXX)
+ APIOverloaded = 130000,
+ #endregion
+
+ #region Stage Errors (150XXX)
+ StageAlreadyOpened = 150006,
+ #endregion
+
+ #region Reply and Thread Errors (160XXX)
+ CannotReplyWithoutReadMessageHistory = 160002,
+ MessageAlreadyContainsThread = 160004,
+ ThreadIsLocked = 160005,
+ MaximumActiveThreadsReached = 160006,
+ MaximumAnnouncementThreadsReached = 160007,
+ #endregion
+
+ #region Sticker Uploads (170XXX)
+ InvalidJSONLottie = 170001,
+ LottieCantContainRasters = 170002,
+ StickerMaximumFramerateExceeded = 170003,
+ StickerMaximumFrameCountExceeded = 170004,
+ LottieMaximumDimentionsExceeded = 170005,
+ StickerFramerateBoundsExceeed = 170006,
+ StickerAnimationDurationTooLong = 170007,
+ #endregion
+
+ #region Guild Scheduled Events
+ CannotUpdateFinishedEvent = 180000,
+ FailedStageCreation = 180002,
+ #endregion
+ }
+}
diff --git a/src/Discord.Net.Core/DiscordJsonError.cs b/src/Discord.Net.Core/DiscordJsonError.cs
new file mode 100644
index 000000000..fdf82ea0c
--- /dev/null
+++ b/src/Discord.Net.Core/DiscordJsonError.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents a generic parsed json error received from discord after performing a rest request.
+ ///
+ public struct DiscordJsonError
+ {
+ ///
+ /// Gets the json path of the error.
+ ///
+ public string Path { get; }
+
+ ///
+ /// Gets a collection of errors associated with the specific property at the path.
+ ///
+ public IReadOnlyCollection Errors { get; }
+
+ internal DiscordJsonError(string path, DiscordError[] errors)
+ {
+ Path = path;
+ Errors = errors.ToImmutableArray();
+ }
+ }
+
+ ///
+ /// Represents an error with a property.
+ ///
+ public struct DiscordError
+ {
+ ///
+ /// Gets the code of the error.
+ ///
+ public string Code { get; }
+
+ ///
+ /// Gets the message describing what went wrong.
+ ///
+ public string Message { get; }
+
+ internal DiscordError(string code, string message)
+ {
+ Code = code;
+ Message = message;
+ }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Activities/ActivityProperties.cs b/src/Discord.Net.Core/Entities/Activities/ActivityProperties.cs
index 587b21f03..15a79dff6 100644
--- a/src/Discord.Net.Core/Entities/Activities/ActivityProperties.cs
+++ b/src/Discord.Net.Core/Entities/Activities/ActivityProperties.cs
@@ -37,14 +37,14 @@ namespace Discord
///
/// Indicates that a user is playing an activity in a voice channel with friends.
///
- PARTY_PRIVACY_FRIENDS = 0b1000000,
+ PartyPrivacyFriends = 0b1000000,
///
/// Indicates that a user is playing an activity in a voice channel.
///
- PARTY_PRIVACY_VOICE_CHANNEL = 0b10000000,
+ PartyPrivacyVoiceChannel = 0b10000000,
///
/// Indicates that a user is playing an activity in a voice channel.
///
- EMBEDDED = 0b10000000
+ Embedded = 0b10000000
}
}
diff --git a/src/Discord.Net.Core/Entities/ApplicationFlags.cs b/src/Discord.Net.Core/Entities/ApplicationFlags.cs
new file mode 100644
index 000000000..1ede4257d
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/ApplicationFlags.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents public flags for an application.
+ ///
+ public enum ApplicationFlags
+ {
+ GatewayPresence = 1 << 12,
+ GatewayPresenceLimited = 1 << 13,
+ GatewayGuildMembers = 1 << 14,
+ GatewayGuildMembersLimited = 1 << 15,
+ VerificationPendingGuildLimit = 1 << 16,
+ Embedded = 1 << 17,
+ GatewayMessageContent = 1 << 18,
+ GatewayMessageContentLimited = 1 << 19
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/ApplicationInstallParams.cs b/src/Discord.Net.Core/Entities/ApplicationInstallParams.cs
new file mode 100644
index 000000000..180592f1e
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/ApplicationInstallParams.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents install parameters for an application.
+ ///
+ public class ApplicationInstallParams
+ {
+ ///
+ /// Gets the scopes to install this application.
+ ///
+ public IReadOnlyCollection Scopes { get; }
+
+ ///
+ /// Gets the default permissions to install this application
+ ///
+ public GuildPermission? Permission { get; }
+
+ internal ApplicationInstallParams(string[] scopes, GuildPermission? permission)
+ {
+ Scopes = scopes.ToImmutableArray();
+ Permission = permission;
+ }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
index 95507d297..87dfb3460 100644
--- a/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
+++ b/src/Discord.Net.Core/Entities/Channels/IMessageChannel.cs
@@ -113,6 +113,64 @@ namespace Discord
/// contains the sent message.
///
Task SendFileAsync(Stream stream, string filename, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, bool isSpoiler = false, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
+ ///
+ /// Sends a file to this message channel with an optional caption.
+ ///
+ ///
+ /// This method sends a file as if you are uploading an attachment directly from your Discord client.
+ ///
+ /// If you wish to upload an image and have it embedded in a embed,
+ /// you may upload the file and refer to the file with "attachment://filename.ext" in the
+ /// . See the example section for its usage.
+ ///
+ ///
+ /// The attachment containing the file and description.
+ /// The message to be sent.
+ /// Whether the message should be read aloud by Discord or not.
+ /// The to be sent.
+ /// The options to be used when sending the request.
+ ///
+ /// Specifies if notifications are sent for mentioned users and roles in the message .
+ /// If null, all mentioned roles and users will be notified.
+ ///
+ /// The message references to be included. Used to reply to specific messages.
+ /// The message components to be included with this message. Used for interactions.
+ /// A collection of stickers to send with the file.
+ /// A array of s to send with this response. Max 10.
+ ///
+ /// A task that represents an asynchronous send operation for delivering the message. The task result
+ /// contains the sent message.
+ ///
+ Task SendFileAsync(FileAttachment attachment, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
+ ///
+ /// Sends a collection of files to this message channel.
+ ///
+ ///
+ /// This method sends files as if you are uploading attachments directly from your Discord client.
+ ///
+ /// If you wish to upload an image and have it embedded in a embed,
+ /// you may upload the file and refer to the file with "attachment://filename.ext" in the
+ /// . See the example section for its usage.
+ ///
+ ///
+ /// A collection of attachments to upload.
+ /// The message to be sent.
+ /// Whether the message should be read aloud by Discord or not.
+ /// The to be sent.
+ /// The options to be used when sending the request.
+ ///
+ /// Specifies if notifications are sent for mentioned users and roles in the message .
+ /// If null, all mentioned roles and users will be notified.
+ ///
+ /// The message references to be included. Used to reply to specific messages.
+ /// The message components to be included with this message. Used for interactions.
+ /// A collection of stickers to send with the file.
+ /// A array of s to send with this response. Max 10.
+ ///
+ /// A task that represents an asynchronous send operation for delivering the message. The task result
+ /// contains the sent message.
+ ///
+ Task SendFilesAsync(IEnumerable attachments, string text = null, bool isTTS = false, Embed embed = null, RequestOptions options = null, AllowedMentions allowedMentions = null, MessageReference messageReference = null, MessageComponent component = null, ISticker[] stickers = null, Embed[] embeds = null);
///
/// Gets a message from this message channel.
diff --git a/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs b/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs
index 3b1bc08da..5e0be5b7e 100644
--- a/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs
+++ b/src/Discord.Net.Core/Entities/Channels/IStageChannel.cs
@@ -32,9 +32,6 @@ namespace Discord
///
/// Gets whether or not the stage is live.
///
- ///
- /// If the stage isn't live then this property will be set to .
- ///
bool IsLive { get; }
///
diff --git a/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs b/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
index 70ba872fc..ae0fe674b 100644
--- a/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
+++ b/src/Discord.Net.Core/Entities/Channels/ITextChannel.cs
@@ -141,11 +141,13 @@ namespace Discord
///
///
/// The message which to start the thread from.
+ /// Whether non-moderators can add other non-moderators to a thread; only available when creating a private thread
+ /// The amount of seconds a user has to wait before sending another message (0-21600)
/// The options to be used when sending the request.
///
/// A task that represents the asynchronous create operation. The task result contains a
///
Task CreateThreadAsync(string name, ThreadType type = ThreadType.PublicThread, ThreadArchiveDuration autoArchiveDuration = ThreadArchiveDuration.OneDay,
- IMessage message = null, RequestOptions options = null);
+ IMessage message = null, bool? invitable = null, int? slowmode = null, RequestOptions options = null);
}
}
diff --git a/src/Discord.Net.Core/Entities/Channels/StagePrivacyLevel.cs b/src/Discord.Net.Core/Entities/Channels/StagePrivacyLevel.cs
index c6eb3803f..0582a3e52 100644
--- a/src/Discord.Net.Core/Entities/Channels/StagePrivacyLevel.cs
+++ b/src/Discord.Net.Core/Entities/Channels/StagePrivacyLevel.cs
@@ -6,13 +6,12 @@ namespace Discord
public enum StagePrivacyLevel
{
///
- /// The stage is a public stage.
+ /// The Stage instance is visible publicly, such as on Stage Discovery.
///
Public = 1,
-
///
- /// The stage is non public and is only accessable from the guild.
+ /// The Stage instance is visible to only guild members.
///
- GuildOnly = 2,
+ GuildOnly = 2
}
}
diff --git a/src/Discord.Net.Core/Entities/Channels/VoiceChannelProperties.cs b/src/Discord.Net.Core/Entities/Channels/VoiceChannelProperties.cs
index fb4d47800..251a45c3d 100644
--- a/src/Discord.Net.Core/Entities/Channels/VoiceChannelProperties.cs
+++ b/src/Discord.Net.Core/Entities/Channels/VoiceChannelProperties.cs
@@ -13,5 +13,9 @@ namespace Discord
/// Gets or sets the maximum number of users that can be present in a channel, or null if none.
///
public Optional UserLimit { get; set; }
+ ///
+ /// Gets or sets the channel voice region id, automatic when set to .
+ ///
+ public Optional RTCRegion { get; set; }
}
}
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildFeature.cs b/src/Discord.Net.Core/Entities/Guilds/GuildFeature.cs
new file mode 100644
index 000000000..e3c325227
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildFeature.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ [Flags]
+ public enum GuildFeature
+ {
+ ///
+ /// The guild has no features.
+ ///
+ None = 0,
+ ///
+ /// The guild has access to set an animated guild icon.
+ ///
+ AnimatedIcon = 1 << 0,
+ ///
+ /// The guild has access to set a guild banner image.
+ ///
+ Banner = 1 << 1,
+ ///
+ /// The guild has access to use commerce features (i.e. create store channels).
+ ///
+ Commerce = 1 << 2,
+ ///
+ /// The guild can enable welcome screen, Membership Screening, stage channels and discovery, and receives community updates.
+ ///
+ Community = 1 << 3,
+ ///
+ /// The guild is able to be discovered in the directory.
+ ///
+ Discoverable = 1 << 4,
+ ///
+ /// The guild is able to be featured in the directory.
+ ///
+ Featureable = 1 << 5,
+ ///
+ /// The guild has access to set an invite splash background.
+ ///
+ InviteSplash = 1 << 6,
+ ///
+ /// The guild has enabled Membership Screening.
+ ///
+ MemberVerificationGateEnabled = 1 << 7,
+ ///
+ /// The guild has enabled monetization.
+ ///
+ MonetizationEnabled = 1 << 8,
+ ///
+ /// The guild has increased custom sticker slots.
+ ///
+ MoreStickers = 1 << 9,
+ ///
+ /// The guild has access to create news channels.
+ ///
+ News = 1 << 10,
+ ///
+ /// The guild is partnered.
+ ///
+ Partnered = 1 << 11,
+ ///
+ /// The guild can be previewed before joining via Membership Screening or the directory.
+ ///
+ PreviewEnabled = 1 << 12,
+ ///
+ /// The guild has access to create private threads.
+ ///
+ PrivateThreads = 1 << 13,
+ ///
+ /// The guild is able to set role icons.
+ ///
+ RoleIcons = 1 << 14,
+ ///
+ /// The guild has access to the seven day archive time for threads.
+ ///
+ SevenDayThreadArchive = 1 << 15,
+ ///
+ /// The guild has access to the three day archive time for threads.
+ ///
+ ThreeDayThreadArchive = 1 << 16,
+ ///
+ /// The guild has enabled ticketed events.
+ ///
+ TicketedEventsEnabled = 1 << 17,
+ ///
+ /// The guild has access to set a vanity URL.
+ ///
+ VanityUrl = 1 << 18,
+ ///
+ /// The guild is verified.
+ ///
+ Verified = 1 << 19,
+ ///
+ /// The guild has access to set 384kbps bitrate in voice (previously VIP voice servers).
+ ///
+ VIPRegions = 1 << 20,
+ ///
+ /// The guild has enabled the welcome screen.
+ ///
+ WelcomeScreenEnabled = 1 << 21,
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildFeatures.cs b/src/Discord.Net.Core/Entities/Guilds/GuildFeatures.cs
new file mode 100644
index 000000000..699e47cf3
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildFeatures.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ public class GuildFeatures
+ {
+ ///
+ /// Gets the flags of recognized features for this guild.
+ ///
+ public GuildFeature Value { get; }
+
+ ///
+ /// Gets a collection of experimental features for this guild.
+ ///
+ public IReadOnlyCollection Experimental { get; }
+
+
+ internal GuildFeatures(GuildFeature value, string[] experimental)
+ {
+ Value = value;
+ Experimental = experimental.ToImmutableArray();
+ }
+
+ public bool HasFeature(GuildFeature feature)
+ => Value.HasFlag(feature);
+ public bool HasFeature(string feature)
+ => Experimental.Contains(feature);
+
+ internal void EnsureFeature(GuildFeature feature)
+ {
+ if (!HasFeature(feature))
+ {
+ var vals = Enum.GetValues(typeof(GuildFeature)).Cast();
+
+ var missingValues = vals.Where(x => feature.HasFlag(x) && !Value.HasFlag(x));
+
+ throw new InvalidOperationException($"Missing required guild feature{(missingValues.Count() > 1 ? "s" : "")} {string.Join(", ", missingValues.Select(x => x.ToString()))} in order to execute this operation.");
+ }
+ }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs b/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs
index 981e1198c..d50b2ac38 100644
--- a/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildProperties.cs
@@ -85,8 +85,9 @@ namespace Discord
/// given that the has also been set.
/// A value of will deny guild boost messages from being sent, and allow all
/// other types of messages.
- /// Refer to the extension methods and
- /// to check if these system channel message types
+ /// Refer to the extension methods ,
+ /// , ,
+ /// and to check if these system channel message types
/// are enabled, without the need to manipulate the logic of the flag.
///
public Optional SystemChannelFlags { get; set; }
@@ -108,5 +109,9 @@ namespace Discord
/// the value of will be unused.
///
public Optional PreferredCulture { get; set; }
+ ///
+ /// Gets or sets if the boost progress bar is enabled.
+ ///
+ public Optional IsBoostProgressBarEnabled { get; set; }
}
}
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventPrivacyLevel.cs b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventPrivacyLevel.cs
new file mode 100644
index 000000000..87881104c
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventPrivacyLevel.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents the privacy level of a guild scheduled event.
+ ///
+ public enum GuildScheduledEventPrivacyLevel
+ {
+ ///
+ /// The scheduled event is public and available in discovery.
+ ///
+ [Obsolete("This event type isn't supported yet! check back later.", true)]
+ Public = 1,
+
+ ///
+ /// The scheduled event is only accessible to guild members.
+ ///
+ Private = 2,
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventStatus.cs b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventStatus.cs
new file mode 100644
index 000000000..6e3aa1ab3
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventStatus.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents the status of a guild event.
+ ///
+ public enum GuildScheduledEventStatus
+ {
+ ///
+ /// The event is scheduled for a set time.
+ ///
+ Scheduled = 1,
+
+ ///
+ /// The event has started.
+ ///
+ Active = 2,
+
+ ///
+ /// The event was completed.
+ ///
+ Completed = 3,
+
+ ///
+ /// The event was canceled.
+ ///
+ Cancelled = 4,
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventType.cs b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventType.cs
new file mode 100644
index 000000000..ad741eee1
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventType.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents the type of a guild scheduled event.
+ ///
+ public enum GuildScheduledEventType
+ {
+ ///
+ /// The event doesn't have a set type.
+ ///
+ None = 0,
+
+ ///
+ /// The event is set in a stage channel.
+ ///
+ Stage = 1,
+
+ ///
+ /// The event is set in a voice channel.
+ ///
+ Voice = 2,
+
+ ///
+ /// The event is set for somewhere externally from discord.
+ ///
+ External = 3,
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventsProperties.cs b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventsProperties.cs
new file mode 100644
index 000000000..a3fd729e5
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/GuildScheduledEventsProperties.cs
@@ -0,0 +1,58 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Provides properties that are used to modify an with the specified changes.
+ ///
+ public class GuildScheduledEventsProperties
+ {
+ ///
+ /// Gets or sets the channel id of the event.
+ ///
+ public Optional ChannelId { get; set; }
+
+ ///
+ /// Gets or sets the location of this event.
+ ///
+ public Optional Location { get; set; }
+
+ ///
+ /// Gets or sets the name of the event.
+ ///
+ public Optional Name { get; set; }
+
+ ///
+ /// Gets or sets the privacy level of the event.
+ ///
+ public Optional PrivacyLevel { get; set; }
+
+ ///
+ /// Gets or sets the start time of the event.
+ ///
+ public Optional StartTime { get; set; }
+ ///
+ /// Gets or sets the end time of the event.
+ ///
+ public Optional EndTime { get; set; }
+
+ ///
+ /// Gets or sets the description of the event.
+ ///
+ public Optional Description { get; set; }
+
+ ///
+ /// Gets or sets the type of the event.
+ ///
+ public Optional Type { get; set; }
+
+ ///
+ /// Gets or sets the status of the event.
+ ///
+ public Optional Status { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
index 4a2333645..ebf2ccd4a 100644
--- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs
@@ -207,12 +207,12 @@ namespace Discord
///
IReadOnlyCollection Stickers { get; }
///
- /// Gets a collection of all extra features added to this guild.
+ /// Gets the features for this guild.
///
///
- /// A read-only collection of enabled features in this guild.
+ /// A flags enum containing all the features for the guild.
///
- IReadOnlyCollection Features { get; }
+ GuildFeatures Features { get; }
///
/// Gets a collection of all roles in this guild.
///
@@ -339,6 +339,13 @@ namespace Discord
/// The preferred culture information of this guild.
///
CultureInfo PreferredCulture { get; }
+ ///
+ /// Gets whether the guild has the boost progress bar enabled.
+ ///
+ ///
+ /// if the boost progress bar is enabled; otherwise .
+ ///
+ bool IsBoostProgressBarEnabled { get; }
///
/// Modifies this guild.
@@ -1049,6 +1056,58 @@ namespace Discord
///
Task DeleteStickerAsync(ICustomSticker sticker, RequestOptions options = null);
+ ///
+ /// Gets a event within this guild.
+ ///
+ /// The id of the event.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation.
+ ///
+ Task GetEventAsync(ulong id, RequestOptions options = null);
+
+ ///
+ /// Gets a collection of events within this guild.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous get operation.
+ ///
+ Task> GetEventsAsync(RequestOptions options = null);
+
+ ///
+ /// Creates an event within this guild.
+ ///
+ /// The name of the event.
+ /// The privacy level of the event.
+ /// The start time of the event.
+ /// The type of the event.
+ /// The description of the event.
+ /// The end time of the event.
+ ///
+ /// The channel id of the event.
+ ///
+ /// The event must have a type of or
+ /// in order to use this property.
+ ///
+ ///
+ /// A collection of speakers for the event.
+ /// The location of the event; links are supported
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous create operation.
+ ///
+ Task CreateEventAsync(
+ string name,
+ DateTimeOffset startTime,
+ GuildScheduledEventType type,
+ GuildScheduledEventPrivacyLevel privacyLevel = GuildScheduledEventPrivacyLevel.Private,
+ string description = null,
+ DateTimeOffset? endTime = null,
+ ulong? channelId = null,
+ string location = null,
+ RequestOptions options = null);
+
///
/// Gets this guilds application commands.
///
diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuildScheduledEvent.cs b/src/Discord.Net.Core/Entities/Guilds/IGuildScheduledEvent.cs
new file mode 100644
index 000000000..e50f4cc2b
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Guilds/IGuildScheduledEvent.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ ///
+ /// Represents a generic guild scheduled event.
+ ///
+ public interface IGuildScheduledEvent : IEntity
+ {
+ ///
+ /// Gets the guild this event is scheduled in.
+ ///
+ IGuild Guild { get; }
+
+ ///
+ /// Gets the optional channel id where this event will be hosted.
+ ///
+ ulong? ChannelId { get; }
+
+ ///
+ /// Gets the user who created the event.
+ ///
+ IUser Creator { get; }
+
+ ///
+ /// Gets the name of the event.
+ ///
+ string Name { get; }
+
+ ///
+ /// Gets the description of the event.
+ ///
+ ///
+ /// This field is when the event doesn't have a discription.
+ ///
+ string Description { get; }
+
+ ///
+ /// Gets the start time of the event.
+ ///
+ DateTimeOffset StartTime { get; }
+
+ ///
+ /// Gets the optional end time of the event.
+ ///
+ DateTimeOffset? EndTime { get; }
+
+ ///
+ /// Gets the privacy level of the event.
+ ///
+ GuildScheduledEventPrivacyLevel PrivacyLevel { get; }
+
+ ///
+ /// Gets the status of the event.
+ ///
+ GuildScheduledEventStatus Status { get; }
+
+ ///
+ /// Gets the type of the event.
+ ///
+ GuildScheduledEventType Type { get; }
+
+ ///
+ /// Gets the optional entity id of the event. The "entity" of the event
+ /// can be a stage instance event as is seperate from .
+ ///
+ ulong? EntityId { get; }
+
+ ///
+ /// Gets the location of the event if the is external.
+ ///
+ string Location { get; }
+
+ ///
+ /// Gets the user count of the event.
+ ///
+ int? UserCount { get; }
+
+ ///
+ /// Starts the event.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous start operation.
+ ///
+ Task StartAsync(RequestOptions options = null);
+ ///
+ /// Ends or canceles the event.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous end operation.
+ ///
+ Task EndAsync(RequestOptions options = null);
+
+ ///
+ /// Modifies the guild event.
+ ///
+ /// The delegate containing the properties to modify the event with.
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous modification operation.
+ ///
+ Task ModifyAsync(Action func, RequestOptions options = null);
+
+ ///
+ /// Deletes the current event.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// A task that represents the asynchronous delete operation.
+ ///
+ Task DeleteAsync(RequestOptions options = null);
+
+ ///
+ /// Gets a collection of N users interested in the event.
+ ///
+ ///
+ ///
+ /// The returned collection is an asynchronous enumerable object; one must call
+ /// to access the individual messages as a
+ /// collection.
+ ///
+ /// This method will attempt to fetch all users that are interested in the event.
+ /// The library will attempt to split up the requests according to and .
+ /// In other words, if there are 300 users, and the constant
+ /// is 100, the request will be split into 3 individual requests; thus returning 3 individual asynchronous
+ /// responses, hence the need of flattening.
+ ///
+ /// The options to be used when sending the request.
+ ///
+ /// Paged collection of users.
+ ///
+ IAsyncEnumerable> GetUsersAsync(RequestOptions options = null);
+
+ ///
+ /// Gets a collection of N users interested in the event.
+ ///
+ ///
+ ///
+ /// The returned collection is an asynchronous enumerable object; one must call
+ /// to access the individual users as a
+ /// collection.
+ ///
+ ///
+ /// Do not fetch too many users at once! This may cause unwanted preemptive rate limit or even actual
+ /// rate limit, causing your bot to freeze!
+ ///
+ /// This method will attempt to fetch the number of users specified under around
+ /// the user depending on the . The library will
+ /// attempt to split up the requests according to your and
+ /// . In other words, should the user request 500 users,
+ /// and the constant is 100, the request will
+ /// be split into 5 individual requests; thus returning 5 individual asynchronous responses, hence the need
+ /// of flattening.
+ ///
+ /// The ID of the starting user to get the users from.
+ /// The direction of the users to be gotten from.
+ /// The numbers of users to be gotten from.
+ /// The options to be used when sending the request.
+ ///
+ /// Paged collection of users.
+ ///
+ IAsyncEnumerable> GetUsersAsync(ulong fromUserId, Direction dir, int limit = DiscordConfig.MaxGuildEventUsersPerBatch, RequestOptions options = null);
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Guilds/SystemChannelMessageDeny.cs b/src/Discord.Net.Core/Entities/Guilds/SystemChannelMessageDeny.cs
index 3f69693d0..06de7b812 100644
--- a/src/Discord.Net.Core/Entities/Guilds/SystemChannelMessageDeny.cs
+++ b/src/Discord.Net.Core/Entities/Guilds/SystemChannelMessageDeny.cs
@@ -17,6 +17,14 @@ namespace Discord
///
/// Deny the messages that are sent when a user boosts the guild.
///
- GuildBoost = 0b10
+ GuildBoost = 0b10,
+ ///
+ /// Deny the messages that are related to guild setup.
+ ///
+ GuildSetupTip = 0b100,
+ ///
+ /// Deny the reply with sticker button on welcome messages.
+ ///
+ WelcomeMessageReply = 0b1000
}
}
diff --git a/src/Discord.Net.Core/Entities/IApplication.cs b/src/Discord.Net.Core/Entities/IApplication.cs
index 2174baff9..9f9881340 100644
--- a/src/Discord.Net.Core/Entities/IApplication.cs
+++ b/src/Discord.Net.Core/Entities/IApplication.cs
@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+
namespace Discord
{
///
@@ -16,8 +18,16 @@ namespace Discord
///
/// Gets the RPC origins of the application.
///
- string[] RPCOrigins { get; }
- ulong Flags { get; }
+ IReadOnlyCollection RPCOrigins { get; }
+ ApplicationFlags Flags { get; }
+ ///
+ /// Gets a collection of install parameters for this application.
+ ///
+ ApplicationInstallParams InstallParams { get; }
+ ///
+ /// Gets a collection of tags related to the application.
+ ///
+ IReadOnlyCollection Tags { get; }
///
/// Gets the icon URL of the application.
///
diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs
index 10aa6ab85..9a69d9d18 100644
--- a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOption.cs
@@ -66,6 +66,17 @@ namespace Discord
/// Gets or sets whether or not this option supports autocomplete.
///
public bool IsAutocomplete { get; set; }
+
+ ///
+ /// Gets or sets the smallest number value the user can input.
+ ///
+ public double? MinValue { get; set; }
+
+ ///
+ /// Gets or sets the largest number value the user can input.
+ ///
+ public double? MaxValue { get; set; }
+
///
/// Gets or sets the choices for string and int types for the user to pick from.
///
diff --git a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs
index a9910a0af..6a908b075 100644
--- a/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/ApplicationCommandOptionChoice.cs
@@ -9,6 +9,7 @@ namespace Discord
{
private string _name;
private object _value;
+
///
/// Gets or sets the name of this choice.
///
@@ -24,9 +25,9 @@ namespace Discord
}
///
- /// Gets or sets the value of this choice.
+ /// Gets the value of this choice.
///
- /// Discord only accepts int, string, and doubles as the input.
+ /// Discord only accepts int, double/floats, and string as the input.
///
///
public object Value
@@ -34,8 +35,8 @@ namespace Discord
get => _value;
set
{
- if (value != null && value is not int && value is not string && value is not double)
- throw new ArgumentException("The value of a choice must be a string, int, or double!");
+ if (value != null && value is not string && !value.IsNumericType())
+ throw new ArgumentException("The value of a choice must be a string or a numeric type!");
_value = value;
}
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/AutocompleteOption.cs b/src/Discord.Net.Core/Entities/Interactions/AutocompleteOption.cs
index 4f7d3cb5f..eb22a9d27 100644
--- a/src/Discord.Net.Core/Entities/Interactions/AutocompleteOption.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/AutocompleteOption.cs
@@ -6,7 +6,7 @@ namespace Discord
public class AutocompleteOption
{
///
- /// Gets the type of this option
+ /// Gets the type of this option.
///
public ApplicationCommandOptionType Type { get; }
diff --git a/src/Discord.Net.Core/Entities/Interactions/AutocompleteResult.cs b/src/Discord.Net.Core/Entities/Interactions/AutocompleteResult.cs
index a4333ceb2..0603a5a50 100644
--- a/src/Discord.Net.Core/Entities/Interactions/AutocompleteResult.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/AutocompleteResult.cs
@@ -45,15 +45,13 @@ namespace Discord
public object Value
{
get => _value;
- set => _value = value switch
+ set
{
- string str => str,
- int integer => integer,
- long lng => lng,
- double number => number,
- null => throw new ArgumentNullException(nameof(value), $"{nameof(Value)} cannot be null."),
- _ => throw new ArgumentException($"Type {value.GetType().Name} cannot be set as a value! Only string, int, and double allowed!")
- };
+ if (value is not string && !value.IsNumericType())
+ throw new ArgumentException($"{nameof(value)} must be a numeric type or a string!");
+
+ _value = value;
+ }
}
///
diff --git a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IMessageCommandInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IMessageCommandInteraction.cs
new file mode 100644
index 000000000..b1b331e8b
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IMessageCommandInteraction.cs
@@ -0,0 +1,13 @@
+namespace Discord
+{
+ ///
+ /// Represents a Message Command interaction.
+ ///
+ public interface IMessageCommandInteraction : IDiscordInteraction
+ {
+ ///
+ /// Gets the data associated with this interaction.
+ ///
+ new IMessageCommandInteractionData Data { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IMessageCommandInteractionData.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IMessageCommandInteractionData.cs
new file mode 100644
index 000000000..311eef2d6
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IMessageCommandInteractionData.cs
@@ -0,0 +1,13 @@
+namespace Discord
+{
+ ///
+ /// Represents the data tied with the interaction.
+ ///
+ public interface IMessageCommandInteractionData : IApplicationCommandInteractionData
+ {
+ ///
+ /// Gets the message associated with this message command.
+ ///
+ IMessage Message { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IUserCommandInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IUserCommandInteraction.cs
new file mode 100644
index 000000000..f7cfd67f0
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IUserCommandInteraction.cs
@@ -0,0 +1,13 @@
+namespace Discord
+{
+ ///
+ /// Represents a User Command interaction.
+ ///
+ public interface IUserCommandInteraction : IDiscordInteraction
+ {
+ ///
+ /// Gets the data associated with this interaction.
+ ///
+ new IUserCommandInteractionData Data { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IUserCommandInteractionData.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IUserCommandInteractionData.cs
new file mode 100644
index 000000000..36e482ec9
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/IUserCommandInteractionData.cs
@@ -0,0 +1,13 @@
+namespace Discord
+{
+ ///
+ /// Represents the data tied with the interaction.
+ ///
+ public interface IUserCommandInteractionData : IApplicationCommandInteractionData
+ {
+ ///
+ /// Gets the user who this command targets.
+ ///
+ IUser User { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandBuilder.cs
similarity index 93%
rename from src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandBuilder.cs
rename to src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandBuilder.cs
index 5e7bb660b..c7a7cf741 100644
--- a/src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandBuilder.cs
@@ -19,7 +19,7 @@ namespace Discord
set
{
Preconditions.NotNullOrEmpty(value, nameof(Name));
- Preconditions.AtLeast(value.Length, 3, nameof(Name));
+ Preconditions.AtLeast(value.Length, 1, nameof(Name));
Preconditions.AtMost(value.Length, MaxNameLength, nameof(Name));
_name = value;
@@ -68,7 +68,7 @@ namespace Discord
///
/// The default permission value to set.
/// The current builder.
- public MessageCommandBuilder WithDefaultPermission (bool isDefaultPermission)
+ public MessageCommandBuilder WithDefaultPermission(bool isDefaultPermission)
{
IsDefaultPermission = isDefaultPermission;
return this;
diff --git a/src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandProperties.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandProperties.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Context Menus/MessageCommandProperties.cs
rename to src/Discord.Net.Core/Entities/Interactions/ContextMenus/MessageCommandProperties.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandBuilder.cs
similarity index 92%
rename from src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandBuilder.cs
rename to src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandBuilder.cs
index f9c1c6f67..bd1078be3 100644
--- a/src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandBuilder.cs
@@ -19,7 +19,7 @@ namespace Discord
set
{
Preconditions.NotNullOrEmpty(value, nameof(Name));
- Preconditions.AtLeast(value.Length, 3, nameof(Name));
+ Preconditions.AtLeast(value.Length, 1, nameof(Name));
Preconditions.AtMost(value.Length, MaxNameLength, nameof(Name));
_name = value;
@@ -27,7 +27,7 @@ namespace Discord
}
///
- /// Gets or sets whether the command is enabled by default when the app is added to a guild
+ /// Gets or sets whether the command is enabled by default when the app is added to a guild.
///
public bool IsDefaultPermission { get; set; } = true;
@@ -66,7 +66,7 @@ namespace Discord
///
/// The default permission value to set.
/// The current builder.
- public UserCommandBuilder WithDefaultPermission (bool isDefaultPermission)
+ public UserCommandBuilder WithDefaultPermission(bool isDefaultPermission)
{
IsDefaultPermission = isDefaultPermission;
return this;
diff --git a/src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandProperties.cs b/src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandProperties.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Context Menus/UserCommandProperties.cs
rename to src/Discord.Net.Core/Entities/Interactions/ContextMenus/UserCommandProperties.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
index 7f33e7747..72045a52a 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommand.cs
@@ -15,7 +15,7 @@ namespace Discord
ulong ApplicationId { get; }
///
- /// Gets the type of the command
+ /// Gets the type of the command.
///
ApplicationCommandType Type { get; }
@@ -30,12 +30,12 @@ namespace Discord
string Description { get; }
///
- /// Gets whether or not the command is enabled by default when the app is added to a guild.
+ /// Gets whether the command is enabled by default when the app is added to a guild.
///
bool IsDefaultPermission { get; }
///
- /// Gets the options for this application command.
+ /// Gets a collection of options for this application command.
///
IReadOnlyCollection Options { get; }
diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionData.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionData.cs
index 6cfd62e72..428f20fb6 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionData.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionData.cs
@@ -5,7 +5,7 @@ namespace Discord
///
/// Represents data of an Interaction Command, see .
///
- public interface IApplicationCommandInteractionData
+ public interface IApplicationCommandInteractionData : IDiscordInteractionData
{
///
/// Gets the snowflake id of this command.
diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionDataOption.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionDataOption.cs
index 2a7e9b01e..072d2b32b 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionDataOption.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandInteractionDataOption.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Discord
{
///
- /// Represents a option group for a command, see .
+ /// Represents a option group for a command.
///
public interface IApplicationCommandInteractionDataOption
{
@@ -15,7 +15,7 @@ namespace Discord
///
/// Gets the value of the pair.
///
- /// This objects type can be any one of the option types in
+ /// This objects type can be any one of the option types in .
///
///
object Value { get; }
diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs
index 1ca5fc56a..440c4bd6b 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOption.cs
@@ -3,7 +3,7 @@ using System.Collections.Generic;
namespace Discord
{
///
- /// Options for the , see The docs.
+ /// Options for the .
///
public interface IApplicationCommandOption
{
@@ -13,37 +13,47 @@ namespace Discord
ApplicationCommandOptionType Type { get; }
///
- /// Gets the name of this command option, 1-32 character name.
+ /// Gets the name of this command option.
///
string Name { get; }
///
- /// Gets the discription of this command option, 1-100 character description.
+ /// Gets the description of this command option.
///
string Description { get; }
///
- /// Gets the first required option for the user to complete--only one option can be default.
+ /// Gets whether or not this is the first required option for the user to complete.
///
bool? IsDefault { get; }
///
- /// Gets if the parameter is required or optional, default is .
+ /// Gets whether or not the parameter is required or optional.
///
bool? IsRequired { get; }
///
- /// Gets a collection of choices for the user to pick from.
+ /// Gets the smallest number value the user can input.
+ ///
+ double? MinValue { get; }
+
+ ///
+ /// Gets the largest number value the user can input.
+ ///
+ double? MaxValue { get; }
+
+ ///
+ /// Gets the choices for string and int types for the user to pick from.
///
IReadOnlyCollection Choices { get; }
///
- /// Gets the nested options of this option.
+ /// Gets the sub-options for this command option.
///
IReadOnlyCollection Options { get; }
///
- /// The allowed channel types for this option.
+ /// Gets the allowed channel types for this option.
///
IReadOnlyCollection ChannelTypes { get; }
}
diff --git a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs
index 9b7aa3858..631706c6f 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IApplicationCommandOptionChoice.cs
@@ -6,7 +6,7 @@ namespace Discord
public interface IApplicationCommandOptionChoice
{
///
- /// Gets the name of this choice.
+ /// Gets the choice name.
///
string Name { get; }
diff --git a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs
index 925ae08fc..d9e250118 100644
--- a/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/IDiscordInteraction.cs
@@ -4,36 +4,32 @@ using System.Threading.Tasks;
namespace Discord
{
///
- /// Represents a discord interaction
- ///
- /// An interaction is the base "thing" that is sent when a user invokes a command, and is the same for Slash Commands
- /// and other future interaction types. see .
- ///
+ /// Represents a discord interaction.
///
public interface IDiscordInteraction : ISnowflakeEntity
{
///
- /// The id of the interaction.
+ /// Gets the id of the interaction.
///
new ulong Id { get; }
///
- /// The type of this .
+ /// Gets the type of this .
///
InteractionType Type { get; }
///
- /// Represents the data sent within this interaction.
+ /// Gets the data sent within this interaction.
///
IDiscordInteractionData Data { get; }
///
- /// A continuation token for responding to the interaction.
+ /// Gets the continuation token for responding to the interaction.
///
string Token { get; }
///
- /// read-only property, always 1.
+ /// Gets the version of the interaction, always 1.
///
int Version { get; }
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ActionRowComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ActionRowComponent.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/ActionRowComponent.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/ActionRowComponent.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonComponent.cs
similarity index 99%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonComponent.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonComponent.cs
index a3badf32d..4b9fa2753 100644
--- a/src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonComponent.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonComponent.cs
@@ -27,7 +27,7 @@ namespace Discord
public string CustomId { get; }
///
- /// Gets the URL for a button.
+ /// Gets the URL for a button.
///
///
/// You cannot have a button with a URL and a CustomId.
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonStyle.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonStyle.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/ButtonStyle.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/ButtonStyle.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentBuilder.cs
similarity index 87%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentBuilder.cs
index 91cce1597..4461a4205 100644
--- a/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentBuilder.cs
@@ -31,14 +31,14 @@ namespace Discord
set
{
if (value == null)
- throw new ArgumentNullException(paramName: nameof(ActionRows), message: "Cannot set an component builder's components collection to null.");
+ throw new ArgumentNullException(nameof(value), $"{nameof(ActionRows)} cannot be null.");
if (value.Count > MaxActionRowCount)
- throw new ArgumentException(message: $"Action row count must be less than or equal to {MaxActionRowCount}.", paramName: nameof(ActionRows));
+ throw new ArgumentOutOfRangeException(nameof(value), $"Action row count must be less than or equal to {MaxActionRowCount}.");
_actionRows = value;
}
}
- private List _actionRows { get; set; }
+ private List _actionRows;
///
/// Creates a new builder from a message.
@@ -56,7 +56,7 @@ namespace Discord
public static ComponentBuilder FromComponents(IReadOnlyCollection components)
{
var builder = new ComponentBuilder();
- for(int i = 0; i != components.Count; i++)
+ for (int i = 0; i != components.Count; i++)
{
var component = components.ElementAt(i);
builder.AddComponent(component, i);
@@ -118,7 +118,7 @@ namespace Discord
public ComponentBuilder WithSelectMenu(SelectMenuBuilder menu, int row = 0)
{
Preconditions.LessThan(row, MaxActionRowCount, nameof(row));
- if (menu.Options.Distinct().Count() != menu.Options.Count())
+ if (menu.Options.Distinct().Count() != menu.Options.Count)
throw new InvalidOperationException("Please make sure that there is no duplicates values.");
var builtMenu = menu.Build();
@@ -218,7 +218,7 @@ namespace Discord
else
{
ActionRowBuilder actionRow;
- if(_actionRows.Count > row)
+ if (_actionRows.Count > row)
actionRow = _actionRows.ElementAt(row);
else
{
@@ -244,10 +244,9 @@ namespace Discord
/// A that can be sent with .
public MessageComponent Build()
{
- if (_actionRows != null)
- return new MessageComponent(_actionRows.Select(x => x.Build()).ToList());
- else
- return MessageComponent.Empty;
+ return _actionRows != null
+ ? new MessageComponent(_actionRows.Select(x => x.Build()).ToList())
+ : MessageComponent.Empty;
}
}
@@ -272,19 +271,18 @@ namespace Discord
set
{
if (value == null)
- throw new ArgumentNullException(message: "Action row components cannot be null!", paramName: nameof(Components));
-
- if (value.Count <= 0)
- throw new ArgumentException(message: "There must be at least 1 component in a row", paramName: nameof(Components));
-
- if (value.Count > MaxChildCount)
- throw new ArgumentException(message: $"Action row can only contain {MaxChildCount} child components!", paramName: nameof(Components));
+ throw new ArgumentNullException(nameof(value), $"{nameof(Components)} cannot be null.");
- _components = value;
+ _components = value.Count switch
+ {
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "There must be at least 1 component in a row."),
+ > MaxChildCount => throw new ArgumentOutOfRangeException(nameof(value), $"Action row can only contain {MaxChildCount} child components!"),
+ _ => value
+ };
}
}
- private List _components { get; set; } = new List();
+ private List _components = new List();
///
/// Adds a list of components to the current row.
@@ -359,18 +357,12 @@ namespace Discord
public string Label
{
get => _label;
- set
+ set => _label = value?.Length switch
{
- if (value != null)
- {
- if (value.Length > MaxButtonLabelLength)
- throw new ArgumentException($"Button label must be {MaxButtonLabelLength} characters or less!", paramName: nameof(Label));
- if (value.Length < 1)
- throw new ArgumentException("Button label must be 1 character or more!", paramName: nameof(Label));
- }
-
- _label = value;
- }
+ > MaxButtonLabelLength => throw new ArgumentOutOfRangeException(nameof(value), $"Label length must be less or equal to {MaxButtonLabelLength}."),
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "Label length must be at least 1."),
+ _ => value
+ };
}
///
@@ -381,17 +373,12 @@ namespace Discord
public string CustomId
{
get => _customId;
- set
+ set => _customId = value?.Length switch
{
- if (value != null)
- {
- if (value.Length > ComponentBuilder.MaxCustomIdLength)
- throw new ArgumentException($"Custom Id must be {ComponentBuilder.MaxCustomIdLength} characters or less!", paramName: nameof(CustomId));
- if (value.Length < 1)
- throw new ArgumentException("Custom Id must be 1 character or more!", paramName: nameof(CustomId));
- }
- _customId = value;
- }
+ > ComponentBuilder.MaxCustomIdLength => throw new ArgumentOutOfRangeException(nameof(value), $"Custom Id length must be less or equal to {ComponentBuilder.MaxCustomIdLength}."),
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "Custom Id length must be at least 1."),
+ _ => value
+ };
}
///
@@ -414,7 +401,6 @@ namespace Discord
///
public bool IsDisabled { get; set; }
-
private string _label;
private string _customId;
@@ -594,8 +580,7 @@ namespace Discord
{
if (string.IsNullOrEmpty(Url))
throw new InvalidOperationException("Link buttons must have a link associated with them");
- else
- UrlValidation.Validate(Url);
+ UrlValidation.ValidateButton(Url);
}
else if (string.IsNullOrEmpty(CustomId))
throw new InvalidOperationException("Non-link buttons must have a custom id associated with them");
@@ -632,17 +617,12 @@ namespace Discord
public string CustomId
{
get => _customId;
- set
+ set => _customId = value?.Length switch
{
- if (value != null)
- {
- if (value.Length > ComponentBuilder.MaxCustomIdLength)
- throw new ArgumentException($"Custom Id must be {ComponentBuilder.MaxCustomIdLength} characters or less!", paramName: nameof(CustomId));
- if (value.Length < 1)
- throw new ArgumentException("Custom Id must be 1 character or more!", paramName: nameof(CustomId));
- }
- _customId = value;
- }
+ > ComponentBuilder.MaxCustomIdLength => throw new ArgumentOutOfRangeException(nameof(value), $"Custom Id length must be less or equal to {ComponentBuilder.MaxCustomIdLength}."),
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "Custom Id length must be at least 1."),
+ _ => value
+ };
}
///
@@ -653,18 +633,12 @@ namespace Discord
public string Placeholder
{
get => _placeholder;
- set
+ set => _placeholder = value?.Length switch
{
- if (value != null)
- {
- if (value.Length > MaxPlaceholderLength)
- throw new ArgumentException($"The placeholder must be {MaxPlaceholderLength} characters or less!", paramName: nameof(Placeholder));
- if (value.Length < 1)
- throw new ArgumentException("The placeholder must be 1 character or more!", paramName: nameof(Placeholder));
- }
-
- _placeholder = value;
- }
+ > MaxPlaceholderLength => throw new ArgumentOutOfRangeException(nameof(value), $"Placeholder length must be less or equal to {MaxPlaceholderLength}."),
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "Placeholder length must be at least 1."),
+ _ => value
+ };
}
///
@@ -676,7 +650,7 @@ namespace Discord
get => _minValues;
set
{
- Preconditions.LessThan(value, MaxValuesCount, nameof(MinValues));
+ Preconditions.AtMost(value, MaxValuesCount, nameof(MinValues));
_minValues = value;
}
}
@@ -690,7 +664,7 @@ namespace Discord
get => _maxValues;
set
{
- Preconditions.LessThan(value, MaxValuesCount, nameof(MaxValues));
+ Preconditions.AtMost(value, MaxValuesCount, nameof(MaxValues));
_maxValues = value;
}
}
@@ -706,9 +680,9 @@ namespace Discord
set
{
if (value != null)
- Preconditions.LessThan(value.Count, MaxOptionCount, nameof(Options));
+ Preconditions.AtMost(value.Count, MaxOptionCount, nameof(Options));
else
- throw new ArgumentNullException(nameof(value));
+ throw new ArgumentNullException(nameof(value), $"{nameof(Options)} cannot be null.");
_options = value;
}
@@ -858,14 +832,14 @@ namespace Discord
/// The value of this option.
/// The description of this option.
/// The emote of this option.
- /// Render this option as selected by default or not.
+ /// Render this option as selected by default or not.
/// Options count reached .
///
/// The current builder.
///
- public SelectMenuBuilder AddOption(string label, string value, string description = null, IEmote emote = null, bool? @default = null)
+ public SelectMenuBuilder AddOption(string label, string value, string description = null, IEmote emote = null, bool? isDefault = null)
{
- AddOption(new SelectMenuOptionBuilder(label, value, description, emote, @default));
+ AddOption(new SelectMenuOptionBuilder(label, value, description, emote, isDefault));
return this;
}
@@ -908,7 +882,7 @@ namespace Discord
/// The maximum length of a .
///
public const int MaxDescriptionLength = 100;
-
+
///
/// The maximum length of a .
///
@@ -922,42 +896,28 @@ namespace Discord
public string Label
{
get => _label;
- set
+ set => _label = value?.Length switch
{
- if (value != null)
- {
- if (value.Length > MaxSelectLabelLength)
- throw new ArgumentException($"Select option label must be {MaxSelectLabelLength} characters or less!", paramName: nameof(Label));
- if (value.Length < 1)
- throw new ArgumentException("Select option label must be 1 character or more!", paramName: nameof(Label));
- }
-
- _label = value;
- }
+ > MaxSelectLabelLength => throw new ArgumentOutOfRangeException(nameof(value), $"Label length must be less or equal to {MaxSelectLabelLength}."),
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "Label length must be at least 1."),
+ _ => value
+ };
}
///
- /// Gets or sets the custom id of the current select menu.
+ /// Gets or sets the value of the current select menu.
///
/// length exceeds .
/// length subceeds 1.
public string Value
{
get => _value;
- set
+ set => _value = value?.Length switch
{
- if (value != null)
- {
- if (value.Length > MaxSelectValueLength)
- throw new ArgumentException($"Select option value must be {MaxSelectValueLength} characters or less!", paramName: nameof(Label));
- if (value.Length < 1)
- throw new ArgumentException("Select option value must be 1 character or more!", paramName: nameof(Label));
- }
- else
- throw new ArgumentException("Select option value must not be null or empty!", paramName: nameof(Label));
-
- _value = value;
- }
+ > MaxSelectValueLength => throw new ArgumentOutOfRangeException(nameof(value), $"Value length must be less or equal to {MaxSelectValueLength}."),
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "Value length must be at least 1."),
+ _ => value
+ };
}
///
@@ -968,18 +928,12 @@ namespace Discord
public string Description
{
get => _description;
- set
+ set => _description = value?.Length switch
{
- if (value != null)
- {
- if (value.Length > MaxDescriptionLength)
- throw new ArgumentException($"The description must be {MaxDescriptionLength} characters or less!", paramName: nameof(Label));
- if (value.Length < 1)
- throw new ArgumentException("The description must be 1 character or more!", paramName: nameof(Label));
- }
-
- _description = value;
- }
+ > MaxDescriptionLength => throw new ArgumentOutOfRangeException(nameof(value), $"Description length must be less or equal to {MaxDescriptionLength}."),
+ 0 => throw new ArgumentOutOfRangeException(nameof(value), "Description length must be at least 1."),
+ _ => value
+ };
}
///
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentType.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentType.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/ComponentType.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/ComponentType.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IComponentInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IComponentInteraction.cs
new file mode 100644
index 000000000..2a46e8f18
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IComponentInteraction.cs
@@ -0,0 +1,18 @@
+namespace Discord
+{
+ ///
+ /// Represents an interaction type for Message Components.
+ ///
+ public interface IComponentInteraction : IDiscordInteraction
+ {
+ ///
+ /// Gets the data received with this interaction, contains the button that was clicked.
+ ///
+ new IComponentInteractionData Data { get; }
+
+ ///
+ /// Gets the message that contained the trigger for this interaction.
+ ///
+ IUserMessage Message { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IComponentInteractionData.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IComponentInteractionData.cs
new file mode 100644
index 000000000..99b9b6f6c
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IComponentInteractionData.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Discord
+{
+ ///
+ /// Represents the data sent with the .
+ ///
+ public interface IComponentInteractionData : IDiscordInteractionData
+ {
+ ///
+ /// Gets the components Custom Id that was clicked.
+ ///
+ string CustomId { get; }
+
+ ///
+ /// Gets the type of the component clicked.
+ ///
+ ComponentType Type { get; }
+
+ ///
+ /// Gets the value(s) of a interaction response.
+ ///
+ IReadOnlyCollection Values { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/IMessageComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/IMessageComponent.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/IMessageComponent.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/IMessageComponent.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/MessageComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/MessageComponent.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/MessageComponent.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/MessageComponent.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/SelectMenuComponent.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs
similarity index 93%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/SelectMenuComponent.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs
index a1ec7acd8..229c1e148 100644
--- a/src/Discord.Net.Core/Entities/Interactions/Message Components/SelectMenuComponent.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuComponent.cs
@@ -11,9 +11,7 @@ namespace Discord
///
public ComponentType Type => ComponentType.SelectMenu;
- ///
- /// Gets the custom id of this Select menu that will be sent with a .
- ///
+ ///
public string CustomId { get; }
///
diff --git a/src/Discord.Net.Core/Entities/Interactions/Message Components/SelectMenuOption.cs b/src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuOption.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Message Components/SelectMenuOption.cs
rename to src/Discord.Net.Core/Entities/Interactions/MessageComponents/SelectMenuOption.cs
diff --git a/src/Discord.Net.Core/Entities/Interactions/SlashCommands/IAutocompleteInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/IAutocompleteInteraction.cs
new file mode 100644
index 000000000..bb5343d84
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/IAutocompleteInteraction.cs
@@ -0,0 +1,13 @@
+namespace Discord
+{
+ ///
+ /// Represents a .
+ ///
+ public interface IAutocompleteInteraction : IDiscordInteraction
+ {
+ ///
+ /// Gets the autocomplete data of this interaction.
+ ///
+ new IAutocompleteInteractionData Data { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/SlashCommands/IAutocompleteInteractionData.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/IAutocompleteInteractionData.cs
new file mode 100644
index 000000000..e6d1e9fae
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/IAutocompleteInteractionData.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+
+namespace Discord
+{
+ ///
+ /// Represents data for a slash commands autocomplete interaction.
+ ///
+ public interface IAutocompleteInteractionData : IDiscordInteractionData
+ {
+ ///
+ /// Gets the name of the invoked command.
+ ///
+ string CommandName { get; }
+
+ ///
+ /// Gets the id of the invoked command.
+ ///
+ ulong CommandId { get; }
+
+ ///
+ /// Gets the type of the invoked command.
+ ///
+ ApplicationCommandType Type { get; }
+
+ ///
+ /// Gets the version of the invoked command.
+ ///
+ ulong Version { get; }
+
+ ///
+ /// Gets the current autocomplete option that is actively being filled out.
+ ///
+ AutocompleteOption Current { get; }
+
+ ///
+ /// Gets a collection of all the other options the executing users has filled out.
+ ///
+ IReadOnlyCollection Options { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/SlashCommands/ISlashCommandInteraction.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/ISlashCommandInteraction.cs
new file mode 100644
index 000000000..556182987
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/ISlashCommandInteraction.cs
@@ -0,0 +1,13 @@
+namespace Discord
+{
+ ///
+ /// Represents a slash command interaction.
+ ///
+ public interface ISlashCommandInteraction : IDiscordInteraction
+ {
+ ///
+ /// Gets the data associated with this interaction.
+ ///
+ new IApplicationCommandInteractionData Data { get; }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Interactions/Slash Commands/SlashCommandBuilder.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandBuilder.cs
similarity index 87%
rename from src/Discord.Net.Core/Entities/Interactions/Slash Commands/SlashCommandBuilder.cs
rename to src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandBuilder.cs
index 737092cb7..b4fc89cc2 100644
--- a/src/Discord.Net.Core/Entities/Interactions/Slash Commands/SlashCommandBuilder.cs
+++ b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandBuilder.cs
@@ -99,7 +99,7 @@ namespace Discord
{
var options = new List();
- Options.ForEach(x => options.Add(x.Build()));
+ Options.OrderByDescending(x => x.IsRequired ?? false).ToList().ForEach(x => options.Add(x.Build()));
props.Options = options;
}
@@ -154,10 +154,12 @@ namespace Discord
/// The options of the option to add.
/// The allowed channel types for this option.
/// The choices of this option.
+ /// The smallest number value the user can input.
+ /// The largest number value the user can input.
/// The current builder.
public SlashCommandBuilder AddOption(string name, ApplicationCommandOptionType type,
- string description, bool? isRequired = null, bool? isDefault = null, bool isAutocomplete = false, List options = null,
- List channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices)
+ string description, bool? isRequired = null, bool? isDefault = null, bool isAutocomplete = false, double? minValue = null, double? maxValue = null,
+ List options = null, List channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices)
{
// Make sure the name matches the requirements from discord
Preconditions.NotNullOrEmpty(name, nameof(name));
@@ -188,7 +190,9 @@ namespace Discord
Type = type,
IsAutocomplete = isAutocomplete,
Choices = (choices ?? Array.Empty()).ToList(),
- ChannelTypes = channelTypes
+ ChannelTypes = channelTypes,
+ MinValue = minValue,
+ MaxValue = maxValue,
};
return AddOption(option);
@@ -310,6 +314,16 @@ namespace Discord
///
public bool IsAutocomplete { get; set; }
+ ///
+ /// Gets or sets the smallest number value the user can input.
+ ///
+ public double? MinValue { get; set; }
+
+ ///
+ /// Gets or sets the largest number value the user can input.
+ ///
+ public double? MaxValue { get; set; }
+
///
/// Gets or sets the choices for string and int types for the user to pick from.
///
@@ -332,6 +346,7 @@ namespace Discord
public ApplicationCommandOptionProperties Build()
{
bool isSubType = Type == ApplicationCommandOptionType.SubCommandGroup;
+ bool isIntType = Type == ApplicationCommandOptionType.Integer;
if (isSubType && (Options == null || !Options.Any()))
throw new InvalidOperationException("SubCommands/SubCommandGroups must have at least one option");
@@ -339,6 +354,12 @@ namespace Discord
if (!isSubType && Options != null && Options.Any() && Type != ApplicationCommandOptionType.SubCommand)
throw new InvalidOperationException($"Cannot have options on {Type} type");
+ if (isIntType && MinValue != null && MinValue % 1 != 0)
+ throw new InvalidOperationException("MinValue cannot have decimals on Integer command options.");
+
+ if (isIntType && MaxValue != null && MaxValue % 1 != 0)
+ throw new InvalidOperationException("MaxValue cannot have decimals on Integer command options.");
+
return new ApplicationCommandOptionProperties
{
Name = Name,
@@ -346,10 +367,14 @@ namespace Discord
IsDefault = IsDefault,
IsRequired = IsRequired,
Type = Type,
- Options = Options?.Count > 0 ? Options.Select(x => x.Build()).ToList() : new List(),
+ Options = Options?.Count > 0
+ ? Options.OrderByDescending(x => x.IsRequired ?? false).Select(x => x.Build()).ToList()
+ : new List(),
Choices = Choices,
IsAutocomplete = IsAutocomplete,
- ChannelTypes = ChannelTypes
+ ChannelTypes = ChannelTypes,
+ MinValue = MinValue,
+ MaxValue = MaxValue
};
}
@@ -365,10 +390,12 @@ namespace Discord
/// The options of the option to add.
/// The allowed channel types for this option.
/// The choices of this option.
+ /// The smallest number value the user can input.
+ /// The largest number value the user can input.
/// The current builder.
public SlashCommandOptionBuilder AddOption(string name, ApplicationCommandOptionType type,
- string description, bool? isRequired = null, bool isDefault = false, bool isAutocomplete = false, List options = null,
- List channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices)
+ string description, bool? required = null, bool isDefault = false, bool isAutocomplete = false, double? minValue = null, double? maxValue = null,
+ List options = null, List channelTypes = null, params ApplicationCommandOptionChoiceProperties[] choices)
{
// Make sure the name matches the requirements from discord
Preconditions.NotNullOrEmpty(name, nameof(name));
@@ -393,9 +420,11 @@ namespace Discord
{
Name = name,
Description = description,
- IsRequired = isRequired,
- IsAutocomplete = isAutocomplete,
+ IsRequired = required,
IsDefault = isDefault,
+ IsAutocomplete = isAutocomplete,
+ MinValue = minValue,
+ MaxValue = maxValue,
Options = options,
Type = type,
Choices = (choices ?? Array.Empty()).ToList(),
@@ -575,6 +604,28 @@ namespace Discord
return this;
}
+ ///
+ /// Sets the current builders min value field.
+ ///
+ /// The value to set.
+ /// The current builder.
+ public SlashCommandOptionBuilder WithMinValue(double value)
+ {
+ MinValue = value;
+ return this;
+ }
+
+ ///
+ /// Sets the current builders max value field.
+ ///
+ /// The value to set.
+ /// The current builder.
+ public SlashCommandOptionBuilder WithMaxValue(double value)
+ {
+ MaxValue = value;
+ return this;
+ }
+
///
/// Sets the current type of this builder.
///
diff --git a/src/Discord.Net.Core/Entities/Interactions/Slash Commands/SlashCommandProperties.cs b/src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandProperties.cs
similarity index 100%
rename from src/Discord.Net.Core/Entities/Interactions/Slash Commands/SlashCommandProperties.cs
rename to src/Discord.Net.Core/Entities/Interactions/SlashCommands/SlashCommandProperties.cs
diff --git a/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs b/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
new file mode 100644
index 000000000..dc5437861
--- /dev/null
+++ b/src/Discord.Net.Core/Entities/Messages/FileAttachment.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ public struct FileAttachment : IDisposable
+ {
+ public string FileName { get; set; }
+ public string Description { get; set; }
+ public bool IsSpoiler { get; set; }
+
+#pragma warning disable IDISP008
+ public Stream Stream { get; }
+#pragma warning restore IDISP008
+
+ private bool _isDisposed;
+
+ ///
+ /// Creates a file attachment from a stream.
+ ///
+ /// The stream to create the attachment from.
+ /// The name of the attachment.
+ /// The description of the attachment.
+ public FileAttachment(Stream stream, string fileName, string description = null, bool isSpoiler = false)
+ {
+ _isDisposed = false;
+ FileName = fileName;
+ Description = description;
+ Stream = stream;
+ IsSpoiler = isSpoiler;
+ }
+
+ ///
+ /// Create the file attachment from a file path.
+ ///
+ ///
+ /// This file path is NOT validated and is passed directly into a
+ /// .
+ ///
+ /// The path to the file.
+ ///
+ /// is a zero-length string, contains only white space, or contains one or more invalid
+ /// characters as defined by .
+ ///
+ /// is null.
+ ///
+ /// The specified path, file name, or both exceed the system-defined maximum length. For example, on
+ /// Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260
+ /// characters.
+ ///
+ /// is in an invalid format.
+ ///
+ /// The specified is invalid, (for example, it is on an unmapped drive).
+ ///
+ ///
+ /// specified a directory.-or- The caller does not have the required permission.
+ ///
+ /// The file specified in was not found.
+ ///
+ /// An I/O error occurred while opening the file.
+ public FileAttachment(string path, string description = null, bool isSpoiler = false)
+ {
+ _isDisposed = false;
+ Stream = File.OpenRead(path);
+ FileName = Path.GetFileName(path);
+ Description = description;
+ IsSpoiler = isSpoiler;
+ }
+
+ public void Dispose()
+ {
+ if (!_isDisposed)
+ {
+ Stream?.Dispose();
+ _isDisposed = true;
+ }
+ }
+ }
+}
diff --git a/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs b/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs
index abd09d856..1a4eaff2d 100644
--- a/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs
+++ b/src/Discord.Net.Core/Entities/Messages/MessageProperties.cs
@@ -1,3 +1,5 @@
+using System.Collections.Generic;
+
namespace Discord
{
///
@@ -48,5 +50,10 @@ namespace Discord
/// Gets or sets the allowed mentions of the message.
///
public Optional AllowedMentions { get; set; }
+
+ ///
+ /// Gets or sets the attachments for the message.
+ ///
+ public Optional> Attachments { get; set; }
}
}
diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs
index ac2f7276b..5a5827c1d 100644
--- a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs
+++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs
@@ -180,10 +180,14 @@ namespace Discord
///
UseApplicationCommands = 0x80_00_00_00,
///
- /// Allows for requesting to speak in stage channels. (This permission is under active development and may be changed or removed.).
+ /// Allows for requesting to speak in stage channels.
///
RequestToSpeak = 0x01_00_00_00_00,
///
+ /// Allows for creating, editing, and deleting guild scheduled events.
+ ///
+ ManageEvents = 0x02_00_00_00_00,
+ ///
/// Allows for deleting and archiving threads, and viewing all private threads.
///
///
diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
index 31f74ea22..8a4ad2189 100644
--- a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
+++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
+using System.Linq;
namespace Discord
{
@@ -87,6 +88,8 @@ namespace Discord
public bool UseApplicationCommands => Permissions.GetValue(RawValue, GuildPermission.UseApplicationCommands);
/// If true, a user may request to speak in stage channels.
public bool RequestToSpeak => Permissions.GetValue(RawValue, GuildPermission.RequestToSpeak);
+ /// If true, a user may create, edit, and delete events.
+ public bool ManageEvents => Permissions.GetValue(RawValue, GuildPermission.ManageEvents);
/// If true, a user may manage threads in this guild.
public bool ManageThreads => Permissions.GetValue(RawValue, GuildPermission.ManageThreads);
/// If true, a user may create public threads in this guild.
@@ -140,6 +143,7 @@ namespace Discord
bool? manageEmojisAndStickers = null,
bool? useApplicationCommands = null,
bool? requestToSpeak = null,
+ bool? manageEvents = null,
bool? manageThreads = null,
bool? createPublicThreads = null,
bool? createPrivateThreads = null,
@@ -182,6 +186,7 @@ namespace Discord
Permissions.SetValue(ref value, manageEmojisAndStickers, GuildPermission.ManageEmojisAndStickers);
Permissions.SetValue(ref value, useApplicationCommands, GuildPermission.UseApplicationCommands);
Permissions.SetValue(ref value, requestToSpeak, GuildPermission.RequestToSpeak);
+ Permissions.SetValue(ref value, manageEvents, GuildPermission.ManageEvents);
Permissions.SetValue(ref value, manageThreads, GuildPermission.ManageThreads);
Permissions.SetValue(ref value, createPublicThreads, GuildPermission.CreatePublicThreads);
Permissions.SetValue(ref value, createPrivateThreads, GuildPermission.CreatePrivateThreads);
@@ -227,6 +232,7 @@ namespace Discord
bool manageEmojisAndStickers = false,
bool useApplicationCommands = false,
bool requestToSpeak = false,
+ bool manageEvents = false,
bool manageThreads = false,
bool createPublicThreads = false,
bool createPrivateThreads = false,
@@ -267,6 +273,7 @@ namespace Discord
manageEmojisAndStickers: manageEmojisAndStickers,
useApplicationCommands: useApplicationCommands,
requestToSpeak: requestToSpeak,
+ manageEvents: manageEvents,
manageThreads: manageThreads,
createPublicThreads: createPublicThreads,
createPrivateThreads: createPrivateThreads,
@@ -310,6 +317,7 @@ namespace Discord
bool? manageEmojisAndStickers = null,
bool? useApplicationCommands = null,
bool? requestToSpeak = null,
+ bool? manageEvents = null,
bool? manageThreads = null,
bool? createPublicThreads = null,
bool? createPrivateThreads = null,
@@ -320,7 +328,7 @@ namespace Discord
viewAuditLog, viewGuildInsights, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles,
readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers,
useVoiceActivation, prioritySpeaker, stream, changeNickname, manageNicknames, manageRoles, manageWebhooks, manageEmojisAndStickers,
- useApplicationCommands, requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads,
+ useApplicationCommands, requestToSpeak, manageEvents, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads,
startEmbeddedActivities);
///
@@ -351,6 +359,18 @@ namespace Discord
return perms;
}
+ internal void Ensure(GuildPermission permissions)
+ {
+ if (!Has(permissions))
+ {
+ var vals = Enum.GetValues(typeof(GuildPermission)).Cast();
+ var currentValues = RawValue;
+ var missingValues = vals.Where(x => permissions.HasFlag(x) && !Permissions.GetValue(currentValues, x));
+
+ throw new InvalidOperationException($"Missing required guild permission{(missingValues.Count() > 1 ? "s" : "")} {string.Join(", ", missingValues.Select(x => x.ToString()))} in order to execute this operation.");
+ }
+ }
+
public override string ToString() => RawValue.ToString();
private string DebuggerDisplay => $"{string.Join(", ", ToList())}";
}
diff --git a/src/Discord.Net.Core/Entities/Roles/IRole.cs b/src/Discord.Net.Core/Entities/Roles/IRole.cs
index c9e7ffef7..59ca41e31 100644
--- a/src/Discord.Net.Core/Entities/Roles/IRole.cs
+++ b/src/Discord.Net.Core/Entities/Roles/IRole.cs
@@ -59,6 +59,13 @@ namespace Discord
///
string Icon { get; }
///
+ /// Gets the unicode emoji of this role.
+ ///
+ ///
+ /// This field is mutually exclusive with , either icon is set or emoji is set.
+ ///
+ Emoji Emoji { get; }
+ ///
/// Gets the permissions granted to members of this role.
///
///
diff --git a/src/Discord.Net.Core/Entities/Users/IUser.cs b/src/Discord.Net.Core/Entities/Users/IUser.cs
index f265bb938..2f79450f3 100644
--- a/src/Discord.Net.Core/Entities/Users/IUser.cs
+++ b/src/Discord.Net.Core/Entities/Users/IUser.cs
@@ -10,18 +10,7 @@ namespace Discord
///
/// Gets the identifier of this user's avatar.
///
- string AvatarId { get; }
- ///
- /// Gets the identifier of this user's banner.
- ///
- string BannerId { get; }
- ///
- /// Gets the user's banner color.
- ///
- ///
- /// A struct representing the accent color of this user's banner.
- ///
- Color? AccentColor { get; }
+ string AvatarId { get; }
///
/// Gets the avatar URL for this user.
///
@@ -46,16 +35,6 @@ namespace Discord
///
string GetAvatarUrl(ImageFormat format = ImageFormat.Auto, ushort size = 128);
///
- /// Gets the banner URL for this user.
- ///
- /// The format to return.
- /// The size of the image to return in. This can be any power of two between 16 and 2048.
- ///
- ///
- /// A string representing the user's avatar URL; null if the user does not have an banner in place.
- ///
- string GetBannerUrl(ImageFormat format = ImageFormat.Auto, ushort size = 256);
- ///
/// Gets the default avatar URL for this user.
///
///
diff --git a/src/Discord.Net.Core/Extensions/GuildExtensions.cs b/src/Discord.Net.Core/Extensions/GuildExtensions.cs
index 58b749cc4..9dd8de82e 100644
--- a/src/Discord.Net.Core/Extensions/GuildExtensions.cs
+++ b/src/Discord.Net.Core/Extensions/GuildExtensions.cs
@@ -20,5 +20,21 @@ namespace Discord
/// A bool indicating if the guild boost messages are enabled in the system channel.
public static bool GetGuildBoostMessagesEnabled(this IGuild guild)
=> !guild.SystemChannelFlags.HasFlag(SystemChannelMessageDeny.GuildBoost);
+
+ ///
+ /// Gets if guild setup system messages are enabled.
+ ///
+ /// The guild to check.
+ /// A bool indicating if the guild setup messages are enabled in the system channel.
+ public static bool GetGuildSetupTipMessagesEnabled(this IGuild guild)
+ => !guild.SystemChannelFlags.HasFlag(SystemChannelMessageDeny.GuildSetupTip);
+
+ ///
+ /// Gets if guild welcome messages have a reply with sticker button.
+ ///
+ /// The guild to check.
+ /// A bool indicating if the guild welcome messages have a reply with sticker button.
+ public static bool GetGuildWelcomeMessageReplyEnabled(this IGuild guild)
+ => !guild.SystemChannelFlags.HasFlag(SystemChannelMessageDeny.WelcomeMessageReply);
}
}
diff --git a/src/Discord.Net.Core/Extensions/ObjectExtensions.cs b/src/Discord.Net.Core/Extensions/ObjectExtensions.cs
new file mode 100644
index 000000000..240fb47aa
--- /dev/null
+++ b/src/Discord.Net.Core/Extensions/ObjectExtensions.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord
+{
+ internal static class ObjectExtensions
+ {
+ public static bool IsNumericType(this object o)
+ {
+ switch (Type.GetTypeCode(o.GetType()))
+ {
+ case TypeCode.Byte:
+ case TypeCode.SByte:
+ case TypeCode.UInt16:
+ case TypeCode.UInt32:
+ case TypeCode.UInt64:
+ case TypeCode.Int16:
+ case TypeCode.Int32:
+ case TypeCode.Int64:
+ case TypeCode.Decimal:
+ case TypeCode.Double:
+ case TypeCode.Single:
+ return true;
+ default:
+ return false;
+ }
+ }
+ }
+}
diff --git a/src/Discord.Net.Core/GatewayIntents.cs b/src/Discord.Net.Core/GatewayIntents.cs
index fb0aac6bc..f2a99e44c 100644
--- a/src/Discord.Net.Core/GatewayIntents.cs
+++ b/src/Discord.Net.Core/GatewayIntents.cs
@@ -39,13 +39,15 @@ namespace Discord
DirectMessageReactions = 1 << 13,
/// This intent includes TYPING_START
DirectMessageTyping = 1 << 14,
+ /// This intent includes GUILD_SCHEDULED_EVENT_CREATE, GUILD_SCHEDULED_EVENT_UPDATE, GUILD_SCHEDULED_EVENT_DELETE, GUILD_SCHEDULED_EVENT_USER_ADD, GUILD_SCHEDULED_EVENT_USER_REMOVE
+ GuildScheduledEvents = 1 << 16,
///
/// This intent includes all but and
/// which are privileged and must be enabled in the Developer Portal.
///
AllUnprivileged = Guilds | GuildBans | GuildEmojis | GuildIntegrations | GuildWebhooks | GuildInvites |
GuildVoiceStates | GuildMessages | GuildMessageReactions | GuildMessageTyping | DirectMessages |
- DirectMessageReactions | DirectMessageTyping,
+ DirectMessageReactions | DirectMessageTyping | GuildScheduledEvents,
///
/// This intent includes all of them, including privileged ones.
///
diff --git a/src/Discord.Net.Core/Net/ApplicationCommandException.cs b/src/Discord.Net.Core/Net/ApplicationCommandException.cs
index 62c80b388..4b4890d12 100644
--- a/src/Discord.Net.Core/Net/ApplicationCommandException.cs
+++ b/src/Discord.Net.Core/Net/ApplicationCommandException.cs
@@ -1,60 +1,15 @@
using System;
+using System.Linq;
namespace Discord.Net
{
- public class ApplicationCommandException : Exception
+ [Obsolete("Please use HttpException instead of this. Will be removed in next major version.", false)]
+ public class ApplicationCommandException : HttpException
{
- ///
- /// Gets the JSON error code returned by Discord.
- ///
- ///
- /// A
- /// JSON error code
- /// from Discord, or null if none.
- ///
- public int? DiscordCode { get; }
-
- ///
- /// Gets the reason of the exception.
- ///
- public string Reason { get; }
-
- ///
- /// Gets the request object used to send the request.
- ///
- public IRequest Request { get; }
-
- ///
- /// The error object returned from discord.
- ///
- ///
- /// Note: This object can be null if discord didn't provide it.
- ///
- public object Error { get; }
-
- ///
- /// The request json used to create the application command. This is useful for checking your commands for any format errors.
- ///
- public string RequestJson { get; }
-
- ///
- /// The underlying that caused this exception to be thrown.
- ///
- public HttpException InnerHttpException { get; }
- ///
- /// Initializes a new instance of the class.
- ///
- ///
- ///
- public ApplicationCommandException(string requestJson, HttpException httpError)
- : base("The application command failed to be created!", httpError)
+ public ApplicationCommandException(HttpException httpError)
+ : base(httpError.HttpCode, httpError.Request, httpError.DiscordCode, httpError.Reason, httpError.Errors.ToArray())
{
- Request = httpError.Request;
- DiscordCode = httpError.DiscordCode;
- Reason = httpError.Reason;
- Error = httpError.Error;
- RequestJson = requestJson;
- InnerHttpException = httpError;
+
}
}
}
diff --git a/src/Discord.Net.Core/Net/HttpException.cs b/src/Discord.Net.Core/Net/HttpException.cs
index 568562b61..07551f0e7 100644
--- a/src/Discord.Net.Core/Net/HttpException.cs
+++ b/src/Discord.Net.Core/Net/HttpException.cs
@@ -1,4 +1,6 @@
using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
using System.Net;
namespace Discord.Net
@@ -25,7 +27,7 @@ namespace Discord.Net
/// JSON error code
/// from Discord, or null if none.
///
- public int? DiscordCode { get; }
+ public DiscordErrorCode? DiscordCode { get; }
///
/// Gets the reason of the exception.
///
@@ -35,12 +37,9 @@ namespace Discord.Net
///
public IRequest Request { get; }
///
- /// The error object returned from discord.
+ /// Gets a collection of json errors describing what went wrong with the request.
///
- ///
- /// Note: This object can be null if discord didn't provide it.
- ///
- public object Error { get; }
+ public IReadOnlyCollection Errors { get; }
///
/// Initializes a new instance of the class.
@@ -49,14 +48,14 @@ namespace Discord.Net
/// The request that was sent prior to the exception.
/// The Discord status code returned.
/// The reason behind the exception.
- public HttpException(HttpStatusCode httpCode, IRequest request, int? discordCode = null, string reason = null, object errors = null)
- : base(CreateMessage(httpCode, discordCode, reason))
+ public HttpException(HttpStatusCode httpCode, IRequest request, DiscordErrorCode? discordCode = null, string reason = null, DiscordJsonError[] errors = null)
+ : base(CreateMessage(httpCode, (int?)discordCode, reason))
{
HttpCode = httpCode;
Request = request;
DiscordCode = discordCode;
Reason = reason;
- Error = errors;
+ Errors = errors?.ToImmutableArray() ?? ImmutableArray.Empty;
}
private static string CreateMessage(HttpStatusCode httpCode, int? discordCode = null, string reason = null)
diff --git a/src/Discord.Net.Core/Utils/Cacheable.cs b/src/Discord.Net.Core/Utils/Cacheable.cs
index 1857ae7a0..4aa768292 100644
--- a/src/Discord.Net.Core/Utils/Cacheable.cs
+++ b/src/Discord.Net.Core/Utils/Cacheable.cs
@@ -63,4 +63,60 @@ namespace Discord
///
public async Task GetOrDownloadAsync() => HasValue ? Value : await DownloadAsync().ConfigureAwait(false);
}
+ public struct Cacheable
+ where TCachedEntity : IEntity, TRelationship
+ where TDownloadableEntity : IEntity, TRelationship
+ where TId : IEquatable
+ {
+ ///
+ /// Gets whether this entity is cached.
+ ///
+ public bool HasValue { get; }
+ ///
+ /// Gets the ID of this entity.
+ ///
+ public TId Id { get; }
+ ///
+ /// Gets the entity if it could be pulled from cache.
+ ///
+ ///
+ /// This value is not guaranteed to be set; in cases where the entity cannot be pulled from cache, it is
+ /// null.
+ ///
+ public TCachedEntity Value { get; }
+ private Func> DownloadFunc { get; }
+
+ internal Cacheable(TCachedEntity value, TId id, bool hasValue, Func> downloadFunc)
+ {
+ Value = value;
+ Id = id;
+ HasValue = hasValue;
+ DownloadFunc = downloadFunc;
+ }
+
+ ///
+ /// Downloads this entity.
+ ///
+ /// Thrown when used from a user account.
+ /// Thrown when the message is deleted.
+ ///
+ /// A task that represents the asynchronous download operation. The task result contains the downloaded
+ /// entity.
+ ///
+ public async Task DownloadAsync()
+ {
+ return await DownloadFunc().ConfigureAwait(false);
+ }
+
+ ///
+ /// Returns the cached entity if it exists; otherwise downloads it.
+ ///
+ /// Thrown when used from a user account.
+ /// Thrown when the message is deleted and is not in cache.
+ ///
+ /// A task that represents the asynchronous operation that attempts to get the message via cache or to
+ /// download the message. The task result contains the downloaded entity.
+ ///
+ public async Task GetOrDownloadAsync() => HasValue ? Value : await DownloadAsync().ConfigureAwait(false);
+ }
}
diff --git a/src/Discord.Net.Rest/API/Common/Application.cs b/src/Discord.Net.Rest/API/Common/Application.cs
index e828f9910..4ef6940a2 100644
--- a/src/Discord.Net.Rest/API/Common/Application.cs
+++ b/src/Discord.Net.Rest/API/Common/Application.cs
@@ -7,7 +7,7 @@ namespace Discord.API
[JsonProperty("description")]
public string Description { get; set; }
[JsonProperty("rpc_origins")]
- public string[] RPCOrigins { get; set; }
+ public Optional RPCOrigins { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("id")]
@@ -18,12 +18,16 @@ namespace Discord.API
public bool IsBotPublic { get; set; }
[JsonProperty("bot_require_code_grant")]
public bool BotRequiresCodeGrant { get; set; }
+ [JsonProperty("install_params")]
+ public Optional InstallParams { get; set; }
+
[JsonProperty("team")]
public Team Team { get; set; }
[JsonProperty("flags"), Int53]
- public Optional Flags { get; set; }
+ public Optional Flags { get; set; }
[JsonProperty("owner")]
public Optional Owner { get; set; }
+ public Optional Tags { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Common/ApplicationCommandOption.cs b/src/Discord.Net.Rest/API/Common/ApplicationCommandOption.cs
index b437d0ebf..1207df282 100644
--- a/src/Discord.Net.Rest/API/Common/ApplicationCommandOption.cs
+++ b/src/Discord.Net.Rest/API/Common/ApplicationCommandOption.cs
@@ -29,6 +29,12 @@ namespace Discord.API
[JsonProperty("autocomplete")]
public Optional Autocomplete { get; set; }
+ [JsonProperty("min_value")]
+ public Optional MinValue { get; set; }
+
+ [JsonProperty("max_value")]
+ public Optional MaxValue { get; set; }
+
[JsonProperty("channel_types")]
public Optional ChannelTypes { get; set; }
@@ -48,6 +54,8 @@ namespace Discord.API
Required = cmd.IsRequired ?? Optional.Unspecified;
Default = cmd.IsDefault ?? Optional.Unspecified;
+ MinValue = cmd.MinValue ?? Optional.Unspecified;
+ MaxValue = cmd.MaxValue ?? Optional.Unspecified;
Name = cmd.Name;
Type = cmd.Type;
@@ -66,6 +74,8 @@ namespace Discord.API
Required = option.IsRequired ?? Optional.Unspecified;
Default = option.IsDefault ?? Optional.Unspecified;
+ MinValue = option.MinValue ?? Optional.Unspecified;
+ MaxValue = option.MaxValue ?? Optional.Unspecified;
ChannelTypes = option.ChannelTypes?.ToArray() ?? Optional.Unspecified;
diff --git a/src/Discord.Net.Rest/API/Common/Attachment.cs b/src/Discord.Net.Rest/API/Common/Attachment.cs
index 0d98fc3a4..7970dc9a5 100644
--- a/src/Discord.Net.Rest/API/Common/Attachment.cs
+++ b/src/Discord.Net.Rest/API/Common/Attachment.cs
@@ -8,6 +8,10 @@ namespace Discord.API
public ulong Id { get; set; }
[JsonProperty("filename")]
public string Filename { get; set; }
+ [JsonProperty("description")]
+ public Optional Description { get; set; }
+ [JsonProperty("content_type")]
+ public Optional ContentType { get; set; }
[JsonProperty("size")]
public int Size { get; set; }
[JsonProperty("url")]
diff --git a/src/Discord.Net.Rest/API/Common/DiscordError.cs b/src/Discord.Net.Rest/API/Common/DiscordError.cs
new file mode 100644
index 000000000..ac1e5e13d
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/DiscordError.cs
@@ -0,0 +1,20 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API
+{
+ [JsonConverter(typeof(Discord.Net.Converters.DiscordErrorConverter))]
+ internal class DiscordError
+ {
+ [JsonProperty("message")]
+ public string Message { get; set; }
+ [JsonProperty("code")]
+ public DiscordErrorCode Code { get; set; }
+ [JsonProperty("errors")]
+ public Optional Errors { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/Error.cs b/src/Discord.Net.Rest/API/Common/Error.cs
new file mode 100644
index 000000000..a2b1777a3
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/Error.cs
@@ -0,0 +1,12 @@
+using Newtonsoft.Json;
+
+namespace Discord.API
+{
+ internal class Error
+ {
+ [JsonProperty("code")]
+ public string Code { get; set; }
+ [JsonProperty("message")]
+ public string Message { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/Guild.cs b/src/Discord.Net.Rest/API/Common/Guild.cs
index fd8a0bdb5..d550c54a0 100644
--- a/src/Discord.Net.Rest/API/Common/Guild.cs
+++ b/src/Discord.Net.Rest/API/Common/Guild.cs
@@ -35,7 +35,7 @@ namespace Discord.API
[JsonProperty("emojis")]
public Emoji[] Emojis { get; set; }
[JsonProperty("features")]
- public string[] Features { get; set; }
+ public GuildFeatures Features { get; set; }
[JsonProperty("mfa_level")]
public MfaLevel MfaLevel { get; set; }
[JsonProperty("application_id")]
@@ -81,5 +81,7 @@ namespace Discord.API
public NsfwLevel NsfwLevel { get; set; }
[JsonProperty("stickers")]
public Sticker[] Stickers { get; set; }
+ [JsonProperty("premium_progress_bar_enabled")]
+ public Optional IsBoostProgressBarEnabled { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Common/GuildScheduledEvent.cs b/src/Discord.Net.Rest/API/Common/GuildScheduledEvent.cs
new file mode 100644
index 000000000..338c24dc9
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/GuildScheduledEvent.cs
@@ -0,0 +1,43 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API
+{
+ internal class GuildScheduledEvent
+ {
+ [JsonProperty("id")]
+ public ulong Id { get; set; }
+ [JsonProperty("guild_id")]
+ public ulong GuildId { get; set; }
+ [JsonProperty("channel_id")]
+ public Optional ChannelId { get; set; }
+ [JsonProperty("creator_id")]
+ public Optional CreatorId { get; set; }
+ [JsonProperty("name")]
+ public string Name { get; set; }
+ [JsonProperty("description")]
+ public Optional Description { get; set; }
+ [JsonProperty("scheduled_start_time")]
+ public DateTimeOffset ScheduledStartTime { get; set; }
+ [JsonProperty("scheduled_end_time")]
+ public DateTimeOffset? ScheduledEndTime { get; set; }
+ [JsonProperty("privacy_level")]
+ public GuildScheduledEventPrivacyLevel PrivacyLevel { get; set; }
+ [JsonProperty("status")]
+ public GuildScheduledEventStatus Status { get; set; }
+ [JsonProperty("entity_type")]
+ public GuildScheduledEventType EntityType { get; set; }
+ [JsonProperty("entity_id")]
+ public ulong? EntityId { get; set; }
+ [JsonProperty("entity_metadata")]
+ public GuildScheduledEventEntityMetadata EntityMetadata { get; set; }
+ [JsonProperty("creator")]
+ public Optional Creator { get; set; }
+ [JsonProperty("user_count")]
+ public Optional UserCount { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/GuildScheduledEventEntityMetadata.cs b/src/Discord.Net.Rest/API/Common/GuildScheduledEventEntityMetadata.cs
new file mode 100644
index 000000000..1db38c0ae
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/GuildScheduledEventEntityMetadata.cs
@@ -0,0 +1,15 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API
+{
+ internal class GuildScheduledEventEntityMetadata
+ {
+ [JsonProperty("location")]
+ public Optional Location { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/GuildScheduledEventUser.cs b/src/Discord.Net.Rest/API/Common/GuildScheduledEventUser.cs
new file mode 100644
index 000000000..1b0b93763
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/GuildScheduledEventUser.cs
@@ -0,0 +1,19 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API
+{
+ internal class GuildScheduledEventUser
+ {
+ [JsonProperty("user")]
+ public User User { get; set; }
+ [JsonProperty("member")]
+ public Optional Member { get; set; }
+ [JsonProperty("guild_scheduled_event_id")]
+ public ulong GuildScheduledEventId { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/InstallParams.cs b/src/Discord.Net.Rest/API/Common/InstallParams.cs
new file mode 100644
index 000000000..1fb987f30
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/InstallParams.cs
@@ -0,0 +1,17 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API
+{
+ internal class InstallParams
+ {
+ [JsonProperty("scopes")]
+ public string[] Scopes { get; set; }
+ [JsonProperty("permissions")]
+ public ulong Permission { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/PropertyErrorDescription.cs b/src/Discord.Net.Rest/API/Common/PropertyErrorDescription.cs
new file mode 100644
index 000000000..145288e5d
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Common/PropertyErrorDescription.cs
@@ -0,0 +1,17 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API
+{
+ internal class ErrorDetails
+ {
+ [JsonProperty("name")]
+ public Optional Name { get; set; }
+ [JsonProperty("errors")]
+ public Error[] Errors { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Common/Role.cs b/src/Discord.Net.Rest/API/Common/Role.cs
index 09fb99885..81f54ccc0 100644
--- a/src/Discord.Net.Rest/API/Common/Role.cs
+++ b/src/Discord.Net.Rest/API/Common/Role.cs
@@ -9,7 +9,9 @@ namespace Discord.API
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("icon")]
- public string Icon { get; set; }
+ public Optional Icon { get; set; }
+ [JsonProperty("unicode_emoji")]
+ public Optional Emoji { get; set; }
[JsonProperty("color")]
public uint Color { get; set; }
[JsonProperty("hoist")]
diff --git a/src/Discord.Net.Rest/API/Rest/CreateGuildScheduledEventParams.cs b/src/Discord.Net.Rest/API/Rest/CreateGuildScheduledEventParams.cs
new file mode 100644
index 000000000..a207d3374
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Rest/CreateGuildScheduledEventParams.cs
@@ -0,0 +1,29 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API.Rest
+{
+ internal class CreateGuildScheduledEventParams
+ {
+ [JsonProperty("channel_id")]
+ public Optional ChannelId { get; set; }
+ [JsonProperty("entity_metadata")]
+ public Optional EntityMetadata { get; set; }
+ [JsonProperty("name")]
+ public string Name { get; set; }
+ [JsonProperty("privacy_level")]
+ public GuildScheduledEventPrivacyLevel PrivacyLevel { get; set; }
+ [JsonProperty("scheduled_start_time")]
+ public DateTimeOffset StartTime { get; set; }
+ [JsonProperty("scheduled_end_time")]
+ public Optional EndTime { get; set; }
+ [JsonProperty("description")]
+ public Optional Description { get; set; }
+ [JsonProperty("entity_type")]
+ public GuildScheduledEventType Type { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs
index aea4b9538..bda0f7ff1 100644
--- a/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs
+++ b/src/Discord.Net.Rest/API/Rest/CreateWebhookMessageParams.cs
@@ -68,6 +68,8 @@ namespace Discord.API.Rest
payload["embeds"] = Embeds.Value;
if (AllowedMentions.IsSpecified)
payload["allowed_mentions"] = AllowedMentions.Value;
+ if (Components.IsSpecified)
+ payload["components"] = Components.Value;
var json = new StringBuilder();
using (var text = new StringWriter(json))
diff --git a/src/Discord.Net.Rest/API/Rest/GetEventUsersParams.cs b/src/Discord.Net.Rest/API/Rest/GetEventUsersParams.cs
new file mode 100644
index 000000000..db3ac666e
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Rest/GetEventUsersParams.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API.Rest
+{
+ internal class GetEventUsersParams
+ {
+ public Optional Limit { get; set; }
+ public Optional RelativeDirection { get; set; }
+ public Optional RelativeUserId { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs
index feda24302..c1a20cb83 100644
--- a/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs
+++ b/src/Discord.Net.Rest/API/Rest/ModifyGuildParams.cs
@@ -35,5 +35,7 @@ namespace Discord.API.Rest
public Optional SystemChannelFlags { get; set; }
[JsonProperty("preferred_locale")]
public string PreferredLocale { get; set; }
+ [JsonProperty("premium_progress_bar_enabled")]
+ public Optional IsBoostProgressBarEnabled { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Rest/ModifyGuildScheduledEventParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyGuildScheduledEventParams.cs
new file mode 100644
index 000000000..3d191a0b3
--- /dev/null
+++ b/src/Discord.Net.Rest/API/Rest/ModifyGuildScheduledEventParams.cs
@@ -0,0 +1,31 @@
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Discord.API.Rest
+{
+ internal class ModifyGuildScheduledEventParams
+ {
+ [JsonProperty("channel_id")]
+ public Optional ChannelId { get; set; }
+ [JsonProperty("entity_metadata")]
+ public Optional EntityMetadata { get; set; }
+ [JsonProperty("name")]
+ public Optional Name { get; set; }
+ [JsonProperty("privacy_level")]
+ public Optional PrivacyLevel { get; set; }
+ [JsonProperty("scheduled_start_time")]
+ public Optional StartTime { get; set; }
+ [JsonProperty("scheduled_end_time")]
+ public Optional EndTime { get; set; }
+ [JsonProperty("description")]
+ public Optional Description { get; set; }
+ [JsonProperty("entity_type")]
+ public Optional Type { get; set; }
+ [JsonProperty("status")]
+ public Optional Status { get; set; }
+ }
+}
diff --git a/src/Discord.Net.Rest/API/Rest/ModifyVoiceChannelParams.cs b/src/Discord.Net.Rest/API/Rest/ModifyVoiceChannelParams.cs
index d55cdb637..2f8cacc69 100644
--- a/src/Discord.Net.Rest/API/Rest/ModifyVoiceChannelParams.cs
+++ b/src/Discord.Net.Rest/API/Rest/ModifyVoiceChannelParams.cs
@@ -9,5 +9,7 @@ namespace Discord.API.Rest
public Optional Bitrate { get; set; }
[JsonProperty("user_limit")]
public Optional UserLimit { get; set; }
+ [JsonProperty("rtc_region")]
+ public Optional RTCRegion { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Rest/StartThreadParams.cs b/src/Discord.Net.Rest/API/Rest/StartThreadParams.cs
index 7810557eb..a13161cd4 100644
--- a/src/Discord.Net.Rest/API/Rest/StartThreadParams.cs
+++ b/src/Discord.Net.Rest/API/Rest/StartThreadParams.cs
@@ -11,6 +11,12 @@ namespace Discord.API.Rest
public ThreadArchiveDuration Duration { get; set; }
[JsonProperty("type")]
- public Optional Type { get; set; }
+ public ThreadType Type { get; set; }
+
+ [JsonProperty("invitable")]
+ public Optional Invitable { get; set; }
+
+ [JsonProperty("rate_limit_per_user")]
+ public Optional Ratelimit { get; set; }
}
}
diff --git a/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs b/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs
index 98fb0e7ca..6340c3e38 100644
--- a/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs
+++ b/src/Discord.Net.Rest/API/Rest/UploadFileParams.cs
@@ -3,6 +3,7 @@ using Discord.Net.Rest;
using Newtonsoft.Json;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Text;
namespace Discord.API.Rest
@@ -11,9 +12,8 @@ namespace Discord.API.Rest
{
private static JsonSerializer _serializer = new JsonSerializer { ContractResolver = new DiscordContractResolver() };
- public Stream File { get; }
+ public FileAttachment[] Files { get; }
- public Optional Filename { get; set; }
public Optional Content { get; set; }
public Optional Nonce { get; set; }
public Optional IsTTS { get; set; }
@@ -21,22 +21,18 @@ namespace Discord.API.Rest
public Optional AllowedMentions { get; set; }
public Optional MessageReference { get; set; }
public Optional MessageComponent { get; set; }
+ public Optional Flags { get; set; }
public Optional Stickers { get; set; }
- public bool IsSpoiler { get; set; } = false;
- public UploadFileParams(Stream file)
+ public UploadFileParams(params Discord.FileAttachment[] attachments)
{
- File = file;
+ Files = attachments;
}
public IReadOnlyDictionary ToDictionary()
{
var d = new Dictionary();
- var filename = Filename.GetValueOrDefault("unknown.dat");
- if (IsSpoiler && !filename.StartsWith(AttachmentExtensions.SpoilerPrefix))
- filename = filename.Insert(0, AttachmentExtensions.SpoilerPrefix);
- d["file"] = new MultipartFile(File, filename);
-
+
var payload = new Dictionary();
if (Content.IsSpecified)
payload["content"] = Content.Value;
@@ -50,12 +46,33 @@ namespace Discord.API.Rest
payload["allowed_mentions"] = AllowedMentions.Value;
if (MessageComponent.IsSpecified)
payload["components"] = MessageComponent.Value;
- if (IsSpoiler)
- payload["hasSpoiler"] = IsSpoiler.ToString();
if (MessageReference.IsSpecified)
payload["message_reference"] = MessageReference.Value;
if (Stickers.IsSpecified)
payload["sticker_ids"] = Stickers.Value;
+ if (Flags.IsSpecified)
+ payload["flags"] = Flags;
+
+ List