mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
API: Documenting the search API
This commit is contained in:
parent
cb6ea80adb
commit
40e32a1689
@ -23,8 +23,10 @@ namespace Kyoo.Abstractions.Models.Attributes
|
||||
{
|
||||
/// <summary>
|
||||
/// An attribute to specify on apis to specify it's documentation's name and category.
|
||||
/// If this is applied on a method, the specified method will be exploded from the controller's page and be
|
||||
/// included on the specified tag page.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||
public class ApiDefinitionAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -54,14 +54,9 @@ namespace Kyoo.Abstractions.Models.Permissions
|
||||
/// If you don't put exactly two of those attributes, the permission attribute will be ill-formed and will
|
||||
/// lead to unspecified behaviors.
|
||||
/// </remarks>
|
||||
/// <param name="type">
|
||||
/// The type of the action
|
||||
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
||||
/// </param>
|
||||
/// <param name="type">The type of the action</param>
|
||||
public PartialPermissionAttribute(string type)
|
||||
{
|
||||
if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
|
||||
type = type[..^3];
|
||||
Type = type.ToLower();
|
||||
}
|
||||
|
||||
|
@ -91,17 +91,16 @@ namespace Kyoo.Abstractions.Models.Permissions
|
||||
/// </summary>
|
||||
/// <param name="type">
|
||||
/// The type of the action
|
||||
/// (if the type ends with api, it will be removed. This allow you to use nameof(YourApi)).
|
||||
/// </param>
|
||||
/// <param name="permission">The kind of permission needed.</param>
|
||||
/// <param name="permission">
|
||||
/// The kind of permission needed.
|
||||
/// </param>
|
||||
/// <param name="group">
|
||||
/// The group of this permission (allow grouped permission like overall.read
|
||||
/// for all read permissions of this group).
|
||||
/// </param>
|
||||
public PermissionAttribute(string type, Kind permission, Group group = Group.Overall)
|
||||
{
|
||||
if (type.EndsWith("API", StringComparison.OrdinalIgnoreCase))
|
||||
type = type[..^3];
|
||||
Type = type.ToLower();
|
||||
Kind = permission;
|
||||
Group = group;
|
||||
|
@ -36,7 +36,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/task", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[ResourceView]
|
||||
[PartialPermission(nameof(TaskApi), Group = Group.Admin)]
|
||||
[PartialPermission("Task", Group = Group.Admin)]
|
||||
[ApiDefinition("Tasks", Group = AdminGroup)]
|
||||
public class TaskApi : ControllerBase
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/genres")]
|
||||
[Route("api/genre", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[PartialPermission(nameof(GenreApi))]
|
||||
[PartialPermission(nameof(Genre))]
|
||||
[ApiDefinition("Genres", Group = MetadataGroup)]
|
||||
public class GenreApi : CrudApi<Genre>
|
||||
{
|
||||
|
@ -34,7 +34,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/provider", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[ResourceView]
|
||||
[PartialPermission(nameof(ProviderApi))]
|
||||
[PartialPermission(nameof(Provider))]
|
||||
[ApiDefinition("Providers", Group = MetadataGroup)]
|
||||
public class ProviderApi : CrudThumbsApi<Provider>
|
||||
{
|
||||
|
@ -39,7 +39,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/people", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[ResourceView]
|
||||
[PartialPermission(nameof(StaffApi))]
|
||||
[PartialPermission(nameof(People))]
|
||||
[ApiDefinition("Staff", Group = MetadataGroup)]
|
||||
public class StaffApi : CrudThumbsApi<People>
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/studios")]
|
||||
[Route("api/studio", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[PartialPermission(nameof(ShowApi))]
|
||||
[PartialPermission(nameof(Show))]
|
||||
[ApiDefinition("Studios", Group = MetadataGroup)]
|
||||
public class StudioApi : CrudApi<Studio>
|
||||
{
|
||||
|
@ -37,7 +37,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/collections")]
|
||||
[Route("api/collection", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[PartialPermission(nameof(CollectionApi))]
|
||||
[PartialPermission(nameof(Collection))]
|
||||
[ApiDefinition("Collections", Group = ResourcesGroup)]
|
||||
public class CollectionApi : CrudThumbsApi<Collection>
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/episode", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[ResourceView]
|
||||
[PartialPermission(nameof(EpisodeApi))]
|
||||
[PartialPermission(nameof(Episode))]
|
||||
[ApiDefinition("Episodes", Group = ResourcesGroup)]
|
||||
public class EpisodeApi : CrudThumbsApi<Episode>
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/library", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[ResourceView]
|
||||
[PartialPermission(nameof(LibraryApi), Group = Group.Admin)]
|
||||
[PartialPermission(nameof(Library), Group = Group.Admin)]
|
||||
[ApiDefinition("Library", Group = ResourcesGroup)]
|
||||
public class LibraryApi : CrudApi<Library>
|
||||
{
|
||||
|
@ -38,6 +38,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/item", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[ResourceView]
|
||||
[PartialPermission(nameof(LibraryItem))]
|
||||
[ApiDefinition("Items", Group = ResourcesGroup)]
|
||||
public class LibraryItemApi : BaseApi
|
||||
{
|
||||
@ -74,7 +75,7 @@ namespace Kyoo.Core.Api
|
||||
/// <response code="400">The filters or the sort parameters are invalid.</response>
|
||||
/// <response code="404">No library with the given ID or slug could be found.</response>
|
||||
[HttpGet]
|
||||
[Permission(nameof(LibraryItemApi), Kind.Read)]
|
||||
[PartialPermission(Kind.Read)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(RequestError))]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
|
194
src/Kyoo.Core/Views/Resources/SearchApi.cs
Normal file
194
src/Kyoo.Core/Views/Resources/SearchApi.cs
Normal file
@ -0,0 +1,194 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
using Kyoo.Abstractions.Models.Permissions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using static Kyoo.Abstractions.Models.Utils.Constants;
|
||||
|
||||
namespace Kyoo.Core.Api
|
||||
{
|
||||
/// <summary>
|
||||
/// An endpoint to search for every resources of kyoo. Searching for only a specific type of resource
|
||||
/// is available on the said endpoint.
|
||||
/// </summary>
|
||||
[Route("api/search/{query}")]
|
||||
[ApiController]
|
||||
[ResourceView]
|
||||
[ApiDefinition("Search", Group = ResourcesGroup)]
|
||||
public class SearchApi : ControllerBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The library manager used to modify or retrieve information in the data store.
|
||||
/// </summary>
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="SearchApi"/>.
|
||||
/// </summary>
|
||||
/// <param name="libraryManager">The library manager used to interact with the data store.</param>
|
||||
public SearchApi(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Global search
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search for collections, shows, episodes, staff, genre and studios at the same time
|
||||
/// </remarks>
|
||||
/// <param name="query">The query to search for.</param>
|
||||
/// <returns>A list of every resources found for the specified query.</returns>
|
||||
[HttpGet]
|
||||
[Permission(nameof(Collection), Kind.Read)]
|
||||
[Permission(nameof(Show), Kind.Read)]
|
||||
[Permission(nameof(Episode), Kind.Read)]
|
||||
[Permission(nameof(People), Kind.Read)]
|
||||
[Permission(nameof(Genre), Kind.Read)]
|
||||
[Permission(nameof(Studio), Kind.Read)]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<SearchResult>> Search(string query)
|
||||
{
|
||||
return new SearchResult
|
||||
{
|
||||
Query = query,
|
||||
Collections = await _libraryManager.Search<Collection>(query),
|
||||
Shows = await _libraryManager.Search<Show>(query),
|
||||
Episodes = await _libraryManager.Search<Episode>(query),
|
||||
People = await _libraryManager.Search<People>(query),
|
||||
Genres = await _libraryManager.Search<Genre>(query),
|
||||
Studios = await _libraryManager.Search<Studio>(query)
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search collections
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search for collections
|
||||
/// </remarks>
|
||||
/// <param name="query">The query to search for.</param>
|
||||
/// <returns>A list of collections found for the specified query.</returns>
|
||||
[HttpGet("collections")]
|
||||
[HttpGet("collection", Order = AlternativeRoute)]
|
||||
[Permission(nameof(Collection), Kind.Read)]
|
||||
[ApiDefinition("Collections")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Task<ICollection<Collection>> SearchCollections(string query)
|
||||
{
|
||||
return _libraryManager.Search<Collection>(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search shows
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search for shows
|
||||
/// </remarks>
|
||||
/// <param name="query">The query to search for.</param>
|
||||
/// <returns>A list of shows found for the specified query.</returns>
|
||||
[HttpGet("shows")]
|
||||
[HttpGet("show", Order = AlternativeRoute)]
|
||||
[Permission(nameof(Show), Kind.Read)]
|
||||
[ApiDefinition("Shows")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Task<ICollection<Show>> SearchShows(string query)
|
||||
{
|
||||
return _libraryManager.Search<Show>(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search episodes
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search for episodes
|
||||
/// </remarks>
|
||||
/// <param name="query">The query to search for.</param>
|
||||
/// <returns>A list of episodes found for the specified query.</returns>
|
||||
[HttpGet("episodes")]
|
||||
[HttpGet("episode", Order = AlternativeRoute)]
|
||||
[Permission(nameof(Episode), Kind.Read)]
|
||||
[ApiDefinition("Episodes")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Task<ICollection<Episode>> SearchEpisodes(string query)
|
||||
{
|
||||
return _libraryManager.Search<Episode>(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search staff
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search for staff
|
||||
/// </remarks>
|
||||
/// <param name="query">The query to search for.</param>
|
||||
/// <returns>A list of staff members found for the specified query.</returns>
|
||||
[HttpGet("staff")]
|
||||
[HttpGet("person", Order = AlternativeRoute)]
|
||||
[HttpGet("people", Order = AlternativeRoute)]
|
||||
[Permission(nameof(People), Kind.Read)]
|
||||
[ApiDefinition("Staff")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Task<ICollection<People>> SearchPeople(string query)
|
||||
{
|
||||
return _libraryManager.Search<People>(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search genres
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search for genres
|
||||
/// </remarks>
|
||||
/// <param name="query">The query to search for.</param>
|
||||
/// <returns>A list of genres found for the specified query.</returns>
|
||||
[HttpGet("genres")]
|
||||
[HttpGet("genre", Order = AlternativeRoute)]
|
||||
[Permission(nameof(Genre), Kind.Read)]
|
||||
[ApiDefinition("Genres")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Task<ICollection<Genre>> SearchGenres(string query)
|
||||
{
|
||||
return _libraryManager.Search<Genre>(query);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search studios
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Search for studios
|
||||
/// </remarks>
|
||||
/// <param name="query">The query to search for.</param>
|
||||
/// <returns>A list of studios found for the specified query.</returns>
|
||||
[HttpGet("studios")]
|
||||
[HttpGet("studio", Order = AlternativeRoute)]
|
||||
[Permission(nameof(Studio), Kind.Read)]
|
||||
[ApiDefinition("Studios")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public Task<ICollection<Studio>> SearchStudios(string query)
|
||||
{
|
||||
return _libraryManager.Search<Studio>(query);
|
||||
}
|
||||
}
|
||||
}
|
@ -37,7 +37,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/seasons")]
|
||||
[Route("api/season", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[PartialPermission(nameof(SeasonApi))]
|
||||
[PartialPermission(nameof(Season))]
|
||||
[ApiDefinition("Seasons", Group = ResourcesGroup)]
|
||||
public class SeasonApi : CrudThumbsApi<Season>
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ namespace Kyoo.Core.Api
|
||||
[Route("api/movie", Order = AlternativeRoute)]
|
||||
[Route("api/movies", Order = AlternativeRoute)]
|
||||
[ApiController]
|
||||
[PartialPermission(nameof(ShowApi))]
|
||||
[PartialPermission(nameof(Show))]
|
||||
[ApiDefinition("Shows", Group = ResourcesGroup)]
|
||||
public class ShowApi : CrudThumbsApi<Show>
|
||||
{
|
||||
|
@ -1,107 +0,0 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Kyoo.Abstractions.Controllers;
|
||||
using Kyoo.Abstractions.Models;
|
||||
using Kyoo.Abstractions.Models.Permissions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Kyoo.Core.Api
|
||||
{
|
||||
[Route("api/search/{query}")]
|
||||
[ApiController]
|
||||
public class SearchApi : ControllerBase
|
||||
{
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
|
||||
public SearchApi(ILibraryManager libraryManager)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
[Permission(nameof(Collection), Kind.Read)]
|
||||
[Permission(nameof(Show), Kind.Read)]
|
||||
[Permission(nameof(Episode), Kind.Read)]
|
||||
[Permission(nameof(People), Kind.Read)]
|
||||
[Permission(nameof(Genre), Kind.Read)]
|
||||
[Permission(nameof(Studio), Kind.Read)]
|
||||
public async Task<ActionResult<SearchResult>> Search(string query)
|
||||
{
|
||||
return new SearchResult
|
||||
{
|
||||
Query = query,
|
||||
Collections = await _libraryManager.Search<Collection>(query),
|
||||
Shows = await _libraryManager.Search<Show>(query),
|
||||
Episodes = await _libraryManager.Search<Episode>(query),
|
||||
People = await _libraryManager.Search<People>(query),
|
||||
Genres = await _libraryManager.Search<Genre>(query),
|
||||
Studios = await _libraryManager.Search<Studio>(query)
|
||||
};
|
||||
}
|
||||
|
||||
[HttpGet("collection")]
|
||||
[HttpGet("collections")]
|
||||
[Permission(nameof(Collection), Kind.Read)]
|
||||
public Task<ICollection<Collection>> SearchCollections(string query)
|
||||
{
|
||||
return _libraryManager.Search<Collection>(query);
|
||||
}
|
||||
|
||||
[HttpGet("show")]
|
||||
[HttpGet("shows")]
|
||||
[Permission(nameof(Show), Kind.Read)]
|
||||
public Task<ICollection<Show>> SearchShows(string query)
|
||||
{
|
||||
return _libraryManager.Search<Show>(query);
|
||||
}
|
||||
|
||||
[HttpGet("episode")]
|
||||
[HttpGet("episodes")]
|
||||
[Permission(nameof(Episode), Kind.Read)]
|
||||
public Task<ICollection<Episode>> SearchEpisodes(string query)
|
||||
{
|
||||
return _libraryManager.Search<Episode>(query);
|
||||
}
|
||||
|
||||
[HttpGet("people")]
|
||||
[Permission(nameof(People), Kind.Read)]
|
||||
public Task<ICollection<People>> SearchPeople(string query)
|
||||
{
|
||||
return _libraryManager.Search<People>(query);
|
||||
}
|
||||
|
||||
[HttpGet("genre")]
|
||||
[HttpGet("genres")]
|
||||
[Permission(nameof(Genre), Kind.Read)]
|
||||
public Task<ICollection<Genre>> SearchGenres(string query)
|
||||
{
|
||||
return _libraryManager.Search<Genre>(query);
|
||||
}
|
||||
|
||||
[HttpGet("studio")]
|
||||
[HttpGet("studios")]
|
||||
[Permission(nameof(Studio), Kind.Read)]
|
||||
public Task<ICollection<Studio>> SearchStudios(string query)
|
||||
{
|
||||
return _libraryManager.Search<Studio>(query);
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Kyoo.Swagger.Models;
|
||||
using NSwag;
|
||||
using NSwag.Generation.AspNetCore;
|
||||
|
||||
@ -49,13 +50,16 @@ namespace Kyoo.Swagger
|
||||
{
|
||||
if (!postProcess.ExtensionData.TryGetValue("x-tagGroups", out object list))
|
||||
return;
|
||||
List<dynamic> tagGroups = (List<dynamic>)list;
|
||||
List<TagGroups> tagGroups = (List<TagGroups>)list;
|
||||
postProcess.ExtensionData["x-tagGroups"] = tagGroups
|
||||
.OrderBy(x => x.name)
|
||||
.Select(x => new
|
||||
.OrderBy(x => x.Name)
|
||||
.Select(x =>
|
||||
{
|
||||
name = x.name.Substring(x.name.IndexOf(':') + 1),
|
||||
x.tags
|
||||
x.Name = x.Name[(x.Name.IndexOf(':') + 1)..];
|
||||
x.Tags = x.Tags
|
||||
.OrderBy(y => y)
|
||||
.ToList();
|
||||
return x;
|
||||
})
|
||||
.ToList();
|
||||
};
|
||||
|
@ -20,6 +20,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Kyoo.Abstractions.Models.Attributes;
|
||||
using Kyoo.Swagger.Models;
|
||||
using Namotion.Reflection;
|
||||
using NSwag;
|
||||
using NSwag.Generation.AspNetCore;
|
||||
@ -44,6 +45,10 @@ namespace Kyoo.Swagger
|
||||
ApiDefinitionAttribute def = context.ControllerType.GetCustomAttribute<ApiDefinitionAttribute>();
|
||||
string name = def?.Name ?? context.ControllerType.Name;
|
||||
|
||||
ApiDefinitionAttribute methodOverride = context.MethodInfo.GetCustomAttribute<ApiDefinitionAttribute>();
|
||||
if (methodOverride != null)
|
||||
name = methodOverride.Name;
|
||||
|
||||
context.OperationDescription.Operation.Tags.Add(name);
|
||||
if (context.Document.Tags.All(x => x.Name != name))
|
||||
{
|
||||
@ -58,20 +63,20 @@ namespace Kyoo.Swagger
|
||||
return true;
|
||||
|
||||
context.Document.ExtensionData ??= new Dictionary<string, object>();
|
||||
context.Document.ExtensionData.TryAdd("x-tagGroups", new List<dynamic>());
|
||||
List<dynamic> obj = (List<dynamic>)context.Document.ExtensionData["x-tagGroups"];
|
||||
dynamic existing = obj.FirstOrDefault(x => x.name == def.Group);
|
||||
context.Document.ExtensionData.TryAdd("x-tagGroups", new List<TagGroups>());
|
||||
List<TagGroups> obj = (List<TagGroups>)context.Document.ExtensionData["x-tagGroups"];
|
||||
TagGroups existing = obj.FirstOrDefault(x => x.Name == def.Group);
|
||||
if (existing != null)
|
||||
{
|
||||
if (!existing.tags.Contains(def.Name))
|
||||
existing.tags.Add(def.Name);
|
||||
if (!existing.Tags.Contains(def.Name))
|
||||
existing.Tags.Add(def.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
obj.Add(new
|
||||
obj.Add(new TagGroups
|
||||
{
|
||||
name = def.Group,
|
||||
tags = new List<string> { def.Name }
|
||||
Name = def.Group,
|
||||
Tags = new List<string> { def.Name }
|
||||
});
|
||||
}
|
||||
|
||||
@ -88,19 +93,19 @@ namespace Kyoo.Swagger
|
||||
/// </param>
|
||||
public static void AddLeftoversToOthersGroup(this OpenApiDocument postProcess)
|
||||
{
|
||||
List<dynamic> tagGroups = (List<dynamic>)postProcess.ExtensionData["x-tagGroups"];
|
||||
List<TagGroups> tagGroups = (List<TagGroups>)postProcess.ExtensionData["x-tagGroups"];
|
||||
List<string> tagsWithoutGroup = postProcess.Tags
|
||||
.Select(x => x.Name)
|
||||
.Where(x => tagGroups
|
||||
.SelectMany<dynamic, string>(y => y.tags)
|
||||
.SelectMany(y => y.Tags)
|
||||
.All(y => y != x))
|
||||
.ToList();
|
||||
if (tagsWithoutGroup.Any())
|
||||
{
|
||||
tagGroups.Add(new
|
||||
tagGroups.Add(new TagGroups
|
||||
{
|
||||
name = "Others",
|
||||
tags = tagsWithoutGroup
|
||||
Name = "Others",
|
||||
Tags = tagsWithoutGroup
|
||||
});
|
||||
}
|
||||
}
|
||||
|
42
src/Kyoo.Swagger/Models/TagGroups.cs
Normal file
42
src/Kyoo.Swagger/Models/TagGroups.cs
Normal file
@ -0,0 +1,42 @@
|
||||
// Kyoo - A portable and vast media library solution.
|
||||
// Copyright (c) Kyoo.
|
||||
//
|
||||
// See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||
//
|
||||
// Kyoo is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// any later version.
|
||||
//
|
||||
// Kyoo is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using NSwag;
|
||||
|
||||
namespace Kyoo.Swagger.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A class representing a group of tags in the <see cref="OpenApiDocument"/>
|
||||
/// </summary>
|
||||
public class TagGroups
|
||||
{
|
||||
/// <summary>
|
||||
/// The name of the tag group.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The list of tags in this group.
|
||||
/// </summary>
|
||||
[JsonProperty(PropertyName = "tags")]
|
||||
public List<string> Tags { get; set; }
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user