From 98a2bfff96014657540ba4bb284f16c61ceb9677 Mon Sep 17 00:00:00 2001 From: da3dsoul Date: Wed, 4 Oct 2023 23:02:15 -0400 Subject: [PATCH] Add more string expressions --- .../Logic/Strings/StringEndsWithExpression.cs | 85 +++++++++++++++++++ .../Strings/StringRegexMatchesExpression.cs | 84 ++++++++++++++++++ .../Strings/StringStartsWithExpression.cs | 85 +++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 Shoko.Server/Filters/Logic/Strings/StringEndsWithExpression.cs create mode 100644 Shoko.Server/Filters/Logic/Strings/StringRegexMatchesExpression.cs create mode 100644 Shoko.Server/Filters/Logic/Strings/StringStartsWithExpression.cs diff --git a/Shoko.Server/Filters/Logic/Strings/StringEndsWithExpression.cs b/Shoko.Server/Filters/Logic/Strings/StringEndsWithExpression.cs new file mode 100644 index 000000000..7b5e1dc92 --- /dev/null +++ b/Shoko.Server/Filters/Logic/Strings/StringEndsWithExpression.cs @@ -0,0 +1,85 @@ +using System; +using Shoko.Server.Filters.Interfaces; + +namespace Shoko.Server.Filters.Logic.Strings; + +public class StringEndsWithExpression : FilterExpression, IWithStringSelectorParameter, IWithSecondStringSelectorParameter, IWithStringParameter +{ + public StringEndsWithExpression(FilterExpression left, FilterExpression right) + { + Left = left; + Right = right; + } + + public StringEndsWithExpression(FilterExpression left, string parameter) + { + Left = left; + Parameter = parameter; + } + + public StringEndsWithExpression() { } + + public FilterExpression Left { get; set; } + public FilterExpression Right { get; set; } + public string Parameter { get; set; } + public override bool TimeDependent => Left.TimeDependent || (Right?.TimeDependent ?? false); + public override bool UserDependent => Left.UserDependent || (Right?.UserDependent ?? false); + public override string HelpDescription => "This passes if the left selector ends with either the right selector or the parameter"; + + public override bool Evaluate(IFilterable filterable) + { + var left = Left.Evaluate(filterable); + var right = Parameter ?? Right?.Evaluate(filterable); + if (string.IsNullOrEmpty(left) || string.IsNullOrEmpty(right)) + { + return false; + } + + return left.EndsWith(right, StringComparison.InvariantCultureIgnoreCase); + } + + protected bool Equals(StringEndsWithExpression other) + { + return base.Equals(other) && Equals(Left, other.Left) && Equals(Right, other.Right) && Parameter == other.Parameter; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + + return Equals((StringEndsWithExpression)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(base.GetHashCode(), Left, Right, Parameter); + } + + public static bool operator ==(StringEndsWithExpression left, StringEndsWithExpression right) + { + return Equals(left, right); + } + + public static bool operator !=(StringEndsWithExpression left, StringEndsWithExpression right) + { + return !Equals(left, right); + } + + public override bool IsType(FilterExpression expression) + { + return expression is StringEndsWithExpression exp && Left.IsType(exp.Left) && (Right?.IsType(exp.Right) ?? true); + } +} diff --git a/Shoko.Server/Filters/Logic/Strings/StringRegexMatchesExpression.cs b/Shoko.Server/Filters/Logic/Strings/StringRegexMatchesExpression.cs new file mode 100644 index 000000000..95978a99b --- /dev/null +++ b/Shoko.Server/Filters/Logic/Strings/StringRegexMatchesExpression.cs @@ -0,0 +1,84 @@ +using System; +using System.Text.RegularExpressions; +using Shoko.Server.Filters.Interfaces; + +namespace Shoko.Server.Filters.Logic.Strings; + +public class StringRegexMatchesExpression : FilterExpression, IWithStringSelectorParameter, IWithStringParameter +{ + private readonly Regex _regex; + public StringRegexMatchesExpression(FilterExpression left, string parameter) + { + Left = left; + Parameter = parameter; + try + { + _regex = new Regex(parameter, RegexOptions.Compiled | RegexOptions.IgnoreCase); + } + catch { /* ignore */ } + } + + public StringRegexMatchesExpression() { } + + public FilterExpression Left { get; set; } + public string Parameter { get; set; } + public override bool TimeDependent => Left.TimeDependent; + public override bool UserDependent => Left.UserDependent; + public override string HelpDescription => "This passes if the left selector matches the regular expression given in the parameter"; + + public override bool Evaluate(IFilterable filterable) + { + var left = Left.Evaluate(filterable); + if (string.IsNullOrEmpty(left) || _regex == null) + { + return false; + } + + return _regex.IsMatch(left); + } + + protected bool Equals(StringRegexMatchesExpression other) + { + return base.Equals(other) && Equals(Left, other.Left) && Parameter == other.Parameter; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + + return Equals((StringRegexMatchesExpression)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(base.GetHashCode(), Left, Parameter); + } + + public static bool operator ==(StringRegexMatchesExpression left, StringRegexMatchesExpression right) + { + return Equals(left, right); + } + + public static bool operator !=(StringRegexMatchesExpression left, StringRegexMatchesExpression right) + { + return !Equals(left, right); + } + + public override bool IsType(FilterExpression expression) + { + return expression is StringRegexMatchesExpression exp && Left.IsType(exp.Left); + } +} diff --git a/Shoko.Server/Filters/Logic/Strings/StringStartsWithExpression.cs b/Shoko.Server/Filters/Logic/Strings/StringStartsWithExpression.cs new file mode 100644 index 000000000..d0d1074fd --- /dev/null +++ b/Shoko.Server/Filters/Logic/Strings/StringStartsWithExpression.cs @@ -0,0 +1,85 @@ +using System; +using Shoko.Server.Filters.Interfaces; + +namespace Shoko.Server.Filters.Logic.Strings; + +public class StringStartsWithExpression : FilterExpression, IWithStringSelectorParameter, IWithSecondStringSelectorParameter, IWithStringParameter +{ + public StringStartsWithExpression(FilterExpression left, FilterExpression right) + { + Left = left; + Right = right; + } + + public StringStartsWithExpression(FilterExpression left, string parameter) + { + Left = left; + Parameter = parameter; + } + + public StringStartsWithExpression() { } + + public FilterExpression Left { get; set; } + public FilterExpression Right { get; set; } + public string Parameter { get; set; } + public override bool TimeDependent => Left.TimeDependent || (Right?.TimeDependent ?? false); + public override bool UserDependent => Left.UserDependent || (Right?.UserDependent ?? false); + public override string HelpDescription => "This passes if the left selector starts with either the right selector or the parameter"; + + public override bool Evaluate(IFilterable filterable) + { + var left = Left.Evaluate(filterable); + var right = Parameter ?? Right?.Evaluate(filterable); + if (string.IsNullOrEmpty(left) || string.IsNullOrEmpty(right)) + { + return false; + } + + return left.StartsWith(right, StringComparison.InvariantCultureIgnoreCase); + } + + protected bool Equals(StringStartsWithExpression other) + { + return base.Equals(other) && Equals(Left, other.Left) && Equals(Right, other.Right) && Parameter == other.Parameter; + } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) + { + return false; + } + + if (ReferenceEquals(this, obj)) + { + return true; + } + + if (obj.GetType() != this.GetType()) + { + return false; + } + + return Equals((StringStartsWithExpression)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(base.GetHashCode(), Left, Right, Parameter); + } + + public static bool operator ==(StringStartsWithExpression left, StringStartsWithExpression right) + { + return Equals(left, right); + } + + public static bool operator !=(StringStartsWithExpression left, StringStartsWithExpression right) + { + return !Equals(left, right); + } + + public override bool IsType(FilterExpression expression) + { + return expression is StringStartsWithExpression exp && Left.IsType(exp.Left) && (Right?.IsType(exp.Right) ?? true); + } +}