Added FilterList
Several upcoming features will be making use of the same whitelist and blacklist filtering concept that RegexResponder currently uses.
This commit is contained in:
parent
bd46c53a02
commit
8d228a4d7c
4 changed files with 96 additions and 56 deletions
|
@ -7,8 +7,6 @@ using System.Linq;
|
||||||
|
|
||||||
namespace Noikoio.RegexBot.ConfigItem
|
namespace Noikoio.RegexBot.ConfigItem
|
||||||
{
|
{
|
||||||
enum FilterType { None, Whitelist, Blacklist }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a structure in bot configuration that contains a list of
|
/// Represents a structure in bot configuration that contains a list of
|
||||||
/// channels, roles, and users.
|
/// channels, roles, and users.
|
||||||
|
@ -70,7 +68,7 @@ namespace Noikoio.RegexBot.ConfigItem
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="msg">An incoming message.</param>
|
/// <param name="msg">An incoming message.</param>
|
||||||
/// <returns>
|
/// <returns>
|
||||||
/// True if the <see cref="SocketMessage"/> occurred within a channel specified in this list,
|
/// True if '<paramref name="msg"/>' occurred within a channel specified in this list,
|
||||||
/// or if the message author belongs to one or more roles in this list, or if the user itself
|
/// or if the message author belongs to one or more roles in this list, or if the user itself
|
||||||
/// is defined within this list.
|
/// is defined within this list.
|
||||||
/// </returns>
|
/// </returns>
|
||||||
|
@ -125,28 +123,5 @@ namespace Noikoio.RegexBot.ConfigItem
|
||||||
// No match.
|
// No match.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Helper method for reading whitelist and blacklist filtering lists.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="section">
|
|
||||||
/// A JSON object which presumably contains an array named "whitelist" or "blacklist".
|
|
||||||
/// </param>
|
|
||||||
public static (FilterType, EntityList) GetFilterList(JObject section)
|
|
||||||
{
|
|
||||||
var mode = FilterType.None;
|
|
||||||
EntityList list;
|
|
||||||
if (section["whitelist"] != null) mode = FilterType.Whitelist;
|
|
||||||
if (section["blacklist"] != null)
|
|
||||||
{
|
|
||||||
if (mode == FilterType.Whitelist)
|
|
||||||
throw new RuleImportException("Cannot have whitelist AND blacklist defined.");
|
|
||||||
mode = FilterType.Blacklist;
|
|
||||||
}
|
|
||||||
if (mode == FilterType.None) list = new EntityList(); // might even be fine to keep it null?
|
|
||||||
else list = new EntityList(section[mode == FilterType.Whitelist ? "whitelist" : "blacklist"]);
|
|
||||||
|
|
||||||
return (mode, list);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
91
ConfigItem/FilterList.cs
Normal file
91
ConfigItem/FilterList.cs
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Noikoio.RegexBot.ConfigItem
|
||||||
|
{
|
||||||
|
enum FilterType { None, Whitelist, Blacklist }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents whitelist/blacklist configuration, including exemptions.
|
||||||
|
/// </summary>
|
||||||
|
struct FilterList
|
||||||
|
{
|
||||||
|
FilterType _type;
|
||||||
|
EntityList _filterList;
|
||||||
|
EntityList _exemptions;
|
||||||
|
|
||||||
|
public FilterType FilterMode => _type;
|
||||||
|
public EntityList FilterEntities => _filterList;
|
||||||
|
public EntityList FilterExemptions => _exemptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="conf">
|
||||||
|
/// A JSON object which presumably contains an array named "whitelist" or "blacklist",
|
||||||
|
/// and optionally one named "exempt".
|
||||||
|
/// </param>
|
||||||
|
/// <exception cref="RuleImportException">
|
||||||
|
/// Thrown if both "whitelist" and "blacklist" definitions were found, if
|
||||||
|
/// "exempt" was found without a corresponding "whitelist" or "blacklist",
|
||||||
|
/// or if there was an issue parsing an EntityList within these definitions.
|
||||||
|
/// </exception>
|
||||||
|
public FilterList(JObject conf)
|
||||||
|
{
|
||||||
|
_type = FilterType.None;
|
||||||
|
|
||||||
|
if (conf["whitelist"] != null) _type = FilterType.Whitelist;
|
||||||
|
if (conf["blacklist"] != null)
|
||||||
|
{
|
||||||
|
if (_type != FilterType.None)
|
||||||
|
throw new RuleImportException("Cannot have both 'whitelist' and 'blacklist' values defined.");
|
||||||
|
_type = FilterType.Blacklist;
|
||||||
|
}
|
||||||
|
if (_type == FilterType.None)
|
||||||
|
{
|
||||||
|
_filterList = null;
|
||||||
|
_exemptions = null;
|
||||||
|
if (conf["exempt"] != null)
|
||||||
|
throw new RuleImportException("Cannot have 'exempt' defined if no corresponding " +
|
||||||
|
"'whitelist' or 'blacklist' has been defined in the same section.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_filterList = new EntityList(conf[_type == FilterType.Whitelist ? "whitelist" : "blacklist"]);
|
||||||
|
_exemptions = new EntityList(conf["exempt"]); // EntityList constructor checks for null value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the parameters of '<paramref name="msg"/>' are a match with filtering
|
||||||
|
/// rules defined in this instance.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="msg">An incoming message.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// True if the user or channel specified by '<paramref name="msg"/>' is filtered by
|
||||||
|
/// the configuration defined in this instance.
|
||||||
|
/// </returns>
|
||||||
|
public bool IsFiltered(SocketMessage msg)
|
||||||
|
{
|
||||||
|
if (FilterMode == FilterType.None) return false;
|
||||||
|
|
||||||
|
bool inFilter = FilterEntities.ExistsInList(msg);
|
||||||
|
|
||||||
|
if (FilterMode == FilterType.Whitelist)
|
||||||
|
{
|
||||||
|
if (!inFilter) return true;
|
||||||
|
return FilterExemptions.ExistsInList(msg);
|
||||||
|
}
|
||||||
|
else if (FilterMode == FilterType.Blacklist)
|
||||||
|
{
|
||||||
|
if (!inFilter) return false;
|
||||||
|
return !FilterExemptions.ExistsInList(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("this shouldn't happen");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -128,7 +128,7 @@ namespace Noikoio.RegexBot.Feature.RegexResponder
|
||||||
// Moderator bypass check
|
// Moderator bypass check
|
||||||
if (rule.AllowModBypass == true && srv.Moderators.ExistsInList(msg)) return;
|
if (rule.AllowModBypass == true && srv.Moderators.ExistsInList(msg)) return;
|
||||||
// Individual rule filtering check
|
// Individual rule filtering check
|
||||||
if (IsFiltered(rule, msg)) return;
|
if (rule.Filter.IsFiltered(msg)) return;
|
||||||
|
|
||||||
// And finally, pattern matching checks
|
// And finally, pattern matching checks
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
@ -220,26 +220,6 @@ namespace Noikoio.RegexBot.Feature.RegexResponder
|
||||||
|
|
||||||
return result.ToString();
|
return result.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsFiltered(RuleConfig r, SocketMessage m)
|
|
||||||
{
|
|
||||||
if (r.FilterMode == FilterType.None) return false;
|
|
||||||
|
|
||||||
bool inFilter = r.FilterList.ExistsInList(m);
|
|
||||||
|
|
||||||
if (r.FilterMode == FilterType.Whitelist)
|
|
||||||
{
|
|
||||||
if (!inFilter) return true;
|
|
||||||
return r.FilterExemptions.ExistsInList(m);
|
|
||||||
}
|
|
||||||
else if (r.FilterMode == FilterType.Blacklist)
|
|
||||||
{
|
|
||||||
if (!inFilter) return false;
|
|
||||||
return !r.FilterExemptions.ExistsInList(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // this shouldn't happen™
|
|
||||||
}
|
|
||||||
|
|
||||||
private string[] SplitParams(string cmd, int? limit = null)
|
private string[] SplitParams(string cmd, int? limit = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,9 +15,7 @@ namespace Noikoio.RegexBot.Feature.RegexResponder
|
||||||
private string _displayName;
|
private string _displayName;
|
||||||
private IEnumerable<Regex> _regex;
|
private IEnumerable<Regex> _regex;
|
||||||
private IEnumerable<string> _responses;
|
private IEnumerable<string> _responses;
|
||||||
private FilterType _filtermode;
|
private FilterList _filter;
|
||||||
private EntityList _filterlist;
|
|
||||||
private EntityList _filterexempt;
|
|
||||||
private int? _minLength;
|
private int? _minLength;
|
||||||
private int? _maxLength;
|
private int? _maxLength;
|
||||||
private bool _modBypass;
|
private bool _modBypass;
|
||||||
|
@ -26,9 +24,7 @@ namespace Noikoio.RegexBot.Feature.RegexResponder
|
||||||
public string DisplayName => _displayName;
|
public string DisplayName => _displayName;
|
||||||
public IEnumerable<Regex> Regex => _regex;
|
public IEnumerable<Regex> Regex => _regex;
|
||||||
public IEnumerable<string> Responses => _responses;
|
public IEnumerable<string> Responses => _responses;
|
||||||
public FilterType FilterMode => _filtermode;
|
public FilterList Filter => _filter;
|
||||||
public EntityList FilterList => _filterlist;
|
|
||||||
public EntityList FilterExemptions => _filterexempt;
|
|
||||||
public int? MinLength => _minLength;
|
public int? MinLength => _minLength;
|
||||||
public int? MaxLength => _maxLength;
|
public int? MaxLength => _maxLength;
|
||||||
public bool AllowModBypass => _modBypass;
|
public bool AllowModBypass => _modBypass;
|
||||||
|
@ -131,9 +127,7 @@ namespace Noikoio.RegexBot.Feature.RegexResponder
|
||||||
_responses = responses.ToArray();
|
_responses = responses.ToArray();
|
||||||
|
|
||||||
// (white|black)list filtering
|
// (white|black)list filtering
|
||||||
(_filtermode, _filterlist) = EntityList.GetFilterList(ruleconf);
|
_filter = new FilterList(ruleconf);
|
||||||
// filtering exemptions
|
|
||||||
_filterexempt = new EntityList(ruleconf["exempt"]);
|
|
||||||
|
|
||||||
// moderator bypass toggle - true by default, must be explicitly set to false
|
// moderator bypass toggle - true by default, must be explicitly set to false
|
||||||
bool? modoverride = ruleconf["AllowModBypass"]?.Value<bool>();
|
bool? modoverride = ruleconf["AllowModBypass"]?.Value<bool>();
|
||||||
|
|
Loading…
Reference in a new issue