You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
jellyfin/Jellyfin.Api/Controllers/FilterController.cs

219 lines
9.2 KiB

#nullable enable
#pragma warning disable CA1801
using System;
using System.Linq;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Entities.Movies;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Playlists;
using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Querying;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Jellyfin.Api.Controllers
{
/// <summary>
/// Filters controller.
/// </summary>
[Authorize]
public class FilterController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
private readonly IUserManager _userManager;
/// <summary>
/// Initializes a new instance of the <see cref="FilterController"/> class.
/// </summary>
/// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
public FilterController(ILibraryManager libraryManager, IUserManager userManager)
{
_libraryManager = libraryManager;
_userManager = userManager;
}
/// <summary>
/// Gets legacy query filters.
/// </summary>
/// <param name="userId">Optional. User id.</param>
/// <param name="parentId">Optional. Parent id.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
/// <param name="mediaTypes">Optional. Filter by MediaType. Allows multiple, comma delimited.</param>
/// <returns>Legacy query filters.</returns>
[HttpGet("/Items/Filters")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryFiltersLegacy> GetQueryFiltersLegacy(
[FromQuery] Guid? userId,
[FromQuery] string? parentId,
[FromQuery] string? includeItemTypes,
[FromQuery] string? mediaTypes)
{
var parentItem = string.IsNullOrEmpty(parentId)
? null
: _libraryManager.GetItemById(parentId);
var user = userId == null || userId == Guid.Empty
? null
: _userManager.GetUserById(userId.Value);
if (string.Equals(includeItemTypes, nameof(BoxSet), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, nameof(Playlist), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, nameof(Trailer), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
{
parentItem = null;
}
var item = string.IsNullOrEmpty(parentId)
? user == null
? _libraryManager.RootFolder
: _libraryManager.GetUserRootFolder()
: parentItem;
var query = new InternalItemsQuery
{
User = user,
MediaTypes = (mediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries),
IncludeItemTypes = (includeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries),
Recursive = true,
EnableTotalRecordCount = false,
DtoOptions = new DtoOptions
{
Fields = new[] { ItemFields.Genres, ItemFields.Tags },
EnableImages = false,
EnableUserData = false
}
};
var itemList = ((Folder)item!).GetItemList(query);
return new QueryFiltersLegacy
{
Years = itemList.Select(i => i.ProductionYear ?? -1)
.Where(i => i > 0)
.Distinct()
.OrderBy(i => i)
.ToArray(),
Genres = itemList.SelectMany(i => i.Genres)
.DistinctNames()
.OrderBy(i => i)
.ToArray(),
Tags = itemList
.SelectMany(i => i.Tags)
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(i => i)
.ToArray(),
OfficialRatings = itemList
.Select(i => i.OfficialRating)
.Where(i => !string.IsNullOrWhiteSpace(i))
.Distinct(StringComparer.OrdinalIgnoreCase)
.OrderBy(i => i)
.ToArray()
};
}
/// <summary>
/// Gets query filters.
/// </summary>
/// <param name="userId">Optional. User id.</param>
/// <param name="parentId">Optional. Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
/// <param name="mediaTypes">[Unused] Optional. Filter by MediaType. Allows multiple, comma delimited.</param>
/// <param name="isAiring">Optional. Is item airing.</param>
/// <param name="isMovie">Optional. Is item movie.</param>
/// <param name="isSports">Optional. Is item sports.</param>
/// <param name="isKids">Optional. Is item kids.</param>
/// <param name="isNews">Optional. Is item news.</param>
/// <param name="isSeries">Optional. Is item series.</param>
/// <param name="recursive">Optional. Search recursive.</param>
/// <returns>Query filters.</returns>
[HttpGet("/Items/Filters2")]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryFilters> GetQueryFilters(
[FromQuery] Guid? userId,
[FromQuery] string? parentId,
[FromQuery] string? includeItemTypes,
[FromQuery] string? mediaTypes,
[FromQuery] bool? isAiring,
[FromQuery] bool? isMovie,
[FromQuery] bool? isSports,
[FromQuery] bool? isKids,
[FromQuery] bool? isNews,
[FromQuery] bool? isSeries,
[FromQuery] bool? recursive)
{
var parentItem = string.IsNullOrEmpty(parentId)
? null
: _libraryManager.GetItemById(parentId);
var user = userId == null || userId == Guid.Empty
? null
: _userManager.GetUserById(userId.Value);
if (string.Equals(includeItemTypes, nameof(BoxSet), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, nameof(Playlist), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, nameof(Trailer), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, "Program", StringComparison.OrdinalIgnoreCase))
{
parentItem = null;
}
var filters = new QueryFilters();
var genreQuery = new InternalItemsQuery(user)
{
IncludeItemTypes =
(includeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries),
DtoOptions = new DtoOptions
{
Fields = Array.Empty<ItemFields>(),
EnableImages = false,
EnableUserData = false
},
IsAiring = isAiring,
IsMovie = isMovie,
IsSports = isSports,
IsKids = isKids,
IsNews = isNews,
IsSeries = isSeries
};
if ((recursive ?? true) || parentItem is UserView || parentItem is ICollectionFolder)
{
genreQuery.AncestorIds = parentItem == null ? Array.Empty<Guid>() : new[] { parentItem.Id };
}
else
{
genreQuery.Parent = parentItem;
}
if (string.Equals(includeItemTypes, nameof(MusicAlbum), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, nameof(MusicVideo), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, nameof(MusicArtist), StringComparison.OrdinalIgnoreCase) ||
string.Equals(includeItemTypes, nameof(Audio), StringComparison.OrdinalIgnoreCase))
{
filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair
{
Name = i.Item1.Name,
Id = i.Item1.Id
}).ToArray();
}
else
{
filters.Genres = _libraryManager.GetGenres(genreQuery).Items.Select(i => new NameGuidPair
{
Name = i.Item1.Name,
Id = i.Item1.Id
}).ToArray();
}
return filters;
}
}
}