From 699554ad11fe947375dfcf83f33feb9e0f333b86 Mon Sep 17 00:00:00 2001 From: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com> Date: Sun, 19 Nov 2023 00:15:20 +0300 Subject: [PATCH] [Features] Automod member profile moderation, new application fields, use clyde ai & guild invenory settings (#2791) * guild inventory settings * `UseClydeAI` (1L << 47) permission * automod member profile moderation * Dnet: The Enums update (new application fields) * ah yeah, `IApplication` * some oversights * y did I change this * oh bruh nvm * `CreateGuildExpressions` permission --------- Co-authored-by: Quin Lynch <49576606+quinchs@users.noreply.github.com> --- .../ApplicationDiscoverabilityState.cs | 34 ++++ .../ApplicationExplicitContentFilterLevel.cs | 14 ++ .../ApplicationInteractionsVersion.cs | 14 ++ ...ApplicationMonetizationEligibilityFlags.cs | 80 +++++++++ .../ApplicationMonetizationState.cs | 19 +++ .../Applications/ApplicationRpcState.cs | 29 ++++ .../Applications/ApplicationStoreState.cs | 29 ++++ .../ApplicationVerificationState.cs | 24 +++ .../Applications/DiscoveryEligibilityFlags.cs | 100 ++++++++++++ .../Entities/Applications/IApplication.cs | 78 +++++++-- .../AutoModeration/AutoModActionType.cs | 40 +++-- .../Guilds/AutoModeration/AutoModEventType.cs | 26 ++- .../AutoModeration/AutoModTriggerType.cs | 5 + .../Entities/Guilds/GuildInventorySettings.cs | 14 ++ .../Entities/Guilds/IGuild.cs | 5 + .../Entities/Permissions/ChannelPermission.cs | 5 + .../Permissions/ChannelPermissions.cs | 18 ++- .../Entities/Permissions/GuildPermission.cs | 10 ++ .../Entities/Permissions/GuildPermissions.cs | 18 ++- .../API/Common/Application.cs | 152 +++++++++++------- src/Discord.Net.Rest/API/Common/Guild.cs | 3 + .../API/Common/GuildInventorySettings.cs | 9 ++ .../Entities/Guilds/GuildHelper.cs | 16 +- .../Entities/Guilds/RestGuild.cs | 5 + .../Entities/RestApplication.cs | 52 ++++++ .../Entities/Guilds/SocketGuild.cs | 6 + .../ChannelPermissionsTests.cs | 2 + .../GuildPermissionsTests.cs | 4 + 28 files changed, 692 insertions(+), 119 deletions(-) create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationDiscoverabilityState.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationExplicitContentFilterLevel.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationInteractionsVersion.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationEligibilityFlags.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationState.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationRpcState.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationStoreState.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/ApplicationVerificationState.cs create mode 100644 src/Discord.Net.Core/Entities/Applications/DiscoveryEligibilityFlags.cs create mode 100644 src/Discord.Net.Core/Entities/Guilds/GuildInventorySettings.cs create mode 100644 src/Discord.Net.Rest/API/Common/GuildInventorySettings.cs diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationDiscoverabilityState.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationDiscoverabilityState.cs new file mode 100644 index 0000000000..5152c02754 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationDiscoverabilityState.cs @@ -0,0 +1,34 @@ +namespace Discord; + +public enum ApplicationDiscoverabilityState +{ + /// + /// Application has no discoverability state. + /// + None = 0, + + /// + /// Application is ineligible for the application directory. + /// + Ineligible = 1, + + /// + /// Application is not listed in the application directory. + /// + NotDiscoverable = 2, + + /// + /// Application is listed in the application directory. + /// + Discoverable = 3, + + /// + /// Application is featureable in the application directory. + /// + Featureable = 4, + + /// + /// Application has been blocked from appearing in the application directory. + /// + Blocked = 5, +} diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationExplicitContentFilterLevel.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationExplicitContentFilterLevel.cs new file mode 100644 index 0000000000..45977e1874 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationExplicitContentFilterLevel.cs @@ -0,0 +1,14 @@ +namespace Discord; + +public enum ApplicationExplicitContentFilterLevel +{ + /// + /// Media content will not be filtered. + /// + Disabled = 0, + + /// + /// Media content will be filtered. + /// + Enabled = 1, +} diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationInteractionsVersion.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationInteractionsVersion.cs new file mode 100644 index 0000000000..18c219d2ae --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationInteractionsVersion.cs @@ -0,0 +1,14 @@ +namespace Discord; + +public enum ApplicationInteractionsVersion +{ + /// + /// Only Interaction Create events are sent as documented (default). + /// + Version1 = 1, + + /// + /// A selection of chosen events are sent. + /// + Version2 = 2, +} diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationEligibilityFlags.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationEligibilityFlags.cs new file mode 100644 index 0000000000..1ccfb8f84f --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationEligibilityFlags.cs @@ -0,0 +1,80 @@ +using System; + +namespace Discord; + +/// +/// Gets the monetization eligibility flags for the application combined as a bitfield. +/// +[Flags] +public enum ApplicationMonetizationEligibilityFlags +{ + /// + /// The application has no monetization eligibility flags set. + /// + None = 0, + + /// + /// Application is verified. + /// + Verified = 1 << 0, + + /// + /// Application is owned by a team. + /// + HasTeam = 1 << 1, + + /// + /// Application has the message content intent approved or uses application commands. + /// + ApprovedCommands = 1 << 2, + + /// + /// Application has terms of service set. + /// + TermsOfService = 1 << 3, + + /// + /// Application has a privacy policy set. + /// + PrivacyPolicy = 1 << 4, + + /// + /// Application's name is safe for work. + /// + SafeName = 1 << 5, + + /// + /// Application's description is safe for work. + /// + SafeDescription = 1 << 6, + + /// + /// Application's role connections metadata is safe for work. + /// + SafeRoleConnections = 1 << 7, + + /// + /// Application is not quarantined. + /// + NotQuarantined = 1 << 9, + + /// + /// Application's team members all have verified emails. + /// + TeamMembersEmailVerified = 1 << 15, + + /// + /// Application's team members all have MFA enabled. + /// + TeamMembersMfaEnabled = 1 << 16, + + /// + /// Application has no issues blocking monetization. + /// + NoBlockingIssues = 1 << 17, + + /// + /// Application's team has a valid payout status. + /// + ValidPayoutStatus = 1 << 18, +} diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationState.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationState.cs new file mode 100644 index 0000000000..05670a6210 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationMonetizationState.cs @@ -0,0 +1,19 @@ +namespace Discord; + +public enum ApplicationMonetizationState +{ + /// + /// Application has no monetization set up. + /// + None = 1, + + /// + /// Application has monetization set up. + /// + Enabled = 2, + + /// + /// Application has been blocked from monetizing. + /// + Blocked = 3, +} diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationRpcState.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationRpcState.cs new file mode 100644 index 0000000000..3660fb11ad --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationRpcState.cs @@ -0,0 +1,29 @@ +namespace Discord; + +public enum ApplicationRpcState +{ + /// + /// Application does not have access to RPC. + /// + Disabled = 0, + + /// + /// Application has not yet been applied for RPC access. + /// + Unsubmitted = 1, + + /// + /// Application has submitted a RPC access request. + /// + Submitted = 2, + + /// + /// Application has been approved for RPC access. + /// + Approved = 3, + + /// + /// Application has been rejected from RPC access. + /// + Rejected = 4, +} diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationStoreState.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationStoreState.cs new file mode 100644 index 0000000000..db5c4db3cb --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationStoreState.cs @@ -0,0 +1,29 @@ +namespace Discord; + +public enum ApplicationStoreState +{ + /// + /// Application does not have a commerce license. + /// + None = 1, + + /// + /// Application has a commerce license but has not yet submitted a store approval request. + /// + Paid = 2, + + /// + /// Application has submitted a store approval request. + /// + Submitted = 3, + + /// + /// Application has been approved for the store. + /// + Approved = 4, + + /// + /// Application has been rejected from the store. + /// + Rejected = 5, +} diff --git a/src/Discord.Net.Core/Entities/Applications/ApplicationVerificationState.cs b/src/Discord.Net.Core/Entities/Applications/ApplicationVerificationState.cs new file mode 100644 index 0000000000..6a52c31ec1 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/ApplicationVerificationState.cs @@ -0,0 +1,24 @@ +namespace Discord; + +public enum ApplicationVerificationState +{ + /// + /// Application is ineligible for verification. + /// + Ineligible = 1, + + /// + /// Application has not yet been applied for verification. + /// + Unsubmitted = 2, + + /// + /// Application has submitted a verification request. + /// + Submitted = 3, + + /// + /// Application has been verified. + /// + Succeeded = 4, +} diff --git a/src/Discord.Net.Core/Entities/Applications/DiscoveryEligibilityFlags.cs b/src/Discord.Net.Core/Entities/Applications/DiscoveryEligibilityFlags.cs new file mode 100644 index 0000000000..c426be440a --- /dev/null +++ b/src/Discord.Net.Core/Entities/Applications/DiscoveryEligibilityFlags.cs @@ -0,0 +1,100 @@ +using System; + +namespace Discord; + +/// +/// Gets the discovery eligibility flags for the application combined as a bitfield. +/// +[Flags] +public enum DiscoveryEligibilityFlags +{ + /// + /// The application has no eligibility flags. + /// + None = 0, + + /// + /// Application is verified. + /// + Verified = 1 << 0, + + /// + /// Application has at least one tag set. + /// + Tag = 1 << 1, + + /// + /// Application has a description. + /// + Description = 1 << 2, + + /// + /// Application has terms of service set. + /// + TermsOfService = 1 << 3, + + /// + /// Application has a privacy policy set. + /// + PrivacyPolicy = 1 << 4, + + /// + /// Application has a custom install URL or install parameters. + /// + InstallParams = 1 << 5, + + /// + /// Application's name is safe for work. + /// + SafeName = 1 << 6, + + /// + /// Application's description is safe for work. + /// + SafeDescription = 1 << 7, + + /// + /// Application has the message content intent approved or uses application commands. + /// + ApprovedCommands = 1 << 8, + + /// + /// Application has a support guild set. + /// + SupportGuild = 1 << 9, + + /// + /// Application's commands are safe for work. + /// + SafeCommands = 1 << 10, + + /// + /// Application's owner has MFA enabled. + /// + MfaEnabled = 1 << 11, + + /// + /// Application's directory long description is safe for work. + /// + SafeDirectoryOverview = 1 << 12, + + /// + /// Application has at least one supported locale set. + /// + SupportedLocales = 1 << 13, + + /// + /// Application's directory short description is safe for work. + /// + SafeShortDescription = 1 << 14, + + /// + /// Application's role connections metadata is safe for work. + /// + SafeRoleConnections = 1 << 15, + + /// + /// Application is eligible for discovery. + /// + Eligible = 1 << 16, +} diff --git a/src/Discord.Net.Core/Entities/Applications/IApplication.cs b/src/Discord.Net.Core/Entities/Applications/IApplication.cs index c9a31f9c91..f936ad32d5 100644 --- a/src/Discord.Net.Core/Entities/Applications/IApplication.cs +++ b/src/Discord.Net.Core/Entities/Applications/IApplication.cs @@ -54,45 +54,105 @@ public interface IApplication : ISnowflakeEntity /// /// Gets the url of the app's terms of service. /// - public string TermsOfService { get; } + string TermsOfService { get; } /// /// Gets the the url of the app's privacy policy. /// - public string PrivacyPolicy { get; } + string PrivacyPolicy { get; } /// /// Gets application's default custom authorization url. if disabled. /// - public string CustomInstallUrl { get; } + string CustomInstallUrl { get; } /// /// Gets the application's role connection verification entry point. if not set. /// - public string RoleConnectionsVerificationUrl { get; } + string RoleConnectionsVerificationUrl { get; } /// /// Gets the hex encoded key for verification in interactions. /// - public string VerifyKey { get; } + string VerifyKey { get; } /// /// Gets the partial guild object of the application's developer's support server. if not set. /// - public PartialGuild Guild { get; } + PartialGuild Guild { get; } /// /// Gets the redirect uris configured for the application. /// - public IReadOnlyCollection RedirectUris { get;} + IReadOnlyCollection RedirectUris { get;} /// /// Gets application's interactions endpoint url. if not set. /// - public string InteractionsEndpointUrl { get; } + string InteractionsEndpointUrl { get; } /// /// Gets the approximate count of the guild the application was added to. if not returned. /// - public int? ApproximateGuildCount { get; } + int? ApproximateGuildCount { get; } + + /// + /// Gets the application's discoverability state. + /// + ApplicationDiscoverabilityState DiscoverabilityState { get; } + + /// + /// Gets the application's discovery eligibility flags. + /// + DiscoveryEligibilityFlags DiscoveryEligibilityFlags { get; } + + /// + /// Gets the application's explicit content filter level for uploaded media content used in application commands. + /// + ApplicationExplicitContentFilterLevel ExplicitContentFilterLevel { get; } + + /// + /// Gets whether the bot is allowed to hook into the application's game directly. + /// + bool IsHook { get; } + + /// + /// Gets event types to be sent to the interaction endpoint. + /// + IReadOnlyCollection InteractionEventTypes { get; } + + /// + /// Gets the interactions version application uses. + /// + ApplicationInteractionsVersion InteractionsVersion { get; } + + /// + /// Whether the application has premium subscriptions. + /// + bool IsMonetized { get; } + + /// + /// Gets the application's monetization eligibility flags. + /// + ApplicationMonetizationEligibilityFlags MonetizationEligibilityFlags { get; } + + /// + /// Gets the application's monetization state. + /// + ApplicationMonetizationState MonetizationState { get; } + + /// + /// Gets the application's rpc state. + /// + ApplicationRpcState RpcState { get; } + + /// + /// Gets the application's store state. + /// + ApplicationStoreState StoreState { get; } + + /// + /// Gets the application's verification state. + /// + ApplicationVerificationState VerificationState { get; } } } diff --git a/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModActionType.cs b/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModActionType.cs index 29e95d9188..cf84e72ea9 100644 --- a/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModActionType.cs +++ b/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModActionType.cs @@ -1,26 +1,24 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Discord; -namespace Discord +public enum AutoModActionType { - public enum AutoModActionType - { - /// - /// Blocks the content of a message according to the rule. - /// - BlockMessage = 1, + /// + /// Blocks the content of a message according to the rule. + /// + BlockMessage = 1, - /// - /// Logs user content to a specified channel. - /// - SendAlertMessage = 2, + /// + /// Logs user content to a specified channel. + /// + SendAlertMessage = 2, - /// - /// Timeout user for a specified duration. - /// - Timeout = 3, - } + /// + /// Timeout user for a specified duration. + /// + Timeout = 3, + + /// + /// Prevents a member from using text, voice, or other interactions. + /// + BlockMemberInteraction = 4 } diff --git a/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModEventType.cs b/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModEventType.cs index 6ed93d53b3..436f90e952 100644 --- a/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModEventType.cs +++ b/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModEventType.cs @@ -1,19 +1,17 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +namespace Discord; -namespace Discord +/// +/// An enum indecating in what event context a rule should be checked. +/// +public enum AutoModEventType { /// - /// An enum indecating in what event context a rule should be checked. + /// When a member sends or edits a message in the guild. /// - public enum AutoModEventType - { - /// - /// When a member sends or edits a message in the guild. - /// - MessageSend = 1 - } + MessageSend = 1, + + /// + /// When a member edits their profile. + /// + MemberUpdate = 2 } diff --git a/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModTriggerType.cs b/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModTriggerType.cs index 0c3eb2322e..fb25babfa5 100644 --- a/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModTriggerType.cs +++ b/src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModTriggerType.cs @@ -35,5 +35,10 @@ public enum AutoModTriggerType /// Check if content contains more unique mentions than allowed. /// MentionSpam = 5, + + /// + /// Check if member profile contains words from a user defined list of keywords. + /// + MemberProfile = 6 } } diff --git a/src/Discord.Net.Core/Entities/Guilds/GuildInventorySettings.cs b/src/Discord.Net.Core/Entities/Guilds/GuildInventorySettings.cs new file mode 100644 index 0000000000..f54e27e4f1 --- /dev/null +++ b/src/Discord.Net.Core/Entities/Guilds/GuildInventorySettings.cs @@ -0,0 +1,14 @@ +namespace Discord; + +public struct GuildInventorySettings +{ + /// + /// Gets whether everyone can collect the pack to use emojis across servers. + /// + public bool IsEmojiPackCollectible { get; } + + internal GuildInventorySettings(bool isEmojiPackCollectible) + { + IsEmojiPackCollectible = isEmojiPackCollectible; + } +} diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index 6e62e59cd2..13354cffec 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -376,6 +376,11 @@ public interface IGuild : IDeletable, ISnowflakeEntity /// ulong MaxUploadLimit { get; } + /// + /// Get the inventory settings on the guild. if not available in the guild. + /// + GuildInventorySettings? InventorySettings { get; } + /// /// Gets the incidents data for this guild. /// diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs index a0ee23fa17..72b4917021 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermission.cs @@ -183,6 +183,11 @@ public enum ChannelPermission : ulong /// SendVoiceMessages = 1L << 46, + /// + /// Allows members to interact with the Clyde AI bot. + /// + UseClydeAI = 1L << 47, + /// /// Allows setting voice channel status. /// diff --git a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs index e317401853..4b527e348e 100644 --- a/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/ChannelPermissions.cs @@ -18,17 +18,17 @@ public struct ChannelPermissions /// /// Gets a that grants all permissions for text channels. /// - public static readonly ChannelPermissions Text = new(0b10001_001111_110010_110011_111101_111111_111101_010001); + public static readonly ChannelPermissions Text = new(0b110001_001111_110010_110011_111101_111111_111101_010001); /// /// Gets a that grants all permissions for voice channels. /// - public static readonly ChannelPermissions Voice = new(0b1_010001_001010_001010_110011_111101_111111_111101_010001); + public static readonly ChannelPermissions Voice = new(0b1_110001_001010_001010_110011_111101_111111_111101_010001); /// /// Gets a that grants all permissions for stage channels. /// - public static readonly ChannelPermissions Stage = new(0b10000_000010_001110_010001_010101_111111_111001_010001); + public static readonly ChannelPermissions Stage = new(0b110000_000010_001110_010001_010101_111111_111001_010001); /// /// Gets a that grants all permissions for category channels. @@ -48,7 +48,7 @@ public struct ChannelPermissions /// /// Gets a that grants all permissions for forum channels. /// - public static readonly ChannelPermissions Forum = new(0b01_001110_010010_110011_111101_111111_111101_010001); + public static readonly ChannelPermissions Forum = new(0b000001_001110_010010_110011_111101_111111_111101_010001); /// /// Gets a that grants all permissions for media channels. @@ -148,10 +148,11 @@ public static ChannelPermissions All(IChannel channel) public bool CreateEvents => Permissions.GetValue(RawValue, ChannelPermission.CreateEvents); /// If , a user can send voice messages in this channel. public bool SendVoiceMessages => Permissions.GetValue(RawValue, ChannelPermission.SendVoiceMessages); + /// If , a user can use the Clyde AI bot in this channel. + public bool UseClydeAI => Permissions.GetValue(RawValue, ChannelPermission.UseClydeAI); /// If , a user can set the status of a voice channel. public bool SetVoiceChannelStatus => Permissions.GetValue(RawValue, GuildPermission.SetVoiceChannelStatus); - /// Creates a new with the provided packed value. public ChannelPermissions(ulong rawValue) { RawValue = rawValue; } @@ -189,6 +190,7 @@ private ChannelPermissions(ulong initialValue, bool? useSoundboard = null, bool? createEvents = null, bool? sendVoiceMessages = null, + bool? useClydeAI = null, bool? setVoiceChannelStatus = null) { ulong value = initialValue; @@ -226,6 +228,7 @@ private ChannelPermissions(ulong initialValue, Permissions.SetValue(ref value, useSoundboard, ChannelPermission.UseSoundboard); Permissions.SetValue(ref value, createEvents, ChannelPermission.CreateEvents); Permissions.SetValue(ref value, sendVoiceMessages, ChannelPermission.SendVoiceMessages); + Permissions.SetValue(ref value, useClydeAI, ChannelPermission.UseClydeAI); Permissions.SetValue(ref value, setVoiceChannelStatus, ChannelPermission.SetVoiceChannelStatus); RawValue = value; @@ -266,12 +269,13 @@ public ChannelPermissions( bool useSoundboard = false, bool createEvents = false, bool sendVoiceMessages = false, + bool useClydeAI = false, bool setVoiceChannelStatus = false) : this(0, createInstantInvite, manageChannel, addReactions, viewChannel, sendMessages, sendTTSMessages, manageMessages, embedLinks, attachFiles, readMessageHistory, mentionEveryone, useExternalEmojis, connect, speak, muteMembers, deafenMembers, moveMembers, useVoiceActivation, prioritySpeaker, stream, manageRoles, manageWebhooks, useApplicationCommands, requestToSpeak, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads, - startEmbeddedActivities, useSoundboard, createEvents, sendVoiceMessages, setVoiceChannelStatus) + startEmbeddedActivities, useSoundboard, createEvents, sendVoiceMessages, useClydeAI, setVoiceChannelStatus) { } /// Creates a new from this one, changing the provided non-null permissions. @@ -309,6 +313,7 @@ public ChannelPermissions Modify( bool? useSoundboard = null, bool? createEvents = null, bool? sendVoiceMessages = null, + bool? useClydeAI = null, bool? setVoiceChannelStatus = null) => new ChannelPermissions(RawValue, createInstantInvite, @@ -344,6 +349,7 @@ public ChannelPermissions Modify( useSoundboard, createEvents, sendVoiceMessages, + useClydeAI, setVoiceChannelStatus); public bool Has(ChannelPermission permission) => Permissions.GetValue(RawValue, permission); diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs index 0646ee709e..978161d755 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermission.cs @@ -263,11 +263,21 @@ public enum GuildPermission : ulong /// UseSoundboard = 1L << 42, + /// + /// Allows for creating emojis, stickers, and soundboard sounds, and editing and deleting those created by the current user. + /// + CreateGuildExpressions = 1L << 43, + /// /// Allows sending voice messages. /// SendVoiceMessages = 1L << 46, + /// + /// Allows members to interact with the Clyde AI bot. + /// + UseClydeAI = 1L << 47, + /// /// Allows setting voice channel status. /// diff --git a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs index 3b9b84e31d..90e41dd205 100644 --- a/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs +++ b/src/Discord.Net.Core/Entities/Permissions/GuildPermissions.cs @@ -108,8 +108,12 @@ public struct GuildPermissions public bool UseSoundboard => Permissions.GetValue(RawValue, GuildPermission.UseSoundboard); /// If , a user can view monetization analytics in this guild. public bool ViewMonetizationAnalytics => Permissions.GetValue(RawValue, GuildPermission.ViewMonetizationAnalytics); - /// If , a user can send voice messages in this channel. + /// If , a user can send voice messages in this guild. public bool SendVoiceMessages => Permissions.GetValue(RawValue, GuildPermission.SendVoiceMessages); + /// If , a user can use the Clyde AI bot in this guild. + public bool UseClydeAI => Permissions.GetValue(RawValue, GuildPermission.UseClydeAI); + /// If , a user can create guild expressions in this guild. + public bool CreateGuildExpressions => Permissions.GetValue(RawValue, GuildPermission.CreateGuildExpressions); /// If , a user can set the status of a voice channel. public bool SetVoiceChannelStatus => Permissions.GetValue(RawValue, GuildPermission.SetVoiceChannelStatus); @@ -164,6 +168,8 @@ private GuildPermissions(ulong initialValue, bool? useSoundboard = null, bool? viewMonetizationAnalytics = null, bool? sendVoiceMessages = null, + bool? useClydeAI = null, + bool? createGuildExpressions = null, bool? setVoiceChannelStatus = null) { ulong value = initialValue; @@ -212,6 +218,8 @@ private GuildPermissions(ulong initialValue, Permissions.SetValue(ref value, useSoundboard, GuildPermission.UseSoundboard); Permissions.SetValue(ref value, viewMonetizationAnalytics, GuildPermission.ViewMonetizationAnalytics); Permissions.SetValue(ref value, sendVoiceMessages, GuildPermission.SendVoiceMessages); + Permissions.SetValue(ref value, useClydeAI, GuildPermission.UseClydeAI); + Permissions.SetValue(ref value, createGuildExpressions, GuildPermission.CreateGuildExpressions); Permissions.SetValue(ref value, setVoiceChannelStatus, GuildPermission.SetVoiceChannelStatus); RawValue = value; @@ -263,6 +271,8 @@ public GuildPermissions( bool useSoundboard = false, bool viewMonetizationAnalytics = false, bool sendVoiceMessages = false, + bool useClydeAI = false, + bool createGuildExpressions = false, bool setVoiceChannelStatus = false) : this(0, createInstantInvite: createInstantInvite, @@ -309,6 +319,8 @@ public GuildPermissions( useSoundboard: useSoundboard, viewMonetizationAnalytics: viewMonetizationAnalytics, sendVoiceMessages: sendVoiceMessages, + useClydeAI: useClydeAI, + createGuildExpressions: createGuildExpressions, setVoiceChannelStatus: setVoiceChannelStatus) { } @@ -358,13 +370,15 @@ public GuildPermissions Modify( bool? useSoundboard = null, bool? viewMonetizationAnalytics = null, bool? sendVoiceMessages = null, + bool? useClydeAI = null, + bool? createGuildExpressions = null, bool? setVoiceChannelStatus = null) => new GuildPermissions(RawValue, createInstantInvite, kickMembers, banMembers, administrator, manageChannels, manageGuild, addReactions, 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, manageEvents, manageThreads, createPublicThreads, createPrivateThreads, useExternalStickers, sendMessagesInThreads, - startEmbeddedActivities, moderateMembers, useSoundboard, viewMonetizationAnalytics, sendVoiceMessages, setVoiceChannelStatus); + startEmbeddedActivities, moderateMembers, useSoundboard, viewMonetizationAnalytics, sendVoiceMessages, useClydeAI, createGuildExpressions, setVoiceChannelStatus); /// /// Returns a value that indicates if a specific is enabled diff --git a/src/Discord.Net.Rest/API/Common/Application.cs b/src/Discord.Net.Rest/API/Common/Application.cs index 8a297cfa8a..d446b4440f 100644 --- a/src/Discord.Net.Rest/API/Common/Application.cs +++ b/src/Discord.Net.Rest/API/Common/Application.cs @@ -1,63 +1,97 @@ using Newtonsoft.Json; -namespace Discord.API +namespace Discord.API; + +internal class Application { - internal class Application - { - [JsonProperty("description")] - public string Description { get; set; } - [JsonProperty("rpc_origins")] - public Optional RPCOrigins { get; set; } - [JsonProperty("name")] - public string Name { get; set; } - [JsonProperty("id")] - public ulong Id { get; set; } - [JsonProperty("icon")] - public string Icon { get; set; } - - [JsonProperty("bot_public")] - public Optional IsBotPublic { get; set; } - [JsonProperty("bot_require_code_grant")] - public Optional 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; } - [JsonProperty("owner")] - public Optional Owner { get; set; } - [JsonProperty("tags")] - public Optional Tags { get; set; } - - [JsonProperty("verify_key")] - public string VerifyKey { get; set; } - - [JsonProperty("approximate_guild_count")] - public Optional ApproximateGuildCount { get; set; } - - [JsonProperty("guild")] - public Optional PartialGuild { get; set; } - - /// Urls - [JsonProperty("terms_of_service_url")] - public string TermsOfService { get; set; } - - [JsonProperty("privacy_policy_url")] - public string PrivacyPolicy { get; set; } - - [JsonProperty("custom_install_url")] - public Optional CustomInstallUrl { get; set; } - - [JsonProperty("role_connections_verification_url")] - public Optional RoleConnectionsUrl { get; set; } - - [JsonProperty("interactions_endpoint_url")] - public Optional InteractionsEndpointUrl { get; set; } - - [JsonProperty("redirect_uris")] - public Optional RedirectUris { get; set; } - - } + [JsonProperty("description")] + public string Description { get; set; } + [JsonProperty("rpc_origins")] + public Optional RPCOrigins { get; set; } + [JsonProperty("name")] + public string Name { get; set; } + [JsonProperty("id")] + public ulong Id { get; set; } + [JsonProperty("icon")] + public string Icon { get; set; } + + [JsonProperty("bot_public")] + public Optional IsBotPublic { get; set; } + [JsonProperty("bot_require_code_grant")] + public Optional 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; } + [JsonProperty("owner")] + public Optional Owner { get; set; } + [JsonProperty("tags")] + public Optional Tags { get; set; } + + [JsonProperty("verify_key")] + public string VerifyKey { get; set; } + + [JsonProperty("approximate_guild_count")] + public Optional ApproximateGuildCount { get; set; } + + [JsonProperty("guild")] + public Optional PartialGuild { get; set; } + + /// Urls + [JsonProperty("terms_of_service_url")] + public string TermsOfService { get; set; } + + [JsonProperty("privacy_policy_url")] + public string PrivacyPolicy { get; set; } + + [JsonProperty("custom_install_url")] + public Optional CustomInstallUrl { get; set; } + + [JsonProperty("role_connections_verification_url")] + public Optional RoleConnectionsUrl { get; set; } + + [JsonProperty("interactions_endpoint_url")] + public Optional InteractionsEndpointUrl { get; set; } + + [JsonProperty("redirect_uris")] + public Optional RedirectUris { get; set; } + + [JsonProperty("discoverability_state")] + public Optional DiscoverabilityState { get; set; } + + [JsonProperty("discovery_eligibility_flags")] + public Optional DiscoveryEligibilityFlags { get; set; } + + [JsonProperty("explicit_content_filter")] + public Optional ExplicitContentFilter { get; set; } + + [JsonProperty("hook")] + public bool IsHook { get; set; } + + [JsonProperty("interactions_event_types")] + public Optional InteractionsEventTypes { get; set; } + + [JsonProperty("interactions_version")] + public Optional InteractionsVersion { get; set; } + + [JsonProperty("is_monetized")] + public bool IsMonetized { get; set; } + + [JsonProperty("monetization_eligibility_flags")] + public Optional MonetizationEligibilityFlags { get; set; } + + [JsonProperty("monetization_state")] + public Optional MonetizationState { get; set; } + + [JsonProperty("rpc_application_state")] + public Optional RpcState { get; set; } + + [JsonProperty("store_application_state")] + public Optional StoreState { get; set; } + + [JsonProperty("verification_state")] + public Optional VerificationState { get; set; } } diff --git a/src/Discord.Net.Rest/API/Common/Guild.cs b/src/Discord.Net.Rest/API/Common/Guild.cs index 67a0c9b250..21912f111e 100644 --- a/src/Discord.Net.Rest/API/Common/Guild.cs +++ b/src/Discord.Net.Rest/API/Common/Guild.cs @@ -92,6 +92,9 @@ internal class Guild [JsonProperty("max_stage_video_channel_users")] public Optional MaxStageVideoChannelUsers { get; set; } + [JsonProperty("inventory_settings")] + public Optional InventorySettings { get; set; } + [JsonProperty("incidents_data")] public GuildIncidentsData IncidentsData { get; set; } } diff --git a/src/Discord.Net.Rest/API/Common/GuildInventorySettings.cs b/src/Discord.Net.Rest/API/Common/GuildInventorySettings.cs new file mode 100644 index 0000000000..c85faf010b --- /dev/null +++ b/src/Discord.Net.Rest/API/Common/GuildInventorySettings.cs @@ -0,0 +1,9 @@ +using Newtonsoft.Json; + +namespace Discord.API; + +internal class GuildInventorySettings +{ + [JsonProperty("is_emoji_pack_collectible")] + public Optional IsEmojiPackCollectible { get; set; } +} diff --git a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs index 65774f057c..87222879cd 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/GuildHelper.cs @@ -457,7 +457,7 @@ public static async Task CreateMediaChannelAsync(IGuild guild, AvailableTags = props.Tags.GetValueOrDefault(Array.Empty()).Select( x => new ModifyForumTagParams { - Id = x.Id, + Id = x.Id ?? Optional.Unspecified, Name = x.Name, EmojiId = x.Emoji is Emote emote ? emote.Id @@ -1197,8 +1197,8 @@ public static async Task CreateAutoModRuleAsync(IGuild guild if (args.RegexPatterns.IsSpecified) { - if (args.TriggerType.Value is not AutoModTriggerType.Keyword) - throw new ArgumentException(message: $"Regex patterns can only be used with 'Keyword' trigger type.", paramName: nameof(args.RegexPatterns)); + if (args.TriggerType.Value is not AutoModTriggerType.Keyword and not AutoModTriggerType.MemberProfile) + throw new ArgumentException(message: $"Regex patterns can only be used with 'Keyword' or 'MemberProfile' trigger type.", paramName: nameof(args.RegexPatterns)); Preconditions.AtMost(args.RegexPatterns.Value.Length, AutoModRuleProperties.MaxRegexPatternCount, nameof(args.RegexPatterns), $"Regex pattern count must be less than or equal to {AutoModRuleProperties.MaxRegexPatternCount}."); @@ -1208,8 +1208,8 @@ public static async Task CreateAutoModRuleAsync(IGuild guild if (args.KeywordFilter.IsSpecified) { - if (args.TriggerType.Value != AutoModTriggerType.Keyword) - throw new ArgumentException(message: $"Keyword filter can only be used with 'Keyword' trigger type.", paramName: nameof(args.KeywordFilter)); + if (args.TriggerType.Value is not AutoModTriggerType.Keyword and not AutoModTriggerType.MemberProfile) + throw new ArgumentException(message: $"Keyword filter can only be used with 'Keyword' or 'MemberProfile' trigger type.", paramName: nameof(args.KeywordFilter)); Preconditions.AtMost(args.KeywordFilter.Value.Length, AutoModRuleProperties.MaxKeywordCount, nameof(args.KeywordFilter), $"Keyword count must be less than or equal to {AutoModRuleProperties.MaxKeywordCount}"); @@ -1222,8 +1222,8 @@ public static async Task CreateAutoModRuleAsync(IGuild guild if (args.AllowList.IsSpecified) { - if (args.TriggerType.Value is not AutoModTriggerType.Keyword or AutoModTriggerType.KeywordPreset) - throw new ArgumentException(message: $"Allow list can only be used with 'Keyword' or 'KeywordPreset' trigger type.", paramName: nameof(args.AllowList)); + if (args.TriggerType.Value is not AutoModTriggerType.Keyword and not AutoModTriggerType.KeywordPreset and not AutoModTriggerType.MemberProfile) + throw new ArgumentException(message: $"Allow list can only be used with 'Keyword', 'KeywordPreset' or 'MemberProfile' trigger type.", paramName: nameof(args.AllowList)); if (args.TriggerType.Value is AutoModTriggerType.Keyword) Preconditions.AtMost(args.AllowList.Value.Length, AutoModRuleProperties.MaxAllowListCountKeyword, nameof(args.AllowList), $"Allow list entry count must be less than or equal to {AutoModRuleProperties.MaxAllowListCountKeyword}."); @@ -1258,7 +1258,7 @@ public static async Task CreateAutoModRuleAsync(IGuild guild if (args.ExemptChannels.IsSpecified) Preconditions.AtMost(args.ExemptChannels.Value.Length, AutoModRuleProperties.MaxExemptChannels, nameof(args.ExemptChannels), $"Exempt channels count must be less than or equal to {AutoModRuleProperties.MaxExemptChannels}."); - if (!args.Actions.IsSpecified && args.Actions.Value.Length == 0) + if (!args.Actions.IsSpecified || args.Actions.Value.Length == 0) { throw new ArgumentException(message: $"At least 1 action must be set for an auto moderation rule.", paramName: nameof(args.Actions)); } diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 3981814359..486b83c943 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -118,6 +118,9 @@ public ulong MaxUploadLimit /// public GuildIncidentsData IncidentsData { get; private set; } + /// + public GuildInventorySettings? InventorySettings { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); @@ -204,6 +207,8 @@ internal void Update(Model model) ApproximatePresenceCount = model.ApproximatePresenceCount.Value; if (model.IsBoostProgressBarEnabled.IsSpecified) IsBoostProgressBarEnabled = model.IsBoostProgressBarEnabled.Value; + if (model.InventorySettings.IsSpecified) + InventorySettings = model.InventorySettings.Value is null ? null : new (model.InventorySettings.Value.IsEmojiPackCollectible.GetValueOrDefault(false)); if (model.Emojis != null) { diff --git a/src/Discord.Net.Rest/Entities/RestApplication.cs b/src/Discord.Net.Rest/Entities/RestApplication.cs index b35322f992..6b253cf62d 100644 --- a/src/Discord.Net.Rest/Entities/RestApplication.cs +++ b/src/Discord.Net.Rest/Entities/RestApplication.cs @@ -64,6 +64,42 @@ public class RestApplication : RestEntity, IApplication /// public ApplicationInstallParams InstallParams { get; private set; } + /// + public ApplicationDiscoverabilityState DiscoverabilityState { get; private set; } + + /// + public DiscoveryEligibilityFlags DiscoveryEligibilityFlags { get; private set; } + + /// + public ApplicationExplicitContentFilterLevel ExplicitContentFilterLevel { get; private set; } + + /// + public bool IsHook { get; private set; } + + /// + public IReadOnlyCollection InteractionEventTypes { get; private set; } + + /// + public ApplicationInteractionsVersion InteractionsVersion { get; private set; } + + /// + public bool IsMonetized { get; private set; } + + /// + public ApplicationMonetizationEligibilityFlags MonetizationEligibilityFlags { get; private set; } + + /// + public ApplicationMonetizationState MonetizationState { get; private set; } + + /// + public ApplicationRpcState RpcState { get; private set; } + + /// + public ApplicationStoreState StoreState { get; private set; } + + /// + public ApplicationVerificationState VerificationState { get; private set; } + /// public IReadOnlyCollection Tags { get; private set; } @@ -113,6 +149,22 @@ internal void Update(Model model) RedirectUris = model.RedirectUris.Value.ToImmutableArray(); ApproximateGuildCount = model.ApproximateGuildCount.IsSpecified ? model.ApproximateGuildCount.Value : null; + + DiscoverabilityState = model.DiscoverabilityState.GetValueOrDefault(ApplicationDiscoverabilityState.None); + DiscoveryEligibilityFlags = model.DiscoveryEligibilityFlags.GetValueOrDefault(DiscoveryEligibilityFlags.None); + ExplicitContentFilterLevel = model.ExplicitContentFilter.GetValueOrDefault(ApplicationExplicitContentFilterLevel.Disabled); + IsHook = model.IsHook; + + InteractionEventTypes = model.InteractionsEventTypes.GetValueOrDefault(Array.Empty()).ToImmutableArray(); + InteractionsVersion = model.InteractionsVersion.GetValueOrDefault(ApplicationInteractionsVersion.Version1); + + IsMonetized = model.IsMonetized; + MonetizationEligibilityFlags = model.MonetizationEligibilityFlags.GetValueOrDefault(ApplicationMonetizationEligibilityFlags.None); + MonetizationState = model.MonetizationState.GetValueOrDefault(ApplicationMonetizationState.None); + + RpcState = model.RpcState.GetValueOrDefault(ApplicationRpcState.Disabled); + StoreState = model.StoreState.GetValueOrDefault(ApplicationStoreState.None); + VerificationState = model.VerificationState.GetValueOrDefault(ApplicationVerificationState.Ineligible); } /// Unable to update this object from a different application token. diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index 1740e37233..f03bbed7c4 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -146,6 +146,9 @@ public class SocketGuild : SocketEntity, IGuild, IDisposable /// public GuildIncidentsData IncidentsData { get; private set; } + /// + public GuildInventorySettings? InventorySettings { get; private set; } + /// public DateTimeOffset CreatedAt => SnowflakeUtils.FromSnowflake(Id); /// @@ -571,6 +574,9 @@ internal void Update(ClientState state, Model model) PreferredCulture = PreferredLocale == null ? null : new CultureInfo(PreferredLocale); if (model.IsBoostProgressBarEnabled.IsSpecified) IsBoostProgressBarEnabled = model.IsBoostProgressBarEnabled.Value; + if (model.InventorySettings.IsSpecified) + InventorySettings = model.InventorySettings.Value is null ? null : new(model.InventorySettings.Value.IsEmojiPackCollectible.GetValueOrDefault(false)); + IncidentsData = model.IncidentsData is not null ? new GuildIncidentsData { DmsDisabledUntil = model.IncidentsData.DmsDisabledUntil, InvitesDisabledUntil = model.IncidentsData.InvitesDisabledUntil } : new GuildIncidentsData(); diff --git a/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs b/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs index 97b5782a4d..de7d0ae01d 100644 --- a/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs +++ b/test/Discord.Net.Tests.Unit/ChannelPermissionsTests.cs @@ -93,6 +93,7 @@ void AssertFlag(Func cstr, ChannelPermission flag) AssertFlag(() => new ChannelPermissions(useSoundboard: true), ChannelPermission.UseSoundboard); AssertFlag(() => new ChannelPermissions(createEvents: true), ChannelPermission.CreateEvents); AssertFlag(() => new ChannelPermissions(sendVoiceMessages: true), ChannelPermission.SendVoiceMessages); + AssertFlag(() => new ChannelPermissions(useClydeAI: true), ChannelPermission.UseClydeAI); AssertFlag(() => new ChannelPermissions(setVoiceChannelStatus: true), ChannelPermission.SetVoiceChannelStatus); } @@ -159,6 +160,7 @@ void AssertUtil(ChannelPermission permission, AssertUtil(ChannelPermission.PrioritySpeaker, x => x.PrioritySpeaker, (p, enable) => p.Modify(prioritySpeaker: enable)); AssertUtil(ChannelPermission.Stream, x => x.Stream, (p, enable) => p.Modify(stream: enable)); AssertUtil(ChannelPermission.SendVoiceMessages, x => x.SendVoiceMessages, (p, enable) => p.Modify(sendVoiceMessages: enable)); + AssertUtil(ChannelPermission.UseClydeAI, x => x.UseClydeAI, (p, enable) => p.Modify(useClydeAI: enable)); AssertUtil(ChannelPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: enable)); } diff --git a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs index 6c58e3ad82..102860c8a3 100644 --- a/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs +++ b/test/Discord.Net.Tests.Unit/GuildPermissionsTests.cs @@ -103,6 +103,8 @@ void AssertFlag(Func cstr, GuildPermission flag) AssertFlag(() => new GuildPermissions(viewMonetizationAnalytics: true), GuildPermission.ViewMonetizationAnalytics); AssertFlag(() => new GuildPermissions(useSoundboard: true), GuildPermission.UseSoundboard); AssertFlag(() => new GuildPermissions(sendVoiceMessages: true), GuildPermission.SendVoiceMessages); + AssertFlag(() => new GuildPermissions(useClydeAI: true), GuildPermission.UseClydeAI); + AssertFlag(() => new GuildPermissions(createGuildExpressions: true), GuildPermission.CreateGuildExpressions); AssertFlag(() => new GuildPermissions(setVoiceChannelStatus: true), GuildPermission.SetVoiceChannelStatus); } @@ -185,6 +187,8 @@ void AssertUtil(GuildPermission permission, AssertUtil(GuildPermission.ViewMonetizationAnalytics, x => x.ViewMonetizationAnalytics, (p, enable) => p.Modify(viewMonetizationAnalytics: enable)); AssertUtil(GuildPermission.UseSoundboard, x => x.UseSoundboard, (p, enable) => p.Modify(useSoundboard: enable)); AssertUtil(GuildPermission.SendVoiceMessages, x => x.SendVoiceMessages, (p, enable) => p.Modify(sendVoiceMessages: enable)); + AssertUtil(GuildPermission.UseClydeAI, x => x.UseClydeAI, (p, enable) => p.Modify(useClydeAI: enable)); + AssertUtil(GuildPermission.CreateGuildExpressions, x => x.CreateGuildExpressions, (p, enable) => p.Modify(createGuildExpressions: enable)); AssertUtil(GuildPermission.SetVoiceChannelStatus, x => x.SetVoiceChannelStatus, (p, enable) => p.Modify(setVoiceChannelStatus: enable)); } }