Browse Source

working state

pull/2578/head
Misha133 2 years ago
parent
commit
afc98e3286
7 changed files with 374 additions and 39 deletions
  1. +102
    -0
      src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModRule.cs
  2. +253
    -21
      src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModRuleBuilder.cs
  3. +1
    -1
      src/Discord.Net.Core/Entities/Guilds/IGuild.cs
  4. +2
    -2
      src/Discord.Net.Rest/DiscordRestApiClient.cs
  5. +4
    -4
      src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs
  6. +8
    -7
      src/Discord.Net.Rest/Extensions/EntityExtensions.cs
  7. +4
    -4
      src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs

+ 102
- 0
src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModRule.cs View File

@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Discord
{
/// <summary>
/// Provides properties used to create a <see cref="IAutoModRule"/>.
/// </summary>
public class AutoModRule
{
/// <summary>
/// Gets the name for the rule.
/// </summary>
public string Name { get; }

/// <summary>
/// Gets the event type for the rule.
/// </summary>
public AutoModEventType EventType { get; }

/// <summary>
/// Gets the trigger type for the rule.
/// </summary>
public AutoModTriggerType TriggerType { get; }

/// <summary>
/// Gets the keyword filter for the rule.
/// </summary>
public string[] KeywordFilter { get; }

/// <summary>
/// Gets regex patterns for the rule.
/// </summary>
public string[] RegexPatterns { get; }

/// <summary>
/// Gets the allow list for the rule.
/// </summary>
public string[] AllowList { get; }

/// <summary>
/// Gets total mention limit for the rule.
/// </summary>
public int? MentionLimit { get; }

/// <summary>
/// Gets the presets for the rule.
/// </summary>
public KeywordPresetTypes[] Presets { get; }

/// <summary>
/// Gets the actions for the rule.
/// </summary>
public AutoModRuleAction[] Actions { get; }

/// <summary>
/// Gets whether or not the rule is enabled.
/// </summary>
public bool Enabled { get; }

/// <summary>
/// Gets the exempt roles for the rule.
/// </summary>
public ulong[] ExemptRoles { get; }

/// <summary>
/// Gets the exempt channels for the rule.
/// </summary>
public ulong[] ExemptChannels { get; }
internal AutoModRule(string name,
AutoModEventType eventType,
AutoModTriggerType triggerType,
string[] keywordFilter,
string[] regexPatterns,
string[] allowList,
int? mentionLimit,
KeywordPresetTypes[] presets,
AutoModRuleAction[] actions,
bool enabled,
ulong[] exemptRoles,
ulong[] exemptChannels)
{
Name = name;
EventType = eventType;
TriggerType = triggerType;
KeywordFilter = keywordFilter;
RegexPatterns = regexPatterns;
AllowList = allowList;
MentionLimit = mentionLimit;
Presets = presets;
Actions = actions;
Enabled = enabled;
ExemptRoles = exemptRoles;
ExemptChannels = exemptChannels;
}
}

}

+ 253
- 21
src/Discord.Net.Core/Entities/Guilds/AutoModeration/AutoModRuleBuilder.cs View File

@@ -1,5 +1,8 @@
using Newtonsoft.Json.Linq;

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;

namespace Discord;
@@ -24,10 +27,9 @@ public class AutoModRuleBuilder
private const int MaxExemptRoles = 20;
private const int MaxExemptChannels = 50;

private List<string> _keywordFilter = new ();
private List<string> _regexPatterns = new ();
private List<string> _allowList = new ();
private List<AutoModRuleActionBuilder> _actions = new ();
private List<string> _keywordFilter = new();
private List<string> _regexPatterns = new();
private List<string> _allowList = new();

private List<ulong> _exemptRoles = new();
private List<ulong> _exemptChannels = new();
@@ -123,8 +125,8 @@ public class AutoModRuleBuilder
get { return _exemptChannels; }
set
{
if (value.Count > MaxExemptRoles)
throw new ArgumentException(message: $"Exempt channels count must be less than or equal to {MaxExemptRoles}.", paramName: nameof(RegexPatterns));
if (value.Count > MaxExemptChannels)
throw new ArgumentException(message: $"Exempt channels count must be less than or equal to {MaxExemptChannels}.", paramName: nameof(RegexPatterns));

_exemptChannels = value;
}
@@ -133,7 +135,17 @@ public class AutoModRuleBuilder
/// <summary>
///
/// </summary>
public HashSet<KeywordPresetTypes> Presets = new ();
public HashSet<KeywordPresetTypes> Presets
{
get => _presets;
set
{
if (TriggerType != AutoModTriggerType.KeywordPreset)
throw new ArgumentException(message: $"Keyword presets scan only be used with 'KeywordPreset' trigger type.", paramName: nameof(AllowList));

_presets = value;
}
}

/// <summary>
///
@@ -143,12 +155,12 @@ public class AutoModRuleBuilder
/// <summary>
///
/// </summary>
public AutoModEventType EventType { get; set; }
public AutoModEventType EventType { get; set; } = AutoModEventType.MessageSend;

/// <summary>
///
/// </summary>
public AutoModTriggerType TriggerType { get; }
public AutoModTriggerType TriggerType { get; }

/// <summary>
///
@@ -165,13 +177,14 @@ public class AutoModRuleBuilder
throw new ArgumentException(message: $"Mention limit must be less than or equal to {MaxMentionLimit}.", paramName: nameof(MentionLimit));
_mentionLimit = value;
}

}

/// <summary>
///
/// </summary>
public List<AutoModRuleActionBuilder> Actions;
public List<AutoModRuleActionBuilder> Actions = new();

private HashSet<KeywordPresetTypes> _presets = new();

/// <summary>
///
@@ -186,6 +199,224 @@ public class AutoModRuleBuilder
{
TriggerType = type;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder WithName(string name)
{
Name = name;
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder WithEnabled(bool enabled)
{
Enabled = enabled;
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder WithEventType(AutoModEventType eventType)
{
EventType = eventType;
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder WithMentionLimit(int limit)
{
MentionLimit = limit;
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddKeywordFilter(string keyword)
{
if (TriggerType != AutoModTriggerType.Keyword)
throw new ArgumentException(message: $"Keyword filter can only be used with 'Keyword' trigger type.");

if (KeywordFilter.Count >= MaxKeywordCount)
throw new ArgumentException(message: $"Keyword count must be less than or equal to {MaxKeywordCount}.");

if (keyword.Length > MaxKeywordLength)
throw new ArgumentException(message: $"Keyword length must be less than or equal to {MaxKeywordLength}.");

KeywordFilter.Add(keyword);

return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddAllowList(string keyword)
{
if (TriggerType is not AutoModTriggerType.Keyword or AutoModTriggerType.KeywordPreset)
throw new ArgumentException(message: $"Allow list can only be used with 'Keyword' or 'KeywordPreset' trigger type.");

if (TriggerType == AutoModTriggerType.Keyword && AllowList.Count >= MaxAllowListCountKeyword)
throw new ArgumentException(message: $"Allow list entry count must be less than or equal to {MaxAllowListCountKeyword}.");

if (TriggerType == AutoModTriggerType.KeywordPreset && AllowList.Count > MaxAllowListCountKeywordPreset)
throw new ArgumentException(message: $"Allow list entry count must be less than or equal to {MaxAllowListCountKeywordPreset}.");

if (keyword.Length > MaxAllowListEntryLength)
throw new ArgumentException(message: $"Allow list entry length must be less than or equal to {MaxAllowListEntryLength}.");

AllowList.Add(keyword);

return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddKeywordPreset(KeywordPresetTypes type)
{
if (TriggerType != AutoModTriggerType.KeywordPreset)
throw new ArgumentException(message: $"Keyword presets scan only be used with 'KeywordPreset' trigger type.", paramName: nameof(AllowList));

Presets.Add(type);
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddRegexPattern(string regex)
{
if (TriggerType != AutoModTriggerType.Keyword)
throw new ArgumentException(message: $"Regex patterns can only be used with 'Keyword' trigger type.");

if (RegexPatterns.Count >= MaxRegexPatternCount)
throw new ArgumentException(message: $"Regex pattern count must be less than or equal to {MaxRegexPatternCount}.");

if (regex.Length > MaxRegexPatternLength)
throw new ArgumentException(message: $"Regex pattern must be less than or equal to {MaxRegexPatternLength}.");

RegexPatterns.Add(regex);

return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddExemptRole(IRole role)
{
AddExemptRole(role.Id);
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddExemptRole(ulong roleId)
{
ExemptRoles.Add(roleId);
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddExemptChannel(IMessageChannel channel)
{
AddExemptChannel(channel.Id);
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddExemptChannel(ulong channelId)
{
ExemptChannels.Add(channelId);
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRuleBuilder AddAction(AutoModRuleActionBuilder builder)
{
Actions.Add(builder);
return this;
}

/// <summary>
///
/// </summary>
/// <returns></returns>
public static AutoModRuleBuilder FromAutoModRule(IAutoModRule rule)
=> new(rule.TriggerType)
{
Name = rule.Name,
AllowList = rule.AllowList.ToList(),
RegexPatterns = rule.RegexPatterns.ToList(),
KeywordFilter = rule.KeywordFilter.ToList(),
Presets = new HashSet<KeywordPresetTypes>(rule.Presets),
ExemptChannels = rule.ExemptChannels.ToList(),
ExemptRoles = rule.ExemptRoles.ToList(),
Actions = rule.Actions.Select(AutoModRuleActionBuilder.FromModel).ToList(),
MentionLimit = rule.MentionTotalLimit,
Enabled = rule.Enabled,
EventType = rule.EventType
};
/// <summary>
///
/// </summary>
/// <returns></returns>
public AutoModRule Build()
{
if (string.IsNullOrWhiteSpace(Name))
throw new ArgumentException("Name of the rule must not be empty", paramName: nameof(Name));

Preconditions.AtLeast(1, Actions.Count, nameof(Actions), "Auto moderation rule must have at least 1 action");

if(TriggerType is AutoModTriggerType.Keyword)
Preconditions.AtLeast(1, KeywordFilter.Count + RegexPatterns.Count, nameof(KeywordFilter), "Auto moderation rule must have at least 1 keyword or regex pattern");

if(TriggerType is AutoModTriggerType.MentionSpam && MentionLimit is null)
throw new ArgumentException("Mention limit must not be empty", paramName: nameof(MentionLimit));
return new(Name,
EventType,
TriggerType,
KeywordFilter.ToArray(),
RegexPatterns.ToArray(),
AllowList.ToArray(),
MentionLimit,
Presets.ToArray(),
Actions.Select(x => new AutoModRuleAction(x.Type, x.ChannelId, (int?)x.TimeoutDuration?.TotalSeconds)).ToArray(),
Enabled,
ExemptRoles.ToArray(),
ExemptChannels.ToArray());
}

}

/// <summary>
@@ -205,17 +436,23 @@ public class AutoModRuleActionBuilder
/// <summary>
/// Get or sets the channel id on which to post alerts.
/// </summary>
/// <remarks>
/// This property will be <see langword="null"/> if <see cref="Type"/> is not <see cref="AutoModActionType.SendAlertMessage"/>
/// </remarks>
public ulong? ChannelId { get; set; }

/// <summary>
/// Gets or sets the duration of which a user will be timed out for breaking this rule.
/// </summary>
/// <remarks>
/// This property will be <see langword="null"/> if <see cref="Type"/> is not <see cref="AutoModActionType.Timeout"/>
/// </remarks>
public TimeSpan? TimeoutDuration
{
get => _timeoutDuration;
set
{
if(value is { TotalSeconds: > MaxTimeoutSeconds })
if (value is { TotalSeconds: > MaxTimeoutSeconds })
throw new ArgumentException(message: $"Field count must be less than or equal to {MaxTimeoutSeconds}.", paramName: nameof(TimeoutDuration));

_timeoutDuration = value;
@@ -225,18 +462,13 @@ public class AutoModRuleActionBuilder
/// <summary>
///
/// </summary>
public AutoModRuleActionBuilder()
{

}

/// <summary>
///
/// </summary>
public AutoModRuleActionBuilder(AutoModActionType type, ulong? channelId, TimeSpan? duration)
public AutoModRuleActionBuilder(AutoModActionType type, ulong? channelId = null, TimeSpan? duration = null)
{
Type = type;
ChannelId = channelId;
TimeoutDuration = duration;
}

internal static AutoModRuleActionBuilder FromModel(AutoModRuleAction action)
=> new(action.Type, action.ChannelId, action.TimeoutDuration);
}

+ 1
- 1
src/Discord.Net.Core/Entities/Guilds/IGuild.cs View File

@@ -1290,6 +1290,6 @@ namespace Discord
/// <returns>
/// A task that represents the asynchronous creation operation. The task result contains the created <see cref="WelcomeScreen"/>.
/// </returns>
Task<IAutoModRule> CreateAutoModRuleAsync(AutoModRuleBuilder builder, RequestOptions options = null);
Task<IAutoModRule> CreateAutoModRuleAsync(AutoModRule props, RequestOptions options = null);
}
}

+ 2
- 2
src/Discord.Net.Rest/DiscordRestApiClient.cs View File

@@ -2129,7 +2129,7 @@ namespace Discord.API

options = RequestOptions.CreateOrClone(options);

return await SendJsonAsync<AutoModerationRule>("POST", () => $"guilds/{guildId}/auto-moderation", args, new BucketIds(guildId), options: options);
return await SendJsonAsync<AutoModerationRule>("POST", () => $"guilds/{guildId}/auto-moderation/rules", args, new BucketIds(guildId), options: options);
}

public async Task<AutoModerationRule> ModifyGuildAutoModRuleAsync(ulong guildId, ulong ruleId, ModifyAutoModRuleParams args, RequestOptions options)
@@ -2139,7 +2139,7 @@ namespace Discord.API

options = RequestOptions.CreateOrClone(options);

return await SendJsonAsync<AutoModerationRule>("PATCH", () => $"guilds/{guildId}/auto-moderation/{ruleId}", args, new BucketIds(guildId), options: options);
return await SendJsonAsync<AutoModerationRule>("PATCH", () => $"guilds/{guildId}/auto-moderation/rules/{ruleId}", args, new BucketIds(guildId), options: options);
}

public async Task DeleteGuildAutoModRuleAsync(ulong guildId, ulong ruleId, RequestOptions options)


+ 4
- 4
src/Discord.Net.Rest/Entities/Guilds/RestGuild.cs View File

@@ -1217,9 +1217,9 @@ namespace Discord.Rest
}

/// <inheritdoc cref="IGuild.CreateAutoModRuleAsync"/>
public async Task<RestAutoModRule> CreateAutoModRuleAsync(AutoModRuleBuilder builder, RequestOptions options = null)
public async Task<RestAutoModRule> CreateAutoModRuleAsync(AutoModRule props, RequestOptions options = null)
{
var rule = await GuildHelper.CreateAutoModRuleAsync(this, builder.ToProperties(), Discord, options);
var rule = await GuildHelper.CreateAutoModRuleAsync(this, props.ToProperties(), Discord, options);

return RestAutoModRule.Create(Discord, rule);
}
@@ -1581,8 +1581,8 @@ namespace Discord.Rest
=> await GetAutoModRulesAsync(options).ConfigureAwait(false);

/// <inheritdoc/>
async Task<IAutoModRule> IGuild.CreateAutoModRuleAsync(AutoModRuleBuilder builder, RequestOptions options)
=> await CreateAutoModRuleAsync(builder, options).ConfigureAwait(false);
async Task<IAutoModRule> IGuild.CreateAutoModRuleAsync(AutoModRule props, RequestOptions options)
=> await CreateAutoModRuleAsync(props, options).ConfigureAwait(false);

#endregion
}


+ 8
- 7
src/Discord.Net.Rest/Extensions/EntityExtensions.cs View File

@@ -215,17 +215,18 @@ namespace Discord.Rest
};
}

public static API.Rest.CreateAutoModRuleParams ToProperties(this AutoModRuleBuilder builder)
public static API.Rest.CreateAutoModRuleParams ToProperties(this AutoModRule builder)
{
return new API.Rest.CreateAutoModRuleParams
{
Name = builder.Name,
TriggerMetadata = new API.TriggerMetadata
{
KeywordFilter = builder.KeywordFilter?.ToArray(),
AllowList = builder.AllowList?.ToArray(),
KeywordFilter = builder.KeywordFilter ?? Optional<string[]>.Unspecified,
AllowList = builder.AllowList ?? Optional<string[]>.Unspecified,
MentionLimit = builder.MentionLimit ?? Optional<int>.Unspecified,
Presets = builder.Presets?.ToArray(),
RegexPatterns = builder.RegexPatterns?.ToArray(),
Presets = builder.Presets ?? Optional<KeywordPresetTypes[]>.Unspecified,
RegexPatterns = builder.RegexPatterns ?? Optional<string[]>.Unspecified,
},
TriggerType = builder.TriggerType,
Actions = builder.Actions?.Select(x => new API.AutoModAction
@@ -239,8 +240,8 @@ namespace Discord.Rest
}).ToArray(),
Enabled = builder.Enabled,
EventType = builder.EventType,
ExemptChannels = builder.ExemptChannels?.ToArray() ?? Optional<ulong[]>.Unspecified,
ExemptRoles = builder.ExemptRoles?.ToArray() ?? Optional <ulong[]>.Unspecified,
ExemptChannels = builder.ExemptChannels ?? Optional<ulong[]>.Unspecified,
ExemptRoles = builder.ExemptRoles ?? Optional<ulong[]>.Unspecified,
};
}
}


+ 4
- 4
src/Discord.Net.WebSocket/Entities/Guilds/SocketGuild.cs View File

@@ -1867,9 +1867,9 @@ namespace Discord.WebSocket
}

/// <inheritdoc cref="IGuild.CreateAutoModRuleAsync"/>
public async Task<SocketAutoModRule> CreateAutoModRuleAsync(AutoModRuleBuilder builder, RequestOptions options = null)
public async Task<SocketAutoModRule> CreateAutoModRuleAsync(AutoModRule props, RequestOptions options = null)
{
var rule = await GuildHelper.CreateAutoModRuleAsync(this, builder.ToProperties(), Discord, options);
var rule = await GuildHelper.CreateAutoModRuleAsync(this, props.ToProperties(), Discord, options);

return AddOrUpdateAutoModRule(rule);
}
@@ -2130,8 +2130,8 @@ namespace Discord.WebSocket
=> await GetAutoModRulesAsync(options).ConfigureAwait(false);

/// <inheritdoc/>
async Task<IAutoModRule> IGuild.CreateAutoModRuleAsync(AutoModRuleBuilder builder, RequestOptions options)
=> await CreateAutoModRuleAsync(builder, options).ConfigureAwait(false);
async Task<IAutoModRule> IGuild.CreateAutoModRuleAsync(AutoModRule props, RequestOptions options)
=> await CreateAutoModRuleAsync(props, options).ConfigureAwait(false);

#endregion
}


Loading…
Cancel
Save