mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-11-03 19:17:24 -05:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into query-fields
This commit is contained in:
		
						commit
						b9406e5444
					
				@ -9,6 +9,7 @@ using MediaBrowser.Controller.Dto;
 | 
				
			|||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -99,7 +100,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
@ -308,7 +309,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ using MediaBrowser.Controller.Dto;
 | 
				
			|||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -100,7 +101,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ using MediaBrowser.Controller.Entities;
 | 
				
			|||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Controller.Playlists;
 | 
					using MediaBrowser.Controller.Playlists;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -71,7 +72,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var item = _libraryManager.GetItemById(id);
 | 
					            var item = _libraryManager.GetItemById(id);
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
@ -108,7 +109,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var album = _libraryManager.GetItemById(id);
 | 
					            var album = _libraryManager.GetItemById(id);
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
@ -145,7 +146,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var playlist = (Playlist)_libraryManager.GetItemById(id);
 | 
					            var playlist = (Playlist)_libraryManager.GetItemById(id);
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
@ -182,7 +183,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
                ? _userManager.GetUserById(userId.Value)
 | 
					                ? _userManager.GetUserById(userId.Value)
 | 
				
			||||||
@ -218,7 +219,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var item = _libraryManager.GetItemById(id);
 | 
					            var item = _libraryManager.GetItemById(id);
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
@ -255,7 +256,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var item = _libraryManager.GetItemById(id);
 | 
					            var item = _libraryManager.GetItemById(id);
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
@ -292,7 +293,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var item = _libraryManager.GetItemById(id);
 | 
					            var item = _libraryManager.GetItemById(id);
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
 | 
				
			|||||||
@ -185,7 +185,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFilter[] filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? imageTypes,
 | 
					            [FromQuery] ImageType[] imageTypes,
 | 
				
			||||||
            [FromQuery] string? sortBy,
 | 
					            [FromQuery] string? sortBy,
 | 
				
			||||||
            [FromQuery] bool? isPlayed,
 | 
					            [FromQuery] bool? isPlayed,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
@ -342,7 +342,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
                    PersonIds = RequestHelpers.GetGuids(personIds),
 | 
					                    PersonIds = RequestHelpers.GetGuids(personIds),
 | 
				
			||||||
                    PersonTypes = RequestHelpers.Split(personTypes, ',', true),
 | 
					                    PersonTypes = RequestHelpers.Split(personTypes, ',', true),
 | 
				
			||||||
                    Years = RequestHelpers.Split(years, ',', true).Select(int.Parse).ToArray(),
 | 
					                    Years = RequestHelpers.Split(years, ',', true).Select(int.Parse).ToArray(),
 | 
				
			||||||
                    ImageTypes = RequestHelpers.Split(imageTypes, ',', true).Select(v => Enum.Parse<ImageType>(v, true)).ToArray(),
 | 
					                    ImageTypes = imageTypes,
 | 
				
			||||||
                    VideoTypes = RequestHelpers.Split(videoTypes, ',', true).Select(v => Enum.Parse<VideoType>(v, true)).ToArray(),
 | 
					                    VideoTypes = RequestHelpers.Split(videoTypes, ',', true).Select(v => Enum.Parse<VideoType>(v, true)).ToArray(),
 | 
				
			||||||
                    AdjacentTo = adjacentTo,
 | 
					                    AdjacentTo = adjacentTo,
 | 
				
			||||||
                    ItemIds = RequestHelpers.GetGuids(ids),
 | 
					                    ItemIds = RequestHelpers.GetGuids(ids),
 | 
				
			||||||
@ -536,7 +536,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? excludeItemTypes,
 | 
					            [FromQuery] string? excludeItemTypes,
 | 
				
			||||||
            [FromQuery] string? includeItemTypes,
 | 
					            [FromQuery] string? includeItemTypes,
 | 
				
			||||||
            [FromQuery] bool enableTotalRecordCount = true,
 | 
					            [FromQuery] bool enableTotalRecordCount = true,
 | 
				
			||||||
 | 
				
			|||||||
@ -26,6 +26,7 @@ using MediaBrowser.Controller.Library;
 | 
				
			|||||||
using MediaBrowser.Controller.LiveTv;
 | 
					using MediaBrowser.Controller.LiveTv;
 | 
				
			||||||
using MediaBrowser.Controller.Net;
 | 
					using MediaBrowser.Controller.Net;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.LiveTv;
 | 
					using MediaBrowser.Model.LiveTv;
 | 
				
			||||||
using MediaBrowser.Model.Net;
 | 
					using MediaBrowser.Model.Net;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
@ -145,7 +146,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? isDisliked,
 | 
					            [FromQuery] bool? isDisliked,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] string? sortBy,
 | 
					            [FromQuery] string? sortBy,
 | 
				
			||||||
@ -262,7 +263,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? seriesTimerId,
 | 
					            [FromQuery] string? seriesTimerId,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] bool? isMovie,
 | 
					            [FromQuery] bool? isMovie,
 | 
				
			||||||
@ -349,7 +350,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? seriesTimerId,
 | 
					            [FromQuery] string? seriesTimerId,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] bool enableTotalRecordCount = true)
 | 
					            [FromQuery] bool enableTotalRecordCount = true)
 | 
				
			||||||
@ -560,7 +561,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? genreIds,
 | 
					            [FromQuery] string? genreIds,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] string? seriesTimerId,
 | 
					            [FromQuery] string? seriesTimerId,
 | 
				
			||||||
            [FromQuery] Guid? librarySeriesId,
 | 
					            [FromQuery] Guid? librarySeriesId,
 | 
				
			||||||
@ -704,7 +705,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? isSports,
 | 
					            [FromQuery] bool? isSports,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? genreIds,
 | 
					            [FromQuery] string? genreIds,
 | 
				
			||||||
            [FromQuery] ItemFields[] fields,
 | 
					            [FromQuery] ItemFields[] fields,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
 | 
				
			|||||||
@ -11,6 +11,7 @@ using MediaBrowser.Controller.Entities;
 | 
				
			|||||||
using MediaBrowser.Controller.Entities.Audio;
 | 
					using MediaBrowser.Controller.Entities.Audio;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -99,7 +100,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ using MediaBrowser.Controller.Dto;
 | 
				
			|||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -99,7 +100,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ using MediaBrowser.Controller.Dto;
 | 
				
			|||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Controller.Playlists;
 | 
					using MediaBrowser.Controller.Playlists;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Playlists;
 | 
					using MediaBrowser.Model.Playlists;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
@ -151,7 +152,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes)
 | 
					            [FromQuery] ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var playlist = (Playlist)_libraryManager.GetItemById(playlistId);
 | 
					            var playlist = (Playlist)_libraryManager.GetItemById(playlistId);
 | 
				
			||||||
            if (playlist == null)
 | 
					            if (playlist == null)
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ using MediaBrowser.Controller.Dto;
 | 
				
			|||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -98,7 +99,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
 | 
				
			|||||||
@ -150,7 +150,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] ItemFilter[] filters,
 | 
					            [FromQuery] ItemFilter[] filters,
 | 
				
			||||||
            [FromQuery] bool? isFavorite,
 | 
					            [FromQuery] bool? isFavorite,
 | 
				
			||||||
            [FromQuery] string? mediaTypes,
 | 
					            [FromQuery] string? mediaTypes,
 | 
				
			||||||
            [FromQuery] string? imageTypes,
 | 
					            [FromQuery] ImageType[] imageTypes,
 | 
				
			||||||
            [FromQuery] string? sortBy,
 | 
					            [FromQuery] string? sortBy,
 | 
				
			||||||
            [FromQuery] bool? isPlayed,
 | 
					            [FromQuery] bool? isPlayed,
 | 
				
			||||||
            [FromQuery] string? genres,
 | 
					            [FromQuery] string? genres,
 | 
				
			||||||
@ -159,7 +159,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? years,
 | 
					            [FromQuery] string? years,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] string? person,
 | 
					            [FromQuery] string? person,
 | 
				
			||||||
            [FromQuery] string? personIds,
 | 
					            [FromQuery] string? personIds,
 | 
				
			||||||
            [FromQuery] string? personTypes,
 | 
					            [FromQuery] string? personTypes,
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,7 @@ using MediaBrowser.Controller.Entities.TV;
 | 
				
			|||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Controller.TV;
 | 
					using MediaBrowser.Controller.TV;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -77,7 +78,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? parentId,
 | 
					            [FromQuery] string? parentId,
 | 
				
			||||||
            [FromQuery] bool? enableImges,
 | 
					            [FromQuery] bool? enableImges,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] bool enableTotalRecordCount = true)
 | 
					            [FromQuery] bool enableTotalRecordCount = true)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -134,7 +135,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? parentId,
 | 
					            [FromQuery] string? parentId,
 | 
				
			||||||
            [FromQuery] bool? enableImges,
 | 
					            [FromQuery] bool? enableImges,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] bool? enableUserData)
 | 
					            [FromQuery] bool? enableUserData)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
@ -206,7 +207,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] int? limit,
 | 
					            [FromQuery] int? limit,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] string? sortBy)
 | 
					            [FromQuery] string? sortBy)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
@ -325,7 +326,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? adjacentTo,
 | 
					            [FromQuery] string? adjacentTo,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] bool? enableUserData)
 | 
					            [FromQuery] bool? enableUserData)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
					            var user = userId.HasValue && !userId.Equals(Guid.Empty)
 | 
				
			||||||
 | 
				
			|||||||
@ -272,7 +272,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] bool? isPlayed,
 | 
					            [FromQuery] bool? isPlayed,
 | 
				
			||||||
            [FromQuery] bool? enableImages,
 | 
					            [FromQuery] bool? enableImages,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int limit = 20,
 | 
					            [FromQuery] int limit = 20,
 | 
				
			||||||
            [FromQuery] bool groupItems = true)
 | 
					            [FromQuery] bool groupItems = true)
 | 
				
			||||||
 | 
				
			|||||||
@ -371,7 +371,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            var baseUrlParam = string.Format(
 | 
					            var baseUrlParam = string.Format(
 | 
				
			||||||
                CultureInfo.InvariantCulture,
 | 
					                CultureInfo.InvariantCulture,
 | 
				
			||||||
                "\"hls{0}\"",
 | 
					                "\"hls/{0}/\"",
 | 
				
			||||||
                Path.GetFileNameWithoutExtension(outputPath));
 | 
					                Path.GetFileNameWithoutExtension(outputPath));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return string.Format(
 | 
					            return string.Format(
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@ using MediaBrowser.Controller.Dto;
 | 
				
			|||||||
using MediaBrowser.Controller.Entities;
 | 
					using MediaBrowser.Controller.Entities;
 | 
				
			||||||
using MediaBrowser.Controller.Library;
 | 
					using MediaBrowser.Controller.Library;
 | 
				
			||||||
using MediaBrowser.Model.Dto;
 | 
					using MediaBrowser.Model.Dto;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Authorization;
 | 
					using Microsoft.AspNetCore.Authorization;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
@ -77,7 +78,7 @@ namespace Jellyfin.Api.Controllers
 | 
				
			|||||||
            [FromQuery] string? sortBy,
 | 
					            [FromQuery] string? sortBy,
 | 
				
			||||||
            [FromQuery] bool? enableUserData,
 | 
					            [FromQuery] bool? enableUserData,
 | 
				
			||||||
            [FromQuery] int? imageTypeLimit,
 | 
					            [FromQuery] int? imageTypeLimit,
 | 
				
			||||||
            [FromQuery] string? enableImageTypes,
 | 
					            [FromQuery] ImageType[] enableImageTypes,
 | 
				
			||||||
            [FromQuery] Guid? userId,
 | 
					            [FromQuery] Guid? userId,
 | 
				
			||||||
            [FromQuery] bool recursive = true,
 | 
					            [FromQuery] bool recursive = true,
 | 
				
			||||||
            [FromQuery] bool? enableImages = true)
 | 
					            [FromQuery] bool? enableImages = true)
 | 
				
			||||||
 | 
				
			|||||||
@ -106,7 +106,7 @@ namespace Jellyfin.Api.Extensions
 | 
				
			|||||||
            bool? enableImages,
 | 
					            bool? enableImages,
 | 
				
			||||||
            bool? enableUserData,
 | 
					            bool? enableUserData,
 | 
				
			||||||
            int? imageTypeLimit,
 | 
					            int? imageTypeLimit,
 | 
				
			||||||
            string? enableImageTypes)
 | 
					            ImageType[] enableImageTypes)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            dtoOptions.EnableImages = enableImages ?? true;
 | 
					            dtoOptions.EnableImages = enableImages ?? true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -120,11 +120,9 @@ namespace Jellyfin.Api.Extensions
 | 
				
			|||||||
                dtoOptions.EnableUserData = enableUserData.Value;
 | 
					                dtoOptions.EnableUserData = enableUserData.Value;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!string.IsNullOrWhiteSpace(enableImageTypes))
 | 
					            if (enableImageTypes.Length != 0)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                dtoOptions.ImageTypes = enableImageTypes.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
 | 
					                dtoOptions.ImageTypes = enableImageTypes;
 | 
				
			||||||
                    .Select(v => (ImageType)Enum.Parse(typeof(ImageType), v, true))
 | 
					 | 
				
			||||||
                    .ToArray();
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return dtoOptions;
 | 
					            return dtoOptions;
 | 
				
			||||||
 | 
				
			|||||||
@ -155,7 +155,7 @@ namespace Jellyfin.Api.Helpers
 | 
				
			|||||||
                return new FileContentResult(Array.Empty<byte>(), MimeTypes.GetMimeType("playlist.m3u8"));
 | 
					                return new FileContentResult(Array.Empty<byte>(), MimeTypes.GetMimeType("playlist.m3u8"));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var totalBitrate = state.OutputAudioBitrate ?? 0 + state.OutputVideoBitrate ?? 0;
 | 
					            var totalBitrate = (state.OutputAudioBitrate ?? 0) + (state.OutputVideoBitrate ?? 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            var builder = new StringBuilder();
 | 
					            var builder = new StringBuilder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,7 @@ using Jellyfin.Data.Enums;
 | 
				
			|||||||
using MediaBrowser.Common.Extensions;
 | 
					using MediaBrowser.Common.Extensions;
 | 
				
			||||||
using MediaBrowser.Controller.Net;
 | 
					using MediaBrowser.Controller.Net;
 | 
				
			||||||
using MediaBrowser.Controller.Session;
 | 
					using MediaBrowser.Controller.Session;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
using Microsoft.AspNetCore.Http;
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Jellyfin.Api.Helpers
 | 
					namespace Jellyfin.Api.Helpers
 | 
				
			||||||
@ -132,5 +133,31 @@ namespace Jellyfin.Api.Helpers
 | 
				
			|||||||
                .Select(i => new Guid(i))
 | 
					                .Select(i => new Guid(i))
 | 
				
			||||||
                .ToArray();
 | 
					                .ToArray();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /// <summary>
 | 
				
			||||||
 | 
					        /// Gets the item fields.
 | 
				
			||||||
 | 
					        /// </summary>
 | 
				
			||||||
 | 
					        /// <param name="fields">The fields string.</param>
 | 
				
			||||||
 | 
					        /// <returns>IEnumerable{ItemFields}.</returns>
 | 
				
			||||||
 | 
					        internal static ItemFields[] GetItemFields(string? fields)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (string.IsNullOrEmpty(fields))
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return Array.Empty<ItemFields>();
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return Split(fields, ',', true)
 | 
				
			||||||
 | 
					                .Select(v =>
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    if (Enum.TryParse(v, true, out ItemFields value))
 | 
				
			||||||
 | 
					                    {
 | 
				
			||||||
 | 
					                        return (ItemFields?)value;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return null;
 | 
				
			||||||
 | 
					                }).Where(i => i.HasValue)
 | 
				
			||||||
 | 
					                .Select(i => i!.Value)
 | 
				
			||||||
 | 
					                .ToArray();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
using System.Diagnostics.CodeAnalysis;
 | 
					using System.Diagnostics.CodeAnalysis;
 | 
				
			||||||
using System.Text.Json.Serialization;
 | 
					using System.Text.Json.Serialization;
 | 
				
			||||||
using MediaBrowser.Common.Json.Converters;
 | 
					using MediaBrowser.Common.Json.Converters;
 | 
				
			||||||
 | 
					using MediaBrowser.Model.Entities;
 | 
				
			||||||
using MediaBrowser.Model.Querying;
 | 
					using MediaBrowser.Model.Querying;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace Jellyfin.Api.Models.LiveTvDtos
 | 
					namespace Jellyfin.Api.Models.LiveTvDtos
 | 
				
			||||||
@ -141,7 +142,9 @@ namespace Jellyfin.Api.Models.LiveTvDtos
 | 
				
			|||||||
        /// Gets or sets the image types to include in the output.
 | 
					        /// Gets or sets the image types to include in the output.
 | 
				
			||||||
        /// Optional.
 | 
					        /// Optional.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
        public string? EnableImageTypes { get; set; }
 | 
					        [JsonConverter(typeof(JsonCommaDelimitedArrayConverterFactory))]
 | 
				
			||||||
 | 
					        [SuppressMessage("Microsoft.Performance", "CA1819:ReturnArrays", MessageId = "EnableImageTypes", Justification = "Imported from ServiceStack")]
 | 
				
			||||||
 | 
					        public ImageType[] EnableImageTypes { get; set; } = Array.Empty<ImageType>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Gets or sets include user data.
 | 
					        /// Gets or sets include user data.
 | 
				
			||||||
 | 
				
			|||||||
@ -2,6 +2,7 @@
 | 
				
			|||||||
#pragma warning disable CA1307
 | 
					#pragma warning disable CA1307
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using System;
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Concurrent;
 | 
				
			||||||
using System.Collections.Generic;
 | 
					using System.Collections.Generic;
 | 
				
			||||||
using System.Globalization;
 | 
					using System.Globalization;
 | 
				
			||||||
using System.Linq;
 | 
					using System.Linq;
 | 
				
			||||||
@ -48,6 +49,8 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
        private readonly DefaultAuthenticationProvider _defaultAuthenticationProvider;
 | 
					        private readonly DefaultAuthenticationProvider _defaultAuthenticationProvider;
 | 
				
			||||||
        private readonly DefaultPasswordResetProvider _defaultPasswordResetProvider;
 | 
					        private readonly DefaultPasswordResetProvider _defaultPasswordResetProvider;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private readonly IDictionary<Guid, User> _users;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <summary>
 | 
					        /// <summary>
 | 
				
			||||||
        /// Initializes a new instance of the <see cref="UserManager"/> class.
 | 
					        /// Initializes a new instance of the <see cref="UserManager"/> class.
 | 
				
			||||||
        /// </summary>
 | 
					        /// </summary>
 | 
				
			||||||
@ -81,38 +84,28 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
            _invalidAuthProvider = _authenticationProviders.OfType<InvalidAuthProvider>().First();
 | 
					            _invalidAuthProvider = _authenticationProviders.OfType<InvalidAuthProvider>().First();
 | 
				
			||||||
            _defaultAuthenticationProvider = _authenticationProviders.OfType<DefaultAuthenticationProvider>().First();
 | 
					            _defaultAuthenticationProvider = _authenticationProviders.OfType<DefaultAuthenticationProvider>().First();
 | 
				
			||||||
            _defaultPasswordResetProvider = _passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
 | 
					            _defaultPasswordResetProvider = _passwordResetProviders.OfType<DefaultPasswordResetProvider>().First();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _users = new ConcurrentDictionary<Guid, User>();
 | 
				
			||||||
 | 
					            using var dbContext = _dbProvider.CreateContext();
 | 
				
			||||||
 | 
					            foreach (var user in dbContext.Users
 | 
				
			||||||
 | 
					                .Include(user => user.Permissions)
 | 
				
			||||||
 | 
					                .Include(user => user.Preferences)
 | 
				
			||||||
 | 
					                .Include(user => user.AccessSchedules)
 | 
				
			||||||
 | 
					                .Include(user => user.ProfileImage)
 | 
				
			||||||
 | 
					                .AsEnumerable())
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                _users.Add(user.Id, user);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
        public event EventHandler<GenericEventArgs<User>>? OnUserUpdated;
 | 
					        public event EventHandler<GenericEventArgs<User>>? OnUserUpdated;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
        public IEnumerable<User> Users
 | 
					        public IEnumerable<User> Users => _users.Values;
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                using var dbContext = _dbProvider.CreateContext();
 | 
					 | 
				
			||||||
                return dbContext.Users
 | 
					 | 
				
			||||||
                    .Include(user => user.Permissions)
 | 
					 | 
				
			||||||
                    .Include(user => user.Preferences)
 | 
					 | 
				
			||||||
                    .Include(user => user.AccessSchedules)
 | 
					 | 
				
			||||||
                    .Include(user => user.ProfileImage)
 | 
					 | 
				
			||||||
                    .ToList();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
        public IEnumerable<Guid> UsersIds
 | 
					        public IEnumerable<Guid> UsersIds => _users.Keys;
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            get
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                using var dbContext = _dbProvider.CreateContext();
 | 
					 | 
				
			||||||
                return dbContext.Users
 | 
					 | 
				
			||||||
                    .AsQueryable()
 | 
					 | 
				
			||||||
                    .Select(user => user.Id)
 | 
					 | 
				
			||||||
                    .ToList();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
        public User? GetUserById(Guid id)
 | 
					        public User? GetUserById(Guid id)
 | 
				
			||||||
@ -122,13 +115,8 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
                throw new ArgumentException("Guid can't be empty", nameof(id));
 | 
					                throw new ArgumentException("Guid can't be empty", nameof(id));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            using var dbContext = _dbProvider.CreateContext();
 | 
					            _users.TryGetValue(id, out var user);
 | 
				
			||||||
            return dbContext.Users
 | 
					            return user;
 | 
				
			||||||
                .Include(user => user.Permissions)
 | 
					 | 
				
			||||||
                .Include(user => user.Preferences)
 | 
					 | 
				
			||||||
                .Include(user => user.AccessSchedules)
 | 
					 | 
				
			||||||
                .Include(user => user.ProfileImage)
 | 
					 | 
				
			||||||
                .FirstOrDefault(user => user.Id == id);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
@ -139,14 +127,7 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
                throw new ArgumentException("Invalid username", nameof(name));
 | 
					                throw new ArgumentException("Invalid username", nameof(name));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            using var dbContext = _dbProvider.CreateContext();
 | 
					            return _users.Values.FirstOrDefault(u => string.Equals(u.Username, name, StringComparison.OrdinalIgnoreCase));
 | 
				
			||||||
            return dbContext.Users
 | 
					 | 
				
			||||||
                .Include(user => user.Permissions)
 | 
					 | 
				
			||||||
                .Include(user => user.Preferences)
 | 
					 | 
				
			||||||
                .Include(user => user.AccessSchedules)
 | 
					 | 
				
			||||||
                .Include(user => user.ProfileImage)
 | 
					 | 
				
			||||||
                .AsEnumerable()
 | 
					 | 
				
			||||||
                .FirstOrDefault(u => string.Equals(u.Username, name, StringComparison.OrdinalIgnoreCase));
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
@ -205,13 +186,17 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
                ? await dbContext.Users.AsQueryable().Select(u => u.InternalId).MaxAsync().ConfigureAwait(false)
 | 
					                ? await dbContext.Users.AsQueryable().Select(u => u.InternalId).MaxAsync().ConfigureAwait(false)
 | 
				
			||||||
                : 0;
 | 
					                : 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return new User(
 | 
					            var user = new User(
 | 
				
			||||||
                name,
 | 
					                name,
 | 
				
			||||||
                _defaultAuthenticationProvider.GetType().FullName,
 | 
					                _defaultAuthenticationProvider.GetType().FullName,
 | 
				
			||||||
                _defaultPasswordResetProvider.GetType().FullName)
 | 
					                _defaultPasswordResetProvider.GetType().FullName)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                InternalId = max + 1
 | 
					                InternalId = max + 1
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            _users.Add(user.Id, user);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return user;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
@ -237,28 +222,12 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
        /// <inheritdoc/>
 | 
					        /// <inheritdoc/>
 | 
				
			||||||
        public void DeleteUser(Guid userId)
 | 
					        public void DeleteUser(Guid userId)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            using var dbContext = _dbProvider.CreateContext();
 | 
					            if (!_users.TryGetValue(userId, out var user))
 | 
				
			||||||
            var user = dbContext.Users
 | 
					 | 
				
			||||||
                .Include(u => u.Permissions)
 | 
					 | 
				
			||||||
                .Include(u => u.Preferences)
 | 
					 | 
				
			||||||
                .Include(u => u.AccessSchedules)
 | 
					 | 
				
			||||||
                .Include(u => u.ProfileImage)
 | 
					 | 
				
			||||||
                .FirstOrDefault(u => u.Id == userId);
 | 
					 | 
				
			||||||
            if (user == null)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                throw new ResourceNotFoundException(nameof(userId));
 | 
					                throw new ResourceNotFoundException(nameof(userId));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (dbContext.Users.Find(user.Id) == null)
 | 
					            if (_users.Count == 1)
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                throw new ArgumentException(string.Format(
 | 
					 | 
				
			||||||
                    CultureInfo.InvariantCulture,
 | 
					 | 
				
			||||||
                    "The user cannot be deleted because there is no user with the Name {0} and Id {1}.",
 | 
					 | 
				
			||||||
                    user.Username,
 | 
					 | 
				
			||||||
                    user.Id));
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (dbContext.Users.Count() == 1)
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                throw new InvalidOperationException(string.Format(
 | 
					                throw new InvalidOperationException(string.Format(
 | 
				
			||||||
                    CultureInfo.InvariantCulture,
 | 
					                    CultureInfo.InvariantCulture,
 | 
				
			||||||
@ -277,6 +246,8 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
                    nameof(userId));
 | 
					                    nameof(userId));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            using var dbContext = _dbProvider.CreateContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Clear all entities related to the user from the database.
 | 
					            // Clear all entities related to the user from the database.
 | 
				
			||||||
            if (user.ProfileImage != null)
 | 
					            if (user.ProfileImage != null)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
@ -288,6 +259,7 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
            dbContext.RemoveRange(user.AccessSchedules);
 | 
					            dbContext.RemoveRange(user.AccessSchedules);
 | 
				
			||||||
            dbContext.Users.Remove(user);
 | 
					            dbContext.Users.Remove(user);
 | 
				
			||||||
            dbContext.SaveChanges();
 | 
					            dbContext.SaveChanges();
 | 
				
			||||||
 | 
					            _users.Remove(userId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            _eventManager.Publish(new UserDeletedEventArgs(user));
 | 
					            _eventManager.Publish(new UserDeletedEventArgs(user));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -589,9 +561,7 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
        public async Task InitializeAsync()
 | 
					        public async Task InitializeAsync()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            // TODO: Refactor the startup wizard so that it doesn't require a user to already exist.
 | 
					            // TODO: Refactor the startup wizard so that it doesn't require a user to already exist.
 | 
				
			||||||
            await using var dbContext = _dbProvider.CreateContext();
 | 
					            if (_users.Any())
 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (await dbContext.Users.AsQueryable().AnyAsync().ConfigureAwait(false))
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -604,6 +574,7 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            _logger.LogWarning("No users, creating one with username {UserName}", defaultName);
 | 
					            _logger.LogWarning("No users, creating one with username {UserName}", defaultName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await using var dbContext = _dbProvider.CreateContext();
 | 
				
			||||||
            var newUser = await CreateUserInternalAsync(defaultName, dbContext).ConfigureAwait(false);
 | 
					            var newUser = await CreateUserInternalAsync(defaultName, dbContext).ConfigureAwait(false);
 | 
				
			||||||
            newUser.SetPermission(PermissionKind.IsAdministrator, true);
 | 
					            newUser.SetPermission(PermissionKind.IsAdministrator, true);
 | 
				
			||||||
            newUser.SetPermission(PermissionKind.EnableContentDeletion, true);
 | 
					            newUser.SetPermission(PermissionKind.EnableContentDeletion, true);
 | 
				
			||||||
@ -753,6 +724,7 @@ namespace Jellyfin.Server.Implementations.Users
 | 
				
			|||||||
            using var dbContext = _dbProvider.CreateContext();
 | 
					            using var dbContext = _dbProvider.CreateContext();
 | 
				
			||||||
            dbContext.Remove(user.ProfileImage);
 | 
					            dbContext.Remove(user.ProfileImage);
 | 
				
			||||||
            dbContext.SaveChanges();
 | 
					            dbContext.SaveChanges();
 | 
				
			||||||
 | 
					            user.ProfileImage = null;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        private static bool IsValidUsername(string name)
 | 
					        private static bool IsValidUsername(string name)
 | 
				
			||||||
 | 
				
			|||||||
@ -42,7 +42,7 @@
 | 
				
			|||||||
    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.9" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.9" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.9" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks" Version="3.1.9" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.9" />
 | 
					    <PackageReference Include="Microsoft.Extensions.Diagnostics.HealthChecks.EntityFrameworkCore" Version="3.1.9" />
 | 
				
			||||||
    <PackageReference Include="prometheus-net" Version="3.6.0" />
 | 
					    <PackageReference Include="prometheus-net" Version="4.0.0" />
 | 
				
			||||||
    <PackageReference Include="prometheus-net.AspNetCore" Version="3.6.0" />
 | 
					    <PackageReference Include="prometheus-net.AspNetCore" Version="3.6.0" />
 | 
				
			||||||
    <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
 | 
					    <PackageReference Include="Serilog.AspNetCore" Version="3.4.0" />
 | 
				
			||||||
    <PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
 | 
					    <PackageReference Include="Serilog.Enrichers.Thread" Version="3.1.0" />
 | 
				
			||||||
 | 
				
			|||||||
@ -1380,24 +1380,40 @@ namespace MediaBrowser.Controller.MediaEncoding
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream)
 | 
					        public int? GetAudioBitrateParam(BaseEncodingJobOptions request, MediaStream audioStream)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            if (audioStream == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (request.AudioBitRate.HasValue)
 | 
					            if (request.AudioBitRate.HasValue)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Don't encode any higher than this
 | 
					                // Don't encode any higher than this
 | 
				
			||||||
                return Math.Min(384000, request.AudioBitRate.Value);
 | 
					                return Math.Min(384000, request.AudioBitRate.Value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return null;
 | 
					            // Empty bitrate area is not allow on iOS
 | 
				
			||||||
 | 
					            // Default audio bitrate to 128K if it is not being requested
 | 
				
			||||||
 | 
					            // https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options
 | 
				
			||||||
 | 
					            return 128000;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public int? GetAudioBitrateParam(int? audioBitRate, MediaStream audioStream)
 | 
					        public int? GetAudioBitrateParam(int? audioBitRate, MediaStream audioStream)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					            if (audioStream == null)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                return null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (audioBitRate.HasValue)
 | 
					            if (audioBitRate.HasValue)
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                // Don't encode any higher than this
 | 
					                // Don't encode any higher than this
 | 
				
			||||||
                return Math.Min(384000, audioBitRate.Value);
 | 
					                return Math.Min(384000, audioBitRate.Value);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return null;
 | 
					            // Empty bitrate area is not allow on iOS
 | 
				
			||||||
 | 
					            // Default audio bitrate to 128K if it is not being requested
 | 
				
			||||||
 | 
					            // https://ffmpeg.org/ffmpeg-codecs.html#toc-Codec-Options
 | 
				
			||||||
 | 
					            return 128000;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions, bool isHls)
 | 
					        public string GetAudioFilterParam(EncodingJobInfo state, EncodingOptions encodingOptions, bool isHls)
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@
 | 
				
			|||||||
    <PackageReference Include="xunit" Version="2.4.1" />
 | 
					    <PackageReference Include="xunit" Version="2.4.1" />
 | 
				
			||||||
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
 | 
					    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
 | 
				
			||||||
    <PackageReference Include="coverlet.collector" Version="1.3.0" />
 | 
					    <PackageReference Include="coverlet.collector" Version="1.3.0" />
 | 
				
			||||||
    <PackageReference Include="Moq" Version="4.14.6" />
 | 
					    <PackageReference Include="Moq" Version="4.14.7" />
 | 
				
			||||||
  </ItemGroup>
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  <!-- Code Analyzers -->
 | 
					  <!-- Code Analyzers -->
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
    <PackageReference Include="AutoFixture" Version="4.13.0" />
 | 
					    <PackageReference Include="AutoFixture" Version="4.13.0" />
 | 
				
			||||||
    <PackageReference Include="AutoFixture.AutoMoq" Version="4.13.0" />
 | 
					    <PackageReference Include="AutoFixture.AutoMoq" Version="4.13.0" />
 | 
				
			||||||
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
 | 
					    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.7.1" />
 | 
				
			||||||
    <PackageReference Include="Moq" Version="4.14.6" />
 | 
					    <PackageReference Include="Moq" Version="4.14.7" />
 | 
				
			||||||
    <PackageReference Include="xunit" Version="2.4.1" />
 | 
					    <PackageReference Include="xunit" Version="2.4.1" />
 | 
				
			||||||
    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
 | 
					    <PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
 | 
				
			||||||
    <PackageReference Include="coverlet.collector" Version="1.3.0" />
 | 
					    <PackageReference Include="coverlet.collector" Version="1.3.0" />
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user