diff --git a/Shoko.Server/API/APIExtensions.cs b/Shoko.Server/API/APIExtensions.cs index 05a7c7095..5594efd16 100644 --- a/Shoko.Server/API/APIExtensions.cs +++ b/Shoko.Server/API/APIExtensions.cs @@ -122,8 +122,9 @@ public static IServiceCollection AddAPI(this IServiceCollection services) options.AddPlugins(); - options.MapType(() => new OpenApiSchema { Type = "string" }); - options.MapType(() => new OpenApiSchema { Type = "string" }); + options.SchemaFilter>(); + options.SchemaFilter>(); + options.SchemaFilter>(); options.CustomSchemaIds(GetTypeName); }); diff --git a/Shoko.Server/API/Swagger/EnumSchemaFilter.cs b/Shoko.Server/API/Swagger/EnumSchemaFilter.cs new file mode 100644 index 000000000..cd9226c09 --- /dev/null +++ b/Shoko.Server/API/Swagger/EnumSchemaFilter.cs @@ -0,0 +1,21 @@ +using System; +using Microsoft.OpenApi.Any; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Shoko.Server.API.Swagger; + +public class EnumSchemaFilter : ISchemaFilter where T : struct, Enum +{ + private string[] _names; + + public void Apply(OpenApiSchema model, SchemaFilterContext context) + { + if (!context.Type.IsEnum) return; + if (context.Type != typeof(T)) return; + + model.Enum.Clear(); + _names ??= Enum.GetNames(); + Array.ForEach(_names, name => model.Enum.Add(new OpenApiString(name))); + } +} diff --git a/Shoko.Server/API/v3/Controllers/FilterController.cs b/Shoko.Server/API/v3/Controllers/FilterController.cs index 0f658a36f..50e8bda73 100644 --- a/Shoko.Server/API/v3/Controllers/FilterController.cs +++ b/Shoko.Server/API/v3/Controllers/FilterController.cs @@ -92,12 +92,14 @@ public ActionResult AddNewFilter(Filter.Input.CreateOrUpdateFilterBody b /// /// Lists the available expressions. - /// The word "Filterable" is used a lot. It is a generic word for a series or group, depending on what the filter is set to apply to. - /// Expression: The identifier used to create the expression. eg. And, Not, HasTag. - /// Type: Parameters have a type, and this is the type that needs to match. - /// Left, Right, Parameter, and SecondParameter show what type the expression supports as parameters. - /// Left and Right are Expressions or Selectors. Parameters are constants. /// + /// + /// The word "Filterable" is used a lot. It is a generic word for a series or group, depending on what the filter is set to apply to. + /// Expression: The identifier used to create the expression. eg. And, Not, HasTag. + /// Type: Parameters have a type, and this is the type that needs to match. + /// Left, Right, Parameter, and SecondParameter show what type the expression supports as parameters. + /// Left and Right are Expressions or Selectors. Parameters are constants. + /// [HttpGet("Expressions")] public ActionResult GetExpressions() { @@ -163,12 +165,14 @@ public ActionResult AddNewFilter(Filter.Input.CreateOrUpdateFilterBody b /// /// Lists the available sorting expressions. These are basically selectors that the filter system uses to sort. - /// The word "Filterable" is used a lot. It is a generic word for a series or group, depending on what the filter is set to apply to. - /// Type: The identifier used to create the expression. eg. AddedDate. - /// IsInverted: Whether the sorting should be in descending order. - /// Next: If the expression returns equal values, it defers to the next expression to sort more predictably. - /// For example, MissingEpisodeCount,Descending -> AirDate, Descending would have thing with the most missing episodes, then the last aired first. /// + /// + /// The word "Filterable" is used a lot. It is a generic word for a series or group, depending on what the filter is set to apply to. + /// Type: The identifier used to create the expression. eg. AddedDate. + /// IsInverted: Whether the sorting should be in descending order. + /// Next: If the expression returns equal values, it defers to the next expression to sort more predictably. + /// For example, MissingEpisodeCount,Descending -> AirDate, Descending would have thing with the most missing episodes, then the last aired first. + /// [HttpGet("SortingCriteria")] public ActionResult GetSortingCriteria() { diff --git a/Shoko.Server/API/v3/Models/Shoko/Filter.cs b/Shoko.Server/API/v3/Models/Shoko/Filter.cs index 09670030c..4237988b1 100644 --- a/Shoko.Server/API/v3/Models/Shoko/Filter.cs +++ b/Shoko.Server/API/v3/Models/Shoko/Filter.cs @@ -69,39 +69,39 @@ public class FilterIDs : IDs public class FilterCondition { /// - /// Condition Type. What it does. - /// This is not the GroupFilterConditionType, but the type of the FilterExpression, with 'Expression' removed. + /// Condition Type. What it does.
+ /// This is not the GroupFilterConditionType, but the type of the FilterExpression, with 'Expression' removed.
/// ex. And, Or, Not, HasAudioLanguage ///
[Required] public string Type { get; set; } /// - /// The first, or left, child expression. - /// This might be another logic operator like And, a selector for data like Today's Date, or an expression like HasAudioLanguage. + /// The first, or left, child expression.
+ /// This might be another logic operator like And, a selector for data like Today's Date, or an expression like HasAudioLanguage.
/// Whether this is included depends on the expression. ///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public FilterCondition? Left { get; set; } /// - /// The second, or right, child expression. - /// This might be another logic operator like And, a selector for data like Today's Date, or an expression like HasAudioLanguage. + /// The second, or right, child expression.
+ /// This might be another logic operator like And, a selector for data like Today's Date, or an expression like HasAudioLanguage.
/// Whether this is included depends on the expression. ///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public FilterCondition? Right { get; set; } /// - /// The actual value to compare. Dependent on the expression type. + /// The actual value to compare. Dependent on the expression type.
/// Coerced this to string to make things easier. ///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] public string? Parameter { get; set; } /// - /// The actual value to compare. Dependent on the expression type. - /// Very few things have a second parameter. Seasons are one of them + /// The actual value to compare. Dependent on the expression type.
+ /// Very few things have a second parameter. Seasons are one of them
/// Coerced this to string to make things easier. ///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] @@ -111,7 +111,7 @@ public class FilterCondition public class FilterExpressionHelp { /// - /// The internal type name of the FilterExpression + /// The internal type name of the FilterExpression
/// This is what you give the API, not actually the internal type (it is the internal type without the word Expression) ///
[Required] @@ -138,7 +138,7 @@ public class FilterExpressionHelp public FilterExpressionParameterType? Left { get; init; } /// - /// The parameter types that the property requires + /// The parameter types that the property requires
/// If multiple are given, then at least one is required ///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] @@ -146,7 +146,7 @@ public class FilterExpressionHelp public FilterExpressionParameterType? Right { get; init; } /// - /// The parameter type that the property requires. + /// The parameter type that the property requires.
/// This will always be a string for simplicity in type safety, but the type is what it expects ///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] @@ -164,7 +164,7 @@ public class FilterExpressionHelp public string[]? PossibleSecondParameters { get; init; } /// - /// The parameter type that the property requires + /// The parameter type that the property requires
/// This will always be a string for simplicity in type safety, but the type is what it expects ///
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)] @@ -188,8 +188,8 @@ public bool ShouldSerializePossibleSecondParameters() } /// - /// The type of the parameter. Expressions return a boolean, Selectors return the type of their name, and the rest are values from the user. - /// Dates are in yyyy-MM-dd format + /// The type of the parameter. Expressions return a boolean, Selectors return the type of their name, and the rest are values from the user.
+ /// Dates are in yyyy-MM-dd format
/// TimeSpans are in d:HH:mm:ss.ffff format (f is milliseconds) ///
public enum FilterExpressionParameterType @@ -208,7 +208,7 @@ public enum FilterExpressionParameterType public class SortingCriteriaHelp { /// - /// The internal type name of the FilterExpression + /// The internal type name of the FilterExpression
/// This is what you give the API, not actually the internal type (it is the internal type without the word Expression) ///
[Required] @@ -222,16 +222,16 @@ public class SortingCriteriaHelp } /// - /// Sorting Criteria hold info on how Group Filters sort their items. + /// Sorting Criteria hold info on how Group Filters sort their items.
/// It is in a List to follow an OrderBy().ThenBy().ThenBy(), allowing /// consistent results with fallbacks. ///
public class SortingCriteria { /// - /// The sorting type. What it is sorted on. - /// This is not the GroupFilterSorting, but the type of the SortingExpression, with 'Expression' removed. - /// ex. And, Or, Not, HasAudioLanguage + /// The sorting type. What it is sorted on.
+ /// This is not the GroupFilterSorting, but the type of the SortingExpression, with 'Expression' removed.
+ /// ex. And, Or, Not, HasAudioLanguage
///
[Required] public string Type { get; set; } diff --git a/Shoko.Server/Filters/Info/InSeasonExpression.cs b/Shoko.Server/Filters/Info/InSeasonExpression.cs index 45deea3e2..a0d5e152e 100644 --- a/Shoko.Server/Filters/Info/InSeasonExpression.cs +++ b/Shoko.Server/Filters/Info/InSeasonExpression.cs @@ -17,7 +17,8 @@ public InSeasonExpression() { } public AnimeSeason Season { get; set; } public override bool TimeDependent => false; public override bool UserDependent => false; - public override string HelpDescription => "This passes if any of the anime aired in the season given in the parameters"; + public override string HelpDescription => "This passes if any of the anime aired in the season given in the parameters." + + "The first parameter is the Year, while the second parameter is the Season."; public override string[] HelpPossibleSecondParameters => new[] { AnimeSeason.Winter.ToString(), AnimeSeason.Spring.ToString(),