Skip to content

Commit

Permalink
feat: add available/preferred image type expressions
Browse files Browse the repository at this point in the history
Added four new filter expressions;

- `HasAvailableImageExpression` — Check if a single series or group of series has the image type available.

- `HasPreferredImageExpression` — Check if a single series or group of series has an image set as preferred  for the image type.

- `AvailableImageTypesSelector` — Get a set of the available image types for a single series or group of series (as strings) to use with the string set expressions in case you need to do more advanced checks.

- `PreferredImageTypesSelector` — Get a set of the preferred image types for a single series or group of series (as strings) to use with the string set expressions in case you need to do more advanced checks.

Closes #1187
  • Loading branch information
revam committed Oct 19, 2024
1 parent 98aa738 commit d79b2d5
Show file tree
Hide file tree
Showing 10 changed files with 358 additions and 2 deletions.
12 changes: 10 additions & 2 deletions Shoko.Server/Filters/FilterExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ public static Filterable ToFilterable(this SVR_AnimeSeries series)
series.Years,
SeasonsDelegate = () =>
series.AniDB_Anime?.Seasons.ToHashSet() ?? [],
AvailableImageTypesDelegate = () =>
series.GetAvailableImageTypes(),
PreferredImageTypesDelegate = () =>
series.GetPreferredImageTypes(),
HasTmdbLinkDelegate = () =>
series.TmdbShowCrossReferences.Count is > 0 || series.TmdbMovieCrossReferences.Count is > 0,
HasMissingTmdbLinkDelegate = () =>
Expand Down Expand Up @@ -199,9 +203,13 @@ public static Filterable ToFilterable(this SVR_AnimeGroup group)
CustomTagsDelegate = () =>
group.CustomTags.Select(a => a.TagName).ToHashSet(),
YearsDelegate = () =>
group.Years.ToHashSet(),
group.Years,
SeasonsDelegate = () =>
group.Seasons.ToHashSet(),
group.Seasons,
AvailableImageTypesDelegate = () =>
group.AvailableImageTypes,
PreferredImageTypesDelegate = () =>
group.PreferredImageTypes,
HasTmdbLinkDelegate = () =>
series.Any(a => a.TmdbShowCrossReferences.Count is > 0 || a.TmdbMovieCrossReferences.Count is > 0),
HasMissingTmdbLinkDelegate = () =>
Expand Down
17 changes: 17 additions & 0 deletions Shoko.Server/Filters/Filterable.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Shoko.Models.Enums;
using Shoko.Plugin.Abstractions.Enums;
using Shoko.Server.Filters.Interfaces;

namespace Shoko.Server.Filters;
Expand Down Expand Up @@ -45,6 +46,8 @@ public class Filterable : IFilterable
private readonly Lazy<int> _totalEpisodeCount;
private readonly Lazy<IReadOnlySet<string>> _videoSources;
private readonly Lazy<IReadOnlySet<int>> _years;
private readonly Lazy<IReadOnlySet<ImageEntityType>> _availableImageTypes;
private readonly Lazy<IReadOnlySet<ImageEntityType>> _preferredImageTypes;

public string Name => _name.Value;

Expand Down Expand Up @@ -123,6 +126,20 @@ public Func<IReadOnlySet<int>> YearsDelegate
init => _seasons = new Lazy<IReadOnlySet<(int year, AnimeSeason season)>>(value);
}

public IReadOnlySet<ImageEntityType> AvailableImageTypes => _availableImageTypes.Value;

public Func<IReadOnlySet<ImageEntityType>> AvailableImageTypesDelegate
{
init => _availableImageTypes = new Lazy<IReadOnlySet<ImageEntityType>>(value);
}

public IReadOnlySet<ImageEntityType> PreferredImageTypes => _preferredImageTypes.Value;

public Func<IReadOnlySet<ImageEntityType>> PreferredImageTypesDelegate
{
init => _preferredImageTypes = new Lazy<IReadOnlySet<ImageEntityType>>(value);
}

public bool HasTmdbLink => _hasTmdbLink.Value;

public Func<bool> HasTmdbLinkDelegate
Expand Down
81 changes: 81 additions & 0 deletions Shoko.Server/Filters/Info/HasAvailableImageExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Linq;
using Shoko.Plugin.Abstractions.Enums;
using Shoko.Server.Filters.Interfaces;
using Shoko.Server.Repositories;

namespace Shoko.Server.Filters.Info;

public class HasAvailableImageExpression : FilterExpression<bool>, IWithStringParameter
{
public HasAvailableImageExpression(string parameter)
{
if (Enum.TryParse<ImageEntityType>(parameter, out var imageEntityType))
imageEntityType = ImageEntityType.None;
Parameter = imageEntityType;
}

public HasAvailableImageExpression() { }

public ImageEntityType Parameter { get; set; }
public override bool TimeDependent => true;
public override bool UserDependent => false;
public override string HelpDescription => "This condition passes if any of the anime has the available image type.";
public override string[] HelpPossibleParameters => RepoFactory.AnimeSeries.GetAllImageTypes().Select(a => a.ToString()).ToArray();

string IWithStringParameter.Parameter
{
get => Parameter.ToString();
set
{
if (Enum.TryParse<ImageEntityType>(value, out var imageEntityType))
imageEntityType = ImageEntityType.None;
Parameter = imageEntityType;
}
}

public override bool Evaluate(IFilterable filterable, IFilterableUserInfo userInfo)
{
return filterable.AvailableImageTypes.Contains(Parameter);
}

protected bool Equals(HasAvailableImageExpression other)
{
return base.Equals(other) && 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((HasAvailableImageExpression)obj);
}

public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode(), Parameter);
}

public static bool operator ==(HasAvailableImageExpression left, HasAvailableImageExpression right)
{
return Equals(left, right);
}

public static bool operator !=(HasAvailableImageExpression left, HasAvailableImageExpression right)
{
return !Equals(left, right);
}
}
81 changes: 81 additions & 0 deletions Shoko.Server/Filters/Info/HasPreferredImageExpression.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System;
using System.Linq;
using Shoko.Plugin.Abstractions.Enums;
using Shoko.Server.Filters.Interfaces;
using Shoko.Server.Repositories;

namespace Shoko.Server.Filters.Info;

public class HasPreferredImageExpression : FilterExpression<bool>, IWithStringParameter
{
public HasPreferredImageExpression(string parameter)
{
if (Enum.TryParse<ImageEntityType>(parameter, out var imageEntityType))
imageEntityType = ImageEntityType.None;
Parameter = imageEntityType;
}

public HasPreferredImageExpression() { }

public ImageEntityType Parameter { get; set; }
public override bool TimeDependent => true;
public override bool UserDependent => false;
public override string HelpDescription => "This condition passes if any of the anime has the preferred image type.";
public override string[] HelpPossibleParameters => RepoFactory.AnimeSeries.GetAllImageTypes().Select(a => a.ToString()).ToArray();

string IWithStringParameter.Parameter
{
get => Parameter.ToString();
set
{
if (Enum.TryParse<ImageEntityType>(value, out var imageEntityType))
imageEntityType = ImageEntityType.None;
Parameter = imageEntityType;
}
}

public override bool Evaluate(IFilterable filterable, IFilterableUserInfo userInfo)
{
return filterable.PreferredImageTypes.Contains(Parameter);
}

protected bool Equals(HasPreferredImageExpression other)
{
return base.Equals(other) && 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((HasPreferredImageExpression)obj);
}

public override int GetHashCode()
{
return HashCode.Combine(base.GetHashCode(), Parameter);
}

public static bool operator ==(HasPreferredImageExpression left, HasPreferredImageExpression right)
{
return Equals(left, right);
}

public static bool operator !=(HasPreferredImageExpression left, HasPreferredImageExpression right)
{
return !Equals(left, right);
}
}
11 changes: 11 additions & 0 deletions Shoko.Server/Filters/Interfaces/IFilterable.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using Shoko.Models.Enums;
using Shoko.Plugin.Abstractions.Enums;

namespace Shoko.Server.Filters.Interfaces;

Expand Down Expand Up @@ -61,6 +62,16 @@ public interface IFilterable
/// </summary>
IReadOnlySet<(int year, AnimeSeason season)> Seasons { get; }

/// <summary>
/// Available image types.
/// </summary>
IReadOnlySet<ImageEntityType> AvailableImageTypes { get; }

/// <summary>
/// Preferred image types.
/// </summary>
IReadOnlySet<ImageEntityType> PreferredImageTypes { get; }

/// <summary>
/// Has at least one TMDB Link
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Linq;
using Shoko.Server.Filters.Interfaces;

namespace Shoko.Server.Filters.Selectors.StringSetSelectors;

public class AvailableImageTypesSelector : FilterExpression<IReadOnlySet<string>>
{
public override bool TimeDependent => false;
public override bool UserDependent => false;
public override string HelpDescription => "This returns a set of all the available image types in a filterable.";
public override FilterExpressionGroup Group => FilterExpressionGroup.Selector;

public override IReadOnlySet<string> Evaluate(IFilterable filterable, IFilterableUserInfo userInfo)
{
return filterable.AvailableImageTypes.Select(t => t.ToString()).ToHashSet();
}

protected bool Equals(AvailableImageTypesSelector other)
{
return base.Equals(other);
}

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((AvailableImageTypesSelector)obj);
}

public override int GetHashCode()
{
return GetType().FullName!.GetHashCode();
}

public static bool operator ==(AvailableImageTypesSelector left, AvailableImageTypesSelector right)
{
return Equals(left, right);
}

public static bool operator !=(AvailableImageTypesSelector left, AvailableImageTypesSelector right)
{
return !Equals(left, right);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using System.Collections.Generic;
using System.Linq;
using Shoko.Server.Filters.Interfaces;

namespace Shoko.Server.Filters.Selectors.StringSetSelectors;

public class PreferredImageTypesSelector : FilterExpression<IReadOnlySet<string>>
{
public override bool TimeDependent => false;
public override bool UserDependent => false;
public override string HelpDescription => "This returns a set of all the preferred image types in a filterable.";
public override FilterExpressionGroup Group => FilterExpressionGroup.Selector;

public override IReadOnlySet<string> Evaluate(IFilterable filterable, IFilterableUserInfo userInfo)
{
return filterable.PreferredImageTypes.Select(t => t.ToString()).ToHashSet();
}

protected bool Equals(PreferredImageTypesSelector other)
{
return base.Equals(other);
}

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((PreferredImageTypesSelector)obj);
}

public override int GetHashCode()
{
return GetType().FullName!.GetHashCode();
}

public static bool operator ==(PreferredImageTypesSelector left, PreferredImageTypesSelector right)
{
return Equals(left, right);
}

public static bool operator !=(PreferredImageTypesSelector left, PreferredImageTypesSelector right)
{
return !Equals(left, right);
}
}
8 changes: 8 additions & 0 deletions Shoko.Server/Models/SVR_AnimeGroup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ public List<SVR_AnimeSeries> AllSeries

public HashSet<(int Year, AnimeSeason Season)> Seasons => AllSeries.SelectMany(a => a.AniDB_Anime?.Seasons ?? []).ToHashSet();

public HashSet<ImageEntityType> AvailableImageTypes => AllSeries
.SelectMany(ser => ser.GetAvailableImageTypes())
.ToHashSet();

public HashSet<ImageEntityType> PreferredImageTypes => AllSeries
.SelectMany(ser => ser.GetPreferredImageTypes())
.ToHashSet();

public List<SVR_AniDB_Anime_Title> Titles => AllSeries
.SelectMany(ser => ser.AniDB_Anime?.Titles ?? [])
.DistinctBy(tit => tit.AniDB_Anime_TitleID)
Expand Down
Loading

0 comments on commit d79b2d5

Please sign in to comment.