aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Api
diff options
context:
space:
mode:
Diffstat (limited to 'Jellyfin.Api')
-rw-r--r--Jellyfin.Api/Controllers/ArtistsController.cs6
-rw-r--r--Jellyfin.Api/Controllers/ChannelsController.cs12
-rw-r--r--Jellyfin.Api/Controllers/DashboardController.cs3
-rw-r--r--Jellyfin.Api/Controllers/DisplayPreferencesController.cs6
-rw-r--r--Jellyfin.Api/Controllers/DynamicHlsController.cs17
-rw-r--r--Jellyfin.Api/Controllers/FilterController.cs12
-rw-r--r--Jellyfin.Api/Controllers/GenresController.cs27
-rw-r--r--Jellyfin.Api/Controllers/HlsSegmentController.cs4
-rw-r--r--Jellyfin.Api/Controllers/ImageController.cs54
-rw-r--r--Jellyfin.Api/Controllers/InstantMixController.cs42
-rw-r--r--Jellyfin.Api/Controllers/ItemRefreshController.cs4
-rw-r--r--Jellyfin.Api/Controllers/ItemsController.cs6
-rw-r--r--Jellyfin.Api/Controllers/LibraryController.cs58
-rw-r--r--Jellyfin.Api/Controllers/LiveTvController.cs52
-rw-r--r--Jellyfin.Api/Controllers/MediaInfoController.cs10
-rw-r--r--Jellyfin.Api/Controllers/MoviesController.cs6
-rw-r--r--Jellyfin.Api/Controllers/MusicGenresController.cs6
-rw-r--r--Jellyfin.Api/Controllers/PersonsController.cs11
-rw-r--r--Jellyfin.Api/Controllers/PlaylistsController.cs4
-rw-r--r--Jellyfin.Api/Controllers/PluginsController.cs71
-rw-r--r--Jellyfin.Api/Controllers/SearchController.cs8
-rw-r--r--Jellyfin.Api/Controllers/SessionController.cs6
-rw-r--r--Jellyfin.Api/Controllers/StudiosController.cs6
-rw-r--r--Jellyfin.Api/Controllers/SuggestionsController.cs4
-rw-r--r--Jellyfin.Api/Controllers/TvShowsController.cs31
-rw-r--r--Jellyfin.Api/Controllers/UniversalAudioController.cs5
-rw-r--r--Jellyfin.Api/Controllers/UserController.cs2
-rw-r--r--Jellyfin.Api/Controllers/UserLibraryController.cs12
-rw-r--r--Jellyfin.Api/Controllers/UserViewsController.cs11
-rw-r--r--Jellyfin.Api/Controllers/VideosController.cs24
-rw-r--r--Jellyfin.Api/Controllers/YearsController.cs20
-rw-r--r--Jellyfin.Api/Helpers/AudioHelper.cs6
-rw-r--r--Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs22
-rw-r--r--Jellyfin.Api/Helpers/MediaInfoHelper.cs189
-rw-r--r--Jellyfin.Api/Helpers/ProgressiveFileStream.cs16
-rw-r--r--Jellyfin.Api/Helpers/StreamingHelpers.cs4
-rw-r--r--Jellyfin.Api/Helpers/TranscodingJobHelper.cs39
-rw-r--r--Jellyfin.Api/Jellyfin.Api.csproj6
-rw-r--r--Jellyfin.Api/Models/PluginDtos/MBRegistrationRecord.cs40
-rw-r--r--Jellyfin.Api/Models/PluginDtos/PluginSecurityInfo.cs18
40 files changed, 323 insertions, 557 deletions
diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs
index b54825775..44796bcc4 100644
--- a/Jellyfin.Api/Controllers/ArtistsController.cs
+++ b/Jellyfin.Api/Controllers/ArtistsController.cs
@@ -126,7 +126,7 @@ namespace Jellyfin.Api.Controllers
User? user = null;
BaseItem parentItem = _libraryManager.GetParentItem(parentId, userId);
- if (userId.HasValue && !userId.Equals(Guid.Empty))
+ if (userId.HasValue && !userId.Equals(default))
{
user = _userManager.GetUserById(userId.Value);
}
@@ -329,7 +329,7 @@ namespace Jellyfin.Api.Controllers
User? user = null;
BaseItem parentItem = _libraryManager.GetParentItem(parentId, userId);
- if (userId.HasValue && !userId.Equals(Guid.Empty))
+ if (userId.HasValue && !userId.Equals(default))
{
user = _userManager.GetUserById(userId.Value);
}
@@ -467,7 +467,7 @@ namespace Jellyfin.Api.Controllers
var item = _libraryManager.GetArtist(name, dtoOptions);
- if (userId.HasValue && !userId.Equals(Guid.Empty))
+ if (userId.HasValue && !userId.Value.Equals(default))
{
var user = _userManager.GetUserById(userId.Value);
diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs
index 54bd80095..d5b589a3f 100644
--- a/Jellyfin.Api/Controllers/ChannelsController.cs
+++ b/Jellyfin.Api/Controllers/ChannelsController.cs
@@ -125,9 +125,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var query = new InternalItemsQuery(user)
{
@@ -199,9 +199,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] Guid[] channelIds)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var query = new InternalItemsQuery(user)
{
diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs
index 87cb418d9..c8411f44b 100644
--- a/Jellyfin.Api/Controllers/DashboardController.cs
+++ b/Jellyfin.Api/Controllers/DashboardController.cs
@@ -4,10 +4,12 @@ using System.IO;
using System.Linq;
using System.Net.Mime;
using Jellyfin.Api.Attributes;
+using Jellyfin.Api.Constants;
using Jellyfin.Api.Models;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Model.Net;
using MediaBrowser.Model.Plugins;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
@@ -46,6 +48,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("web/ConfigurationPages")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
+ [Authorize(Policy = Policies.DefaultAuthorization)]
public ActionResult<IEnumerable<ConfigurationPageInfo>> GetConfigurationPages(
[FromQuery] bool? enableInMainMenu)
{
diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs
index 0b2604640..27eb22339 100644
--- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs
+++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs
@@ -126,9 +126,11 @@ namespace Jellyfin.Api.Controllers
HomeSectionType.SmallLibraryTiles,
HomeSectionType.Resume,
HomeSectionType.ResumeAudio,
+ HomeSectionType.ResumeBook,
HomeSectionType.LiveTv,
HomeSectionType.NextUp,
- HomeSectionType.LatestMedia, HomeSectionType.None,
+ HomeSectionType.LatestMedia,
+ HomeSectionType.None,
};
if (!Guid.TryParse(displayPreferencesId, out var itemId))
@@ -182,7 +184,7 @@ namespace Jellyfin.Api.Controllers
var order = int.Parse(key.AsSpan().Slice("homesection".Length));
if (!Enum.TryParse<HomeSectionType>(displayPreferences.CustomPrefs[key], true, out var type))
{
- type = order < 7 ? defaults[order] : HomeSectionType.None;
+ type = order < 8 ? defaults[order] : HomeSectionType.None;
}
displayPreferences.CustomPrefs.Remove(key);
diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs
index f2fdeeea5..f8e8d975c 100644
--- a/Jellyfin.Api/Controllers/DynamicHlsController.cs
+++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs
@@ -1599,7 +1599,6 @@ namespace Jellyfin.Api.Controllers
state.BaseRequest.BreakOnNonKeyFrames = false;
}
- var inputModifier = _encodingHelper.GetInputModifier(state, _encodingOptions);
var mapArgs = state.IsOutputVideo ? _encodingHelper.GetMapArgs(state) : string.Empty;
var directory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath));
@@ -1608,12 +1607,15 @@ namespace Jellyfin.Api.Controllers
var outputExtension = EncodingHelper.GetSegmentFileExtension(state.Request.SegmentContainer);
var outputTsArg = outputPrefix + "%d" + outputExtension;
- var segmentFormat = outputExtension.TrimStart('.');
- if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase))
+ var segmentFormat = string.Empty;
+ var segmentContainer = outputExtension.TrimStart('.');
+ var inputModifier = _encodingHelper.GetInputModifier(state, _encodingOptions, segmentContainer);
+
+ if (string.Equals(segmentContainer, "ts", StringComparison.OrdinalIgnoreCase))
{
segmentFormat = "mpegts";
}
- else if (string.Equals(segmentFormat, "mp4", StringComparison.OrdinalIgnoreCase))
+ else if (string.Equals(segmentContainer, "mp4", StringComparison.OrdinalIgnoreCase))
{
var outputFmp4HeaderArg = OperatingSystem.IsWindows() switch
{
@@ -1627,7 +1629,8 @@ namespace Jellyfin.Api.Controllers
}
else
{
- _logger.LogError("Invalid HLS segment container: {SegmentFormat}", segmentFormat);
+ _logger.LogError("Invalid HLS segment container: {SegmentContainer}, default to mpegts", segmentContainer);
+ segmentFormat = "mpegts";
}
var maxMuxingQueueSize = _encodingOptions.MaxMuxingQueueSize > 128
@@ -1647,7 +1650,7 @@ namespace Jellyfin.Api.Controllers
CultureInfo.InvariantCulture,
"{0} {1} -map_metadata -1 -map_chapters -1 -threads {2} {3} {4} {5} -copyts -avoid_negative_ts disabled -max_muxing_queue_size {6} -f hls -max_delay 5000000 -hls_time {7} -hls_segment_type {8} -start_number {9}{10} -hls_segment_filename \"{12}\" -hls_playlist_type {11} -hls_list_size 0 -y \"{13}\"",
inputModifier,
- _encodingHelper.GetInputArgument(state, _encodingOptions),
+ _encodingHelper.GetInputArgument(state, _encodingOptions, segmentContainer),
threads,
mapArgs,
GetVideoArguments(state, startNumber, isEventPlaylist),
@@ -1944,7 +1947,7 @@ namespace Jellyfin.Api.Controllers
return Task.CompletedTask;
});
- return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath), false, HttpContext);
+ return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath));
}
private int? GetCurrentTranscodingIndex(string playlist, string segmentExtension)
diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs
index a4f12666d..11808b1b8 100644
--- a/Jellyfin.Api/Controllers/FilterController.cs
+++ b/Jellyfin.Api/Controllers/FilterController.cs
@@ -52,9 +52,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
BaseItem? item = null;
if (includeItemTypes.Length != 1
@@ -144,9 +144,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? isSeries,
[FromQuery] bool? recursive)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
BaseItem? parentItem = null;
if (includeItemTypes.Length == 1
diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs
index 37e6ae184..e28a50750 100644
--- a/Jellyfin.Api/Controllers/GenresController.cs
+++ b/Jellyfin.Api/Controllers/GenresController.cs
@@ -95,7 +95,9 @@ namespace Jellyfin.Api.Controllers
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
- User? user = userId.HasValue && userId != Guid.Empty ? _userManager.GetUserById(userId.Value) : null;
+ User? user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var parentItem = _libraryManager.GetParentItem(parentId, userId);
@@ -157,29 +159,26 @@ namespace Jellyfin.Api.Controllers
var dtoOptions = new DtoOptions()
.AddClientFields(Request);
- Genre item = new Genre();
- if (genreName.IndexOf(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase) != -1)
+ Genre? item;
+ if (genreName.Contains(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase))
{
- var result = GetItemFromSlugName<Genre>(_libraryManager, genreName, dtoOptions, BaseItemKind.Genre);
-
- if (result != null)
- {
- item = result;
- }
+ item = GetItemFromSlugName<Genre>(_libraryManager, genreName, dtoOptions, BaseItemKind.Genre);
}
else
{
item = _libraryManager.GetGenre(genreName);
}
- if (userId.HasValue && !userId.Equals(Guid.Empty))
- {
- var user = _userManager.GetUserById(userId.Value);
+ item ??= new Genre();
- return _dtoService.GetBaseItemDto(item, dtoOptions, user);
+ if (userId is null || userId.Value.Equals(default))
+ {
+ return _dtoService.GetBaseItemDto(item, dtoOptions);
}
- return _dtoService.GetBaseItemDto(item, dtoOptions);
+ var user = _userManager.GetUserById(userId.Value);
+
+ return _dtoService.GetBaseItemDto(item, dtoOptions, user);
}
private T? GetItemFromSlugName<T>(ILibraryManager libraryManager, string name, DtoOptions dtoOptions, BaseItemKind baseItemKind)
diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs
index 7325dca0a..78634f0bf 100644
--- a/Jellyfin.Api/Controllers/HlsSegmentController.cs
+++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs
@@ -69,7 +69,7 @@ namespace Jellyfin.Api.Controllers
return BadRequest("Invalid segment.");
}
- return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file), false, HttpContext);
+ return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file));
}
/// <summary>
@@ -186,7 +186,7 @@ namespace Jellyfin.Api.Controllers
return Task.CompletedTask;
});
- return FileStreamResponseHelpers.GetStaticFileResult(path, MimeTypes.GetMimeType(path), false, HttpContext);
+ return FileStreamResponseHelpers.GetStaticFileResult(path, MimeTypes.GetMimeType(path));
}
}
}
diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs
index aafffc2a1..05d80ba35 100644
--- a/Jellyfin.Api/Controllers/ImageController.cs
+++ b/Jellyfin.Api/Controllers/ImageController.cs
@@ -570,8 +570,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -654,8 +653,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -738,8 +736,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -822,8 +819,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -906,8 +902,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -990,8 +985,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -1074,8 +1068,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -1158,8 +1151,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -1242,8 +1234,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -1326,8 +1317,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -1410,8 +1400,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -1494,8 +1483,7 @@ namespace Jellyfin.Api.Controllers
blur,
backgroundColor,
foregroundLayer,
- item,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ item)
.ConfigureAwait(false);
}
@@ -1596,7 +1584,6 @@ namespace Jellyfin.Api.Controllers
backgroundColor,
foregroundLayer,
null,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase),
info)
.ConfigureAwait(false);
}
@@ -1698,7 +1685,6 @@ namespace Jellyfin.Api.Controllers
backgroundColor,
foregroundLayer,
null,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase),
info)
.ConfigureAwait(false);
}
@@ -1784,8 +1770,7 @@ namespace Jellyfin.Api.Controllers
return await GetImageResult(
options,
cacheDuration,
- ImmutableDictionary<string, string>.Empty,
- Request.Method.Equals(HttpMethods.Head, StringComparison.OrdinalIgnoreCase))
+ ImmutableDictionary<string, string>.Empty)
.ConfigureAwait(false);
}
@@ -1907,7 +1892,6 @@ namespace Jellyfin.Api.Controllers
string? backgroundColor,
string? foregroundLayer,
BaseItem? item,
- bool isHeadRequest,
ItemImageInfo? imageInfo = null)
{
if (percentPlayed.HasValue)
@@ -1988,8 +1972,7 @@ namespace Jellyfin.Api.Controllers
return await GetImageResult(
options,
cacheDuration,
- responseHeaders,
- isHeadRequest).ConfigureAwait(false);
+ responseHeaders).ConfigureAwait(false);
}
private ImageFormat[] GetOutputFormats(ImageFormat? format)
@@ -2068,8 +2051,7 @@ namespace Jellyfin.Api.Controllers
private async Task<ActionResult> GetImageResult(
ImageProcessingOptions imageProcessingOptions,
TimeSpan? cacheDuration,
- IDictionary<string, string> headers,
- bool isHeadRequest)
+ IDictionary<string, string> headers)
{
var (imagePath, imageContentType, dateImageModified) = await _imageProcessor.ProcessImage(imageProcessingOptions).ConfigureAwait(false);
@@ -2120,12 +2102,6 @@ namespace Jellyfin.Api.Controllers
}
}
- // if the request is a head request, return a NoContent result with the same headers as it would with a GET request
- if (isHeadRequest)
- {
- return NoContent();
- }
-
return PhysicalFile(imagePath, imageContentType ?? MediaTypeNames.Text.Plain);
}
}
diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs
index e9d48b624..9abea5938 100644
--- a/Jellyfin.Api/Controllers/InstantMixController.cs
+++ b/Jellyfin.Api/Controllers/InstantMixController.cs
@@ -75,9 +75,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
var item = _libraryManager.GetItemById(id);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -111,9 +111,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
var album = _libraryManager.GetItemById(id);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -147,9 +147,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
var playlist = (Playlist)_libraryManager.GetItemById(id);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -182,9 +182,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? imageTypeLimit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -218,9 +218,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
var item = _libraryManager.GetItemById(id);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -254,9 +254,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
var item = _libraryManager.GetItemById(id);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -327,9 +327,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes)
{
var item = _libraryManager.GetItemById(id);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
diff --git a/Jellyfin.Api/Controllers/ItemRefreshController.cs b/Jellyfin.Api/Controllers/ItemRefreshController.cs
index 49865eb5e..9340737b5 100644
--- a/Jellyfin.Api/Controllers/ItemRefreshController.cs
+++ b/Jellyfin.Api/Controllers/ItemRefreshController.cs
@@ -15,7 +15,7 @@ namespace Jellyfin.Api.Controllers
/// Item Refresh Controller.
/// </summary>
[Route("Items")]
- [Authorize(Policy = Policies.DefaultAuthorization)]
+ [Authorize(Policy = Policies.RequiresElevation)]
public class ItemRefreshController : BaseJellyfinApiController
{
private readonly ILibraryManager _libraryManager;
@@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers
[Description("Refreshes metadata for an item.")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
- public ActionResult Post(
+ public ActionResult RefreshItem(
[FromRoute, Required] Guid itemId,
[FromQuery] MetadataRefreshMode metadataRefreshMode = MetadataRefreshMode.None,
[FromQuery] MetadataRefreshMode imageRefreshMode = MetadataRefreshMode.None,
diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs
index dc7af0a20..2794a06f3 100644
--- a/Jellyfin.Api/Controllers/ItemsController.cs
+++ b/Jellyfin.Api/Controllers/ItemsController.cs
@@ -228,7 +228,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool enableTotalRecordCount = true,
[FromQuery] bool? enableImages = true)
{
- var user = userId == Guid.Empty ? null : _userManager.GetUserById(userId);
+ var user = userId.Equals(default) ? null : _userManager.GetUserById(userId);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
@@ -799,7 +799,7 @@ namespace Jellyfin.Api.Controllers
var ancestorIds = Array.Empty<Guid>();
var excludeFolderIds = user.GetPreferenceValues<Guid>(PreferenceKind.LatestItemExcludes);
- if (parentIdGuid.Equals(Guid.Empty) && excludeFolderIds.Length > 0)
+ if (parentIdGuid.Equals(default) && excludeFolderIds.Length > 0)
{
ancestorIds = _libraryManager.GetUserRootFolder().GetChildren(user, true)
.Where(i => i is Folder)
@@ -812,7 +812,7 @@ namespace Jellyfin.Api.Controllers
if (excludeActiveSessions)
{
excludeItemIds = _sessionManager.Sessions
- .Where(s => s.UserId == userId && s.NowPlayingItem != null)
+ .Where(s => s.UserId.Equals(userId) && s.NowPlayingItem != null)
.Select(s => s.NowPlayingItem.Id)
.ToArray();
}
diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs
index c65462ab5..4cc17dd0f 100644
--- a/Jellyfin.Api/Controllers/LibraryController.cs
+++ b/Jellyfin.Api/Controllers/LibraryController.cs
@@ -149,14 +149,14 @@ namespace Jellyfin.Api.Controllers
[FromQuery] Guid? userId,
[FromQuery] bool inheritFromParent = false)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
-
- var item = itemId.Equals(Guid.Empty)
- ? (!userId.Equals(Guid.Empty)
- ? _libraryManager.GetUserRootFolder()
- : _libraryManager.RootFolder)
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
+
+ var item = itemId.Equals(default)
+ ? (userId is null || userId.Value.Equals(default)
+ ? _libraryManager.RootFolder
+ : _libraryManager.GetUserRootFolder())
: _libraryManager.GetItemById(itemId);
if (item == null)
@@ -215,14 +215,14 @@ namespace Jellyfin.Api.Controllers
[FromQuery] Guid? userId,
[FromQuery] bool inheritFromParent = false)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
-
- var item = itemId.Equals(Guid.Empty)
- ? (!userId.Equals(Guid.Empty)
- ? _libraryManager.GetUserRootFolder()
- : _libraryManager.RootFolder)
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
+
+ var item = itemId.Equals(default)
+ ? (userId is null || userId.Value.Equals(default)
+ ? _libraryManager.RootFolder
+ : _libraryManager.GetUserRootFolder())
: _libraryManager.GetItemById(itemId);
if (item == null)
@@ -407,9 +407,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery] Guid? userId,
[FromQuery] bool? isFavorite)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var counts = new ItemCounts
{
@@ -449,9 +449,9 @@ namespace Jellyfin.Api.Controllers
var baseItemDtos = new List<BaseItemDto>();
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions().AddClientFields(Request);
BaseItem? parent = item.GetParent();
@@ -689,10 +689,10 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields)
{
- var item = itemId.Equals(Guid.Empty)
- ? (!userId.Equals(Guid.Empty)
- ? _libraryManager.GetUserRootFolder()
- : _libraryManager.RootFolder)
+ var item = itemId.Equals(default)
+ ? (userId is null || userId.Value.Equals(default)
+ ? _libraryManager.RootFolder
+ : _libraryManager.GetUserRootFolder())
: _libraryManager.GetItemById(itemId);
if (item is Episode || (item is IItemByName && item is not MusicArtist))
@@ -700,9 +700,9 @@ namespace Jellyfin.Api.Controllers
return new QueryResult<BaseItemDto>();
}
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request);
diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs
index 484b0a974..05340099b 100644
--- a/Jellyfin.Api/Controllers/LiveTvController.cs
+++ b/Jellyfin.Api/Controllers/LiveTvController.cs
@@ -180,9 +180,9 @@ namespace Jellyfin.Api.Controllers
dtoOptions,
CancellationToken.None);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var fieldsList = dtoOptions.Fields.ToList();
fieldsList.Remove(ItemFields.CanDelete);
@@ -211,10 +211,10 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
public ActionResult<BaseItemDto> GetChannel([FromRoute, Required] Guid channelId, [FromQuery] Guid? userId)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
- var item = channelId.Equals(Guid.Empty)
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
+ var item = channelId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(channelId);
@@ -382,9 +382,9 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
public ActionResult<QueryResult<BaseItemDto>> GetRecordingFolders([FromQuery] Guid? userId)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var folders = _liveTvManager.GetRecordingFolders(user);
var returnArray = _dtoService.GetBaseItemDtos(folders, new DtoOptions(), user);
@@ -404,10 +404,10 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
public ActionResult<BaseItemDto> GetRecording([FromRoute, Required] Guid recordingId, [FromQuery] Guid? userId)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
- var item = recordingId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId);
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
+ var item = recordingId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(recordingId);
var dtoOptions = new DtoOptions()
.AddClientFields(Request);
@@ -561,9 +561,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields,
[FromQuery] bool enableTotalRecordCount = true)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var query = new InternalItemsQuery(user)
{
@@ -588,7 +588,7 @@ namespace Jellyfin.Api.Controllers
GenreIds = genreIds
};
- if (librarySeriesId != null && !librarySeriesId.Equals(Guid.Empty))
+ if (librarySeriesId.HasValue && !librarySeriesId.Equals(default))
{
query.IsSeries = true;
@@ -617,7 +617,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)]
public async Task<ActionResult<QueryResult<BaseItemDto>>> GetPrograms([FromBody] GetProgramsDto body)
{
- var user = body.UserId.Equals(Guid.Empty) ? null : _userManager.GetUserById(body.UserId);
+ var user = body.UserId.Equals(default) ? null : _userManager.GetUserById(body.UserId);
var query = new InternalItemsQuery(user)
{
@@ -642,7 +642,7 @@ namespace Jellyfin.Api.Controllers
GenreIds = body.GenreIds
};
- if (!body.LibrarySeriesId.Equals(Guid.Empty))
+ if (!body.LibrarySeriesId.Equals(default))
{
query.IsSeries = true;
@@ -700,9 +700,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableUserData,
[FromQuery] bool enableTotalRecordCount = true)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var query = new InternalItemsQuery(user)
{
@@ -738,9 +738,9 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] string programId,
[FromQuery] Guid? userId)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
return await _liveTvManager.GetProgram(programId, CancellationToken.None, user).ConfigureAwait(false);
}
diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs
index b422eb78c..75df18204 100644
--- a/Jellyfin.Api/Controllers/MediaInfoController.cs
+++ b/Jellyfin.Api/Controllers/MediaInfoController.cs
@@ -126,7 +126,7 @@ namespace Jellyfin.Api.Controllers
var authInfo = await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false);
var profile = playbackInfoDto?.DeviceProfile;
- _logger.LogInformation("GetPostedPlaybackInfo profile: {@Profile}", profile);
+ _logger.LogDebug("GetPostedPlaybackInfo profile: {@Profile}", profile);
if (profile == null)
{
@@ -225,14 +225,6 @@ namespace Jellyfin.Api.Controllers
}
}
- if (info.MediaSources != null)
- {
- foreach (var mediaSource in info.MediaSources)
- {
- _mediaInfoHelper.NormalizeMediaSourceContainer(mediaSource, profile!, DlnaProfileType.Video);
- }
- }
-
return info;
}
diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs
index db72ff2f8..420dd9923 100644
--- a/Jellyfin.Api/Controllers/MoviesController.cs
+++ b/Jellyfin.Api/Controllers/MoviesController.cs
@@ -68,9 +68,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int categoryLimit = 5,
[FromQuery] int itemLimit = 8)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var dtoOptions = new DtoOptions { Fields = fields }
.AddClientFields(Request);
diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs
index c4c03aa4f..0499b2985 100644
--- a/Jellyfin.Api/Controllers/MusicGenresController.cs
+++ b/Jellyfin.Api/Controllers/MusicGenresController.cs
@@ -95,7 +95,9 @@ namespace Jellyfin.Api.Controllers
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, false, imageTypeLimit, enableImageTypes);
- User? user = userId.HasValue && userId != Guid.Empty ? _userManager.GetUserById(userId.Value) : null;
+ User? user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var parentItem = _libraryManager.GetParentItem(parentId, userId);
@@ -156,7 +158,7 @@ namespace Jellyfin.Api.Controllers
item = _libraryManager.GetMusicGenre(genreName);
}
- if (userId.HasValue && !userId.Equals(Guid.Empty))
+ if (userId.HasValue && !userId.Value.Equals(default))
{
var user = _userManager.GetUserById(userId.Value);
diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs
index ffc748a6e..be4b9eded 100644
--- a/Jellyfin.Api/Controllers/PersonsController.cs
+++ b/Jellyfin.Api/Controllers/PersonsController.cs
@@ -82,12 +82,9 @@ namespace Jellyfin.Api.Controllers
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
- User? user = null;
-
- if (userId.HasValue && !userId.Equals(Guid.Empty))
- {
- user = _userManager.GetUserById(userId.Value);
- }
+ User? user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var isFavoriteInFilters = filters.Any(f => f == ItemFilter.IsFavorite);
var peopleItems = _libraryManager.GetPeopleItems(new InternalPeopleQuery(
@@ -127,7 +124,7 @@ namespace Jellyfin.Api.Controllers
return NotFound();
}
- if (userId.HasValue && !userId.Equals(Guid.Empty))
+ if (userId.HasValue && !userId.Value.Equals(default))
{
var user = _userManager.GetUserById(userId.Value);
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs
index c18f1b427..ad85f2fb2 100644
--- a/Jellyfin.Api/Controllers/PlaylistsController.cs
+++ b/Jellyfin.Api/Controllers/PlaylistsController.cs
@@ -181,7 +181,9 @@ namespace Jellyfin.Api.Controllers
return NotFound();
}
- var user = !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId) : null;
+ var user = userId.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId);
var items = playlist.GetManageableItems().ToArray();
diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs
index b41df1abb..b227dba2d 100644
--- a/Jellyfin.Api/Controllers/PluginsController.cs
+++ b/Jellyfin.Api/Controllers/PluginsController.cs
@@ -7,7 +7,6 @@ using System.Text.Json;
using System.Threading.Tasks;
using Jellyfin.Api.Attributes;
using Jellyfin.Api.Constants;
-using Jellyfin.Api.Models.PluginDtos;
using Jellyfin.Extensions.Json;
using MediaBrowser.Common.Plugins;
using MediaBrowser.Common.Updates;
@@ -44,61 +43,6 @@ namespace Jellyfin.Api.Controllers
}
/// <summary>
- /// Get plugin security info.
- /// </summary>
- /// <response code="200">Plugin security info returned.</response>
- /// <returns>Plugin security info.</returns>
- [Obsolete("This endpoint should not be used.")]
- [HttpGet("SecurityInfo")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- public static ActionResult<PluginSecurityInfo> GetPluginSecurityInfo()
- {
- return new PluginSecurityInfo
- {
- IsMbSupporter = true,
- SupporterKey = "IAmTotallyLegit"
- };
- }
-
- /// <summary>
- /// Gets registration status for a feature.
- /// </summary>
- /// <param name="name">Feature name.</param>
- /// <response code="200">Registration status returned.</response>
- /// <returns>Mb registration record.</returns>
- [Obsolete("This endpoint should not be used.")]
- [HttpPost("RegistrationRecords/{name}")]
- [ProducesResponseType(StatusCodes.Status200OK)]
- public static ActionResult<MBRegistrationRecord> GetRegistrationStatus([FromRoute, Required] string name)
- {
- return new MBRegistrationRecord
- {
- IsRegistered = true,
- RegChecked = true,
- TrialVersion = false,
- IsValid = true,
- RegError = false
- };
- }
-
- /// <summary>
- /// Gets registration status for a feature.
- /// </summary>
- /// <param name="name">Feature name.</param>
- /// <response code="501">Not implemented.</response>
- /// <returns>Not Implemented.</returns>
- /// <exception cref="NotImplementedException">This endpoint is not implemented.</exception>
- [Obsolete("Paid plugins are not supported")]
- [HttpGet("Registrations/{name}")]
- [ProducesResponseType(StatusCodes.Status501NotImplemented)]
- public static ActionResult GetRegistration([FromRoute, Required] string name)
- {
- // TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins,
- // delete all these registration endpoints. They are only kept for compatibility.
- throw new NotImplementedException();
- }
-
- /// <summary>
/// Gets a list of currently installed plugins.
/// </summary>
/// <response code="200">Installed plugins returned.</response>
@@ -317,20 +261,5 @@ namespace Jellyfin.Api.Controllers
return NotFound();
}
-
- /// <summary>
- /// Updates plugin security info.
- /// </summary>
- /// <param name="pluginSecurityInfo">Plugin security info.</param>
- /// <response code="204">Plugin security info updated.</response>
- /// <returns>An <see cref="NoContentResult"/>.</returns>
- [Obsolete("This endpoint should not be used.")]
- [HttpPost("SecurityInfo")]
- [Authorize(Policy = Policies.RequiresElevation)]
- [ProducesResponseType(StatusCodes.Status204NoContent)]
- public ActionResult UpdatePluginSecurityInfo([FromBody, Required] PluginSecurityInfo pluginSecurityInfo)
- {
- return NoContent();
- }
}
}
diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs
index 26acb4cdc..6ffedccbd 100644
--- a/Jellyfin.Api/Controllers/SearchController.cs
+++ b/Jellyfin.Api/Controllers/SearchController.cs
@@ -121,11 +121,7 @@ namespace Jellyfin.Api.Controllers
IsSports = isSports
});
- return new SearchHintResult
- {
- TotalRecordCount = result.TotalRecordCount,
- SearchHints = result.Items.Select(GetSearchHintResult).ToArray()
- };
+ return new SearchHintResult(result.Items.Select(GetSearchHintResult).ToArray(), result.TotalRecordCount);
}
/// <summary>
@@ -209,7 +205,7 @@ namespace Jellyfin.Api.Controllers
break;
}
- if (!item.ChannelId.Equals(Guid.Empty))
+ if (!item.ChannelId.Equals(default))
{
var channel = _libraryManager.GetItemById(item.ChannelId);
result.ChannelName = channel?.Name;
diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs
index a6bbd40cc..860bccb9b 100644
--- a/Jellyfin.Api/Controllers/SessionController.cs
+++ b/Jellyfin.Api/Controllers/SessionController.cs
@@ -74,7 +74,7 @@ namespace Jellyfin.Api.Controllers
result = result.Where(i => string.Equals(i.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase));
}
- if (controllableByUserId.HasValue && !controllableByUserId.Equals(Guid.Empty))
+ if (controllableByUserId.HasValue && !controllableByUserId.Equals(default))
{
result = result.Where(i => i.SupportsRemoteControl);
@@ -82,12 +82,12 @@ namespace Jellyfin.Api.Controllers
if (!user.HasPermission(PermissionKind.EnableRemoteControlOfOtherUsers))
{
- result = result.Where(i => i.UserId.Equals(Guid.Empty) || i.ContainsUser(controllableByUserId.Value));
+ result = result.Where(i => i.UserId.Equals(default) || i.ContainsUser(controllableByUserId.Value));
}
if (!user.HasPermission(PermissionKind.EnableSharedDeviceControl))
{
- result = result.Where(i => !i.UserId.Equals(Guid.Empty));
+ result = result.Where(i => !i.UserId.Equals(default));
}
if (activeWithinSeconds.HasValue && activeWithinSeconds.Value > 0)
diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs
index 4422ef32c..053c7baaa 100644
--- a/Jellyfin.Api/Controllers/StudiosController.cs
+++ b/Jellyfin.Api/Controllers/StudiosController.cs
@@ -91,7 +91,9 @@ namespace Jellyfin.Api.Controllers
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
- User? user = userId.HasValue && userId != Guid.Empty ? _userManager.GetUserById(userId.Value) : null;
+ User? user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var parentItem = _libraryManager.GetParentItem(parentId, userId);
@@ -141,7 +143,7 @@ namespace Jellyfin.Api.Controllers
var dtoOptions = new DtoOptions().AddClientFields(Request);
var item = _libraryManager.GetStudio(name);
- if (userId.HasValue && !userId.Equals(Guid.Empty))
+ if (userId.HasValue && !userId.Equals(default))
{
var user = _userManager.GetUserById(userId.Value);
diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs
index 73be26bb2..e9c46dcf3 100644
--- a/Jellyfin.Api/Controllers/SuggestionsController.cs
+++ b/Jellyfin.Api/Controllers/SuggestionsController.cs
@@ -63,7 +63,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? limit,
[FromQuery] bool enableTotalRecordCount = false)
{
- var user = !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId) : null;
+ var user = userId.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId);
var dtoOptions = new DtoOptions().AddClientFields(Request);
var result = _libraryManager.GetItemsResult(new InternalItemsQuery(user)
diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs
index 9425fe519..179a53fd5 100644
--- a/Jellyfin.Api/Controllers/TvShowsController.cs
+++ b/Jellyfin.Api/Controllers/TvShowsController.cs
@@ -68,6 +68,7 @@ namespace Jellyfin.Api.Controllers
/// <param name="nextUpDateCutoff">Optional. Starting date of shows to show in Next Up section.</param>
/// <param name="enableTotalRecordCount">Whether to enable the total records count. Defaults to true.</param>
/// <param name="disableFirstEpisode">Whether to disable sending the first episode in a series as next up.</param>
+ /// <param name="enableRewatching">Whether to include watched episode in next up results.</param>
/// <returns>A <see cref="QueryResult{BaseItemDto}"/> with the next up episodes.</returns>
[HttpGet("NextUp")]
[ProducesResponseType(StatusCodes.Status200OK)]
@@ -84,7 +85,8 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableUserData,
[FromQuery] DateTime? nextUpDateCutoff,
[FromQuery] bool enableTotalRecordCount = true,
- [FromQuery] bool disableFirstEpisode = false)
+ [FromQuery] bool disableFirstEpisode = false,
+ [FromQuery] bool enableRewatching = false)
{
var options = new DtoOptions { Fields = fields }
.AddClientFields(Request)
@@ -100,13 +102,14 @@ namespace Jellyfin.Api.Controllers
UserId = userId ?? Guid.Empty,
EnableTotalRecordCount = enableTotalRecordCount,
DisableFirstEpisode = disableFirstEpisode,
- NextUpDateCutoff = nextUpDateCutoff ?? DateTime.MinValue
+ NextUpDateCutoff = nextUpDateCutoff ?? DateTime.MinValue,
+ EnableRewatching = enableRewatching
},
options);
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var returnItems = _dtoService.GetBaseItemDtos(result.Items, options, user);
@@ -142,9 +145,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
[FromQuery] bool? enableUserData)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var minPremiereDate = DateTime.UtcNow.Date.AddDays(-1);
@@ -213,9 +216,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? enableUserData,
[FromQuery] string? sortBy)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
List<BaseItem> episodes;
@@ -329,9 +332,9 @@ namespace Jellyfin.Api.Controllers
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes,
[FromQuery] bool? enableUserData)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
if (_libraryManager.GetItemById(seriesId) is not Series series)
{
diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs
index bc9527a0b..6fcafd426 100644
--- a/Jellyfin.Api/Controllers/UniversalAudioController.cs
+++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs
@@ -16,6 +16,7 @@ using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.MediaInfo;
+using MediaBrowser.Model.Session;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -223,7 +224,7 @@ namespace Jellyfin.Api.Controllers
DeInterlace = false,
RequireNonAnamorphic = false,
EnableMpegtsM2TsMode = false,
- TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(',', mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()),
+ TranscodeReasons = mediaSource.TranscodeReasons == 0 ? null : mediaSource.TranscodeReasons.ToString(),
Context = EncodingContext.Static,
StreamOptions = new Dictionary<string, string>(),
EnableAdaptiveBitrateStreaming = true
@@ -254,7 +255,7 @@ namespace Jellyfin.Api.Controllers
CopyTimestamps = true,
StartTimeTicks = startTimeTicks,
SubtitleMethod = SubtitleDeliveryMethod.Embed,
- TranscodeReasons = mediaSource.TranscodeReasons == null ? null : string.Join(',', mediaSource.TranscodeReasons.Select(i => i.ToString()).ToArray()),
+ TranscodeReasons = mediaSource.TranscodeReasons == 0 ? null : mediaSource.TranscodeReasons.ToString(),
Context = EncodingContext.Static
};
diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs
index 4263d4fe5..6d15d9185 100644
--- a/Jellyfin.Api/Controllers/UserController.cs
+++ b/Jellyfin.Api/Controllers/UserController.cs
@@ -534,7 +534,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult<UserDto> GetCurrentUser()
{
var userId = ClaimHelpers.GetUserId(Request.HttpContext.User);
- if (userId == null)
+ if (userId is null)
{
return BadRequest();
}
diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs
index 008d2f176..e45f9b58c 100644
--- a/Jellyfin.Api/Controllers/UserLibraryController.cs
+++ b/Jellyfin.Api/Controllers/UserLibraryController.cs
@@ -76,7 +76,7 @@ namespace Jellyfin.Api.Controllers
{
var user = _userManager.GetUserById(userId);
- var item = itemId.Equals(Guid.Empty)
+ var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
@@ -116,7 +116,7 @@ namespace Jellyfin.Api.Controllers
{
var user = _userManager.GetUserById(userId);
- var item = itemId.Equals(Guid.Empty)
+ var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
@@ -197,7 +197,7 @@ namespace Jellyfin.Api.Controllers
{
var user = _userManager.GetUserById(userId);
- var item = itemId.Equals(Guid.Empty)
+ var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
@@ -227,7 +227,7 @@ namespace Jellyfin.Api.Controllers
{
var user = _userManager.GetUserById(userId);
- var item = itemId.Equals(Guid.Empty)
+ var item = itemId.Equals(default)
? _libraryManager.GetUserRootFolder()
: _libraryManager.GetItemById(itemId);
@@ -347,7 +347,7 @@ namespace Jellyfin.Api.Controllers
{
var user = _userManager.GetUserById(userId);
- var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
+ var item = itemId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
// Get the user data for this item
var data = _userDataRepository.GetUserData(user, item);
@@ -370,7 +370,7 @@ namespace Jellyfin.Api.Controllers
{
var user = _userManager.GetUserById(userId);
- var item = itemId.Equals(Guid.Empty) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
+ var item = itemId.Equals(default) ? _libraryManager.GetUserRootFolder() : _libraryManager.GetItemById(itemId);
// Get the user data for this item
var data = _userDataRepository.GetUserData(user, item);
diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs
index 04171da8a..5cc8c906f 100644
--- a/Jellyfin.Api/Controllers/UserViewsController.cs
+++ b/Jellyfin.Api/Controllers/UserViewsController.cs
@@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
+using Jellyfin.Api.Constants;
using Jellyfin.Api.Extensions;
using Jellyfin.Api.ModelBinders;
using Jellyfin.Api.Models.UserViewDtos;
@@ -15,6 +16,7 @@ using MediaBrowser.Model.Dto;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Library;
using MediaBrowser.Model.Querying;
+using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
@@ -24,6 +26,7 @@ namespace Jellyfin.Api.Controllers
/// User views controller.
/// </summary>
[Route("")]
+ [Authorize(Policy = Policies.DefaultAuthorization)]
public class UserViewsController : BaseJellyfinApiController
{
private readonly IUserManager _userManager;
@@ -65,7 +68,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>An <see cref="OkResult"/> containing the user views.</returns>
[HttpGet("Users/{userId}/Views")]
[ProducesResponseType(StatusCodes.Status200OK)]
- public async Task<ActionResult<QueryResult<BaseItemDto>>> GetUserViews(
+ public QueryResult<BaseItemDto> GetUserViews(
[FromRoute, Required] Guid userId,
[FromQuery] bool? includeExternalContent,
[FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] presetViews,
@@ -87,12 +90,6 @@ namespace Jellyfin.Api.Controllers
query.PresetViews = presetViews;
}
- var app = (await _authContext.GetAuthorizationInfo(Request).ConfigureAwait(false)).Client ?? string.Empty;
- if (app.IndexOf("emby rt", StringComparison.OrdinalIgnoreCase) != -1)
- {
- query.PresetViews = new[] { CollectionType.Movies, CollectionType.TvShows };
- }
-
var folders = _userViewManager.GetUserViews(query);
var dtoOptions = new DtoOptions().AddClientFields(Request);
diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs
index 89b150598..62c05331e 100644
--- a/Jellyfin.Api/Controllers/VideosController.cs
+++ b/Jellyfin.Api/Controllers/VideosController.cs
@@ -109,14 +109,14 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryResult<BaseItemDto>> GetAdditionalPart([FromRoute, Required] Guid itemId, [FromQuery] Guid? userId)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
-
- var item = itemId.Equals(Guid.Empty)
- ? (!userId.Equals(Guid.Empty)
- ? _libraryManager.GetUserRootFolder()
- : _libraryManager.RootFolder)
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
+
+ var item = itemId.Equals(default)
+ ? (userId is null || userId.Value.Equals(default)
+ ? _libraryManager.RootFolder
+ : _libraryManager.GetUserRootFolder())
: _libraryManager.GetItemById(itemId);
var dtoOptions = new DtoOptions();
@@ -221,7 +221,7 @@ namespace Jellyfin.Api.Controllers
var alternateVersionsOfPrimary = primaryVersion.LinkedAlternateVersions.ToList();
- foreach (var item in items.Where(i => i.Id != primaryVersion.Id))
+ foreach (var item in items.Where(i => !i.Id.Equals(primaryVersion.Id)))
{
item.SetPrimaryVersionId(primaryVersion.Id.ToString("N", CultureInfo.InvariantCulture));
@@ -465,7 +465,7 @@ namespace Jellyfin.Api.Controllers
StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, state.Request.StartTimeTicks, Request, _dlnaManager);
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
- return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, HttpContext).ConfigureAwait(false);
+ return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, HttpContext).ConfigureAwait(false);
}
if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File)
@@ -494,9 +494,7 @@ namespace Jellyfin.Api.Controllers
return FileStreamResponseHelpers.GetStaticFileResult(
state.MediaPath,
- contentType,
- isHeadRequest,
- HttpContext);
+ contentType);
}
// Need to start ffmpeg (because media can't be returned directly)
diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs
index bac77d43b..7c02e2550 100644
--- a/Jellyfin.Api/Controllers/YearsController.cs
+++ b/Jellyfin.Api/Controllers/YearsController.cs
@@ -90,16 +90,11 @@ namespace Jellyfin.Api.Controllers
.AddClientFields(Request)
.AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes);
- User? user = null;
+ User? user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
BaseItem parentItem = _libraryManager.GetParentItem(parentId, userId);
- if (userId.HasValue && !userId.Equals(Guid.Empty))
- {
- user = _userManager.GetUserById(userId.Value);
- }
-
- IList<BaseItem> items;
-
var query = new InternalItemsQuery(user)
{
ExcludeItemTypes = excludeItemTypes,
@@ -110,17 +105,18 @@ namespace Jellyfin.Api.Controllers
bool Filter(BaseItem i) => FilterItem(i, excludeItemTypes, includeItemTypes, mediaTypes);
+ IList<BaseItem> items;
if (parentItem.IsFolder)
{
var folder = (Folder)parentItem;
- if (!userId.Equals(Guid.Empty))
+ if (userId.Equals(default))
{
- items = recursive ? folder.GetRecursiveChildren(user, query).ToList() : folder.GetChildren(user, true).Where(Filter).ToList();
+ items = recursive ? folder.GetRecursiveChildren(Filter) : folder.Children.Where(Filter).ToList();
}
else
{
- items = recursive ? folder.GetRecursiveChildren(Filter) : folder.Children.Where(Filter).ToList();
+ items = recursive ? folder.GetRecursiveChildren(user, query).ToList() : folder.GetChildren(user, true).Where(Filter).ToList();
}
}
else
@@ -185,7 +181,7 @@ namespace Jellyfin.Api.Controllers
var dtoOptions = new DtoOptions()
.AddClientFields(Request);
- if (userId.HasValue && !userId.Equals(Guid.Empty))
+ if (userId.HasValue && !userId.Value.Equals(default))
{
var user = _userManager.GetUserById(userId.Value);
return _dtoService.GetBaseItemDto(item, dtoOptions, user);
diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs
index bec961dad..27497cd59 100644
--- a/Jellyfin.Api/Helpers/AudioHelper.cs
+++ b/Jellyfin.Api/Helpers/AudioHelper.cs
@@ -138,7 +138,7 @@ namespace Jellyfin.Api.Helpers
StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager);
var httpClient = _httpClientFactory.CreateClient(NamedClient.Default);
- return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false);
+ return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false);
}
if (streamingRequest.Static && state.InputProtocol != MediaProtocol.File)
@@ -167,9 +167,7 @@ namespace Jellyfin.Api.Helpers
return FileStreamResponseHelpers.GetStaticFileResult(
state.MediaPath,
- contentType,
- isHeadRequest,
- _httpContextAccessor.HttpContext);
+ contentType);
}
// Need to start ffmpeg (because media can't be returned directly)
diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs
index 6385b62c9..5bdd3fe2e 100644
--- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs
+++ b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs
@@ -22,14 +22,12 @@ namespace Jellyfin.Api.Helpers
/// Returns a static file from a remote source.
/// </summary>
/// <param name="state">The current <see cref="StreamState"/>.</param>
- /// <param name="isHeadRequest">Whether the current request is a HTTP HEAD request so only the headers get returned.</param>
/// <param name="httpClient">The <see cref="HttpClient"/> making the remote request.</param>
/// <param name="httpContext">The current http context.</param>
/// <param name="cancellationToken">A cancellation token that can be used to cancel the operation.</param>
/// <returns>A <see cref="Task{ActionResult}"/> containing the API response.</returns>
public static async Task<ActionResult> GetStaticRemoteStreamResult(
StreamState state,
- bool isHeadRequest,
HttpClient httpClient,
HttpContext httpContext,
CancellationToken cancellationToken = default)
@@ -45,12 +43,6 @@ namespace Jellyfin.Api.Helpers
httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none";
- if (isHeadRequest)
- {
- httpContext.Response.Headers[HeaderNames.ContentType] = contentType;
- return new OkResult();
- }
-
return new FileStreamResult(await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false), contentType);
}
@@ -59,23 +51,11 @@ namespace Jellyfin.Api.Helpers
/// </summary>
/// <param name="path">The path to the file.</param>
/// <param name="contentType">The content type of the file.</param>
- /// <param name="isHeadRequest">Whether the current request is a HTTP HEAD request so only the headers get returned.</param>
- /// <param name="httpContext">The current http context.</param>
/// <returns>An <see cref="ActionResult"/> the file.</returns>
public static ActionResult GetStaticFileResult(
string path,
- string contentType,
- bool isHeadRequest,
- HttpContext httpContext)
+ string contentType)
{
- httpContext.Response.ContentType = contentType;
-
- // if the request is a head request, return an OkResult (200) with the same headers as it would with a GET request
- if (isHeadRequest)
- {
- return new OkResult();
- }
-
return new PhysicalFileResult(path, contentType) { EnableRangeProcessing = true };
}
diff --git a/Jellyfin.Api/Helpers/MediaInfoHelper.cs b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
index 3b8dc7e31..31b979836 100644
--- a/Jellyfin.Api/Helpers/MediaInfoHelper.cs
+++ b/Jellyfin.Api/Helpers/MediaInfoHelper.cs
@@ -89,9 +89,9 @@ namespace Jellyfin.Api.Helpers
string? mediaSourceId = null,
string? liveStreamId = null)
{
- var user = userId.HasValue && !userId.Equals(Guid.Empty)
- ? _userManager.GetUserById(userId.Value)
- : null;
+ var user = userId is null || userId.Value.Equals(default)
+ ? null
+ : _userManager.GetUserById(userId.Value);
var item = _libraryManager.GetItemById(id);
var result = new PlaybackInfoResponse();
@@ -191,7 +191,9 @@ namespace Jellyfin.Api.Helpers
DeviceId = auth.DeviceId,
ItemId = item.Id,
Profile = profile,
- MaxAudioChannels = maxAudioChannels
+ MaxAudioChannels = maxAudioChannels,
+ AllowAudioStreamCopy = allowAudioStreamCopy,
+ AllowVideoStreamCopy = allowVideoStreamCopy
};
if (string.Equals(mediaSourceId, mediaSource.Id, StringComparison.OrdinalIgnoreCase))
@@ -208,7 +210,7 @@ namespace Jellyfin.Api.Helpers
mediaSource.SupportsDirectPlay = false;
}
- if (!enableDirectStream)
+ if (!enableDirectStream || !allowVideoStreamCopy)
{
mediaSource.SupportsDirectStream = false;
}
@@ -235,168 +237,79 @@ namespace Jellyfin.Api.Helpers
user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding));
}
- // Beginning of Playback Determination: Attempt DirectPlay first
- if (mediaSource.SupportsDirectPlay)
- {
- if (mediaSource.IsRemote && user.HasPermission(PermissionKind.ForceRemoteSourceTranscoding))
- {
- mediaSource.SupportsDirectPlay = false;
- }
- else
- {
- var supportsDirectStream = mediaSource.SupportsDirectStream;
-
- // Dummy this up to fool StreamBuilder
- mediaSource.SupportsDirectStream = true;
- options.MaxBitrate = maxBitrate;
+ options.MaxBitrate = GetMaxBitrate(maxBitrate, user, ipAddress);
- if (item is Audio)
- {
- if (!user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding))
- {
- options.ForceDirectPlay = true;
- }
- }
- else if (item is Video)
- {
- if (!user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding)
- && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)
- && !user.HasPermission(PermissionKind.EnablePlaybackRemuxing))
- {
- options.ForceDirectPlay = true;
- }
- }
+ if (!options.ForceDirectStream)
+ {
+ // direct-stream http streaming is currently broken
+ options.EnableDirectStream = false;
+ }
- // The MediaSource supports direct stream, now test to see if the client supports it
- var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)
- ? streamBuilder.BuildAudioItem(options)
- : streamBuilder.BuildVideoItem(options);
+ // Beginning of Playback Determination
+ var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)
+ ? streamBuilder.BuildAudioItem(options)
+ : streamBuilder.BuildVideoItem(options);
- if (streamInfo == null || !streamInfo.IsDirectStream)
- {
- mediaSource.SupportsDirectPlay = false;
- }
+ if (streamInfo != null)
+ {
+ streamInfo.PlaySessionId = playSessionId;
+ streamInfo.StartPositionTicks = startTimeTicks;
- // Set this back to what it was
- mediaSource.SupportsDirectStream = supportsDirectStream;
+ mediaSource.SupportsDirectPlay = streamInfo.PlayMethod == PlayMethod.DirectPlay;
+ // Players do not handle this being set according to PlayMethod
+ mediaSource.SupportsDirectStream = options.EnableDirectStream ? streamInfo.PlayMethod == PlayMethod.DirectPlay || streamInfo.PlayMethod == PlayMethod.DirectStream : streamInfo.PlayMethod == PlayMethod.DirectPlay;
+ mediaSource.SupportsTranscoding = streamInfo.PlayMethod == PlayMethod.DirectStream || mediaSource.TranscodingContainer != null;
- if (streamInfo != null)
+ if (item is Audio)
+ {
+ if (!user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding))
{
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
- mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex;
+ mediaSource.SupportsTranscoding = false;
}
}
- }
-
- if (mediaSource.SupportsDirectStream)
- {
- if (mediaSource.IsRemote && user.HasPermission(PermissionKind.ForceRemoteSourceTranscoding))
+ else if (item is Video)
{
- mediaSource.SupportsDirectStream = false;
- }
- else
- {
- options.MaxBitrate = GetMaxBitrate(maxBitrate, user, ipAddress);
-
- if (item is Audio)
+ if (!user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding)
+ && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)
+ && !user.HasPermission(PermissionKind.EnablePlaybackRemuxing))
{
- if (!user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding))
- {
- options.ForceDirectStream = true;
- }
- }
- else if (item is Video)
- {
- if (!user.HasPermission(PermissionKind.EnableAudioPlaybackTranscoding)
- && !user.HasPermission(PermissionKind.EnableVideoPlaybackTranscoding)
- && user.HasPermission(PermissionKind.EnablePlaybackRemuxing))
- {
- options.ForceDirectStream = true;
- }
- }
-
- // The MediaSource supports direct stream, now test to see if the client supports it
- var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)
- ? streamBuilder.BuildAudioItem(options)
- : streamBuilder.BuildVideoItem(options);
-
- if (streamInfo == null || !streamInfo.IsDirectStream)
- {
- mediaSource.SupportsDirectStream = false;
- }
-
- if (streamInfo != null)
- {
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
- mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex;
+ mediaSource.SupportsTranscoding = false;
}
}
- }
-
- if (mediaSource.SupportsTranscoding)
- {
- options.MaxBitrate = GetMaxBitrate(maxBitrate, user, ipAddress);
-
- // The MediaSource supports direct stream, now test to see if the client supports it
- var streamInfo = string.Equals(item.MediaType, MediaType.Audio, StringComparison.OrdinalIgnoreCase)
- ? streamBuilder.BuildAudioItem(options)
- : streamBuilder.BuildVideoItem(options);
if (mediaSource.IsRemote && user.HasPermission(PermissionKind.ForceRemoteSourceTranscoding))
{
- if (streamInfo != null)
- {
- streamInfo.PlaySessionId = playSessionId;
- streamInfo.StartPositionTicks = startTimeTicks;
- mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
- mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
- mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
- mediaSource.TranscodingContainer = streamInfo.Container;
- mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
-
- // Do this after the above so that StartPositionTicks is set
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
- mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex;
- }
+ mediaSource.SupportsDirectPlay = false;
+ mediaSource.SupportsDirectStream = false;
+
+ mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
+ mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
+ mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
+ mediaSource.TranscodingContainer = streamInfo.Container;
+ mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
}
else
{
- if (streamInfo != null)
+ if (mediaSource.SupportsTranscoding || mediaSource.SupportsDirectStream)
{
- streamInfo.PlaySessionId = playSessionId;
+ streamInfo.PlayMethod = PlayMethod.Transcode;
+ mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
- if (streamInfo.PlayMethod == PlayMethod.Transcode)
+ if (!allowVideoStreamCopy)
{
- streamInfo.StartPositionTicks = startTimeTicks;
- mediaSource.TranscodingUrl = streamInfo.ToUrl("-", auth.Token).TrimStart('-');
-
- if (!allowVideoStreamCopy)
- {
- mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
- }
-
- if (!allowAudioStreamCopy)
- {
- mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
- }
-
- mediaSource.TranscodingContainer = streamInfo.Container;
- mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
+ mediaSource.TranscodingUrl += "&allowVideoStreamCopy=false";
}
if (!allowAudioStreamCopy)
{
mediaSource.TranscodingUrl += "&allowAudioStreamCopy=false";
}
-
- mediaSource.TranscodingContainer = streamInfo.Container;
- mediaSource.TranscodingSubProtocol = streamInfo.SubProtocol;
-
- // Do this after the above so that StartPositionTicks is set
- SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
- mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex;
}
}
+
+ // Do this after the above so that StartPositionTicks is set
+ SetDeviceSpecificSubtitleInfo(streamInfo, mediaSource, auth.Token);
+ mediaSource.DefaultAudioStreamIndex = streamInfo.AudioStreamIndex;
}
foreach (var attachment in mediaSource.MediaAttachments)
diff --git a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs
index 3fa07720a..6f5b64ea8 100644
--- a/Jellyfin.Api/Helpers/ProgressiveFileStream.cs
+++ b/Jellyfin.Api/Helpers/ProgressiveFileStream.cs
@@ -83,10 +83,10 @@ namespace Jellyfin.Api.Helpers
int totalBytesRead = 0;
var stopwatch = Stopwatch.StartNew();
- while (KeepReading(stopwatch.ElapsedMilliseconds))
+ while (true)
{
totalBytesRead += _stream.Read(buffer);
- if (totalBytesRead > 0)
+ if (StopReading(totalBytesRead, stopwatch.ElapsedMilliseconds))
{
break;
}
@@ -109,10 +109,10 @@ namespace Jellyfin.Api.Helpers
int totalBytesRead = 0;
var stopwatch = Stopwatch.StartNew();
- while (KeepReading(stopwatch.ElapsedMilliseconds))
+ while (true)
{
totalBytesRead += await _stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
- if (totalBytesRead > 0)
+ if (StopReading(totalBytesRead, stopwatch.ElapsedMilliseconds))
{
break;
}
@@ -172,10 +172,12 @@ namespace Jellyfin.Api.Helpers
}
}
- private bool KeepReading(long elapsed)
+ private bool StopReading(int bytesRead, long elapsed)
{
- // If the job is null it's a live stream and will require user action to close, but don't keep it open indefinitely
- return !_job?.HasExited ?? elapsed < _timeoutMs;
+ // It should stop reading when anything has been successfully read or if the job has exited
+ // If the job is null, however, it's a live stream and will require user action to close,
+ // but don't keep it open indefinitely if it isn't reading anything
+ return bytesRead > 0 || (_job?.HasExited ?? elapsed >= _timeoutMs);
}
}
}
diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs
index ed071bcd7..34dab75b8 100644
--- a/Jellyfin.Api/Helpers/StreamingHelpers.cs
+++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs
@@ -102,7 +102,7 @@ namespace Jellyfin.Api.Helpers
};
var auth = await authorizationContext.GetAuthorizationInfo(httpRequest).ConfigureAwait(false);
- if (!auth.UserId.Equals(Guid.Empty))
+ if (!auth.UserId.Equals(default))
{
state.User = userManager.GetUserById(auth.UserId);
}
@@ -151,7 +151,7 @@ namespace Jellyfin.Api.Helpers
? mediaSources[0]
: mediaSources.Find(i => string.Equals(i.Id, streamingRequest.MediaSourceId, StringComparison.Ordinal));
- if (mediaSource == null && Guid.Parse(streamingRequest.MediaSourceId) == streamingRequest.Id)
+ if (mediaSource == null && Guid.Parse(streamingRequest.MediaSourceId).Equals(streamingRequest.Id))
{
mediaSource = mediaSources[0];
}
diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
index 3526d56c6..da3c1530c 100644
--- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
+++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs
@@ -13,11 +13,13 @@ using Jellyfin.Api.Models.StreamingDtos;
using Jellyfin.Data.Enums;
using MediaBrowser.Common;
using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.MediaInfo;
@@ -42,6 +44,8 @@ namespace Jellyfin.Api.Helpers
/// </summary>
private static readonly Dictionary<string, SemaphoreSlim> _transcodingLocks = new Dictionary<string, SemaphoreSlim>();
+ private readonly IAttachmentExtractor _attachmentExtractor;
+ private readonly IApplicationPaths _appPaths;
private readonly IAuthorizationContext _authorizationContext;
private readonly EncodingHelper _encodingHelper;
private readonly IFileSystem _fileSystem;
@@ -55,6 +59,8 @@ namespace Jellyfin.Api.Helpers
/// <summary>
/// Initializes a new instance of the <see cref="TranscodingJobHelper"/> class.
/// </summary>
+ /// <param name="attachmentExtractor">Instance of the <see cref="IAttachmentExtractor"/> interface.</param>
+ /// <param name="appPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
/// <param name="logger">Instance of the <see cref="ILogger{TranscodingJobHelpers}"/> interface.</param>
/// <param name="mediaSourceManager">Instance of the <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="fileSystem">Instance of the <see cref="IFileSystem"/> interface.</param>
@@ -65,6 +71,8 @@ namespace Jellyfin.Api.Helpers
/// <param name="encodingHelper">Instance of <see cref="EncodingHelper"/>.</param>
/// <param name="loggerFactory">Instance of the <see cref="ILoggerFactory"/> interface.</param>
public TranscodingJobHelper(
+ IAttachmentExtractor attachmentExtractor,
+ IApplicationPaths appPaths,
ILogger<TranscodingJobHelper> logger,
IMediaSourceManager mediaSourceManager,
IFileSystem fileSystem,
@@ -75,6 +83,8 @@ namespace Jellyfin.Api.Helpers
EncodingHelper encodingHelper,
ILoggerFactory loggerFactory)
{
+ _attachmentExtractor = attachmentExtractor;
+ _appPaths = appPaths;
_logger = logger;
_mediaSourceManager = mediaSourceManager;
_fileSystem = fileSystem;
@@ -449,9 +459,12 @@ namespace Jellyfin.Api.Helpers
var audioCodec = state.ActualOutputAudioCodec;
var videoCodec = state.ActualOutputVideoCodec;
var hardwareAccelerationTypeString = _serverConfigurationManager.GetEncodingOptions().HardwareAccelerationType;
- HardwareEncodingType? hardwareAccelerationType = string.IsNullOrEmpty(hardwareAccelerationTypeString)
- ? null
- : (HardwareEncodingType)Enum.Parse(typeof(HardwareEncodingType), hardwareAccelerationTypeString, true);
+ HardwareEncodingType? hardwareAccelerationType = null;
+ if (!string.IsNullOrEmpty(hardwareAccelerationTypeString)
+ && Enum.TryParse<HardwareEncodingType>(hardwareAccelerationTypeString, out var parsedHardwareAccelerationType))
+ {
+ hardwareAccelerationType = parsedHardwareAccelerationType;
+ }
_sessionManager.ReportTranscodingInfo(deviceId, new TranscodingInfo
{
@@ -467,7 +480,7 @@ namespace Jellyfin.Api.Helpers
IsAudioDirect = EncodingHelper.IsCopyCodec(state.OutputAudioCodec),
IsVideoDirect = EncodingHelper.IsCopyCodec(state.OutputVideoCodec),
HardwareAccelerationType = hardwareAccelerationType,
- TranscodeReasons = state.TranscodeReasons
+ TranscodeReason = state.TranscodeReason
});
}
}
@@ -513,6 +526,22 @@ namespace Jellyfin.Api.Helpers
throw new ArgumentException("FFmpeg path not set.");
}
+ // If subtitles get burned in fonts may need to be extracted from the media file
+ if (state.SubtitleStream != null && state.SubtitleDeliveryMethod == SubtitleDeliveryMethod.Encode)
+ {
+ var attachmentPath = Path.Combine(_appPaths.CachePath, "attachments", state.MediaSource.Id);
+ await _attachmentExtractor.ExtractAllAttachments(state.MediaPath, state.MediaSource, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false);
+
+ if (state.SubtitleStream.IsExternal && string.Equals(Path.GetExtension(state.SubtitleStream.Path), ".mks", StringComparison.OrdinalIgnoreCase))
+ {
+ string subtitlePath = state.SubtitleStream.Path;
+ string subtitlePathArgument = string.Format(CultureInfo.InvariantCulture, "file:\"{0}\"", subtitlePath.Replace("\"", "\\\"", StringComparison.Ordinal));
+ string subtitleId = subtitlePath.GetMD5().ToString("N", CultureInfo.InvariantCulture);
+
+ await _attachmentExtractor.ExtractAllAttachmentsExternal(subtitlePathArgument, subtitleId, attachmentPath, cancellationTokenSource.Token).ConfigureAwait(false);
+ }
+ }
+
var process = new Process
{
StartInfo = new ProcessStartInfo
@@ -753,6 +782,8 @@ namespace Jellyfin.Api.Helpers
job.HasExited = true;
job.ExitCode = process.ExitCode;
+ ReportTranscodingProgress(job, state, null, null, null, null, null);
+
_logger.LogDebug("Disposing stream resources");
state.Dispose();
diff --git a/Jellyfin.Api/Jellyfin.Api.csproj b/Jellyfin.Api/Jellyfin.Api.csproj
index 3a7d39365..2b0436e34 100644
--- a/Jellyfin.Api/Jellyfin.Api.csproj
+++ b/Jellyfin.Api/Jellyfin.Api.csproj
@@ -17,10 +17,10 @@
</PropertyGroup>
<ItemGroup>
- <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.1" />
+ <PackageReference Include="Microsoft.AspNetCore.Authorization" Version="6.0.3" />
<PackageReference Include="Microsoft.Extensions.Http" Version="6.0.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" />
- <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.2.3" />
+ <PackageReference Include="Swashbuckle.AspNetCore.ReDoc" Version="6.3.0" />
</ItemGroup>
<ItemGroup>
@@ -36,7 +36,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="SerilogAnalyzer" Version="0.15.0" PrivateAssets="All" />
- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.376" PrivateAssets="All" />
+ <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.406" PrivateAssets="All" />
<PackageReference Include="SmartAnalyzers.MultithreadingAnalyzer" Version="1.1.31" PrivateAssets="All" />
</ItemGroup>
diff --git a/Jellyfin.Api/Models/PluginDtos/MBRegistrationRecord.cs b/Jellyfin.Api/Models/PluginDtos/MBRegistrationRecord.cs
deleted file mode 100644
index 7f1255f4b..000000000
--- a/Jellyfin.Api/Models/PluginDtos/MBRegistrationRecord.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-
-namespace Jellyfin.Api.Models.PluginDtos
-{
- /// <summary>
- /// MB Registration Record.
- /// </summary>
- public class MBRegistrationRecord
- {
- /// <summary>
- /// Gets or sets expiration date.
- /// </summary>
- public DateTime ExpirationDate { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether is registered.
- /// </summary>
- public bool IsRegistered { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether reg checked.
- /// </summary>
- public bool RegChecked { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether reg error.
- /// </summary>
- public bool RegError { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether trial version.
- /// </summary>
- public bool TrialVersion { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether is valid.
- /// </summary>
- public bool IsValid { get; set; }
- }
-}
diff --git a/Jellyfin.Api/Models/PluginDtos/PluginSecurityInfo.cs b/Jellyfin.Api/Models/PluginDtos/PluginSecurityInfo.cs
deleted file mode 100644
index a90398425..000000000
--- a/Jellyfin.Api/Models/PluginDtos/PluginSecurityInfo.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-namespace Jellyfin.Api.Models.PluginDtos
-{
- /// <summary>
- /// Plugin security info.
- /// </summary>
- public class PluginSecurityInfo
- {
- /// <summary>
- /// Gets or sets the supporter key.
- /// </summary>
- public string? SupporterKey { get; set; }
-
- /// <summary>
- /// Gets or sets a value indicating whether is mb supporter.
- /// </summary>
- public bool IsMbSupporter { get; set; }
- }
-}