diff --git a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs index 63f4a2280..ccd0bb6d0 100644 --- a/src/Discord.Net.Core/Entities/Guilds/IGuild.cs +++ b/src/Discord.Net.Core/Entities/Guilds/IGuild.cs @@ -1267,5 +1267,29 @@ namespace Discord /// A task that represents the asynchronous creation operation. The task result contains a . /// Task ModifyWelcomeScreenAsync(bool enabled, WelcomeScreenChannelProperties[] channels, string description = null, RequestOptions options = null); + + /// + /// Get a list of all rules currently configured for the guild. + /// + /// + /// A task that represents the asynchronous creation operation. The task result contains a collection of . + /// + Task GetAutoModRulesAsync(RequestOptions options = null); + + /// + /// Gets a single rule configured in a guild. Returns if the rule was not found. + /// + /// + /// A task that represents the asynchronous creation operation. The task result contains a . + /// + Task GetAutoModRuleAsync(RequestOptions options = null); + + /// + /// Creates a new auto moderation rule. + /// + /// + /// A task that represents the asynchronous creation operation. The task result contains the created . + /// + Task CreateAutoModRuleAsync(RequestOptions options = null); } } diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestAutoModRule.cs b/src/Discord.Net.Rest/Entities/Guilds/RestAutoModRule.cs new file mode 100644 index 000000000..e88f7fe61 --- /dev/null +++ b/src/Discord.Net.Rest/Entities/Guilds/RestAutoModRule.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; + +using Model = Discord.API.AutoModerationRule; + +namespace Discord.Rest; + +public class RestAutoModRule : RestEntity, IAutoModRule +{ + /// + public DateTimeOffset CreatedAt { get; private set; } + + /// + public ulong GuildId { get; private set; } + + /// + public string Name { get; private set; } + + /// + public ulong CreatorId { get; private set; } + + /// + public AutoModEventType EventType { get; private set; } + + /// + public AutoModTriggerType TriggerType { get; private set; } + + /// + public IReadOnlyCollection KeywordFilter { get; private set; } + + /// + public IReadOnlyCollection RegexPatterns { get; private set; } + + /// + public IReadOnlyCollection AllowList { get; private set; } + + /// + public IReadOnlyCollection Presets { get; private set; } + + /// + public int? MentionTotalLimit { get; private set; } + + /// + public IReadOnlyCollection Actions { get; private set; } + + /// + public bool Enabled { get; private set; } + + /// + public IReadOnlyCollection ExemptRoles { get; private set; } + + /// + public IReadOnlyCollection ExemptChannels { get; private set; } + + internal RestAutoModRule(BaseDiscordClient discord, ulong id) : base(discord, id) + { + + } + + internal static RestAutoModRule Create(BaseDiscordClient discord, Model model) + { + var entity = new RestAutoModRule(discord, model.Id); + entity.Update(model); + return entity; + } + + internal void Update(Model model) + { + Name = model.Name; + CreatorId = model.CreatorId; + GuildId = model.GuildId; + + EventType = model.EventType; + TriggerType = model.TriggerType; + KeywordFilter = model.TriggerMetadata.KeywordFilter.GetValueOrDefault(Array.Empty()).ToImmutableArray(); + Presets = model.TriggerMetadata.Presets.GetValueOrDefault(Array.Empty()).ToImmutableArray(); + RegexPatterns = model.TriggerMetadata.RegexPatterns.GetValueOrDefault(Array.Empty()).ToImmutableArray(); + AllowList = model.TriggerMetadata.AllowList.GetValueOrDefault(Array.Empty()).ToImmutableArray(); + MentionTotalLimit = model.TriggerMetadata.MentionLimit.IsSpecified + ? model.TriggerMetadata.MentionLimit.Value + : null; + Actions = model.Actions.Select(x => new AutoModRuleAction(x.Type, x.Metadata.GetValueOrDefault()?.ChannelId.ToNullable(), x.Metadata.GetValueOrDefault()?.DurationSeconds.ToNullable())).ToImmutableArray(); + Enabled = model.Enabled; + ExemptRoles = model.ExemptRoles.ToImmutableArray(); + ExemptChannels = model.ExemptChannels.ToImmutableArray(); + } + + /// + public Task ModifyAsync(Action func, RequestOptions options = null) => throw new NotImplementedException(); + + /// + public Task DeleteAsync(RequestOptions options = null) => throw new NotImplementedException(); +} diff --git a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs index 79ec77c21..6657907f6 100644 --- a/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs +++ b/src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs @@ -1199,6 +1199,22 @@ namespace Discord.Rest #endregion + #region AutoMod + + /// + public Task GetAutoModRuleAsync(RequestOptions options = null) + => GuildHelper.GetAutoModRuleAsync(this, Discord, options); + + /// + public Task GetAutoModRulesAsync(RequestOptions options = null) + => GuildHelper.GetAutoModRulesAsync(this, Discord, options); + + /// + public Task CreateAutoModRuleAsync(RequestOptions options = null) + => GuildHelper.CreateAutoModRuleAsync(this, Discord, options); + + #endregion + #region IGuild /// bool IGuild.Available => Available; @@ -1543,6 +1559,19 @@ namespace Discord.Rest public Task ModifyWelcomeScreenAsync(bool enabled, WelcomeScreenChannelProperties[] channels, string description = null, RequestOptions options = null) => GuildHelper.ModifyWelcomeScreenAsync(enabled, description, channels, this, Discord, options); + + /// + async Task IGuild.GetAutoModRuleAsync(RequestOptions options) + => await GetAutoModRuleAsync(options).ConfigureAwait(false); + + /// + async Task IGuild.GetAutoModRulesAsync(RequestOptions options) + => await GetAutoModRulesAsync(options).ConfigureAwait(false); + + /// + async Task IGuild.CreateAutoModRuleAsync(RequestOptions options) + => await CreateAutoModRuleAsync(options).ConfigureAwait(false); + #endregion } } diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/AutoModActionExecutedData.cs b/src/Discord.Net.WebSocket/Entities/Guilds/AutoModActionExecutedData.cs index 65f131fd0..611b39441 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/AutoModActionExecutedData.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/AutoModActionExecutedData.cs @@ -4,22 +4,62 @@ namespace Discord.WebSocket; public class AutoModActionExecutedData { + /// + /// Gets the id of the rule which action belongs to. + /// public Cacheable Rule { get; } + /// + /// Gets the trigger type of rule which was triggered. + /// public AutoModTriggerType TriggerType { get; } + /// + /// Gets the user which generated the content which triggered the rule. + /// public Cacheable User { get; } + /// + /// Gets the channel in which user content was posted. + /// public Cacheable Channel { get; } + /// + /// Gets the message that triggered the action. + /// + /// + /// This property will be if the message was blocked byt automod. + /// public Cacheable Message { get; } + /// + /// Gets the id of the system auto moderation messages posted as a result of this action. + /// + /// + /// This property will be if this event does not correspond to an action + /// with type . + /// public ulong AlertMessageId { get; } - + + /// + /// Gets the user-generated text content. + /// + /// + /// This property will be empty if is disabled. + /// public string Content { get; } + /// + /// Gets the substring in content that triggered the rule. + /// + /// + /// This property will be empty if is disabled. + /// public string MatchedContent { get; } + /// + /// Gets the word or phrase configured in the rule that triggered the rule. + /// public string MatchedKeyword { get; } internal AutoModActionExecutedData(Cacheable rule, diff --git a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs index 0786023fd..3da718e9d 100644 --- a/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs +++ b/src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs @@ -1810,6 +1810,22 @@ namespace Discord.WebSocket internal SocketGuild Clone() => MemberwiseClone() as SocketGuild; #endregion + #region AutoMod + + /// + public Task GetAutoModRuleAsync(RequestOptions options = null) + => GuildHelper.GetAutoModRuleAsync(this, Discord, options); + + /// + public Task GetAutoModRulesAsync(RequestOptions options = null) + => GuildHelper.GetAutoModRulesAsync(this, Discord, options); + + /// + public Task CreateAutoModRuleAsync(RequestOptions options = null) + => GuildHelper.CreateAutoModRuleAsync(this, Discord, options); + + #endregion + #region IGuild /// ulong? IGuild.AFKChannelId => AFKChannelId; @@ -2054,6 +2070,19 @@ namespace Discord.WebSocket _audioLock?.Dispose(); _audioClient?.Dispose(); } + + /// + async Task IGuild.GetAutoModRuleAsync(RequestOptions options) + => await GetAutoModRuleAsync(options).ConfigureAwait(false); + + /// + async Task IGuild.GetAutoModRulesAsync(RequestOptions options) + => await GetAutoModRulesAsync(options).ConfigureAwait(false); + + /// + async Task IGuild.CreateAutoModRuleAsync(RequestOptions options) + => await CreateAutoModRuleAsync(options).ConfigureAwait(false); + #endregion } }