aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api')
-rw-r--r--Jellyfin.Api/Controllers/AlbumsController.cs135
-rw-r--r--Jellyfin.Api/Controllers/ArtistsController.cs14
-rw-r--r--Jellyfin.Api/Controllers/ChannelsController.cs14
-rw-r--r--Jellyfin.Api/Controllers/FilterController.cs6
-rw-r--r--Jellyfin.Api/Controllers/GenresController.cs7
-rw-r--r--Jellyfin.Api/Controllers/InstantMixController.cs49
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs10
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs160
-rw-r--r--Jellyfin.Api/Controllers/LiveTvController.cs37
-rw-r--r--Jellyfin.Api/Controllers/MoviesController.cs6
-rw-r--r--Jellyfin.Api/Controllers/MusicGenresController.cs7
-rw-r--r--Jellyfin.Api/Controllers/PackageController.cs3
-rw-r--r--Jellyfin.Api/Controllers/PersonsController.cs9
-rw-r--r--Jellyfin.Api/Controllers/PlaylistsController.cs7
-rw-r--r--Jellyfin.Api/Controllers/RemoteImageController.cs2
-rw-r--r--Jellyfin.Api/Controllers/StudiosController.cs7
-rw-r--r--Jellyfin.Api/Controllers/TrailersController.cs2
-rw-r--r--Jellyfin.Api/Controllers/TvShowsController.cs24
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs7
-rw-r--r--Jellyfin.Api/Controllers/VideoAttachmentsController.cs2
-rw-r--r--Jellyfin.Api/Controllers/YearsController.cs7
-rw-r--r--Jellyfin.Api/Extensions/DtoExtensions.cs46
-rw-r--r--Jellyfin.Api/Helpers/HlsHelpers.cs2
-rw-r--r--Jellyfin.Api/Helpers/RequestHelpers.cs2
-rw-r--r--Jellyfin.Api/Helpers/SimilarItemsHelper.cs182
-rw-r--r--Jellyfin.Api/Helpers/StreamingHelpers.cs2
-rw-r--r--Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs65
-rw-r--r--Jellyfin.Api/Models/LibraryDtos/LibraryOptionsResultDto.cs15
-rw-r--r--Jellyfin.Api/Models/LibraryDtos/LibraryTypeOptionsDto.cs15
-rw-r--r--Jellyfin.Api/Models/LiveTvDtos/ChannelMappingOptionsDto.cs6
-rw-r--r--Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs8
-rw-r--r--Jellyfin.Api/Models/MediaInfoDtos/OpenLiveStreamDto.cs7
32 files changed, 241 insertions, 624 deletions
diff --git a/Jellyfin.Api/Controllers/AlbumsController.cs b/Jellyfin.Api/Controllers/AlbumsController.cs
deleted file mode 100644
index 357f646a2b..0000000000
--- a/Jellyfin.Api/Controllers/AlbumsController.cs
+++ /dev/null
@@ -1,135 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel.DataAnnotations;
-using System.Linq;
-using Jellyfin.Api.Extensions;
-using Jellyfin.Api.Helpers;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Entities.Audio;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Querying;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
-
-namespace Jellyfin.Api.Controllers
-{
- /// <summary>
- /// The albums controller.
- /// </summary>
- [Route("")]
- public class AlbumsController : BaseJellyfinApiController
- {
- private readonly IUserManager _userManager;
- private readonly ILibraryManager _libraryManager;
- private readonly IDtoService _dtoService;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="AlbumsController"/> class.
- /// </summary>
- /// <param name="userManager">Instance of the <see cref="IUserManager"/> interface.</param>
- /// <param name="libraryManager">Instance of the <see cref="ILibraryManager"/> interface.</param>
- /// <param name="dtoService">Instance of the <see cref="IDtoService"/> interface.</param>
- public AlbumsController(
- IUserManager userManager,
- ILibraryManager libraryManager,
- IDtoService dtoService)
- {
- _userManager = userManager;
- _libraryManager = libraryManager;
- _dtoService = dtoService;
- }
-
- /// <summary>
- /// Finds albums similar to a given album.
- /// </summary>
- /// <param name="albumId">The album id.</param>
- /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
- /// <param name="excludeArtistIds">Optional. Ids of artists to exclude.</param>
- /// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <response code="200">Similar albums returned.</response>
- /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with similar albums.</returns>
- [HttpGet("Albums/{albumId}/Similar")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult<QueryResult<BaseItemDto>> GetSimilarAlbums(
- [FromRoute, Required] string albumId,
- [FromQuery] Guid? userId,
- [FromQuery] string? excludeArtistIds,
- [FromQuery] int? limit)
- {
- var dtoOptions = new DtoOptions().AddClientFields(Request);
-
- return SimilarItemsHelper.GetSimilarItemsResult(
- dtoOptions,
- _userManager,
- _libraryManager,
- _dtoService,
- userId,
- albumId,
- excludeArtistIds,
- limit,
- new[] { typeof(MusicAlbum) },
- GetAlbumSimilarityScore);
- }
-
- /// <summary>
- /// Finds artists similar to a given artist.
- /// </summary>
- /// <param name="artistId">The artist id.</param>
- /// <param name="userId">Optional. Filter by user id, and attach user data.</param>
- /// <param name="excludeArtistIds">Optional. Ids of artists to exclude.</param>
- /// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <response code="200">Similar artists returned.</response>
- /// <returns>A <see cref="QueryResult{BaseItemDto}"/> with similar artists.</returns>
- [HttpGet("Artists/{artistId}/Similar")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult<QueryResult<BaseItemDto>> GetSimilarArtists(
- [FromRoute, Required] string artistId,
- [FromQuery] Guid? userId,
- [FromQuery] string? excludeArtistIds,
- [FromQuery] int? limit)
- {
- var dtoOptions = new DtoOptions().AddClientFields(Request);
-
- return SimilarItemsHelper.GetSimilarItemsResult(
- dtoOptions,
- _userManager,
- _libraryManager,
- _dtoService,
- userId,
- artistId,
- excludeArtistIds,
- limit,
- new[] { typeof(MusicArtist) },
- SimilarItemsHelper.GetSimiliarityScore);
- }
-
- /// <summary>
- /// Gets a similairty score of two albums.
- /// </summary>
- /// <param name="item1">The first item.</param>
- /// <param name="item1People">The item1 people.</param>
- /// <param name="allPeople">All people.</param>
- /// <param name="item2">The second item.</param>
- /// <returns>System.Int32.</returns>
- private int GetAlbumSimilarityScore(BaseItem item1, List<PersonInfo> item1People, List<PersonInfo> allPeople, BaseItem item2)
- {
- var points = SimilarItemsHelper.GetSimiliarityScore(item1, item1People, allPeople, item2);
-
- var album1 = (MusicAlbum)item1;
- var album2 = (MusicAlbum)item2;
-
- var artists1 = album1
- .GetAllArtists()
- .DistinctNames()
- .ToList();
-
- var artists2 = new HashSet<string>(
- album2.GetAllArtists().DistinctNames(),
- StringComparer.OrdinalIgnoreCase);
-
- return points + artists1.Where(artists2.Contains).Sum(i => 5);
- }
- }
-}
diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs
index a35d7a556f..9bad206e02 100644
--- a/Jellyfin.Api/Controllers/ArtistsController.cs
+++ b/Jellyfin.Api/Controllers/ArtistsController.cs
@@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="searchTerm">Optional. Search term.</param>
/// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
/// <param name="filters">Optional. Specify additional filters to apply.</param>
@@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] string? searchTerm,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery] string? includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
@@ -114,8 +114,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true,
[FromQuery] bool enableTotalRecordCount = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -262,7 +261,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="searchTerm">Optional. Search term.</param>
/// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
/// <param name="filters">Optional. Specify additional filters to apply.</param>
@@ -297,7 +296,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] string? searchTerm,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery] string? includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
@@ -323,8 +322,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true,
[FromQuery] bool enableTotalRecordCount = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs
index 20fc96ba83..ec9d7cdce1 100644
--- a/Jellyfin.Api/Controllers/ChannelsController.cs
+++ b/Jellyfin.Api/Controllers/ChannelsController.cs
@@ -108,7 +108,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="sortOrder">Optional. Sort Order - Ascending,Descending.</param>
/// <param name="filters">Optional. Specify additional filters to apply.</param>
/// <param name="sortBy">Optional. Specify one or more sort orders, comma delimited. Options: Album, AlbumArtist, Artist, Budget, CommunityRating, CriticRating, DateCreated, DatePlayed, PlayCount, PremiereDate, ProductionYear, SortName, Random, Revenue, Runtime.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <response code="200">Channel items returned.</response>
/// <returns>
/// A <see cref="Task"/> representing the request to get the channel items.
@@ -124,7 +124,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? sortOrder,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] string? sortBy,
- [FromQuery] string? fields)
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields)
{
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
@@ -137,8 +137,7 @@ namespace Jellyfin.Api.Controllers
ChannelIds = new[] { channelId },
ParentId = folderId ?? Guid.Empty,
OrderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder),
- DtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ DtoOptions = new DtoOptions { Fields = fields }
};
foreach (var filter in filters)
@@ -185,7 +184,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="filters">Optional. Specify additional filters to apply.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="channelIds">Optional. Specify one or more channel id's, comma delimited.</param>
/// <response code="200">Latest channel items returned.</response>
/// <returns>
@@ -198,7 +197,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? startIndex,
[FromQuery] int? limit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? channelIds)
{
var user = userId.HasValue && !userId.Equals(Guid.Empty)
@@ -214,8 +213,7 @@ namespace Jellyfin.Api.Controllers
.Where(i => !string.IsNullOrWhiteSpace(i))
.Select(i => new Guid(i))
.ToArray(),
- DtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ DtoOptions = new DtoOptions { Fields = fields }
};
foreach (var filter in filters)
diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs
index 2a567c8461..008bb58d16 100644
--- a/Jellyfin.Api/Controllers/FilterController.cs
+++ b/Jellyfin.Api/Controllers/FilterController.cs
@@ -78,8 +78,8 @@ namespace Jellyfin.Api.Controllers
var query = new InternalItemsQuery
{
User = user,
- MediaTypes = (mediaTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries),
- IncludeItemTypes = (includeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries),
+ MediaTypes = (mediaTypes ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries),
+ IncludeItemTypes = (includeItemTypes ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries),
Recursive = true,
EnableTotalRecordCount = false,
DtoOptions = new DtoOptions
@@ -168,7 +168,7 @@ namespace Jellyfin.Api.Controllers
var genreQuery = new InternalItemsQuery(user)
{
IncludeItemTypes =
- (includeItemTypes ?? string.Empty).Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries),
+ (includeItemTypes ?? string.Empty).Split(',', StringSplitOptions.RemoveEmptyEntries),
DtoOptions = new DtoOptions
{
Fields = Array.Empty<ItemFields>(),
diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs
index 9c009d7847..9c222135d0 100644
--- a/Jellyfin.Api/Controllers/GenresController.cs
+++ b/Jellyfin.Api/Controllers/GenresController.cs
@@ -52,7 +52,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="searchTerm">The search term.</param>
/// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited.</param>
/// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
@@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] string? searchTerm,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery] string? includeItemTypes,
[FromQuery] bool? isFavorite,
@@ -86,8 +86,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true,
[FromQuery] bool enableTotalRecordCount = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs
index 2f342d0a8a..d17a26db43 100644
--- a/Jellyfin.Api/Controllers/InstantMixController.cs
+++ b/Jellyfin.Api/Controllers/InstantMixController.cs
@@ -56,7 +56,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="id">The item id.</param>
/// <param name="userId">Optional. Filter by user id, and attach user data.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -69,7 +69,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid id,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -79,8 +79,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
@@ -93,7 +92,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="id">The item id.</param>
/// <param name="userId">Optional. Filter by user id, and attach user data.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -106,7 +105,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid id,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -116,8 +115,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions);
@@ -130,7 +128,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="id">The item id.</param>
/// <param name="userId">Optional. Filter by user id, and attach user data.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -143,7 +141,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid id,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -153,8 +151,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions);
@@ -167,7 +164,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="name">The genre name.</param>
/// <param name="userId">Optional. Filter by user id, and attach user data.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -180,7 +177,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] string name,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -189,8 +186,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions);
@@ -203,7 +199,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="id">The item id.</param>
/// <param name="userId">Optional. Filter by user id, and attach user data.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -216,7 +212,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid id,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -226,8 +222,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
@@ -240,7 +235,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="id">The item id.</param>
/// <param name="userId">Optional. Filter by user id, and attach user data.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -253,7 +248,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid id,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -263,8 +258,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
@@ -277,7 +271,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="id">The item id.</param>
/// <param name="userId">Optional. Filter by user id, and attach user data.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -290,7 +284,7 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] Guid id,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -300,8 +294,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions);
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index adc95f7574..d8d371ebc3 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -180,7 +180,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? searchTerm,
[FromQuery] string? sortOrder,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery] string? includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
@@ -234,8 +234,7 @@ namespace Jellyfin.Api.Controllers
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -533,7 +532,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] string? searchTerm,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? mediaTypes,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -545,8 +544,7 @@ namespace Jellyfin.Api.Controllers
{
var user = _userManager.GetUserById(userId);
var parentIdGuid = string.IsNullOrWhiteSpace(parentId) ? Guid.Empty : new Guid(parentId);
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index 60bbc5022a..1b115d800b 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -12,6 +12,7 @@ using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.Helpers;
+using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.LibraryDtos;
using Jellyfin.Data.Entities;
using MediaBrowser.Common.Progress;
@@ -680,12 +681,12 @@ namespace Jellyfin.Api.Controllers
/// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
/// <response code="200">Similar items returned.</response>
/// <returns>A <see cref="QueryResult{BaseItemDto}"/> containing the similar items.</returns>
- [HttpGet("Artists/{itemId}/Similar", Name = "GetSimilarArtists2")]
+ [HttpGet("Artists/{itemId}/Similar", Name = "GetSimilarArtists")]
[HttpGet("Items/{itemId}/Similar")]
- [HttpGet("Albums/{itemId}/Similar", Name = "GetSimilarAlbums2")]
- [HttpGet("Shows/{itemId}/Similar", Name = "GetSimilarShows2")]
- [HttpGet("Movies/{itemId}/Similar", Name = "GetSimilarMovies2")]
- [HttpGet("Trailers/{itemId}/Similar", Name = "GetSimilarTrailers2")]
+ [HttpGet("Albums/{itemId}/Similar", Name = "GetSimilarAlbums")]
+ [HttpGet("Shows/{itemId}/Similar", Name = "GetSimilarShows")]
+ [HttpGet("Movies/{itemId}/Similar", Name = "GetSimilarMovies")]
+ [HttpGet("Trailers/{itemId}/Similar", Name = "GetSimilarTrailers")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryResult<BaseItemDto>> GetSimilarItems(
@@ -693,7 +694,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? excludeArtistIds,
[FromQuery] Guid? userId,
[FromQuery] int? limit,
- [FromQuery] string? fields)
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields)
{
var item = itemId.Equals(Guid.Empty)
? (!userId.Equals(Guid.Empty)
@@ -701,33 +702,71 @@ namespace Jellyfin.Api.Controllers
: _libraryManager.RootFolder)
: _libraryManager.GetItemById(itemId);
+ if (item is Episode || (item is IItemByName && !(item is MusicArtist)))
+ {
+ return new QueryResult<BaseItemDto>();
+ }
+
+ var user = userId.HasValue && !userId.Equals(Guid.Empty)
+ ? _userManager.GetUserById(userId.Value)
+ : null;
+ var dtoOptions = new DtoOptions { Fields = fields }
+ .AddClientFields(Request);
+
var program = item as IHasProgramAttributes;
- var isMovie = item is MediaBrowser.Controller.Entities.Movies.Movie || (program != null && program.IsMovie) || item is Trailer;
- if (program != null && program.IsSeries)
+ bool? isMovie = item is Movie || (program != null && program.IsMovie) || item is Trailer;
+ bool? isSeries = item is Series || (program != null && program.IsSeries);
+
+ var includeItemTypes = new List<string>();
+ if (isMovie.Value)
{
- return GetSimilarItemsResult(
- item,
- excludeArtistIds,
- userId,
- limit,
- fields,
- new[] { nameof(Series) },
- false);
+ includeItemTypes.Add(nameof(Movie));
+ if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
+ {
+ includeItemTypes.Add(nameof(Trailer));
+ includeItemTypes.Add(nameof(LiveTvProgram));
+ }
+ }
+ else if (isSeries.Value)
+ {
+ includeItemTypes.Add(nameof(Series));
+ }
+ else
+ {
+ // For non series and movie types these columns are typically null
+ isSeries = null;
+ isMovie = null;
+ includeItemTypes.Add(item.GetType().Name);
}
- if (item is MediaBrowser.Controller.Entities.TV.Episode || (item is IItemByName && !(item is MusicArtist)))
+ var query = new InternalItemsQuery(user)
{
- return new QueryResult<BaseItemDto>();
+ Limit = limit,
+ IncludeItemTypes = includeItemTypes.ToArray(),
+ IsMovie = isMovie,
+ IsSeries = isSeries,
+ SimilarTo = item,
+ DtoOptions = dtoOptions,
+ EnableTotalRecordCount = !isMovie ?? true,
+ EnableGroupByMetadataKey = isMovie ?? false,
+ MinSimilarityScore = 2 // A remnant from album/artist scoring
+ };
+
+ // ExcludeArtistIds
+ if (!string.IsNullOrEmpty(excludeArtistIds))
+ {
+ query.ExcludeArtistIds = RequestHelpers.GetGuids(excludeArtistIds);
}
- return GetSimilarItemsResult(
- item,
- excludeArtistIds,
- userId,
- limit,
- fields,
- new[] { item.GetType().Name },
- isMovie);
+ List<BaseItem> itemsResult = _libraryManager.GetItemList(query);
+
+ var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
+
+ return new QueryResult<BaseItemDto>
+ {
+ Items = returnList,
+ TotalRecordCount = itemsResult.Count
+ };
}
/// <summary>
@@ -880,75 +919,6 @@ namespace Jellyfin.Api.Controllers
}
}
- private QueryResult<BaseItemDto> GetSimilarItemsResult(
- BaseItem item,
- string? excludeArtistIds,
- Guid? userId,
- int? limit,
- string? fields,
- string[] includeItemTypes,
- bool isMovie)
- {
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
- .AddClientFields(Request);
-
- var query = new InternalItemsQuery(user)
- {
- Limit = limit,
- IncludeItemTypes = includeItemTypes,
- IsMovie = isMovie,
- SimilarTo = item,
- DtoOptions = dtoOptions,
- EnableTotalRecordCount = !isMovie,
- EnableGroupByMetadataKey = isMovie
- };
-
- // ExcludeArtistIds
- if (!string.IsNullOrEmpty(excludeArtistIds))
- {
- query.ExcludeArtistIds = RequestHelpers.GetGuids(excludeArtistIds);
- }
-
- List<BaseItem> itemsResult;
-
- if (isMovie)
- {
- var itemTypes = new List<string> { nameof(MediaBrowser.Controller.Entities.Movies.Movie) };
- if (_serverConfigurationManager.Configuration.EnableExternalContentInSuggestions)
- {
- itemTypes.Add(nameof(Trailer));
- itemTypes.Add(nameof(LiveTvProgram));
- }
-
- query.IncludeItemTypes = itemTypes.ToArray();
- itemsResult = _libraryManager.GetArtists(query).Items.Select(i => i.Item1).ToList();
- }
- else if (item is MusicArtist)
- {
- query.IncludeItemTypes = Array.Empty<string>();
-
- itemsResult = _libraryManager.GetArtists(query).Items.Select(i => i.Item1).ToList();
- }
- else
- {
- itemsResult = _libraryManager.GetItemList(query);
- }
-
- var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
-
- var result = new QueryResult<BaseItemDto>
- {
- Items = returnList,
- TotalRecordCount = itemsResult.Count
- };
-
- return result;
- }
-
private static string[] GetRepresentativeItemTypes(string? contentType)
{
return contentType switch
diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs
index 384a487055..29c0f1df4d 100644
--- a/Jellyfin.Api/Controllers/LiveTvController.cs
+++ b/Jellyfin.Api/Controllers/LiveTvController.cs
@@ -119,7 +119,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
/// <param name="enableImageTypes">"Optional. The image types to include in the output.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="sortBy">Optional. Key to sort by.</param>
/// <param name="sortOrder">Optional. Sort order.</param>
@@ -148,15 +148,14 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages,
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableUserData,
[FromQuery] string? sortBy,
[FromQuery] SortOrder? sortOrder,
[FromQuery] bool enableFavoriteSorting = false,
[FromQuery] bool addCurrentProgram = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -240,7 +239,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
/// <param name="enableImageTypes">Optional. The image types to include in the output.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="isMovie">Optional. Filter for movies.</param>
/// <param name="isSeries">Optional. Filter for series.</param>
@@ -265,7 +264,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages,
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableUserData,
[FromQuery] bool? isMovie,
[FromQuery] bool? isSeries,
@@ -275,8 +274,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? isLibraryItem,
[FromQuery] bool enableTotalRecordCount = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -297,7 +295,7 @@ namespace Jellyfin.Api.Controllers
IsKids = isKids,
IsSports = isSports,
IsLibraryItem = isLibraryItem,
- Fields = RequestHelpers.GetItemFields(fields),
+ Fields = fields,
ImageTypeLimit = imageTypeLimit,
EnableImages = enableImages
}, dtoOptions);
@@ -317,7 +315,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
/// <param name="enableImageTypes">Optional. The image types to include in the output.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="enableTotalRecordCount">Optional. Return total record count.</param>
/// <response code="200">Live tv recordings returned.</response>
@@ -352,7 +350,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages,
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableUserData,
[FromQuery] bool enableTotalRecordCount = true)
{
@@ -531,7 +529,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="seriesTimerId">Optional. Filter by series timer id.</param>
/// <param name="librarySeriesId">Optional. Filter by library series id.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableTotalRecordCount">Retrieve total record count.</param>
/// <response code="200">Live tv epgs returned.</response>
/// <returns>
@@ -566,7 +564,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableUserData,
[FromQuery] string? seriesTimerId,
[FromQuery] Guid? librarySeriesId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool enableTotalRecordCount = true)
{
var user = userId.HasValue && !userId.Equals(Guid.Empty)
@@ -607,8 +605,7 @@ namespace Jellyfin.Api.Controllers
}
}
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
@@ -663,8 +660,7 @@ namespace Jellyfin.Api.Controllers
}
}
- var dtoOptions = new DtoOptions()
- .AddItemFields(body.Fields)
+ var dtoOptions = new DtoOptions { Fields = body.Fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(body.EnableImages, body.EnableUserData, body.ImageTypeLimit, body.EnableImageTypes);
return await _liveTvManager.GetPrograms(query, dtoOptions, CancellationToken.None).ConfigureAwait(false);
@@ -686,7 +682,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
/// <param name="enableImageTypes">Optional. The image types to include in the output.</param>
/// <param name="genreIds">The genres to return guide information for.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableUserData">Optional. include user data.</param>
/// <param name="enableTotalRecordCount">Retrieve total record count.</param>
/// <response code="200">Recommended epgs returned.</response>
@@ -708,7 +704,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
[FromQuery] string? genreIds,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableUserData,
[FromQuery] bool enableTotalRecordCount = true)
{
@@ -730,8 +726,7 @@ namespace Jellyfin.Api.Controllers
GenreIds = RequestHelpers.GetGuids(genreIds)
};
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
return _liveTvManager.GetRecommendedPrograms(query, dtoOptions, CancellationToken.None);
diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs
index afb536e747..ebc148fe56 100644
--- a/Jellyfin.Api/Controllers/MoviesController.cs
+++ b/Jellyfin.Api/Controllers/MoviesController.cs
@@ -4,6 +4,7 @@ using System.Globalization;
using System.Linq;
using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
+using Jellyfin.Api.ModelBinders;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Enums;
using MediaBrowser.Common.Extensions;
@@ -65,15 +66,14 @@ namespace Jellyfin.Api.Controllers
public ActionResult<IEnumerable<RecommendationDto>> GetMovieRecommendations(
[FromQuery] Guid? userId,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] int categoryLimit = 5,
[FromQuery] int itemLimit = 8)
{
var user = userId.HasValue && !userId.Equals(Guid.Empty)
? _userManager.GetUserById(userId.Value)
: null;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request);
var categories = new List<RecommendationDto>();
diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs
index 989c383fdc..229d9ff022 100644
--- a/Jellyfin.Api/Controllers/MusicGenresController.cs
+++ b/Jellyfin.Api/Controllers/MusicGenresController.cs
@@ -52,7 +52,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="searchTerm">The search term.</param>
/// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered in based on item type. This allows multiple, comma delimited.</param>
/// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
@@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] string? searchTerm,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery] string? includeItemTypes,
[FromQuery] bool? isFavorite,
@@ -86,8 +86,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true,
[FromQuery] bool enableTotalRecordCount = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs
index a104af4e63..1f797d6bc3 100644
--- a/Jellyfin.Api/Controllers/PackageController.cs
+++ b/Jellyfin.Api/Controllers/PackageController.cs
@@ -154,12 +154,13 @@ namespace Jellyfin.Api.Controllers
/// <param name="repositoryInfos">The list of package repositories.</param>
/// <response code="204">Package repositories saved.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns>
- [HttpOptions("Repositories")]
+ [HttpPost("Repositories")]
[Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SetRepositories([FromBody] List<RepositoryInfo> repositoryInfos)
{
_serverConfigurationManager.Configuration.PluginRepositories = repositoryInfos;
+ _serverConfigurationManager.SaveConfiguration();
return NoContent();
}
}
diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs
index 80395950cf..6ac3e6417a 100644
--- a/Jellyfin.Api/Controllers/PersonsController.cs
+++ b/Jellyfin.Api/Controllers/PersonsController.cs
@@ -53,8 +53,8 @@ namespace Jellyfin.Api.Controllers
/// </summary>
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="searchTerm">The search term.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
- /// <param name="filters">Optional. Specify additional filters to apply. This allows multiple, comma delimited. Options: IsFolder, IsNotFolder, IsUnplayed, IsPlayed, IsFavorite, IsResumable, Likes, Dislikes.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
+ /// <param name="filters">Optional. Specify additional filters to apply.</param>
/// <param name="isFavorite">Optional filter by items that are marked as favorite, or not. userId is required.</param>
/// <param name="enableUserData">Optional, include user data.</param>
/// <param name="imageTypeLimit">Optional, the max number of images to return, per image type.</param>
@@ -71,7 +71,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<QueryResult<BaseItemDto>> GetPersons(
[FromQuery] int? limit,
[FromQuery] string? searchTerm,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] bool? isFavorite,
[FromQuery] bool? enableUserData,
@@ -83,8 +83,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] Guid? userId,
[FromQuery] bool? enableImages = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs
index f2213f20d8..4b3d8d3d39 100644
--- a/Jellyfin.Api/Controllers/PlaylistsController.cs
+++ b/Jellyfin.Api/Controllers/PlaylistsController.cs
@@ -135,7 +135,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="userId">User id.</param>
/// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="enableImages">Optional. Include image information in output.</param>
/// <param name="enableUserData">Optional. Include user data.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -149,7 +149,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery, Required] Guid userId,
[FromQuery] int? startIndex,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? enableImages,
[FromQuery] bool? enableUserData,
[FromQuery] int? imageTypeLimit,
@@ -177,8 +177,7 @@ namespace Jellyfin.Api.Controllers
items = items.Take(limit.Value).ToArray();
}
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs
index c2bfab175a..5284888d82 100644
--- a/Jellyfin.Api/Controllers/RemoteImageController.cs
+++ b/Jellyfin.Api/Controllers/RemoteImageController.cs
@@ -254,7 +254,7 @@ namespace Jellyfin.Api.Controllers
throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType));
}
- var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last();
+ var ext = response.Content.Headers.ContentType.MediaType.Split('/')[^1];
var fullCachePath = GetFullCachePath(urlHash + "." + ext);
var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid.");
diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs
index c60d14479d..27dcd51bc2 100644
--- a/Jellyfin.Api/Controllers/StudiosController.cs
+++ b/Jellyfin.Api/Controllers/StudiosController.cs
@@ -50,7 +50,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="searchTerm">Optional. Search term.</param>
/// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="excludeItemTypes">Optional. If specified, results will be filtered out based on item type. This allows multiple, comma delimited.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimited.</param>
/// <param name="isFavorite">Optional filter by items that are marked as favorite, or not.</param>
@@ -72,7 +72,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] string? searchTerm,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery] string? includeItemTypes,
[FromQuery] bool? isFavorite,
@@ -86,8 +86,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableImages = true,
[FromQuery] bool enableTotalRecordCount = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs
index 6b4eee718b..d78adcbcdc 100644
--- a/Jellyfin.Api/Controllers/TrailersController.cs
+++ b/Jellyfin.Api/Controllers/TrailersController.cs
@@ -146,7 +146,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? searchTerm,
[FromQuery] string? sortOrder,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters,
[FromQuery] bool? isFavorite,
diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs
index 55cdae39d0..6fd154836b 100644
--- a/Jellyfin.Api/Controllers/TvShowsController.cs
+++ b/Jellyfin.Api/Controllers/TvShowsController.cs
@@ -59,7 +59,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="userId">The user id of the user to get the next up episodes for.</param>
/// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="seriesId">Optional. Filter by series 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="enableImges">Optional. Include image information in output.</param>
@@ -74,7 +74,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] Guid? userId,
[FromQuery] int? startIndex,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? seriesId,
[FromQuery] string? parentId,
[FromQuery] bool? enableImges,
@@ -83,8 +83,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableUserData,
[FromQuery] bool enableTotalRecordCount = true)
{
- var options = new DtoOptions()
- .AddItemFields(fields!)
+ var options = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes!);
@@ -119,7 +118,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="userId">The user id of the user to get the upcoming episodes for.</param>
/// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param>
/// <param name="limit">Optional. The maximum number of records to return.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</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="enableImges">Optional. Include image information in output.</param>
/// <param name="imageTypeLimit">Optional. The max number of images to return, per image type.</param>
@@ -132,7 +131,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] Guid? userId,
[FromQuery] int? startIndex,
[FromQuery] int? limit,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? parentId,
[FromQuery] bool? enableImges,
[FromQuery] int? imageTypeLimit,
@@ -147,8 +146,7 @@ namespace Jellyfin.Api.Controllers
var parentIdGuid = string.IsNullOrWhiteSpace(parentId) ? Guid.Empty : new Guid(parentId);
- var options = new DtoOptions()
- .AddItemFields(fields!)
+ var options = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes!);
@@ -198,7 +196,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<QueryResult<BaseItemDto>> GetEpisodes(
[FromRoute, Required] string seriesId,
[FromQuery] Guid? userId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] int? season,
[FromQuery] string? seasonId,
[FromQuery] bool? isMissing,
@@ -218,8 +216,7 @@ namespace Jellyfin.Api.Controllers
List<BaseItem> episodes;
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields!)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
@@ -321,7 +318,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<QueryResult<BaseItemDto>> GetSeasons(
[FromRoute, Required] string seriesId,
[FromQuery] Guid? userId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool? isSpecialSeason,
[FromQuery] bool? isMissing,
[FromQuery] string? adjacentTo,
@@ -346,8 +343,7 @@ namespace Jellyfin.Api.Controllers
AdjacentTo = adjacentTo
});
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!);
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index faa8a0634b..cfd8511297 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -252,7 +252,7 @@ namespace Jellyfin.Api.Controllers
/// </summary>
/// <param name="userId">User id.</param>
/// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimeted. Options: Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be filtered based on item type. This allows multiple, comma delimeted.</param>
/// <param name="isPlayed">Filter by items that are played, or not.</param>
/// <param name="enableImages">Optional. include image information in output.</param>
@@ -268,7 +268,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<IEnumerable<BaseItemDto>> GetLatestMedia(
[FromRoute, Required] Guid userId,
[FromQuery] Guid? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? includeItemTypes,
[FromQuery] bool? isPlayed,
[FromQuery] bool? enableImages,
@@ -288,8 +288,7 @@ namespace Jellyfin.Api.Controllers
}
}
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs
index 09a1c93e6a..418c0c1230 100644
--- a/Jellyfin.Api/Controllers/VideoAttachmentsController.cs
+++ b/Jellyfin.Api/Controllers/VideoAttachmentsController.cs
@@ -46,7 +46,7 @@ namespace Jellyfin.Api.Controllers
[Produces(MediaTypeNames.Application.Octet)]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public async Task<ActionResult<FileStreamResult>> GetAttachment(
+ public async Task<ActionResult> GetAttachment(
[FromRoute, Required] Guid videoId,
[FromRoute, Required] string mediaSourceId,
[FromRoute, Required] int index)
diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs
index 1712a6a543..1b38e399d6 100644
--- a/Jellyfin.Api/Controllers/YearsController.cs
+++ b/Jellyfin.Api/Controllers/YearsController.cs
@@ -52,7 +52,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="limit">Optional. The maximum number of records to return.</param>
/// <param name="sortOrder">Sort Order - Ascending,Descending.</param>
/// <param name="parentId">Specify this to localize the search to a specific item or folder. Omit to use the root.</param>
- /// <param name="fields">Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.</param>
+ /// <param name="fields">Optional. Specify additional fields of information to return in the output.</param>
/// <param name="excludeItemTypes">Optional. If specified, results will be excluded based on item type. This allows multiple, comma delimited.</param>
/// <param name="includeItemTypes">Optional. If specified, results will be included based on item type. This allows multiple, comma delimited.</param>
/// <param name="mediaTypes">Optional. Filter by MediaType. Allows multiple, comma delimited.</param>
@@ -72,7 +72,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] string? sortOrder,
[FromQuery] string? parentId,
- [FromQuery] string? fields,
+ [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] string? excludeItemTypes,
[FromQuery] string? includeItemTypes,
[FromQuery] string? mediaTypes,
@@ -84,8 +84,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool recursive = true,
[FromQuery] bool? enableImages = true)
{
- var dtoOptions = new DtoOptions()
- .AddItemFields(fields)
+ var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Extensions/DtoExtensions.cs b/Jellyfin.Api/Extensions/DtoExtensions.cs
index 85f8d789e4..f2abd515d3 100644
--- a/Jellyfin.Api/Extensions/DtoExtensions.cs
+++ b/Jellyfin.Api/Extensions/DtoExtensions.cs
@@ -1,6 +1,8 @@
using System;
+using System.Collections.Generic;
using System.Linq;
using Jellyfin.Api.Helpers;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Querying;
@@ -14,42 +16,6 @@ namespace Jellyfin.Api.Extensions
public static class DtoExtensions
{
/// <summary>
- /// Add Dto Item fields.
- /// </summary>
- /// <remarks>
- /// Converted from IHasItemFields.
- /// Legacy order: 1.
- /// </remarks>
- /// <param name="dtoOptions">DtoOptions object.</param>
- /// <param name="fields">Comma delimited string of fields.</param>
- /// <returns>Modified DtoOptions object.</returns>
- internal static DtoOptions AddItemFields(this DtoOptions dtoOptions, string? fields)
- {
- if (string.IsNullOrEmpty(fields))
- {
- dtoOptions.Fields = Array.Empty<ItemFields>();
- }
- else
- {
- dtoOptions.Fields = fields.Split(',')
- .Select(v =>
- {
- if (Enum.TryParse(v, true, out ItemFields value))
- {
- return (ItemFields?)value;
- }
-
- return null;
- })
- .Where(i => i.HasValue)
- .Select(i => i!.Value)
- .ToArray();
- }
-
- return dtoOptions;
- }
-
- /// <summary>
/// Add additional fields depending on client.
/// </summary>
/// <remarks>
@@ -79,7 +45,7 @@ namespace Jellyfin.Api.Extensions
client.IndexOf("media center", StringComparison.OrdinalIgnoreCase) != -1 ||
client.IndexOf("classic", StringComparison.OrdinalIgnoreCase) != -1)
{
- int oldLen = dtoOptions.Fields.Length;
+ int oldLen = dtoOptions.Fields.Count;
var arr = new ItemFields[oldLen + 1];
dtoOptions.Fields.CopyTo(arr, 0);
arr[oldLen] = ItemFields.RecursiveItemCount;
@@ -97,7 +63,7 @@ namespace Jellyfin.Api.Extensions
client.IndexOf("samsung", StringComparison.OrdinalIgnoreCase) != -1 ||
client.IndexOf("androidtv", StringComparison.OrdinalIgnoreCase) != -1)
{
- int oldLen = dtoOptions.Fields.Length;
+ int oldLen = dtoOptions.Fields.Count;
var arr = new ItemFields[oldLen + 1];
dtoOptions.Fields.CopyTo(arr, 0);
arr[oldLen] = ItemFields.ChildCount;
@@ -126,7 +92,7 @@ namespace Jellyfin.Api.Extensions
bool? enableImages,
bool? enableUserData,
int? imageTypeLimit,
- ImageType[] enableImageTypes)
+ IReadOnlyList<ImageType> enableImageTypes)
{
dtoOptions.EnableImages = enableImages ?? true;
@@ -140,7 +106,7 @@ namespace Jellyfin.Api.Extensions
dtoOptions.EnableUserData = enableUserData.Value;
}
- if (enableImageTypes.Length != 0)
+ if (enableImageTypes.Count != 0)
{
dtoOptions.ImageTypes = enableImageTypes;
}
diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs
index 7fd784806e..45ce905668 100644
--- a/Jellyfin.Api/Helpers/HlsHelpers.cs
+++ b/Jellyfin.Api/Helpers/HlsHelpers.cs
@@ -48,7 +48,7 @@ namespace Jellyfin.Api.Helpers
if (line == null)
{
// Nothing currently in buffer.
- continue;
+ break;
}
if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1)
diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs
index 13d6da3174..f06f038ab5 100644
--- a/Jellyfin.Api/Helpers/RequestHelpers.cs
+++ b/Jellyfin.Api/Helpers/RequestHelpers.cs
@@ -74,7 +74,7 @@ namespace Jellyfin.Api.Helpers
}
return removeEmpty
- ? value.Split(new[] { separator }, StringSplitOptions.RemoveEmptyEntries)
+ ? value.Split(separator, StringSplitOptions.RemoveEmptyEntries)
: value.Split(separator);
}
diff --git a/Jellyfin.Api/Helpers/SimilarItemsHelper.cs b/Jellyfin.Api/Helpers/SimilarItemsHelper.cs
deleted file mode 100644
index 6b06f87cd7..0000000000
--- a/Jellyfin.Api/Helpers/SimilarItemsHelper.cs
+++ /dev/null
@@ -1,182 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using MediaBrowser.Controller.Dto;
-using MediaBrowser.Controller.Entities;
-using MediaBrowser.Controller.Library;
-using MediaBrowser.Model.Dto;
-using MediaBrowser.Model.Entities;
-using MediaBrowser.Model.Querying;
-
-namespace Jellyfin.Api.Helpers
-{
- /// <summary>
- /// The similar items helper class.
- /// </summary>
- public static class SimilarItemsHelper
- {
- internal static QueryResult<BaseItemDto> GetSimilarItemsResult(
- DtoOptions dtoOptions,
- IUserManager userManager,
- ILibraryManager libraryManager,
- IDtoService dtoService,
- Guid? userId,
- string id,
- string? excludeArtistIds,
- int? limit,
- Type[] includeTypes,
- Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
- {
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? userManager.GetUserById(userId.Value)
- : null;
-
- var item = string.IsNullOrEmpty(id) ?
- (!userId.Equals(Guid.Empty) ? libraryManager.GetUserRootFolder() :
- libraryManager.RootFolder) : libraryManager.GetItemById(id);
-
- var query = new InternalItemsQuery(user)
- {
- IncludeItemTypes = includeTypes.Select(i => i.Name).ToArray(),
- Recursive = true,
- DtoOptions = dtoOptions,
- ExcludeArtistIds = RequestHelpers.GetGuids(excludeArtistIds)
- };
-
- var inputItems = libraryManager.GetItemList(query);
-
- var items = GetSimilaritems(item, libraryManager, inputItems, getSimilarityScore)
- .ToList();
-
- var returnItems = items;
-
- if (limit.HasValue && limit < returnItems.Count)
- {
- returnItems = returnItems.GetRange(0, limit.Value);
- }
-
- var dtos = dtoService.GetBaseItemDtos(returnItems, dtoOptions, user);
-
- return new QueryResult<BaseItemDto>
- {
- Items = dtos,
- TotalRecordCount = items.Count
- };
- }
-
- /// <summary>
- /// Gets the similaritems.
- /// </summary>
- /// <param name="item">The item.</param>
- /// <param name="libraryManager">The library manager.</param>
- /// <param name="inputItems">The input items.</param>
- /// <param name="getSimilarityScore">The get similarity score.</param>
- /// <returns>IEnumerable{BaseItem}.</returns>
- private static IEnumerable<BaseItem> GetSimilaritems(
- BaseItem item,
- ILibraryManager libraryManager,
- IEnumerable<BaseItem> inputItems,
- Func<BaseItem, List<PersonInfo>, List<PersonInfo>, BaseItem, int> getSimilarityScore)
- {
- var itemId = item.Id;
- inputItems = inputItems.Where(i => i.Id != itemId);
- var itemPeople = libraryManager.GetPeople(item);
- var allPeople = libraryManager.GetPeople(new InternalPeopleQuery
- {
- AppearsInItemId = item.Id
- });
-
- return inputItems.Select(i => new Tuple<BaseItem, int>(i, getSimilarityScore(item, itemPeople, allPeople, i)))
- .Where(i => i.Item2 > 2)
- .OrderByDescending(i => i.Item2)
- .Select(i => i.Item1);
- }
-
- private static IEnumerable<string> GetTags(BaseItem item)
- {
- return item.Tags;
- }
-
- /// <summary>
- /// Gets the similiarity score.
- /// </summary>
- /// <param name="item1">The item1.</param>
- /// <param name="item1People">The item1 people.</param>
- /// <param name="allPeople">All people.</param>
- /// <param name="item2">The item2.</param>
- /// <returns>System.Int32.</returns>
- internal static int GetSimiliarityScore(BaseItem item1, List<PersonInfo> item1People, List<PersonInfo> allPeople, BaseItem item2)
- {
- var points = 0;
-
- if (!string.IsNullOrEmpty(item1.OfficialRating) && string.Equals(item1.OfficialRating, item2.OfficialRating, StringComparison.OrdinalIgnoreCase))
- {
- points += 10;
- }
-
- // Find common genres
- points += item1.Genres.Where(i => item2.Genres.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10);
-
- // Find common tags
- points += GetTags(item1).Where(i => GetTags(item2).Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 10);
-
- // Find common studios
- points += item1.Studios.Where(i => item2.Studios.Contains(i, StringComparer.OrdinalIgnoreCase)).Sum(i => 3);
-
- var item2PeopleNames = allPeople.Where(i => i.ItemId == item2.Id)
- .Select(i => i.Name)
- .Where(i => !string.IsNullOrWhiteSpace(i))
- .DistinctNames()
- .ToDictionary(i => i, StringComparer.OrdinalIgnoreCase);
-
- points += item1People.Where(i => item2PeopleNames.ContainsKey(i.Name)).Sum(i =>
- {
- if (string.Equals(i.Type, PersonType.Director, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Director, StringComparison.OrdinalIgnoreCase))
- {
- return 5;
- }
-
- if (string.Equals(i.Type, PersonType.Actor, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Actor, StringComparison.OrdinalIgnoreCase))
- {
- return 3;
- }
-
- if (string.Equals(i.Type, PersonType.Composer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Composer, StringComparison.OrdinalIgnoreCase))
- {
- return 3;
- }
-
- if (string.Equals(i.Type, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.GuestStar, StringComparison.OrdinalIgnoreCase))
- {
- return 3;
- }
-
- if (string.Equals(i.Type, PersonType.Writer, StringComparison.OrdinalIgnoreCase) || string.Equals(i.Role, PersonType.Writer, StringComparison.OrdinalIgnoreCase))
- {
- return 2;
- }
-
- return 1;
- });
-
- if (item1.ProductionYear.HasValue && item2.ProductionYear.HasValue)
- {
- var diff = Math.Abs(item1.ProductionYear.Value - item2.ProductionYear.Value);
-
- // Add if they came out within the same decade
- if (diff < 10)
- {
- points += 2;
- }
-
- // And more if within five years
- if (diff < 5)
- {
- points += 2;
- }
- }
-
- return points;
- }
- }
-}
diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs
index 04b1077277..0566f4c4dd 100644
--- a/Jellyfin.Api/Helpers/StreamingHelpers.cs
+++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs
@@ -88,7 +88,7 @@ namespace Jellyfin.Api.Helpers
throw new ResourceNotFoundException(nameof(httpRequest.Path));
}
- var url = httpRequest.Path.Value.Split('.').Last();
+ var url = httpRequest.Path.Value.Split('.')[^1];
if (string.IsNullOrEmpty(streamingRequest.AudioCodec))
{
diff --git a/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs b/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs
index 4f012cab20..e90f48d2fe 100644
--- a/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs
+++ b/Jellyfin.Api/ModelBinders/CommaDelimitedArrayModelBinder.cs
@@ -1,7 +1,9 @@
using System;
+using System.Collections.Generic;
using System.ComponentModel;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.ModelBinding;
+using Microsoft.Extensions.Logging;
namespace Jellyfin.Api.ModelBinders
{
@@ -11,6 +13,17 @@ namespace Jellyfin.Api.ModelBinders
/// </summary>
public class CommaDelimitedArrayModelBinder : IModelBinder
{
+ private readonly ILogger<CommaDelimitedArrayModelBinder> _logger;
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CommaDelimitedArrayModelBinder"/> class.
+ /// </summary>
+ /// <param name="logger">Instance of the <see cref="ILogger{CommaDelimitedArrayModelBinder}"/> interface.</param>
+ public CommaDelimitedArrayModelBinder(ILogger<CommaDelimitedArrayModelBinder> logger)
+ {
+ _logger = logger;
+ }
+
/// <inheritdoc/>
public Task BindModelAsync(ModelBindingContext bindingContext)
{
@@ -20,16 +33,8 @@ namespace Jellyfin.Api.ModelBinders
if (valueProviderResult.Length > 1)
{
- var result = Array.CreateInstance(elementType, valueProviderResult.Length);
-
- for (int i = 0; i < valueProviderResult.Length; i++)
- {
- var value = converter.ConvertFromString(valueProviderResult.Values[i].Trim());
-
- result.SetValue(value, i);
- }
-
- bindingContext.Result = ModelBindingResult.Success(result);
+ var typedValues = GetParsedResult(valueProviderResult.Values, elementType, converter);
+ bindingContext.Result = ModelBindingResult.Success(typedValues);
}
else
{
@@ -37,13 +42,8 @@ namespace Jellyfin.Api.ModelBinders
if (value != null)
{
- var values = Array.ConvertAll(
- value.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries),
- x => converter.ConvertFromString(x?.Trim()));
-
- var typedValues = Array.CreateInstance(elementType, values.Length);
- values.CopyTo(typedValues, 0);
-
+ var splitValues = value.Split(',', StringSplitOptions.RemoveEmptyEntries);
+ var typedValues = GetParsedResult(splitValues, elementType, converter);
bindingContext.Result = ModelBindingResult.Success(typedValues);
}
else
@@ -55,5 +55,36 @@ namespace Jellyfin.Api.ModelBinders
return Task.CompletedTask;
}
+
+ private Array GetParsedResult(IReadOnlyList<string> values, Type elementType, TypeConverter converter)
+ {
+ var parsedValues = new object?[values.Count];
+ var convertedCount = 0;
+ for (var i = 0; i < values.Count; i++)
+ {
+ try
+ {
+ parsedValues[i] = converter.ConvertFromString(values[i].Trim());
+ convertedCount++;
+ }
+ catch (FormatException e)
+ {
+ _logger.LogWarning(e, "Error converting value.");
+ }
+ }
+
+ var typedValues = Array.CreateInstance(elementType, convertedCount);
+ var typedValueIndex = 0;
+ for (var i = 0; i < parsedValues.Length; i++)
+ {
+ if (parsedValues[i] != null)
+ {
+ typedValues.SetValue(parsedValues[i], typedValueIndex);
+ typedValueIndex++;
+ }
+ }
+
+ return typedValues;
+ }
}
}
diff --git a/Jellyfin.Api/Models/LibraryDtos/LibraryOptionsResultDto.cs b/Jellyfin.Api/Models/LibraryDtos/LibraryOptionsResultDto.cs
index 33eda33cb9..7de44aa659 100644
--- a/Jellyfin.Api/Models/LibraryDtos/LibraryOptionsResultDto.cs
+++ b/Jellyfin.Api/Models/LibraryDtos/LibraryOptionsResultDto.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics.CodeAnalysis;
+using System;
+using System.Collections.Generic;
namespace Jellyfin.Api.Models.LibraryDtos
{
@@ -10,25 +11,21 @@ namespace Jellyfin.Api.Models.LibraryDtos
/// <summary>
/// Gets or sets the metadata savers.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "MetadataSavers", Justification = "Imported from ServiceStack")]
- public LibraryOptionInfoDto[] MetadataSavers { get; set; } = null!;
+ public IReadOnlyList<LibraryOptionInfoDto> MetadataSavers { get; set; } = Array.Empty<LibraryOptionInfoDto>();
/// <summary>
/// Gets or sets the metadata readers.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "MetadataReaders", Justification = "Imported from ServiceStack")]
- public LibraryOptionInfoDto[] MetadataReaders { get; set; } = null!;
+ public IReadOnlyList<LibraryOptionInfoDto> MetadataReaders { get; set; } = Array.Empty<LibraryOptionInfoDto>();
/// <summary>
/// Gets or sets the subtitle fetchers.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "SubtitleFetchers", Justification = "Imported from ServiceStack")]
- public LibraryOptionInfoDto[] SubtitleFetchers { get; set; } = null!;
+ public IReadOnlyList<LibraryOptionInfoDto> SubtitleFetchers { get; set; } = Array.Empty<LibraryOptionInfoDto>();
/// <summary>
/// Gets or sets the type options.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "TypeOptions", Justification = "Imported from ServiceStack")]
- public LibraryTypeOptionsDto[] TypeOptions { get; set; } = null!;
+ public IReadOnlyList<LibraryTypeOptionsDto> TypeOptions { get; set; } = Array.Empty<LibraryTypeOptionsDto>();
}
}
diff --git a/Jellyfin.Api/Models/LibraryDtos/LibraryTypeOptionsDto.cs b/Jellyfin.Api/Models/LibraryDtos/LibraryTypeOptionsDto.cs
index ad031e95e5..20f45196d2 100644
--- a/Jellyfin.Api/Models/LibraryDtos/LibraryTypeOptionsDto.cs
+++ b/Jellyfin.Api/Models/LibraryDtos/LibraryTypeOptionsDto.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics.CodeAnalysis;
+using System;
+using System.Collections.Generic;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.Entities;
@@ -17,25 +18,21 @@ namespace Jellyfin.Api.Models.LibraryDtos
/// <summary>
/// Gets or sets the metadata fetchers.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "MetadataFetchers", Justification = "Imported from ServiceStack")]
- public LibraryOptionInfoDto[] MetadataFetchers { get; set; } = null!;
+ public IReadOnlyList<LibraryOptionInfoDto> MetadataFetchers { get; set; } = Array.Empty<LibraryOptionInfoDto>();
/// <summary>
/// Gets or sets the image fetchers.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "ImageFetchers", Justification = "Imported from ServiceStack")]
- public LibraryOptionInfoDto[] ImageFetchers { get; set; } = null!;
+ public IReadOnlyList<LibraryOptionInfoDto> ImageFetchers { get; set; } = Array.Empty<LibraryOptionInfoDto>();
/// <summary>
/// Gets or sets the supported image types.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "SupportedImageTypes", Justification = "Imported from ServiceStack")]
- public ImageType[] SupportedImageTypes { get; set; } = null!;
+ public IReadOnlyList<ImageType> SupportedImageTypes { get; set; } = Array.Empty<ImageType>();
/// <summary>
/// Gets or sets the default image options.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "DefaultImageOptions", Justification = "Imported from ServiceStack")]
- public ImageOption[] DefaultImageOptions { get; set; } = null!;
+ public IReadOnlyList<ImageOption> DefaultImageOptions { get; set; } = Array.Empty<ImageOption>();
}
}
diff --git a/Jellyfin.Api/Models/LiveTvDtos/ChannelMappingOptionsDto.cs b/Jellyfin.Api/Models/LiveTvDtos/ChannelMappingOptionsDto.cs
index 970d8acdbc..f43822da77 100644
--- a/Jellyfin.Api/Models/LiveTvDtos/ChannelMappingOptionsDto.cs
+++ b/Jellyfin.Api/Models/LiveTvDtos/ChannelMappingOptionsDto.cs
@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.Dto;
@@ -25,8 +26,7 @@ namespace Jellyfin.Api.Models.LiveTvDtos
/// <summary>
/// Gets or sets list of mappings.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:DontReturnArrays", MessageId = "Mappings", Justification = "Imported from ServiceStack")]
- public NameValuePair[] Mappings { get; set; } = null!;
+ public IReadOnlyList<NameValuePair> Mappings { get; set; } = Array.Empty<NameValuePair>();
/// <summary>
/// Gets or sets provider name.
diff --git a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs
index 5811533936..5ca4408d18 100644
--- a/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs
+++ b/Jellyfin.Api/Models/LiveTvDtos/GetProgramsDto.cs
@@ -1,8 +1,10 @@
using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using MediaBrowser.Common.Json.Converters;
using MediaBrowser.Model.Entities;
+using MediaBrowser.Model.Querying;
namespace Jellyfin.Api.Models.LiveTvDtos
{
@@ -142,8 +144,7 @@ namespace Jellyfin.Api.Models.LiveTvDtos
/// Optional.
/// </summary>
[JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))]
- [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "EnableImageTypes", Justification = "Imported from ServiceStack")]
- public ImageType[] EnableImageTypes { get; set; } = Array.Empty<ImageType>();
+ public IReadOnlyList<ImageType> EnableImageTypes { get; set; } = Array.Empty<ImageType>();
/// <summary>
/// Gets or sets include user data.
@@ -167,6 +168,7 @@ namespace Jellyfin.Api.Models.LiveTvDtos
/// Gets or sets specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines.
/// Optional.
/// </summary>
- public string? Fields { get; set; }
+ [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))]
+ public IReadOnlyList<ItemFields> Fields { get; set; } = Array.Empty<ItemFields>();
}
}
diff --git a/Jellyfin.Api/Models/MediaInfoDtos/OpenLiveStreamDto.cs b/Jellyfin.Api/Models/MediaInfoDtos/OpenLiveStreamDto.cs
index f797a38076..b0b3de8553 100644
--- a/Jellyfin.Api/Models/MediaInfoDtos/OpenLiveStreamDto.cs
+++ b/Jellyfin.Api/Models/MediaInfoDtos/OpenLiveStreamDto.cs
@@ -1,4 +1,5 @@
-using System.Diagnostics.CodeAnalysis;
+using System;
+using System.Collections.Generic;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.MediaInfo;
@@ -17,8 +18,6 @@ namespace Jellyfin.Api.Models.MediaInfoDtos
/// <summary>
/// Gets or sets the device play protocols.
/// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1819:DontReturnArrays", MessageId = "DevicePlayProtocols", Justification = "Imported from ServiceStack")]
- [SuppressMessage("Microsoft.Performance", "SA1011:ClosingBracketsSpace", MessageId = "DevicePlayProtocols", Justification = "Imported from ServiceStack")]
- public MediaProtocol[]? DirectPlayProtocols { get; set; }
+ public IReadOnlyList<MediaProtocol> DirectPlayProtocols { get; set; } = Array.Empty<MediaProtocol>();
}
}