From 4aa0bd064feca0e2e22189051b1bba886ddad215 Mon Sep 17 00:00:00 2001 From: David Ullmer Date: Mon, 27 Jul 2020 09:47:19 +0200 Subject: Move HlsSegmentService to Jellyfin.Api --- Jellyfin.Api/Controllers/HlsSegmentController.cs | 153 +++++++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 Jellyfin.Api/Controllers/HlsSegmentController.cs (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs new file mode 100644 index 000000000..efdb6a369 --- /dev/null +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -0,0 +1,153 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Jellyfin.Api.Constants; +using Jellyfin.Api.Helpers; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.MediaEncoding; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace Jellyfin.Api.Controllers +{ + /// + /// The hls segment controller. + /// + public class HlsSegmentController : BaseJellyfinApiController + { + private readonly IFileSystem _fileSystem; + private readonly IServerConfigurationManager _serverConfigurationManager; + private readonly TranscodingJobHelper _transcodingJobHelper; + + /// + /// Initializes a new instance of the class. + /// + /// Instance of the interface. + /// Instance of the interface. + /// Initialized instance of the . + public HlsSegmentController( + IFileSystem fileSystem, + IServerConfigurationManager serverConfigurationManager, + TranscodingJobHelper transcodingJobHelper) + { + _fileSystem = fileSystem; + _serverConfigurationManager = serverConfigurationManager; + _transcodingJobHelper = transcodingJobHelper; + } + + /// + /// Gets the specified audio segment for an audio item. + /// + /// The item id. + /// The segment id. + /// Hls audio segment returned. + /// A containing the audio stream. + // Can't require authentication just yet due to seeing some requests come from Chrome without full query string + // [Authenticated] + [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.mp3")] + [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.aac")] + [ProducesResponseType(StatusCodes.Status200OK)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] + public ActionResult GetHlsAudioSegmentLegacy([FromRoute] string itemId, [FromRoute] string segmentId) + { + // TODO: Deprecate with new iOS app + var file = segmentId + Path.GetExtension(Request.Path); + file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); + + return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, this); + } + + /// + /// Gets a hls video playlist. + /// + /// The video id. + /// The playlist id. + /// Hls video playlist returned. + /// A containing the playlist. + [HttpGet("/Videos/{itemId}/hls/{playlistId}/stream.m3u8")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status200OK)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] + public ActionResult GetHlsPlaylistLegacy([FromRoute] string itemId, [FromRoute] string playlistId) + { + var file = playlistId + Path.GetExtension(Request.Path); + file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); + + return GetFileResult(file, file); + } + + /// + /// Stops an active encoding. + /// + /// The device id of the client requesting. Used to stop encoding processes when needed. + /// The play session id. + /// Encoding stopped successfully. + /// A indicating success. + [HttpDelete("/Videos/ActiveEncodings")] + [Authorize(Policy = Policies.DefaultAuthorization)] + [ProducesResponseType(StatusCodes.Status204NoContent)] + public ActionResult StopEncodingProcess([FromQuery] string deviceId, [FromQuery] string playSessionId) + { + _transcodingJobHelper.KillTranscodingJobs(deviceId, playSessionId, path => true); + return NoContent(); + } + + /// + /// Gets a hls video segment. + /// + /// The item id. + /// The playlist id. + /// The segment id. + /// The segment container. + /// Hls video segment returned. + /// A containing the video segment. + // Can't require authentication just yet due to seeing some requests come from Chrome without full query string + // [Authenticated] + [HttpGet("/Videos/{itemId}/hls/{playlistId}/{segmentId}.{segmentContainer}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] + public ActionResult GetHlsVideoSegmentLegacy( + [FromRoute] string itemId, + [FromRoute] string playlistId, + [FromRoute] string segmentId, + [FromRoute] string segmentContainer) + { + var file = segmentId + Path.GetExtension(Request.Path); + var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath(); + + file = Path.Combine(transcodeFolderPath, file); + + var normalizedPlaylistId = playlistId; + + var playlistPath = _fileSystem.GetFilePaths(transcodeFolderPath) + .FirstOrDefault(i => + string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) + && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1); + + return GetFileResult(file, playlistPath); + } + + private ActionResult GetFileResult(string path, string playlistPath) + { + var transcodingJob = _transcodingJobHelper.OnTranscodeBeginRequest(playlistPath, TranscodingJobType.Hls); + + Response.OnCompleted(() => + { + if (transcodingJob != null) + { + _transcodingJobHelper.OnTranscodeEndRequest(transcodingJob); + } + + return Task.CompletedTask; + }); + + return FileStreamResponseHelpers.GetStaticFileResult(path, MimeTypes.GetMimeType(path)!, false, this); + } + } +} -- cgit v1.2.3 From 9e00aa3014c0044c0918a775c3394763666b30af Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 3 Aug 2020 14:38:51 -0600 Subject: fix openapi validation errors --- Jellyfin.Api/Controllers/AudioController.cs | 8 ++-- Jellyfin.Api/Controllers/BrandingController.cs | 2 +- Jellyfin.Api/Controllers/DlnaServerController.cs | 12 +++--- Jellyfin.Api/Controllers/DynamicHlsController.cs | 4 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 4 +- Jellyfin.Api/Controllers/ImageController.cs | 28 +++++++------- Jellyfin.Api/Controllers/ItemsController.cs | 2 +- Jellyfin.Api/Controllers/LibraryController.cs | 14 +++---- Jellyfin.Api/Controllers/LiveTvController.cs | 6 +-- Jellyfin.Api/Controllers/SessionController.cs | 2 +- Jellyfin.Api/Controllers/StartupController.cs | 4 +- Jellyfin.Api/Controllers/SubtitleController.cs | 2 +- Jellyfin.Api/Controllers/SyncPlayController.cs | 18 ++++----- Jellyfin.Api/Controllers/SystemController.cs | 4 +- .../Controllers/UniversalAudioController.cs | 6 +-- Jellyfin.Api/Controllers/VideosController.cs | 6 +-- .../Extensions/ApiServiceCollectionExtensions.cs | 11 +++++- tests/Jellyfin.Api.Tests/GetPathValueTests.cs | 45 ---------------------- 18 files changed, 70 insertions(+), 108 deletions(-) delete mode 100644 tests/Jellyfin.Api.Tests/GetPathValueTests.cs (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index ebae1caa0..4de87616c 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -144,10 +144,10 @@ namespace Jellyfin.Api.Controllers /// Optional. The streaming options. /// Audio stream returned. /// A containing the audio file. - [HttpGet("{itemId}/{stream=stream}.{container?}")] - [HttpGet("{itemId}/stream")] - [HttpHead("{itemId}/{stream=stream}.{container?}")] - [HttpHead("{itemId}/stream")] + [HttpGet("{itemId}/{stream=stream}.{container?}", Name = "GetAudioStreamByContainer")] + [HttpGet("{itemId}/stream", Name = "GetAudioStream")] + [HttpHead("{itemId}/{stream=stream}.{container?}", Name = "HeadAudioStreamByContainer")] + [HttpHead("{itemId}/stream", Name = "HeadAudioStream")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetAudioStream( [FromRoute] Guid itemId, diff --git a/Jellyfin.Api/Controllers/BrandingController.cs b/Jellyfin.Api/Controllers/BrandingController.cs index 67790c0e4..1d4836f27 100644 --- a/Jellyfin.Api/Controllers/BrandingController.cs +++ b/Jellyfin.Api/Controllers/BrandingController.cs @@ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers /// or a if the css is not configured. /// [HttpGet("Css")] - [HttpGet("Css.css")] + [HttpGet("Css.css", Name = "GetBrandingCss_2")] [Produces("text/css")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status204NoContent)] diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs index 2f5561adb..ef507f2ed 100644 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ b/Jellyfin.Api/Controllers/DlnaServerController.cs @@ -42,8 +42,8 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Description xml returned. /// An containing the description xml. - [HttpGet("{serverId}/description.xml")] [HttpGet("{serverId}/description")] + [HttpGet("{serverId}/description.xml", Name = "GetDescriptionXml_2")] [Produces(XMLContentType)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetDescriptionXml([FromRoute] string serverId) @@ -60,8 +60,8 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Dlna content directory returned. /// An containing the dlna content directory xml. - [HttpGet("{serverId}/ContentDirectory/ContentDirectory.xml")] [HttpGet("{serverId}/ContentDirectory/ContentDirectory")] + [HttpGet("{serverId}/ContentDirectory/ContentDirectory.xml", Name = "GetContentDirectory_2")] [Produces(XMLContentType)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] @@ -75,8 +75,8 @@ namespace Jellyfin.Api.Controllers /// /// Server UUID. /// Dlna media receiver registrar xml. - [HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar.xml")] [HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar")] + [HttpGet("{serverId}/MediaReceiverRegistrar/MediaReceiverRegistrar.xml", Name = "GetMediaReceiverRegistrar_2")] [Produces(XMLContentType)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] @@ -90,8 +90,8 @@ namespace Jellyfin.Api.Controllers /// /// Server UUID. /// Dlna media receiver registrar xml. - [HttpGet("{serverId}/ConnectionManager/ConnectionManager.xml")] [HttpGet("{serverId}/ConnectionManager/ConnectionManager")] + [HttpGet("{serverId}/ConnectionManager/ConnectionManager.xml", Name = "GetConnectionManager_2")] [Produces(XMLContentType)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] @@ -181,7 +181,7 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// The icon filename. /// Icon stream. - [HttpGet("{serverId}/icons/{filename}")] + [HttpGet("{serverId}/icons/{fileName}")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] public ActionResult GetIconId([FromRoute] string serverId, [FromRoute] string fileName) { @@ -193,7 +193,7 @@ namespace Jellyfin.Api.Controllers /// /// The icon filename. /// Icon stream. - [HttpGet("icons/{filename}")] + [HttpGet("icons/{fileName}")] public ActionResult GetIcon([FromRoute] string fileName) { return GetIconInternal(fileName); diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index b7e1837c9..c4f79ce95 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -165,7 +165,7 @@ namespace Jellyfin.Api.Controllers /// Video stream returned. /// A containing the playlist file. [HttpGet("/Videos/{itemId}/master.m3u8")] - [HttpHead("/Videos/{itemId}/master.m3u8")] + [HttpHead("/Videos/{itemId}/master.m3u8", Name = "HeadMasterHlsVideoPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsVideoPlaylist( [FromRoute] Guid itemId, @@ -335,7 +335,7 @@ namespace Jellyfin.Api.Controllers /// Audio stream returned. /// A containing the playlist file. [HttpGet("/Audio/{itemId}/master.m3u8")] - [HttpHead("/Audio/{itemId}/master.m3u8")] + [HttpHead("/Audio/{itemId}/master.m3u8", Name = "HeadMasterHlsAudioPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsAudioPlaylist( [FromRoute] Guid itemId, diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index efdb6a369..7bf9326a7 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -50,8 +50,8 @@ namespace Jellyfin.Api.Controllers /// A containing the audio stream. // Can't require authentication just yet due to seeing some requests come from Chrome without full query string // [Authenticated] - [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.mp3")] - [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.aac")] + [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.mp3", Name = "GetHlsAudioSegmentLegacyMp3")] + [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsAudioSegmentLegacy([FromRoute] string itemId, [FromRoute] string segmentId) diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 18220c5f3..3a445b1b3 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -82,7 +82,7 @@ namespace Jellyfin.Api.Controllers /// User does not have permission to delete the image. /// A . [HttpPost("/Users/{userId}/Images/{imageType}")] - [HttpPost("/Users/{userId}/Images/{imageType}/{index?}")] + [HttpPost("/Users/{userId}/Images/{imageType}/{index?}", Name = "PostUserImage_2")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")] @@ -128,7 +128,7 @@ namespace Jellyfin.Api.Controllers /// User does not have permission to delete the image. /// A . [HttpDelete("/Users/{userId}/Images/{itemType}")] - [HttpDelete("/Users/{userId}/Images/{itemType}/{index?}")] + [HttpDelete("/Users/{userId}/Images/{itemType}/{index?}", Name = "DeleteUserImage_2")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] [ProducesResponseType(StatusCodes.Status204NoContent)] @@ -167,7 +167,7 @@ namespace Jellyfin.Api.Controllers /// Item not found. /// A on success, or a if item not found. [HttpDelete("/Items/{itemId}/Images/{imageType}")] - [HttpDelete("/Items/{itemId}/Images/{imageType}/{imageIndex?}")] + [HttpDelete("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "DeleteItemImage_2")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -196,7 +196,7 @@ namespace Jellyfin.Api.Controllers /// Item not found. /// A on success, or a if item not found. [HttpPost("/Items/{itemId}/Images/{imageType}")] - [HttpPost("/Items/{itemId}/Images/{imageType}/{imageIndex?}")] + [HttpPost("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "SetItemImage_2")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -342,9 +342,9 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/Items/{itemId}/Images/{imageType}")] - [HttpHead("/Items/{itemId}/Images/{imageType}")] - [HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex?}")] + [HttpHead("/Items/{itemId}/Images/{imageType}", Name = "HeadItemImage")] + [HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "GetItemImage_2")] + [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "HeadItemImage_2")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage( @@ -422,7 +422,7 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}")] - [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}")] + [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}", Name = "HeadItemImage2")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage2( @@ -500,7 +500,7 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/Artists/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Artists/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("/Artists/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadArtistImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetArtistImage( @@ -578,7 +578,7 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/Genres/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Genres/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("/Genres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadGenreImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetGenreImage( @@ -656,7 +656,7 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadMusicGenreImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetMusicGenreImage( @@ -734,7 +734,7 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/Persons/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Persons/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("/Persons/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadPersonImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetPersonImage( @@ -812,7 +812,7 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/Studios/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Studios/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("/Studios/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadStudioImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetStudioImage( @@ -890,7 +890,7 @@ namespace Jellyfin.Api.Controllers /// or a if item not found. /// [HttpGet("/Users/{userId}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Users/{userId}/Images/{imageType}/{imageIndex?}")] + [HttpHead("/Users/{userId}/Images/{imageType}/{imageIndex?}", Name = "HeadUserImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetUserImage( diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 49fb9238f..354741ced 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers /// Optional, include image information in output. /// A with the items. [HttpGet("/Items")] - [HttpGet("/Users/{uId}/Items")] + [HttpGet("/Users/{uId}/Items", Name = "GetItems_2")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetItems( [FromRoute] Guid? uId, diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 5ad466c55..0ec7e2b8c 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -521,7 +521,7 @@ namespace Jellyfin.Api.Controllers /// The tvdbId. /// Report success. /// A . - [HttpPost("/Library/Series/Added")] + [HttpPost("/Library/Series/Added", Name = "PostAddedSeries")] [HttpPost("/Library/Series/Updated")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] @@ -551,7 +551,7 @@ namespace Jellyfin.Api.Controllers /// The imdbId. /// Report success. /// A . - [HttpPost("/Library/Movies/Added")] + [HttpPost("/Library/Movies/Added", Name = "PostAddedMovies")] [HttpPost("/Library/Movies/Updated")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] @@ -679,12 +679,12 @@ namespace Jellyfin.Api.Controllers /// Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls. /// Similar items returned. /// A containing the similar items. - [HttpGet("/Artists/{itemId}/Similar")] + [HttpGet("/Artists/{itemId}/Similar", Name = "GetSimilarArtists2")] [HttpGet("/Items/{itemId}/Similar")] - [HttpGet("/Albums/{itemId}/Similar")] - [HttpGet("/Shows/{itemId}/Similar")] - [HttpGet("/Movies/{itemId}/Similar")] - [HttpGet("/Trailers/{itemId}/Similar")] + [HttpGet("/Albums/{itemId}/Similar", Name = "GetSimilarAlbums2")] + [HttpGet("/Shows/{itemId}/Similar", Name = "GetSimilarShows2")] + [HttpGet("/Movies/{itemId}/Similar", Name = "GetSimilarMovies2")] + [HttpGet("/Trailers/{itemId}/Similar", Name = "GetSimilarTrailers2")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarItems( [FromRoute] Guid itemId, diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index bbe5544f9..89112eea7 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -127,7 +127,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Channels")] [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult> GetChannels( + public ActionResult> GetLiveTvChannels( [FromQuery] ChannelType? type, [FromQuery] Guid? userId, [FromQuery] int? startIndex, @@ -535,7 +535,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Programs")] [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.DefaultAuthorization)] - public async Task>> GetPrograms( + public async Task>> GetLiveTvPrograms( [FromQuery] string? channelIds, [FromQuery] Guid? userId, [FromQuery] DateTime? minStartDate, @@ -933,7 +933,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Obsolete("This endpoint is obsolete.")] - public ActionResult GetRecordingGroup([FromQuery] Guid? groupId) + public ActionResult GetRecordingGroup([FromRoute] Guid? groupId) { return NotFound(); } diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 0c98a8e71..1b300e0d8 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -241,7 +241,7 @@ namespace Jellyfin.Api.Controllers /// The command to send. /// General command sent to session. /// A . - [HttpPost("/Sessions/{sessionId}/Command/{Command}")] + [HttpPost("/Sessions/{sessionId}/Command/{command}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SendGeneralCommand( [FromRoute] string? sessionId, diff --git a/Jellyfin.Api/Controllers/StartupController.cs b/Jellyfin.Api/Controllers/StartupController.cs index f9e4e61b5..c8e3cc4f5 100644 --- a/Jellyfin.Api/Controllers/StartupController.cs +++ b/Jellyfin.Api/Controllers/StartupController.cs @@ -106,7 +106,7 @@ namespace Jellyfin.Api.Controllers /// Initial user retrieved. /// The first user. [HttpGet("User")] - [HttpGet("FirstUser")] + [HttpGet("FirstUser", Name = "GetFirstUser_2")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetFirstUser() { @@ -131,7 +131,7 @@ namespace Jellyfin.Api.Controllers /// [HttpPost("User")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task UpdateUser([FromForm] StartupUserDto startupUserDto) + public async Task UpdateStartupUser([FromForm] StartupUserDto startupUserDto) { var user = _userManager.Users.First(); diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index b62ff80fc..f8c19d15c 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -182,7 +182,7 @@ namespace Jellyfin.Api.Controllers /// File returned. /// A with the subtitle file. [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")] - [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}")] + [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}", Name = "GetSubtitle_2")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetSubtitle( [FromRoute, Required] Guid itemId, diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs index 55ed42227..2b1b95b1b 100644 --- a/Jellyfin.Api/Controllers/SyncPlayController.cs +++ b/Jellyfin.Api/Controllers/SyncPlayController.cs @@ -47,7 +47,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("New")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult CreateNewGroup() + public ActionResult SyncPlayCreateGroup() { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); _syncPlayManager.NewGroup(currentSession, CancellationToken.None); @@ -62,7 +62,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("Join")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult JoinGroup([FromQuery, Required] Guid groupId) + public ActionResult SyncPlayJoinGroup([FromQuery, Required] Guid groupId) { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); @@ -82,7 +82,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("Leave")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult LeaveGroup() + public ActionResult SyncPlayLeaveGroup() { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); _syncPlayManager.LeaveGroup(currentSession, CancellationToken.None); @@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers /// An containing the available SyncPlay groups. [HttpGet("List")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetSyncPlayGroups([FromQuery] Guid? filterItemId) + public ActionResult> SyncPlayGetGroups([FromQuery] Guid? filterItemId) { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); return Ok(_syncPlayManager.ListGroups(currentSession, filterItemId.HasValue ? filterItemId.Value : Guid.Empty)); @@ -110,7 +110,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("Play")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult Play() + public ActionResult SyncPlayPlay() { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var syncPlayRequest = new PlaybackRequest() @@ -128,7 +128,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("Pause")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult Pause() + public ActionResult SyncPlayPause() { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var syncPlayRequest = new PlaybackRequest() @@ -147,7 +147,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("Seek")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult Seek([FromQuery] long positionTicks) + public ActionResult SyncPlaySeek([FromQuery] long positionTicks) { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var syncPlayRequest = new PlaybackRequest() @@ -169,7 +169,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("Buffering")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult Buffering([FromQuery] DateTime when, [FromQuery] long positionTicks, [FromQuery] bool bufferingDone) + public ActionResult SyncPlayBuffering([FromQuery] DateTime when, [FromQuery] long positionTicks, [FromQuery] bool bufferingDone) { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var syncPlayRequest = new PlaybackRequest() @@ -190,7 +190,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("Ping")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult Ping([FromQuery] double ping) + public ActionResult SyncPlayPing([FromQuery] double ping) { var currentSession = RequestHelpers.GetSession(_sessionManager, _authorizationContext, Request); var syncPlayRequest = new PlaybackRequest() diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index bc606f7aa..e0bce3a41 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -85,8 +85,8 @@ namespace Jellyfin.Api.Controllers /// /// Information retrieved. /// The server name. - [HttpGet("Ping")] - [HttpPost("Ping")] + [HttpGet("Ping", Name = "GetPingSystem")] + [HttpPost("Ping", Name = "PostPingSystem")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult PingSystem() { diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 50ab0ac05..5a9bec2b0 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -69,9 +69,9 @@ namespace Jellyfin.Api.Controllers /// Redirected to remote audio stream. /// A containing the audio file. [HttpGet("/Audio/{itemId}/universal")] - [HttpGet("/Audio/{itemId}/{universal=universal}.{container?}")] - [HttpHead("/Audio/{itemId}/universal")] - [HttpHead("/Audio/{itemId}/{universal=universal}.{container?}")] + [HttpGet("/Audio/{itemId}/{universal=universal}.{container?}", Name = "GetUniversalAudioStream_2")] + [HttpHead("/Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")] + [HttpHead("/Audio/{itemId}/{universal=universal}.{container?}", Name = "HeadUniversalAudioStream_2")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status302Found)] diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index d1ef817eb..ebe88a9c0 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -316,10 +316,10 @@ namespace Jellyfin.Api.Controllers /// Optional. The streaming options. /// Video stream returned. /// A containing the audio file. - [HttpGet("{itemId}/{stream=stream}.{container?}")] + [HttpGet("{itemId}/{stream=stream}.{container?}", Name = "GetVideoStream_2")] [HttpGet("{itemId}/stream")] - [HttpHead("{itemId}/{stream=stream}.{container?}")] - [HttpHead("{itemId}/stream")] + [HttpHead("{itemId}/{stream=stream}.{container?}", Name = "HeadVideoStream_2")] + [HttpHead("{itemId}/stream", Name = "HeadVideoStream")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVideoStream( [FromRoute] Guid itemId, diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index cfbabf795..6e91042df 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -198,8 +198,15 @@ namespace Jellyfin.Server.Extensions $"{description.ActionDescriptor.RouteValues["controller"]}_{description.RelativePath}"); // Use method name as operationId - c.CustomOperationIds(description => - description.TryGetMethodInfo(out MethodInfo methodInfo) ? methodInfo.Name : null); + c.CustomOperationIds( + description => + { + description.TryGetMethodInfo(out MethodInfo methodInfo); + // Attribute name, method name, none. + return description?.ActionDescriptor?.AttributeRouteInfo?.Name + ?? methodInfo?.Name + ?? null; + }); // TODO - remove when all types are supported in System.Text.Json c.AddSwaggerTypeMappings(); diff --git a/tests/Jellyfin.Api.Tests/GetPathValueTests.cs b/tests/Jellyfin.Api.Tests/GetPathValueTests.cs deleted file mode 100644 index 397eb2edc..000000000 --- a/tests/Jellyfin.Api.Tests/GetPathValueTests.cs +++ /dev/null @@ -1,45 +0,0 @@ -using MediaBrowser.Api; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Net; -using MediaBrowser.Model.Configuration; -using MediaBrowser.Model.Services; -using Microsoft.Extensions.Logging.Abstractions; -using Moq; -using Xunit; - -namespace Jellyfin.Api.Tests -{ - public class GetPathValueTests - { - [Theory] - [InlineData("https://localhost:8096/ScheduledTasks/1234/Triggers", "", 1, "1234")] - [InlineData("https://localhost:8096/emby/ScheduledTasks/1234/Triggers", "", 1, "1234")] - [InlineData("https://localhost:8096/mediabrowser/ScheduledTasks/1234/Triggers", "", 1, "1234")] - [InlineData("https://localhost:8096/jellyfin/2/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")] - [InlineData("https://localhost:8096/jellyfin/2/emby/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")] - [InlineData("https://localhost:8096/jellyfin/2/mediabrowser/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")] - [InlineData("https://localhost:8096/JELLYFIN/2/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")] - [InlineData("https://localhost:8096/JELLYFIN/2/Emby/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")] - [InlineData("https://localhost:8096/JELLYFIN/2/MediaBrowser/ScheduledTasks/1234/Triggers", "jellyfin/2", 1, "1234")] - public void GetPathValueTest(string path, string baseUrl, int index, string value) - { - var reqMock = Mock.Of(x => x.PathInfo == path); - var conf = new ServerConfiguration() - { - BaseUrl = baseUrl - }; - - var confManagerMock = Mock.Of(x => x.Configuration == conf); - - var service = new TestService( - new NullLogger(), - confManagerMock, - Mock.Of()) - { - Request = reqMock - }; - - Assert.Equal(value, service.GetPathValue(index).ToString()); - } - } -} -- cgit v1.2.3 From 858aecd409914f6a9ca6f86445ec20c8bacc0b59 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 4 Aug 2020 12:48:53 -0600 Subject: Fix all route for base url support --- Jellyfin.Api/Controllers/AlbumsController.cs | 5 +- Jellyfin.Api/Controllers/DashboardController.cs | 11 +++-- Jellyfin.Api/Controllers/DynamicHlsController.cs | 17 ++++--- Jellyfin.Api/Controllers/FilterController.cs | 5 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 11 +++-- Jellyfin.Api/Controllers/ImageController.cs | 57 +++++++++++----------- Jellyfin.Api/Controllers/InstantMixController.cs | 15 +++--- Jellyfin.Api/Controllers/ItemLookupController.cs | 25 +++++----- Jellyfin.Api/Controllers/ItemUpdateController.cs | 7 +-- Jellyfin.Api/Controllers/ItemsController.cs | 7 +-- Jellyfin.Api/Controllers/LibraryController.cs | 51 +++++++++---------- Jellyfin.Api/Controllers/MediaInfoController.cs | 11 +++-- Jellyfin.Api/Controllers/PackageController.cs | 14 +++--- Jellyfin.Api/Controllers/PlaystateController.cs | 19 ++++---- Jellyfin.Api/Controllers/PluginsController.cs | 2 +- Jellyfin.Api/Controllers/SessionController.cs | 33 +++++++------ Jellyfin.Api/Controllers/SubtitleController.cs | 15 +++--- Jellyfin.Api/Controllers/SuggestionsController.cs | 3 +- Jellyfin.Api/Controllers/TrailersController.cs | 2 +- .../Controllers/UniversalAudioController.cs | 9 ++-- Jellyfin.Api/Controllers/UserController.cs | 2 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 21 ++++---- Jellyfin.Api/Controllers/UserViewsController.cs | 5 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 5 +- 24 files changed, 186 insertions(+), 166 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/AlbumsController.cs b/Jellyfin.Api/Controllers/AlbumsController.cs index 01ba7fc32..190d4bd07 100644 --- a/Jellyfin.Api/Controllers/AlbumsController.cs +++ b/Jellyfin.Api/Controllers/AlbumsController.cs @@ -17,6 +17,7 @@ namespace Jellyfin.Api.Controllers /// /// The albums controller. /// + [Route("")] public class AlbumsController : BaseJellyfinApiController { private readonly IUserManager _userManager; @@ -48,7 +49,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The maximum number of records to return. /// Similar albums returned. /// A with similar albums. - [HttpGet("/Albums/{albumId}/Similar")] + [HttpGet("Albums/{albumId}/Similar")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarAlbums( [FromRoute] string albumId, @@ -80,7 +81,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The maximum number of records to return. /// Similar artists returned. /// A with similar artists. - [HttpGet("/Artists/{artistId}/Similar")] + [HttpGet("Artists/{artistId}/Similar")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarArtists( [FromRoute] string artistId, diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index e033c50d5..a7bdb24f6 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -20,6 +20,7 @@ namespace Jellyfin.Api.Controllers /// /// The dashboard controller. /// + [Route("")] public class DashboardController : BaseJellyfinApiController { private readonly ILogger _logger; @@ -64,7 +65,7 @@ namespace Jellyfin.Api.Controllers /// ConfigurationPages returned. /// Server still loading. /// An with infos about the plugins. - [HttpGet("/web/ConfigurationPages")] + [HttpGet("web/ConfigurationPages")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult> GetConfigurationPages( @@ -118,7 +119,7 @@ namespace Jellyfin.Api.Controllers /// ConfigurationPage returned. /// Plugin configuration page not found. /// The configuration page. - [HttpGet("/web/ConfigurationPage")] + [HttpGet("web/ConfigurationPage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetDashboardConfigurationPage([FromQuery] string? name) @@ -172,7 +173,7 @@ namespace Jellyfin.Api.Controllers /// /// Robots.txt returned. /// The robots.txt. - [HttpGet("/robots.txt")] + [HttpGet("robots.txt")] [ProducesResponseType(StatusCodes.Status200OK)] [ApiExplorerSettings(IgnoreApi = true)] public ActionResult GetRobotsTxt() @@ -187,7 +188,7 @@ namespace Jellyfin.Api.Controllers /// Web client returned. /// Server does not host a web client. /// The resource. - [HttpGet("/web/{*resourceName}")] + [HttpGet("web/{*resourceName}")] [ApiExplorerSettings(IgnoreApi = true)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -218,7 +219,7 @@ namespace Jellyfin.Api.Controllers /// /// Favicon.ico returned. /// The favicon. - [HttpGet("/favicon.ico")] + [HttpGet("favicon.ico")] [ProducesResponseType(StatusCodes.Status200OK)] [ApiExplorerSettings(IgnoreApi = true)] public ActionResult GetFavIcon() diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index c4f79ce95..ec65cb95a 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -37,6 +37,7 @@ namespace Jellyfin.Api.Controllers /// /// Dynamic hls controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class DynamicHlsController : BaseJellyfinApiController { @@ -164,8 +165,8 @@ namespace Jellyfin.Api.Controllers /// Enable adaptive bitrate streaming. /// Video stream returned. /// A containing the playlist file. - [HttpGet("/Videos/{itemId}/master.m3u8")] - [HttpHead("/Videos/{itemId}/master.m3u8", Name = "HeadMasterHlsVideoPlaylist")] + [HttpGet("Videos/{itemId}/master.m3u8")] + [HttpHead("Videos/{itemId}/master.m3u8", Name = "HeadMasterHlsVideoPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsVideoPlaylist( [FromRoute] Guid itemId, @@ -334,8 +335,8 @@ namespace Jellyfin.Api.Controllers /// Enable adaptive bitrate streaming. /// Audio stream returned. /// A containing the playlist file. - [HttpGet("/Audio/{itemId}/master.m3u8")] - [HttpHead("/Audio/{itemId}/master.m3u8", Name = "HeadMasterHlsAudioPlaylist")] + [HttpGet("Audio/{itemId}/master.m3u8")] + [HttpHead("Audio/{itemId}/master.m3u8", Name = "HeadMasterHlsAudioPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsAudioPlaylist( [FromRoute] Guid itemId, @@ -503,7 +504,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The streaming options. /// Video stream returned. /// A containing the audio file. - [HttpGet("/Videos/{itemId}/main.m3u8")] + [HttpGet("Videos/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVariantHlsVideoPlaylist( [FromRoute] Guid itemId, @@ -668,7 +669,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The streaming options. /// Audio stream returned. /// A containing the audio file. - [HttpGet("/Audio/{itemId}/main.m3u8")] + [HttpGet("Audio/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVariantHlsAudioPlaylist( [FromRoute] Guid itemId, @@ -835,7 +836,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The streaming options. /// Video stream returned. /// A containing the audio file. - [HttpGet("/Videos/{itemId}/hls1/{playlistId}/{segmentId}.{container}")] + [HttpGet("Videos/{itemId}/hls1/{playlistId}/{segmentId}.{container}")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsVideoSegment( @@ -1004,7 +1005,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The streaming options. /// Video stream returned. /// A containing the audio file. - [HttpGet("/Audio/{itemId}/hls1/{playlistId}/{segmentId}.{container}")] + [HttpGet("Audio/{itemId}/hls1/{playlistId}/{segmentId}.{container}")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsAudioSegment( diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index 9ba5e1161..2a567c846 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -18,6 +18,7 @@ namespace Jellyfin.Api.Controllers /// /// Filters controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class FilterController : BaseJellyfinApiController { @@ -44,7 +45,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Filter by MediaType. Allows multiple, comma delimited. /// Legacy filters retrieved. /// Legacy query filters. - [HttpGet("/Items/Filters")] + [HttpGet("Items/Filters")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetQueryFiltersLegacy( [FromQuery] Guid? userId, @@ -133,7 +134,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Search recursive. /// Filters retrieved. /// Query filters. - [HttpGet("/Items/Filters2")] + [HttpGet("Items/Filters2")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetQueryFilters( [FromQuery] Guid? userId, diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 7bf9326a7..e4a6842bc 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -19,6 +19,7 @@ namespace Jellyfin.Api.Controllers /// /// The hls segment controller. /// + [Route("")] public class HlsSegmentController : BaseJellyfinApiController { private readonly IFileSystem _fileSystem; @@ -50,8 +51,8 @@ namespace Jellyfin.Api.Controllers /// A containing the audio stream. // Can't require authentication just yet due to seeing some requests come from Chrome without full query string // [Authenticated] - [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.mp3", Name = "GetHlsAudioSegmentLegacyMp3")] - [HttpGet("/Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")] + [HttpGet("Audio/{itemId}/hls/{segmentId}/stream.mp3", Name = "GetHlsAudioSegmentLegacyMp3")] + [HttpGet("Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsAudioSegmentLegacy([FromRoute] string itemId, [FromRoute] string segmentId) @@ -70,7 +71,7 @@ namespace Jellyfin.Api.Controllers /// The playlist id. /// Hls video playlist returned. /// A containing the playlist. - [HttpGet("/Videos/{itemId}/hls/{playlistId}/stream.m3u8")] + [HttpGet("Videos/{itemId}/hls/{playlistId}/stream.m3u8")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] @@ -89,7 +90,7 @@ namespace Jellyfin.Api.Controllers /// The play session id. /// Encoding stopped successfully. /// A indicating success. - [HttpDelete("/Videos/ActiveEncodings")] + [HttpDelete("Videos/ActiveEncodings")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult StopEncodingProcess([FromQuery] string deviceId, [FromQuery] string playSessionId) @@ -109,7 +110,7 @@ namespace Jellyfin.Api.Controllers /// A containing the video segment. // Can't require authentication just yet due to seeing some requests come from Chrome without full query string // [Authenticated] - [HttpGet("/Videos/{itemId}/hls/{playlistId}/{segmentId}.{segmentContainer}")] + [HttpGet("Videos/{itemId}/hls/{playlistId}/{segmentId}.{segmentContainer}")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsVideoSegmentLegacy( diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 3a445b1b3..360164ad4 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -30,6 +30,7 @@ namespace Jellyfin.Api.Controllers /// /// Image controller. /// + [Route("")] public class ImageController : BaseJellyfinApiController { private readonly IUserManager _userManager; @@ -81,8 +82,8 @@ namespace Jellyfin.Api.Controllers /// Image updated. /// User does not have permission to delete the image. /// A . - [HttpPost("/Users/{userId}/Images/{imageType}")] - [HttpPost("/Users/{userId}/Images/{imageType}/{index?}", Name = "PostUserImage_2")] + [HttpPost("Users/{userId}/Images/{imageType}")] + [HttpPost("Users/{userId}/Images/{imageType}/{index?}", Name = "PostUserImage_2")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")] @@ -127,8 +128,8 @@ namespace Jellyfin.Api.Controllers /// Image deleted. /// User does not have permission to delete the image. /// A . - [HttpDelete("/Users/{userId}/Images/{itemType}")] - [HttpDelete("/Users/{userId}/Images/{itemType}/{index?}", Name = "DeleteUserImage_2")] + [HttpDelete("Users/{userId}/Images/{itemType}")] + [HttpDelete("Users/{userId}/Images/{itemType}/{index?}", Name = "DeleteUserImage_2")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] [ProducesResponseType(StatusCodes.Status204NoContent)] @@ -166,8 +167,8 @@ namespace Jellyfin.Api.Controllers /// Image deleted. /// Item not found. /// A on success, or a if item not found. - [HttpDelete("/Items/{itemId}/Images/{imageType}")] - [HttpDelete("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "DeleteItemImage_2")] + [HttpDelete("Items/{itemId}/Images/{imageType}")] + [HttpDelete("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "DeleteItemImage_2")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -195,8 +196,8 @@ namespace Jellyfin.Api.Controllers /// Image saved. /// Item not found. /// A on success, or a if item not found. - [HttpPost("/Items/{itemId}/Images/{imageType}")] - [HttpPost("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "SetItemImage_2")] + [HttpPost("Items/{itemId}/Images/{imageType}")] + [HttpPost("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "SetItemImage_2")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -230,7 +231,7 @@ namespace Jellyfin.Api.Controllers /// Image index updated. /// Item not found. /// A on success, or a if item not found. - [HttpPost("/Items/{itemId}/Images/{imageType}/{imageIndex}/Index")] + [HttpPost("Items/{itemId}/Images/{imageType}/{imageIndex}/Index")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -257,7 +258,7 @@ namespace Jellyfin.Api.Controllers /// Item images returned. /// Item not found. /// The list of image infos on success, or if item not found. - [HttpGet("/Items/{itemId}/Images")] + [HttpGet("Items/{itemId}/Images")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult> GetItemImageInfos([FromRoute] Guid itemId) @@ -341,10 +342,10 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/Items/{itemId}/Images/{imageType}")] - [HttpHead("/Items/{itemId}/Images/{imageType}", Name = "HeadItemImage")] - [HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "GetItemImage_2")] - [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "HeadItemImage_2")] + [HttpGet("Items/{itemId}/Images/{imageType}")] + [HttpHead("Items/{itemId}/Images/{imageType}", Name = "HeadItemImage")] + [HttpGet("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "GetItemImage_2")] + [HttpHead("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "HeadItemImage_2")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage( @@ -421,8 +422,8 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}")] - [HttpHead("/Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}", Name = "HeadItemImage2")] + [HttpGet("Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}")] + [HttpHead("Items/{itemId}/Images/{imageType}/{imageIndex}/{tag}/{format}/{maxWidth}/{maxHeight}/{percentPlayed}/{unplayedCount}", Name = "HeadItemImage2")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage2( @@ -499,8 +500,8 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/Artists/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Artists/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadArtistImage")] + [HttpGet("Artists/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("Artists/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadArtistImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetArtistImage( @@ -577,8 +578,8 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/Genres/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Genres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadGenreImage")] + [HttpGet("Genres/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("Genres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadGenreImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetGenreImage( @@ -655,8 +656,8 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/MusicGenres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadMusicGenreImage")] + [HttpGet("MusicGenres/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("MusicGenres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadMusicGenreImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetMusicGenreImage( @@ -733,8 +734,8 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/Persons/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Persons/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadPersonImage")] + [HttpGet("Persons/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("Persons/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadPersonImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetPersonImage( @@ -811,8 +812,8 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/Studios/{name}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Studios/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadStudioImage")] + [HttpGet("Studios/{name}/Images/{imageType}/{imageIndex?}")] + [HttpHead("Studios/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadStudioImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetStudioImage( @@ -889,8 +890,8 @@ namespace Jellyfin.Api.Controllers /// A containing the file stream on success, /// or a if item not found. /// - [HttpGet("/Users/{userId}/Images/{imageType}/{imageIndex?}")] - [HttpHead("/Users/{userId}/Images/{imageType}/{imageIndex?}", Name = "HeadUserImage")] + [HttpGet("Users/{userId}/Images/{imageType}/{imageIndex?}")] + [HttpHead("Users/{userId}/Images/{imageType}/{imageIndex?}", Name = "HeadUserImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetUserImage( diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index bb980af3e..8ca232cef 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -19,6 +19,7 @@ namespace Jellyfin.Api.Controllers /// /// The instant mix controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class InstantMixController : BaseJellyfinApiController { @@ -59,7 +60,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. - [HttpGet("/Songs/{id}/InstantMix")] + [HttpGet("Songs/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromSong( [FromRoute] Guid id, @@ -96,7 +97,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. - [HttpGet("/Albums/{id}/InstantMix")] + [HttpGet("Albums/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromAlbum( [FromRoute] Guid id, @@ -133,7 +134,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. - [HttpGet("/Playlists/{id}/InstantMix")] + [HttpGet("Playlists/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromPlaylist( [FromRoute] Guid id, @@ -170,7 +171,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. - [HttpGet("/MusicGenres/{name}/InstantMix")] + [HttpGet("MusicGenres/{name}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromMusicGenre( [FromRoute] string? name, @@ -206,7 +207,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. - [HttpGet("/Artists/InstantMix")] + [HttpGet("Artists/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromArtists( [FromRoute] Guid id, @@ -243,7 +244,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. - [HttpGet("/MusicGenres/InstantMix")] + [HttpGet("MusicGenres/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromMusicGenres( [FromRoute] Guid id, @@ -280,7 +281,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The image types to include in the output. /// Instant playlist returned. /// A with the playlist items. - [HttpGet("/Items/{id}/InstantMix")] + [HttpGet("Items/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromItem( [FromRoute] Guid id, diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index 44709d0ee..0d9dffbfe 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -30,6 +30,7 @@ namespace Jellyfin.Api.Controllers /// /// Item lookup controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class ItemLookupController : BaseJellyfinApiController { @@ -68,7 +69,7 @@ namespace Jellyfin.Api.Controllers /// External id info retrieved. /// Item not found. /// List of external id info. - [HttpGet("/Items/{itemId}/ExternalIdInfos")] + [HttpGet("Items/{itemId}/ExternalIdInfos")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -92,7 +93,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/Movie")] + [HttpPost("Items/RemoteSearch/Movie")] public async Task>> GetMovieRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -109,7 +110,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/Trailer")] + [HttpPost("Items/RemoteSearch/Trailer")] public async Task>> GetTrailerRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -126,7 +127,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/MusicVideo")] + [HttpPost("Items/RemoteSearch/MusicVideo")] public async Task>> GetMusicVideoRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -143,7 +144,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/Series")] + [HttpPost("Items/RemoteSearch/Series")] public async Task>> GetSeriesRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -160,7 +161,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/BoxSet")] + [HttpPost("Items/RemoteSearch/BoxSet")] public async Task>> GetBoxSetRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -177,7 +178,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/MusicArtist")] + [HttpPost("Items/RemoteSearch/MusicArtist")] public async Task>> GetMusicArtistRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -194,7 +195,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/MusicAlbum")] + [HttpPost("Items/RemoteSearch/MusicAlbum")] public async Task>> GetMusicAlbumRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -211,7 +212,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/Person")] + [HttpPost("Items/RemoteSearch/Person")] [Authorize(Policy = Policies.RequiresElevation)] public async Task>> GetPersonRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { @@ -229,7 +230,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the list of remote search results. /// - [HttpPost("/Items/RemoteSearch/Book")] + [HttpPost("Items/RemoteSearch/Book")] public async Task>> GetBookRemoteSearchResults([FromBody, BindRequired] RemoteSearchQuery query) { var results = await _providerManager.GetRemoteSearchResults(query, CancellationToken.None) @@ -247,7 +248,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an containing the images file stream. /// - [HttpGet("/Items/RemoteSearch/Image")] + [HttpGet("Items/RemoteSearch/Image")] public async Task GetRemoteSearchImage( [FromQuery, Required] string imageUrl, [FromQuery, Required] string providerName) @@ -291,7 +292,7 @@ namespace Jellyfin.Api.Controllers /// A that represents the asynchronous operation to get the remote search results. /// The task result contains an . /// - [HttpPost("/Items/RemoteSearch/Apply/{id}")] + [HttpPost("Items/RemoteSearch/Apply/{id}")] [Authorize(Policy = Policies.RequiresElevation)] public async Task ApplySearchCriteria( [FromRoute] Guid itemId, diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index c9b2aafcc..a5d9d36a3 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -24,6 +24,7 @@ namespace Jellyfin.Api.Controllers /// /// Item update controller. /// + [Route("")] [Authorize(Policy = Policies.RequiresElevation)] public class ItemUpdateController : BaseJellyfinApiController { @@ -63,7 +64,7 @@ namespace Jellyfin.Api.Controllers /// Item updated. /// Item not found. /// An on success, or a if the item could not be found. - [HttpPost("/Items/{itemId}")] + [HttpPost("Items/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult UpdateItem([FromRoute] Guid itemId, [FromBody, BindRequired] BaseItemDto request) @@ -136,7 +137,7 @@ namespace Jellyfin.Api.Controllers /// Item metadata editor returned. /// Item not found. /// An on success containing the metadata editor, or a if the item could not be found. - [HttpGet("/Items/{itemId}/MetadataEditor")] + [HttpGet("Items/{itemId}/MetadataEditor")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetMetadataEditorInfo([FromRoute] Guid itemId) @@ -190,7 +191,7 @@ namespace Jellyfin.Api.Controllers /// Item content type updated. /// Item not found. /// An on success, or a if the item could not be found. - [HttpPost("/Items/{itemId}/ContentType")] + [HttpPost("Items/{itemId}/ContentType")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult UpdateItemContentType([FromRoute] Guid itemId, [FromQuery, BindRequired] string? contentType) diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 354741ced..1b8b68313 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -23,6 +23,7 @@ namespace Jellyfin.Api.Controllers /// /// The items controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class ItemsController : BaseJellyfinApiController { @@ -139,8 +140,8 @@ namespace Jellyfin.Api.Controllers /// Optional. Enable the total record count. /// Optional, include image information in output. /// A with the items. - [HttpGet("/Items")] - [HttpGet("/Users/{uId}/Items", Name = "GetItems_2")] + [HttpGet("Items")] + [HttpGet("Users/{uId}/Items", Name = "GetItems_2")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetItems( [FromRoute] Guid? uId, @@ -523,7 +524,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Include image information in output. /// Items returned. /// A with the items that are resumable. - [HttpGet("/Users/{userId}/Items/Resume")] + [HttpGet("Users/{userId}/Items/Resume")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetResumeItems( [FromRoute] Guid userId, diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 0ec7e2b8c..a4637752d 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -43,6 +43,7 @@ namespace Jellyfin.Api.Controllers /// /// Library Controller. /// + [Route("")] public class LibraryController : BaseJellyfinApiController { private readonly IProviderManager _providerManager; @@ -100,7 +101,7 @@ namespace Jellyfin.Api.Controllers /// File stream returned. /// Item not found. /// A with the original file. - [HttpGet("/Items/{itemId}/File")] + [HttpGet("Items/{itemId}/File")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -121,7 +122,7 @@ namespace Jellyfin.Api.Controllers /// /// Critic reviews returned. /// The list of critic reviews. - [HttpGet("/Items/{itemId}/CriticReviews")] + [HttpGet("Items/{itemId}/CriticReviews")] [Authorize(Policy = Policies.DefaultAuthorization)] [Obsolete("This endpoint is obsolete.")] [ProducesResponseType(StatusCodes.Status200OK)] @@ -139,7 +140,7 @@ namespace Jellyfin.Api.Controllers /// Theme songs returned. /// Item not found. /// The item theme songs. - [HttpGet("/Items/{itemId}/ThemeSongs")] + [HttpGet("Items/{itemId}/ThemeSongs")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -205,7 +206,7 @@ namespace Jellyfin.Api.Controllers /// Theme videos returned. /// Item not found. /// The item theme videos. - [HttpGet("/Items/{itemId}/ThemeVideos")] + [HttpGet("Items/{itemId}/ThemeVideos")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -271,7 +272,7 @@ namespace Jellyfin.Api.Controllers /// Theme songs and videos returned. /// Item not found. /// The item theme videos. - [HttpGet("/Items/{itemId}/ThemeMedia")] + [HttpGet("Items/{itemId}/ThemeMedia")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetThemeMedia( @@ -302,7 +303,7 @@ namespace Jellyfin.Api.Controllers /// /// Library scan started. /// A . - [HttpGet("/Library/Refresh")] + [HttpGet("Library/Refresh")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task RefreshLibrary() @@ -326,7 +327,7 @@ namespace Jellyfin.Api.Controllers /// Item deleted. /// Unauthorized access. /// A . - [HttpDelete("/Items/{itemId}")] + [HttpDelete("Items/{itemId}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] @@ -356,7 +357,7 @@ namespace Jellyfin.Api.Controllers /// Items deleted. /// Unauthorized access. /// A . - [HttpDelete("/Items")] + [HttpDelete("Items")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status401Unauthorized)] @@ -400,7 +401,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Get counts of favorite items. /// Item counts returned. /// Item counts. - [HttpGet("/Items/Counts")] + [HttpGet("Items/Counts")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetItemCounts( @@ -434,7 +435,7 @@ namespace Jellyfin.Api.Controllers /// Item parents returned. /// Item not found. /// Item parents. - [HttpGet("/Items/{itemId}/Ancestors")] + [HttpGet("Items/{itemId}/Ancestors")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -476,7 +477,7 @@ namespace Jellyfin.Api.Controllers /// /// Physical paths returned. /// List of physical paths. - [HttpGet("/Library/PhysicalPaths")] + [HttpGet("Library/PhysicalPaths")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetPhysicalPaths() @@ -491,7 +492,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Filter by folders that are marked hidden, or not. /// Media folders returned. /// List of user media folders. - [HttpGet("/Library/MediaFolders")] + [HttpGet("Library/MediaFolders")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetMediaFolders([FromQuery] bool? isHidden) @@ -521,8 +522,8 @@ namespace Jellyfin.Api.Controllers /// The tvdbId. /// Report success. /// A . - [HttpPost("/Library/Series/Added", Name = "PostAddedSeries")] - [HttpPost("/Library/Series/Updated")] + [HttpPost("Library/Series/Added", Name = "PostAddedSeries")] + [HttpPost("Library/Series/Updated")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult PostUpdatedSeries([FromQuery] string? tvdbId) @@ -551,8 +552,8 @@ namespace Jellyfin.Api.Controllers /// The imdbId. /// Report success. /// A . - [HttpPost("/Library/Movies/Added", Name = "PostAddedMovies")] - [HttpPost("/Library/Movies/Updated")] + [HttpPost("Library/Movies/Added", Name = "PostAddedMovies")] + [HttpPost("Library/Movies/Updated")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult PostUpdatedMovies([FromRoute] string? tmdbId, [FromRoute] string? imdbId) @@ -593,7 +594,7 @@ namespace Jellyfin.Api.Controllers /// A list of updated media paths. /// Report success. /// A . - [HttpPost("/Library/Media/Updated")] + [HttpPost("Library/Media/Updated")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult PostUpdatedMedia([FromBody, BindRequired] MediaUpdateInfoDto[] updates) @@ -614,7 +615,7 @@ namespace Jellyfin.Api.Controllers /// Item not found. /// A containing the media stream. /// User can't download or item can't be downloaded. - [HttpGet("/Items/{itemId}/Download")] + [HttpGet("Items/{itemId}/Download")] [Authorize(Policy = Policies.Download)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -679,12 +680,12 @@ namespace Jellyfin.Api.Controllers /// Optional. Specify additional fields of information to return in the output. This allows multiple, comma delimited. Options: Budget, Chapters, DateCreated, Genres, HomePageUrl, IndexOptions, MediaStreams, Overview, ParentId, Path, People, ProviderIds, PrimaryImageAspectRatio, Revenue, SortName, Studios, Taglines, TrailerUrls. /// Similar items returned. /// A containing the similar items. - [HttpGet("/Artists/{itemId}/Similar", Name = "GetSimilarArtists2")] - [HttpGet("/Items/{itemId}/Similar")] - [HttpGet("/Albums/{itemId}/Similar", Name = "GetSimilarAlbums2")] - [HttpGet("/Shows/{itemId}/Similar", Name = "GetSimilarShows2")] - [HttpGet("/Movies/{itemId}/Similar", Name = "GetSimilarMovies2")] - [HttpGet("/Trailers/{itemId}/Similar", Name = "GetSimilarTrailers2")] + [HttpGet("Artists/{itemId}/Similar", Name = "GetSimilarArtists2")] + [HttpGet("Items/{itemId}/Similar")] + [HttpGet("Albums/{itemId}/Similar", Name = "GetSimilarAlbums2")] + [HttpGet("Shows/{itemId}/Similar", Name = "GetSimilarShows2")] + [HttpGet("Movies/{itemId}/Similar", Name = "GetSimilarMovies2")] + [HttpGet("Trailers/{itemId}/Similar", Name = "GetSimilarTrailers2")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarItems( [FromRoute] Guid itemId, @@ -735,7 +736,7 @@ namespace Jellyfin.Api.Controllers /// Whether this is a new library. /// Library options info returned. /// Library options info. - [HttpGet("/Libraries/AvailableOptions")] + [HttpGet("Libraries/AvailableOptions")] [Authorize(Policy = Policies.FirstTimeSetupOrElevated)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetLibraryOptionsInfo( diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 5b0f46b02..242cbf191 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -34,6 +34,7 @@ namespace Jellyfin.Api.Controllers /// /// The media info controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class MediaInfoController : BaseJellyfinApiController { @@ -88,7 +89,7 @@ namespace Jellyfin.Api.Controllers /// The user id. /// Playback info returned. /// A containing a with the playback information. - [HttpGet("/Items/{itemId}/PlaybackInfo")] + [HttpGet("Items/{itemId}/PlaybackInfo")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPlaybackInfo([FromRoute] Guid itemId, [FromQuery] Guid? userId) { @@ -116,7 +117,7 @@ namespace Jellyfin.Api.Controllers /// Whether to allow to copy the audio stream. Default: true. /// Playback info returned. /// A containing a with the playback info. - [HttpPost("/Items/{itemId}/PlaybackInfo")] + [HttpPost("Items/{itemId}/PlaybackInfo")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPostedPlaybackInfo( [FromRoute] Guid itemId, @@ -237,7 +238,7 @@ namespace Jellyfin.Api.Controllers /// Whether to enable direct stream. Default: true. /// Media source opened. /// A containing a . - [HttpPost("/LiveStreams/Open")] + [HttpPost("LiveStreams/Open")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> OpenLiveStream( [FromQuery] string? openToken, @@ -278,7 +279,7 @@ namespace Jellyfin.Api.Controllers /// The livestream id. /// Livestream closed. /// A indicating success. - [HttpPost("/LiveStreams/Close")] + [HttpPost("LiveStreams/Close")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult CloseLiveStream([FromQuery] string? liveStreamId) { @@ -293,7 +294,7 @@ namespace Jellyfin.Api.Controllers /// Test buffer returned. /// Size has to be a numer between 0 and 10,000,000. /// A with specified bitrate. - [HttpGet("/Playback/BitrateTest")] + [HttpGet("Playback/BitrateTest")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [Produces(MediaTypeNames.Application.Octet)] diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index a6c552790..06c4213fb 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -16,7 +16,7 @@ namespace Jellyfin.Api.Controllers /// /// Package Controller. /// - [Route("Packages")] + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class PackageController : BaseJellyfinApiController { @@ -41,7 +41,7 @@ namespace Jellyfin.Api.Controllers /// The GUID of the associated assembly. /// Package retrieved. /// A containing package information. - [HttpGet("/{name}")] + [HttpGet("Packages/{name}")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPackageInfo( [FromRoute] [Required] string? name, @@ -61,7 +61,7 @@ namespace Jellyfin.Api.Controllers /// /// Available packages returned. /// An containing available packages information. - [HttpGet] + [HttpGet("Packages")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPackages() { @@ -79,7 +79,7 @@ namespace Jellyfin.Api.Controllers /// Package found. /// Package not found. /// A on success, or a if the package could not be found. - [HttpPost("/Installed/{name}")] + [HttpPost("Packages/Installed/{name}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Policy = Policies.RequiresElevation)] @@ -111,7 +111,7 @@ namespace Jellyfin.Api.Controllers /// Installation Id. /// Installation cancelled. /// A on successfully cancelling a package installation. - [HttpDelete("/Installing/{packageId}")] + [HttpDelete("Packages/Installing/{packageId}")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult CancelPackageInstallation( @@ -126,7 +126,7 @@ namespace Jellyfin.Api.Controllers /// /// Package repositories returned. /// An containing the list of package repositories. - [HttpGet("/Repositories")] + [HttpGet("Repositories")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetRepositories() @@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers /// The list of package repositories. /// Package repositories saved. /// A . - [HttpOptions("/Repositories")] + [HttpOptions("Repositories")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SetRepositories([FromBody] List repositoryInfos) diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 3ebd003f1..0422bfe72 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -19,6 +19,7 @@ namespace Jellyfin.Api.Controllers /// /// Playstate controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class PlaystateController : BaseJellyfinApiController { @@ -67,7 +68,7 @@ namespace Jellyfin.Api.Controllers /// Optional. The date the item was played. /// Item marked as played. /// An containing the . - [HttpPost("/Users/{userId}/PlayedItems/{itemId}")] + [HttpPost("Users/{userId}/PlayedItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult MarkPlayedItem( [FromRoute] Guid userId, @@ -93,7 +94,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Item marked as unplayed. /// A containing the . - [HttpDelete("/Users/{userId}/PlayedItem/{itemId}")] + [HttpDelete("Users/{userId}/PlayedItem/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult MarkUnplayedItem([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -115,7 +116,7 @@ namespace Jellyfin.Api.Controllers /// The playback start info. /// Playback start recorded. /// A . - [HttpPost("/Sessions/Playing")] + [HttpPost("Sessions/Playing")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ReportPlaybackStart([FromBody] PlaybackStartInfo playbackStartInfo) { @@ -131,7 +132,7 @@ namespace Jellyfin.Api.Controllers /// The playback progress info. /// Playback progress recorded. /// A . - [HttpPost("/Sessions/Playing/Progress")] + [HttpPost("Sessions/Playing/Progress")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ReportPlaybackProgress([FromBody] PlaybackProgressInfo playbackProgressInfo) { @@ -147,7 +148,7 @@ namespace Jellyfin.Api.Controllers /// Playback session id. /// Playback session pinged. /// A . - [HttpPost("/Sessions/Playing/Ping")] + [HttpPost("Sessions/Playing/Ping")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult PingPlaybackSession([FromQuery] string playSessionId) { @@ -161,7 +162,7 @@ namespace Jellyfin.Api.Controllers /// The playback stop info. /// Playback stop recorded. /// A . - [HttpPost("/Sessions/Playing/Stopped")] + [HttpPost("Sessions/Playing/Stopped")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ReportPlaybackStopped([FromBody] PlaybackStopInfo playbackStopInfo) { @@ -190,7 +191,7 @@ namespace Jellyfin.Api.Controllers /// Indicates if the client can seek. /// Play start recorded. /// A . - [HttpPost("/Users/{userId}/PlayingItems/{itemId}")] + [HttpPost("Users/{userId}/PlayingItems/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackStart( @@ -240,7 +241,7 @@ namespace Jellyfin.Api.Controllers /// Indicates if the player is muted. /// Play progress recorded. /// A . - [HttpPost("/Users/{userId}/PlayingItems/{itemId}/Progress")] + [HttpPost("Users/{userId}/PlayingItems/{itemId}/Progress")] [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackProgress( @@ -292,7 +293,7 @@ namespace Jellyfin.Api.Controllers /// The play session id. /// Playback stop recorded. /// A . - [HttpDelete("/Users/{userId}/PlayingItems/{itemId}")] + [HttpDelete("Users/{userId}/PlayingItems/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackStopped( diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 770d74838..fe10f0f1b 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -188,7 +188,7 @@ namespace Jellyfin.Api.Controllers /// Not Implemented. /// This endpoint is not implemented. [Obsolete("Paid plugins are not supported")] - [HttpGet("/Registrations/{name}")] + [HttpGet("Registrations/{name}")] [ProducesResponseType(StatusCodes.Status501NotImplemented)] public ActionResult GetRegistration([FromRoute] string? name) { diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 1b300e0d8..3e6f577f1 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -23,6 +23,7 @@ namespace Jellyfin.Api.Controllers /// /// The session controller. /// + [Route("")] public class SessionController : BaseJellyfinApiController { private readonly ISessionManager _sessionManager; @@ -57,7 +58,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Filter by sessions that were active in the last n seconds. /// List of sessions returned. /// An with the available sessions. - [HttpGet("/Sessions")] + [HttpGet("Sessions")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSessions( @@ -120,7 +121,7 @@ namespace Jellyfin.Api.Controllers /// The name of the item. /// Instruction sent to session. /// A . - [HttpPost("/Sessions/{sessionId}/Viewing")] + [HttpPost("Sessions/{sessionId}/Viewing")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult DisplayContent( [FromRoute] string? sessionId, @@ -154,7 +155,7 @@ namespace Jellyfin.Api.Controllers /// The . /// Instruction sent to session. /// A . - [HttpPost("/Sessions/{sessionId}/Playing")] + [HttpPost("Sessions/{sessionId}/Playing")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult Play( [FromRoute] string? sessionId, @@ -188,7 +189,7 @@ namespace Jellyfin.Api.Controllers /// The . /// Playstate command sent to session. /// A . - [HttpPost("/Sessions/{sessionId}/Playing/{command}")] + [HttpPost("Sessions/{sessionId}/Playing/{command}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SendPlaystateCommand( [FromRoute] string? sessionId, @@ -210,7 +211,7 @@ namespace Jellyfin.Api.Controllers /// The command to send. /// System command sent to session. /// A . - [HttpPost("/Sessions/{sessionId}/System/{command}")] + [HttpPost("Sessions/{sessionId}/System/{command}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SendSystemCommand( [FromRoute] string? sessionId, @@ -241,7 +242,7 @@ namespace Jellyfin.Api.Controllers /// The command to send. /// General command sent to session. /// A . - [HttpPost("/Sessions/{sessionId}/Command/{command}")] + [HttpPost("Sessions/{sessionId}/Command/{command}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SendGeneralCommand( [FromRoute] string? sessionId, @@ -267,7 +268,7 @@ namespace Jellyfin.Api.Controllers /// The . /// Full general command sent to session. /// A . - [HttpPost("/Sessions/{sessionId}/Command")] + [HttpPost("Sessions/{sessionId}/Command")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SendFullGeneralCommand( [FromRoute] string? sessionId, @@ -300,7 +301,7 @@ namespace Jellyfin.Api.Controllers /// The message timeout. If omitted the user will have to confirm viewing the message. /// Message sent. /// A . - [HttpPost("/Sessions/{sessionId}/Message")] + [HttpPost("Sessions/{sessionId}/Message")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult SendMessageCommand( [FromRoute] string? sessionId, @@ -327,7 +328,7 @@ namespace Jellyfin.Api.Controllers /// The user id. /// User added to session. /// A . - [HttpPost("/Sessions/{sessionId}/User/{userId}")] + [HttpPost("Sessions/{sessionId}/User/{userId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult AddUserToSession( [FromRoute] string? sessionId, @@ -344,7 +345,7 @@ namespace Jellyfin.Api.Controllers /// The user id. /// User removed from session. /// A . - [HttpDelete("/Sessions/{sessionId}/User/{userId}")] + [HttpDelete("Sessions/{sessionId}/User/{userId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult RemoveUserFromSession( [FromRoute] string? sessionId, @@ -365,7 +366,7 @@ namespace Jellyfin.Api.Controllers /// Determines whether the device supports a unique identifier. /// Capabilities posted. /// A . - [HttpPost("/Sessions/Capabilities")] + [HttpPost("Sessions/Capabilities")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult PostCapabilities( [FromQuery] string? id, @@ -398,7 +399,7 @@ namespace Jellyfin.Api.Controllers /// The . /// Capabilities updated. /// A . - [HttpPost("/Sessions/Capabilities/Full")] + [HttpPost("Sessions/Capabilities/Full")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult PostFullCapabilities( [FromQuery] string? id, @@ -421,7 +422,7 @@ namespace Jellyfin.Api.Controllers /// The item id. /// Session reported to server. /// A . - [HttpPost("/Sessions/Viewing")] + [HttpPost("Sessions/Viewing")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult ReportViewing( [FromQuery] string? sessionId, @@ -438,7 +439,7 @@ namespace Jellyfin.Api.Controllers /// /// Session end reported to server. /// A . - [HttpPost("/Sessions/Logout")] + [HttpPost("Sessions/Logout")] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult ReportSessionEnded() { @@ -453,7 +454,7 @@ namespace Jellyfin.Api.Controllers /// /// Auth providers retrieved. /// An with the auth providers. - [HttpGet("/Auth/Providers")] + [HttpGet("Auth/Providers")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetAuthProviders() { @@ -465,7 +466,7 @@ namespace Jellyfin.Api.Controllers /// /// Password reset providers retrieved. /// An with the password reset providers. - [HttpGet("/Auto/PasswordResetProviders")] + [HttpGet("Auto/PasswordResetProviders")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetPasswordResetProviders() { diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index f8c19d15c..22144ab1a 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -30,6 +30,7 @@ namespace Jellyfin.Api.Controllers /// /// Subtitle controller. /// + [Route("")] public class SubtitleController : BaseJellyfinApiController { private readonly ILibraryManager _libraryManager; @@ -80,7 +81,7 @@ namespace Jellyfin.Api.Controllers /// Subtitle deleted. /// Item not found. /// A . - [HttpDelete("/Videos/{itemId}/Subtitles/{index}")] + [HttpDelete("Videos/{itemId}/Subtitles/{index}")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] @@ -107,7 +108,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Only show subtitles which are a perfect match. /// Subtitles retrieved. /// An array of . - [HttpGet("/Items/{itemId}/RemoteSearch/Subtitles/{language}")] + [HttpGet("Items/{itemId}/RemoteSearch/Subtitles/{language}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task>> SearchRemoteSubtitles( @@ -127,7 +128,7 @@ namespace Jellyfin.Api.Controllers /// The subtitle id. /// Subtitle downloaded. /// A . - [HttpPost("/Items/{itemId}/RemoteSearch/Subtitles/{subtitleId}")] + [HttpPost("Items/{itemId}/RemoteSearch/Subtitles/{subtitleId}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task DownloadRemoteSubtitles( @@ -157,7 +158,7 @@ namespace Jellyfin.Api.Controllers /// The item id. /// File returned. /// A with the subtitle file. - [HttpGet("/Providers/Subtitles/Subtitles/{id}")] + [HttpGet("Providers/Subtitles/Subtitles/{id}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [Produces(MediaTypeNames.Application.Octet)] @@ -181,8 +182,8 @@ namespace Jellyfin.Api.Controllers /// Optional. The start position of the subtitle in ticks. /// File returned. /// A with the subtitle file. - [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")] - [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}", Name = "GetSubtitle_2")] + [HttpGet("Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")] + [HttpGet("Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}", Name = "GetSubtitle_2")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetSubtitle( [FromRoute, Required] Guid itemId, @@ -247,7 +248,7 @@ namespace Jellyfin.Api.Controllers /// The subtitle segment length. /// Subtitle playlist retrieved. /// A with the HLS subtitle playlist. - [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/subtitles.m3u8")] + [HttpGet("Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/subtitles.m3u8")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index 55759f316..42db6b6a1 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -16,6 +16,7 @@ namespace Jellyfin.Api.Controllers /// /// The suggestions controller. /// + [Route("")] public class SuggestionsController : BaseJellyfinApiController { private readonly IDtoService _dtoService; @@ -49,7 +50,7 @@ namespace Jellyfin.Api.Controllers /// Whether to enable the total record count. /// Suggestions returned. /// A with the suggestions. - [HttpGet("/Users/{userId}/Suggestions")] + [HttpGet("Users/{userId}/Suggestions")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSuggestions( [FromRoute] Guid userId, diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs index fbab7948f..5157b08ae 100644 --- a/Jellyfin.Api/Controllers/TrailersController.cs +++ b/Jellyfin.Api/Controllers/TrailersController.cs @@ -108,7 +108,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Enable the total record count. /// Optional, include image information in output. /// A with the trailers. - [HttpGet("/Trailers")] + [HttpGet] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetTrailers( [FromQuery] Guid? userId, diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 5a9bec2b0..75df16aa7 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -19,6 +19,7 @@ namespace Jellyfin.Api.Controllers /// /// The universal audio controller. /// + [Route("")] public class UniversalAudioController : BaseJellyfinApiController { private readonly IAuthorizationContext _authorizationContext; @@ -68,10 +69,10 @@ namespace Jellyfin.Api.Controllers /// Audio stream returned. /// Redirected to remote audio stream. /// A containing the audio file. - [HttpGet("/Audio/{itemId}/universal")] - [HttpGet("/Audio/{itemId}/{universal=universal}.{container?}", Name = "GetUniversalAudioStream_2")] - [HttpHead("/Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")] - [HttpHead("/Audio/{itemId}/{universal=universal}.{container?}", Name = "HeadUniversalAudioStream_2")] + [HttpGet("Audio/{itemId}/universal")] + [HttpGet("Audio/{itemId}/{universal=universal}.{container?}", Name = "GetUniversalAudioStream_2")] + [HttpHead("Audio/{itemId}/universal", Name = "HeadUniversalAudioStream")] + [HttpHead("Audio/{itemId}/{universal=universal}.{container?}", Name = "HeadUniversalAudioStream_2")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status302Found)] diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 482baf641..2ce5c7e56 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -450,7 +450,7 @@ namespace Jellyfin.Api.Controllers /// The create user by name request body. /// User created. /// An of the new user. - [HttpPost("/Users/New")] + [HttpPost("New")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> CreateUserByName([FromBody] CreateUserByName request) diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index cedda3b9d..f55ff6f3d 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -25,6 +25,7 @@ namespace Jellyfin.Api.Controllers /// /// User library controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class UserLibraryController : BaseJellyfinApiController { @@ -67,7 +68,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Item returned. /// An containing the d item. - [HttpGet("/Users/{userId}/Items/{itemId}")] + [HttpGet("Users/{userId}/Items/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetItem([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -90,7 +91,7 @@ namespace Jellyfin.Api.Controllers /// User id. /// Root folder returned. /// An containing the user's root folder. - [HttpGet("/Users/{userId}/Items/Root")] + [HttpGet("Users/{userId}/Items/Root")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetRootFolder([FromRoute] Guid userId) { @@ -107,7 +108,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Intros returned. /// An containing the intros to play. - [HttpGet("/Users/{userId}/Items/{itemId}/Intros")] + [HttpGet("Users/{userId}/Items/{itemId}/Intros")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task>> GetIntros([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -135,7 +136,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Item marked as favorite. /// An containing the . - [HttpPost("/Users/{userId}/FavoriteItems/{itemId}")] + [HttpPost("Users/{userId}/FavoriteItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult MarkFavoriteItem([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -149,7 +150,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Item unmarked as favorite. /// An containing the . - [HttpDelete("/Users/{userId}/FavoriteItems/{itemId}")] + [HttpDelete("Users/{userId}/FavoriteItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult UnmarkFavoriteItem([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -163,7 +164,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Personal rating removed. /// An containing the . - [HttpDelete("/Users/{userId}/Items/{itemId}/Rating")] + [HttpDelete("Users/{userId}/Items/{itemId}/Rating")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult DeleteUserItemRating([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -178,7 +179,7 @@ namespace Jellyfin.Api.Controllers /// Whether this is likes. /// Item rating updated. /// An containing the . - [HttpPost("/Users/{userId}/Items/{itemId}/Rating")] + [HttpPost("Users/{userId}/Items/{itemId}/Rating")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult UpdateUserItemRating([FromRoute] Guid userId, [FromRoute] Guid itemId, [FromQuery] bool? likes) { @@ -192,7 +193,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// An containing the item's local trailers. /// The items local trailers. - [HttpGet("/Users/{userId}/Items/{itemId}/LocalTrailers")] + [HttpGet("Users/{userId}/Items/{itemId}/LocalTrailers")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetLocalTrailers([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -227,7 +228,7 @@ namespace Jellyfin.Api.Controllers /// Item id. /// Special features returned. /// An containing the special features. - [HttpGet("/Users/{userId}/Items/{itemId}/SpecialFeatures")] + [HttpGet("Users/{userId}/Items/{itemId}/SpecialFeatures")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSpecialFeatures([FromRoute] Guid userId, [FromRoute] Guid itemId) { @@ -260,7 +261,7 @@ namespace Jellyfin.Api.Controllers /// Whether or not to group items into a parent container. /// Latest media returned. /// An containing the latest media. - [HttpGet("/Users/{userId}/Items/Latest")] + [HttpGet("Users/{userId}/Items/Latest")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetLatestMedia( [FromRoute] Guid userId, diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index f4bd451ef..6df7cc779 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -21,6 +21,7 @@ namespace Jellyfin.Api.Controllers /// /// User views controller. /// + [Route("")] public class UserViewsController : BaseJellyfinApiController { private readonly IUserManager _userManager; @@ -60,7 +61,7 @@ namespace Jellyfin.Api.Controllers /// Whether or not to include hidden content. /// User views returned. /// An containing the user views. - [HttpGet("/Users/{userId}/Views")] + [HttpGet("Users/{userId}/Views")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetUserViews( [FromRoute] Guid userId, @@ -122,7 +123,7 @@ namespace Jellyfin.Api.Controllers /// An containing the user view grouping options /// or a if user not found. /// - [HttpGet("/Users/{userId}/GroupingOptions")] + [HttpGet("Users/{userId}/GroupingOptions")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult> GetGroupingOptions([FromRoute] Guid userId) diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 8520dd163..76188f46d 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -30,6 +30,7 @@ namespace Jellyfin.Api.Controllers /// /// The video hls controller. /// + [Route("")] [Authorize(Policy = Policies.DefaultAuthorization)] public class VideoHlsController : BaseJellyfinApiController { @@ -158,7 +159,7 @@ namespace Jellyfin.Api.Controllers /// Optional. Whether to enable subtitles in the manifest. /// Hls live stream retrieved. /// A containing the hls file. - [HttpGet("/Videos/{itemId}/live.m3u8")] + [HttpGet("Videos/{itemId}/live.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetLiveHlsStream( [FromRoute] Guid itemId, @@ -271,7 +272,7 @@ namespace Jellyfin.Api.Controllers }; var cancellationTokenSource = new CancellationTokenSource(); - var state = await StreamingHelpers.GetStreamingState( + using var state = await StreamingHelpers.GetStreamingState( streamingRequest, Request, _authContext, -- cgit v1.2.3 From c5e9cf15f6476d96eadc1d32e38687c3a5a98a17 Mon Sep 17 00:00:00 2001 From: crobibero Date: Mon, 10 Aug 2020 07:53:32 -0600 Subject: Use proper IHttpContextAccessor --- Jellyfin.Api/Controllers/AudioController.cs | 2 +- Jellyfin.Api/Controllers/DynamicHlsController.cs | 6 ++-- Jellyfin.Api/Controllers/HlsSegmentController.cs | 4 +-- .../Controllers/UniversalAudioController.cs | 5 ++- Jellyfin.Api/Controllers/VideosController.cs | 7 ++--- Jellyfin.Api/Helpers/AudioHelper.cs | 36 ++++++++++++---------- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 23 +++++++------- Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs | 36 ++++++++++------------ 8 files changed, 59 insertions(+), 60 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index 107db9571..d300b4891 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -192,7 +192,7 @@ namespace Jellyfin.Api.Controllers StreamOptions = streamOptions }; - return await _audioHelper.GetAudioStream(this, _transcodingJobType, streamingRequest).ConfigureAwait(false); + return await _audioHelper.GetAudioStream(_transcodingJobType, streamingRequest).ConfigureAwait(false); } } } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 1a85a07b8..b4fe3bc8f 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -272,7 +272,7 @@ namespace Jellyfin.Api.Controllers EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming }; - return await _dynamicHlsHelper.GetMasterHlsPlaylist(this, _transcodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false); + return await _dynamicHlsHelper.GetMasterHlsPlaylist(_transcodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false); } /// @@ -439,7 +439,7 @@ namespace Jellyfin.Api.Controllers EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming }; - return await _dynamicHlsHelper.GetMasterHlsPlaylist(this, _transcodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false); + return await _dynamicHlsHelper.GetMasterHlsPlaylist(_transcodingJobType, streamingRequest, enableAdaptiveBitrateStreaming).ConfigureAwait(false); } /// @@ -1657,7 +1657,7 @@ namespace Jellyfin.Api.Controllers return Task.CompletedTask; }); - return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath)!, false, this); + return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath)!, false, HttpContext); } private long GetEndPositionTicks(StreamState state, int requestedIndex) diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index e4a6842bc..816252f80 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -61,7 +61,7 @@ namespace Jellyfin.Api.Controllers var file = segmentId + Path.GetExtension(Request.Path); file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); - return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, this); + return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, HttpContext); } /// @@ -148,7 +148,7 @@ namespace Jellyfin.Api.Controllers return Task.CompletedTask; }); - return FileStreamResponseHelpers.GetStaticFileResult(path, MimeTypes.GetMimeType(path)!, false, this); + return FileStreamResponseHelpers.GetStaticFileResult(path, MimeTypes.GetMimeType(path)!, false, HttpContext); } } } diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 2ea462488..2a788e03a 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -110,7 +110,6 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool breakOnNonKeyFrames, [FromQuery] bool enableRedirection = true) { - bool isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head; var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); _authorizationContext.GetAuthorizationInfo(Request).DeviceId = deviceId; @@ -222,7 +221,7 @@ namespace Jellyfin.Api.Controllers EnableAdaptiveBitrateStreaming = true }; - return await _dynamicHlsHelper.GetMasterHlsPlaylist(this, TranscodingJobType.Hls, dynamicHlsRequestDto, true) + return await _dynamicHlsHelper.GetMasterHlsPlaylist(TranscodingJobType.Hls, dynamicHlsRequestDto, true) .ConfigureAwait(false); } @@ -251,7 +250,7 @@ namespace Jellyfin.Api.Controllers Context = EncodingContext.Static }; - return await _audioHelper.GetAudioStream(this, TranscodingJobType.Progressive, audioStreamingDto).ConfigureAwait(false); + return await _audioHelper.GetAudioStream(TranscodingJobType.Progressive, audioStreamingDto).ConfigureAwait(false); } private DeviceProfile GetDeviceProfile( diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index fafa722c5..8eee51c2c 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -471,7 +471,7 @@ namespace Jellyfin.Api.Controllers StreamingHelpers.AddDlnaHeaders(state, Response.Headers, true, startTimeTicks, Request, _dlnaManager); using var httpClient = _httpClientFactory.CreateClient(); - return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, this, httpClient).ConfigureAwait(false); + return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, HttpContext).ConfigureAwait(false); } if (@static.HasValue && @static.Value && state.InputProtocol != MediaProtocol.File) @@ -507,7 +507,7 @@ namespace Jellyfin.Api.Controllers state.MediaPath, contentType, isHeadRequest, - this); + HttpContext); } // Need to start ffmpeg (because media can't be returned directly) @@ -517,10 +517,9 @@ namespace Jellyfin.Api.Controllers return await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, - this, + HttpContext, _transcodingJobHelper, ffmpegCommandLineArguments, - Request, _transcodingJobType, cancellationTokenSource).ConfigureAwait(false); } diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index 001028432..694e1f0dd 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -12,6 +12,7 @@ using MediaBrowser.Controller.Net; using MediaBrowser.Model.IO; using MediaBrowser.Model.MediaInfo; using MediaBrowser.Model.Net; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; @@ -35,6 +36,7 @@ namespace Jellyfin.Api.Helpers private readonly IDeviceManager _deviceManager; private readonly TranscodingJobHelper _transcodingJobHelper; private readonly IHttpClientFactory _httpClientFactory; + private readonly IHttpContextAccessor _httpContextAccessor; /// /// Initializes a new instance of the class. @@ -52,6 +54,7 @@ namespace Jellyfin.Api.Helpers /// Instance of the interface. /// Instance of . /// Instance of the interface. + /// Instance of the interface. public AudioHelper( IDlnaManager dlnaManager, IAuthorizationContext authContext, @@ -65,7 +68,8 @@ namespace Jellyfin.Api.Helpers IConfiguration configuration, IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, - IHttpClientFactory httpClientFactory) + IHttpClientFactory httpClientFactory, + IHttpContextAccessor httpContextAccessor) { _dlnaManager = dlnaManager; _authContext = authContext; @@ -80,26 +84,25 @@ namespace Jellyfin.Api.Helpers _deviceManager = deviceManager; _transcodingJobHelper = transcodingJobHelper; _httpClientFactory = httpClientFactory; + _httpContextAccessor = httpContextAccessor; } /// /// Get audio stream. /// - /// Requesting controller. /// Transcoding job type. /// Streaming controller.Request dto. /// A containing the resulting . public async Task GetAudioStream( - BaseJellyfinApiController controller, TranscodingJobType transcodingJobType, StreamingRequestDto streamingRequest) { - bool isHeadRequest = controller.Request.Method == System.Net.WebRequestMethods.Http.Head; + bool isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == System.Net.WebRequestMethods.Http.Head; var cancellationTokenSource = new CancellationTokenSource(); using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - controller.Request, + _httpContextAccessor.HttpContext.Request, _authContext, _mediaSourceManager, _userManager, @@ -118,30 +121,30 @@ namespace Jellyfin.Api.Helpers if (streamingRequest.Static && state.DirectStreamProvider != null) { - StreamingHelpers.AddDlnaHeaders(state, controller.Response.Headers, true, streamingRequest.StartTimeTicks, controller.Request, _dlnaManager); + StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); await new ProgressiveFileCopier(state.DirectStreamProvider, null, _transcodingJobHelper, CancellationToken.None) { AllowEndOfFile = false - }.WriteToAsync(controller.Response.Body, CancellationToken.None) + }.WriteToAsync(_httpContextAccessor.HttpContext.Response.Body, CancellationToken.None) .ConfigureAwait(false); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType - return controller.File(controller.Response.Body, MimeTypes.GetMimeType("file.ts")!); + return new FileStreamResult(_httpContextAccessor.HttpContext.Response.Body, MimeTypes.GetMimeType("file.ts")!); } // Static remote stream if (streamingRequest.Static && state.InputProtocol == MediaProtocol.Http) { - StreamingHelpers.AddDlnaHeaders(state, controller.Response.Headers, true, streamingRequest.StartTimeTicks, controller.Request, _dlnaManager); + StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, true, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); using var httpClient = _httpClientFactory.CreateClient(); - return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, controller, httpClient).ConfigureAwait(false); + return await FileStreamResponseHelpers.GetStaticRemoteStreamResult(state, isHeadRequest, httpClient, _httpContextAccessor.HttpContext).ConfigureAwait(false); } if (streamingRequest.Static && state.InputProtocol != MediaProtocol.File) { - return controller.BadRequest($"Input protocol {state.InputProtocol} cannot be streamed statically"); + return new BadRequestObjectResult($"Input protocol {state.InputProtocol} cannot be streamed statically"); } var outputPath = state.OutputFilePath; @@ -150,7 +153,7 @@ namespace Jellyfin.Api.Helpers var transcodingJob = _transcodingJobHelper.GetTranscodingJob(outputPath, TranscodingJobType.Progressive); var isTranscodeCached = outputPathExists && transcodingJob != null; - StreamingHelpers.AddDlnaHeaders(state, controller.Response.Headers, streamingRequest.Static || isTranscodeCached, streamingRequest.StartTimeTicks, controller.Request, _dlnaManager); + StreamingHelpers.AddDlnaHeaders(state, _httpContextAccessor.HttpContext.Response.Headers, streamingRequest.Static || isTranscodeCached, streamingRequest.StartTimeTicks, _httpContextAccessor.HttpContext.Request, _dlnaManager); // Static stream if (streamingRequest.Static) @@ -162,17 +165,17 @@ namespace Jellyfin.Api.Helpers await new ProgressiveFileCopier(state.MediaPath, null, _transcodingJobHelper, CancellationToken.None) { AllowEndOfFile = false - }.WriteToAsync(controller.Response.Body, CancellationToken.None) + }.WriteToAsync(_httpContextAccessor.HttpContext.Response.Body, CancellationToken.None) .ConfigureAwait(false); - return controller.File(controller.Response.Body, contentType); + return new FileStreamResult(_httpContextAccessor.HttpContext.Response.Body, contentType); } return FileStreamResponseHelpers.GetStaticFileResult( state.MediaPath, contentType, isHeadRequest, - controller); + _httpContextAccessor.HttpContext); } // Need to start ffmpeg (because media can't be returned directly) @@ -182,10 +185,9 @@ namespace Jellyfin.Api.Helpers return await FileStreamResponseHelpers.GetTranscodedFile( state, isHeadRequest, - controller, + _httpContextAccessor.HttpContext, _transcodingJobHelper, ffmpegCommandLineArguments, - controller.Request, transcodingJobType, cancellationTokenSource).ConfigureAwait(false); } diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 127d91430..6a8829d46 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -19,6 +19,7 @@ using MediaBrowser.Model.Dlna; using MediaBrowser.Model.Entities; using MediaBrowser.Model.IO; using MediaBrowser.Model.Net; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; @@ -45,6 +46,7 @@ namespace Jellyfin.Api.Helpers private readonly TranscodingJobHelper _transcodingJobHelper; private readonly INetworkManager _networkManager; private readonly ILogger _logger; + private readonly IHttpContextAccessor _httpContextAccessor; /// /// Initializes a new instance of the class. @@ -63,6 +65,7 @@ namespace Jellyfin.Api.Helpers /// Instance of . /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public DynamicHlsHelper( ILibraryManager libraryManager, IUserManager userManager, @@ -77,7 +80,8 @@ namespace Jellyfin.Api.Helpers IDeviceManager deviceManager, TranscodingJobHelper transcodingJobHelper, INetworkManager networkManager, - ILogger logger) + ILogger logger, + IHttpContextAccessor httpContextAccessor) { _libraryManager = libraryManager; _userManager = userManager; @@ -93,26 +97,24 @@ namespace Jellyfin.Api.Helpers _transcodingJobHelper = transcodingJobHelper; _networkManager = networkManager; _logger = logger; + _httpContextAccessor = httpContextAccessor; } /// /// Get master hls playlist. /// - /// Requesting controller. /// Transcoding job type. /// Streaming request dto. /// Enable adaptive bitrate streaming. /// A containing the resulting . public async Task GetMasterHlsPlaylist( - BaseJellyfinApiController controller, TranscodingJobType transcodingJobType, StreamingRequestDto streamingRequest, bool enableAdaptiveBitrateStreaming) { - var isHeadRequest = controller.Request.Method == WebRequestMethods.Http.Head; + var isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == WebRequestMethods.Http.Head; var cancellationTokenSource = new CancellationTokenSource(); return await GetMasterPlaylistInternal( - controller, streamingRequest, isHeadRequest, enableAdaptiveBitrateStreaming, @@ -121,7 +123,6 @@ namespace Jellyfin.Api.Helpers } private async Task GetMasterPlaylistInternal( - BaseJellyfinApiController controller, StreamingRequestDto streamingRequest, bool isHeadRequest, bool enableAdaptiveBitrateStreaming, @@ -130,7 +131,7 @@ namespace Jellyfin.Api.Helpers { using var state = await StreamingHelpers.GetStreamingState( streamingRequest, - controller.Request, + _httpContextAccessor.HttpContext.Request, _authContext, _mediaSourceManager, _userManager, @@ -147,7 +148,7 @@ namespace Jellyfin.Api.Helpers cancellationTokenSource.Token) .ConfigureAwait(false); - controller.Response.Headers.Add(HeaderNames.Expires, "0"); + _httpContextAccessor.HttpContext.Response.Headers.Add(HeaderNames.Expires, "0"); if (isHeadRequest) { return new FileContentResult(Array.Empty(), MimeTypes.GetMimeType("playlist.m3u8")); @@ -161,7 +162,7 @@ namespace Jellyfin.Api.Helpers var isLiveStream = state.IsSegmentedLiveStream; - var queryString = controller.Request.QueryString.ToString(); + var queryString = _httpContextAccessor.HttpContext.Request.QueryString.ToString(); // from universal audio service if (queryString.IndexOf("SegmentContainer", StringComparison.OrdinalIgnoreCase) == -1 && !string.IsNullOrWhiteSpace(state.Request.SegmentContainer)) @@ -197,12 +198,12 @@ namespace Jellyfin.Api.Helpers if (!string.IsNullOrWhiteSpace(subtitleGroup)) { - AddSubtitles(state, subtitleStreams, builder, controller.Request.HttpContext.User); + AddSubtitles(state, subtitleStreams, builder, _httpContextAccessor.HttpContext.Request.HttpContext.User); } AppendPlaylist(builder, state, playlistUrl, totalBitrate, subtitleGroup); - if (EnableAdaptiveBitrateStreaming(state, isLiveStream, enableAdaptiveBitrateStreaming, controller.Request.HttpContext.Connection.RemoteIpAddress)) + if (EnableAdaptiveBitrateStreaming(state, isLiveStream, enableAdaptiveBitrateStreaming, _httpContextAccessor.HttpContext.Request.HttpContext.Connection.RemoteIpAddress)) { var requestedVideoBitrate = state.VideoRequest == null ? 0 : state.VideoRequest.VideoBitRate ?? 0; diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs index a463783e0..e2f82b2de 100644 --- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs +++ b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs @@ -22,14 +22,14 @@ namespace Jellyfin.Api.Helpers /// /// The current . /// Whether the current request is a HTTP HEAD request so only the headers get returned. - /// The managing the response. /// The making the remote request. + /// The current http context. /// A containing the API response. public static async Task GetStaticRemoteStreamResult( StreamState state, bool isHeadRequest, - ControllerBase controller, - HttpClient httpClient) + HttpClient httpClient, + HttpContext httpContext) { if (state.RemoteHttpHeaders.TryGetValue(HeaderNames.UserAgent, out var useragent)) { @@ -39,14 +39,14 @@ namespace Jellyfin.Api.Helpers using var response = await httpClient.GetAsync(state.MediaPath).ConfigureAwait(false); var contentType = response.Content.Headers.ContentType.ToString(); - controller.Response.Headers[HeaderNames.AcceptRanges] = "none"; + httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none"; if (isHeadRequest) { - return controller.File(Array.Empty(), contentType); + return new FileContentResult(Array.Empty(), contentType); } - return controller.File(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), contentType); + return new FileStreamResult(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), contentType); } /// @@ -55,23 +55,23 @@ namespace Jellyfin.Api.Helpers /// The path to the file. /// The content type of the file. /// Whether the current request is a HTTP HEAD request so only the headers get returned. - /// The managing the response. + /// The current http context. /// An the file. public static ActionResult GetStaticFileResult( string path, string contentType, bool isHeadRequest, - ControllerBase controller) + HttpContext httpContext) { - controller.Response.ContentType = contentType; + httpContext.Response.ContentType = contentType; // 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 controller.NoContent(); + return new NoContentResult(); } - return controller.PhysicalFile(path, contentType); + return new PhysicalFileResult(path, contentType); } /// @@ -79,34 +79,32 @@ namespace Jellyfin.Api.Helpers /// /// The current . /// Whether the current request is a HTTP HEAD request so only the headers get returned. - /// The managing the response. + /// The current http context. /// The singleton. /// The command line arguments to start ffmpeg. - /// The starting the transcoding. /// The . /// The . /// A containing the transcoded file. public static async Task GetTranscodedFile( StreamState state, bool isHeadRequest, - ControllerBase controller, + HttpContext httpContext, TranscodingJobHelper transcodingJobHelper, string ffmpegCommandLineArguments, - HttpRequest request, TranscodingJobType transcodingJobType, CancellationTokenSource cancellationTokenSource) { // Use the command line args with a dummy playlist path var outputPath = state.OutputFilePath; - controller.Response.Headers[HeaderNames.AcceptRanges] = "none"; + httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none"; var contentType = state.GetMimeType(outputPath); // Headers only if (isHeadRequest) { - return controller.File(Array.Empty(), contentType); + return new FileContentResult(Array.Empty(), contentType); } var transcodingLock = transcodingJobHelper.GetTranscodingLock(outputPath); @@ -116,7 +114,7 @@ namespace Jellyfin.Api.Helpers TranscodingJobDto? job; if (!File.Exists(outputPath)) { - job = await transcodingJobHelper.StartFfMpeg(state, outputPath, ffmpegCommandLineArguments, request, transcodingJobType, cancellationTokenSource).ConfigureAwait(false); + job = await transcodingJobHelper.StartFfMpeg(state, outputPath, ffmpegCommandLineArguments, httpContext.Request, transcodingJobType, cancellationTokenSource).ConfigureAwait(false); } else { @@ -127,7 +125,7 @@ namespace Jellyfin.Api.Helpers var memoryStream = new MemoryStream(); await new ProgressiveFileCopier(outputPath, job, transcodingJobHelper, CancellationToken.None).WriteToAsync(memoryStream, CancellationToken.None).ConfigureAwait(false); memoryStream.Position = 0; - return controller.File(memoryStream, contentType); + return new FileStreamResult(memoryStream, contentType); } finally { -- cgit v1.2.3 From 2f33bee2a94f7175050f83d568f8bd65a01a86f8 Mon Sep 17 00:00:00 2001 From: crobibero Date: Tue, 1 Sep 2020 17:26:49 -0600 Subject: Set openapi schema type to file where possible --- .../Attributes/ProducesAudioFileAttribute.cs | 18 ++++++++ Jellyfin.Api/Attributes/ProducesFileAttribute.cs | 28 ++++++++++++ .../Attributes/ProducesImageFileAttribute.cs | 18 ++++++++ .../Attributes/ProducesPlaylistFileAttribute.cs | 18 ++++++++ .../Attributes/ProducesVideoFileAttribute.cs | 18 ++++++++ Jellyfin.Api/Controllers/AudioController.cs | 2 + .../Controllers/ConfigurationController.cs | 3 ++ Jellyfin.Api/Controllers/DashboardController.cs | 3 ++ Jellyfin.Api/Controllers/DlnaServerController.cs | 25 +++++++---- Jellyfin.Api/Controllers/DynamicHlsController.cs | 7 +++ Jellyfin.Api/Controllers/HlsSegmentController.cs | 4 ++ Jellyfin.Api/Controllers/ImageController.cs | 11 ++++- Jellyfin.Api/Controllers/ItemLookupController.cs | 10 +++-- Jellyfin.Api/Controllers/LibraryController.cs | 3 ++ Jellyfin.Api/Controllers/LiveTvController.cs | 4 ++ Jellyfin.Api/Controllers/MediaInfoController.cs | 2 + Jellyfin.Api/Controllers/SubtitleController.cs | 4 ++ Jellyfin.Api/Controllers/SystemController.cs | 9 ++-- .../Controllers/UniversalAudioController.cs | 2 + Jellyfin.Api/Controllers/UserController.cs | 6 +-- Jellyfin.Api/Controllers/VideoHlsController.cs | 2 + Jellyfin.Api/Controllers/VideosController.cs | 4 +- .../Extensions/ApiServiceCollectionExtensions.cs | 3 ++ Jellyfin.Server/Filters/FileResponseFilter.cs | 52 ++++++++++++++++++++++ 24 files changed, 232 insertions(+), 24 deletions(-) create mode 100644 Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs create mode 100644 Jellyfin.Api/Attributes/ProducesFileAttribute.cs create mode 100644 Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs create mode 100644 Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs create mode 100644 Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs create mode 100644 Jellyfin.Server/Filters/FileResponseFilter.cs (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs new file mode 100644 index 000000000..3adb700eb --- /dev/null +++ b/Jellyfin.Api/Attributes/ProducesAudioFileAttribute.cs @@ -0,0 +1,18 @@ +namespace Jellyfin.Api.Attributes +{ + /// + /// Produces file attribute of "image/*". + /// + public class ProducesAudioFileAttribute : ProducesFileAttribute + { + private const string ContentType = "audio/*"; + + /// + /// Initializes a new instance of the class. + /// + public ProducesAudioFileAttribute() + : base(ContentType) + { + } + } +} diff --git a/Jellyfin.Api/Attributes/ProducesFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesFileAttribute.cs new file mode 100644 index 000000000..62a576ede --- /dev/null +++ b/Jellyfin.Api/Attributes/ProducesFileAttribute.cs @@ -0,0 +1,28 @@ +using System; + +namespace Jellyfin.Api.Attributes +{ + /// + /// Internal produces image attribute. + /// + [AttributeUsage(AttributeTargets.Method)] + public class ProducesFileAttribute : Attribute + { + private readonly string[] _contentTypes; + + /// + /// Initializes a new instance of the class. + /// + /// Content types this endpoint produces. + public ProducesFileAttribute(params string[] contentTypes) + { + _contentTypes = contentTypes; + } + + /// + /// Gets the configured content types. + /// + /// the configured content types. + public string[] GetContentTypes() => _contentTypes; + } +} diff --git a/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs new file mode 100644 index 000000000..e15813676 --- /dev/null +++ b/Jellyfin.Api/Attributes/ProducesImageFileAttribute.cs @@ -0,0 +1,18 @@ +namespace Jellyfin.Api.Attributes +{ + /// + /// Produces file attribute of "image/*". + /// + public class ProducesImageFileAttribute : ProducesFileAttribute + { + private const string ContentType = "image/*"; + + /// + /// Initializes a new instance of the class. + /// + public ProducesImageFileAttribute() + : base(ContentType) + { + } + } +} diff --git a/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs new file mode 100644 index 000000000..5d928ab91 --- /dev/null +++ b/Jellyfin.Api/Attributes/ProducesPlaylistFileAttribute.cs @@ -0,0 +1,18 @@ +namespace Jellyfin.Api.Attributes +{ + /// + /// Produces file attribute of "image/*". + /// + public class ProducesPlaylistFileAttribute : ProducesFileAttribute + { + private const string ContentType = "application/x-mpegURL"; + + /// + /// Initializes a new instance of the class. + /// + public ProducesPlaylistFileAttribute() + : base(ContentType) + { + } + } +} diff --git a/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs b/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs new file mode 100644 index 000000000..d8b2856dc --- /dev/null +++ b/Jellyfin.Api/Attributes/ProducesVideoFileAttribute.cs @@ -0,0 +1,18 @@ +namespace Jellyfin.Api.Attributes +{ + /// + /// Produces file attribute of "video/*". + /// + public class ProducesVideoFileAttribute : ProducesFileAttribute + { + private const string ContentType = "video/*"; + + /// + /// Initializes a new instance of the class. + /// + public ProducesVideoFileAttribute() + : base(ContentType) + { + } + } +} diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index 802cd026e..48fd198b5 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Controller.MediaEncoding; @@ -88,6 +89,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("{itemId}/stream.{container}", Name = "HeadAudioStreamByContainer")] [HttpHead("{itemId}/stream", Name = "HeadAudioStream")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesAudioFile] public async Task GetAudioStream( [FromRoute] Guid itemId, [FromRoute] string? container, diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index 20fb0ec87..606e27970 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -1,6 +1,8 @@ using System.ComponentModel.DataAnnotations; +using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.ConfigurationDtos; using MediaBrowser.Common.Json; @@ -73,6 +75,7 @@ namespace Jellyfin.Api.Controllers /// Configuration. [HttpGet("Configuration/{key}")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesFile(MediaTypeNames.Application.Json)] public ActionResult GetNamedConfiguration([FromRoute] string? key) { return _configurationManager.GetConfiguration(key); diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index 33abe3ccd..c1bcc71e3 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Net.Mime; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Models; using MediaBrowser.Common.Plugins; using MediaBrowser.Controller; @@ -123,6 +125,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("web/ConfigurationPage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesFile(MediaTypeNames.Text.Html, "application/x-javascript")] public ActionResult GetDashboardConfigurationPage([FromQuery] string? name) { IPlugin? plugin = null; diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs index ee87d917b..dd91c7058 100644 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ b/Jellyfin.Api/Controllers/DlnaServerController.cs @@ -1,6 +1,8 @@ using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; +using System.Net.Mime; using System.Threading.Tasks; using Emby.Dlna; using Emby.Dlna.Main; @@ -17,8 +19,6 @@ namespace Jellyfin.Api.Controllers [Route("Dlna")] public class DlnaServerController : BaseJellyfinApiController { - private const string XMLContentType = "text/xml; charset=UTF-8"; - private readonly IDlnaManager _dlnaManager; private readonly IContentDirectory _contentDirectory; private readonly IConnectionManager _connectionManager; @@ -44,7 +44,8 @@ namespace Jellyfin.Api.Controllers /// An containing the description xml. [HttpGet("{serverId}/description")] [HttpGet("{serverId}/description.xml", Name = "GetDescriptionXml_2")] - [Produces(XMLContentType)] + [Produces(MediaTypeNames.Text.Xml)] + [ProducesFile(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetDescriptionXml([FromRoute] string serverId) { @@ -62,7 +63,8 @@ namespace Jellyfin.Api.Controllers /// An containing the dlna content directory xml. [HttpGet("{serverId}/ContentDirectory")] [HttpGet("{serverId}/ContentDirectory.xml", Name = "GetContentDirectory_2")] - [Produces(XMLContentType)] + [Produces(MediaTypeNames.Text.Xml)] + [ProducesFile(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] public ActionResult GetContentDirectory([FromRoute] string serverId) @@ -77,7 +79,8 @@ namespace Jellyfin.Api.Controllers /// Dlna media receiver registrar xml. [HttpGet("{serverId}/MediaReceiverRegistrar")] [HttpGet("{serverId}/MediaReceiverRegistrar.xml", Name = "GetMediaReceiverRegistrar_2")] - [Produces(XMLContentType)] + [Produces(MediaTypeNames.Text.Xml)] + [ProducesFile(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] public ActionResult GetMediaReceiverRegistrar([FromRoute] string serverId) @@ -92,7 +95,8 @@ namespace Jellyfin.Api.Controllers /// Dlna media receiver registrar xml. [HttpGet("{serverId}/ConnectionManager")] [HttpGet("{serverId}/ConnectionManager.xml", Name = "GetConnectionManager_2")] - [Produces(XMLContentType)] + [Produces(MediaTypeNames.Text.Xml)] + [ProducesFile(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] public ActionResult GetConnectionManager([FromRoute] string serverId) @@ -183,7 +187,9 @@ namespace Jellyfin.Api.Controllers /// Icon stream. [HttpGet("{serverId}/icons/{fileName}")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetIconId([FromRoute] string serverId, [FromRoute] string fileName) + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesImageFile] + public ActionResult GetIconId([FromRoute] string serverId, [FromRoute] string fileName) { return GetIconInternal(fileName); } @@ -194,12 +200,13 @@ namespace Jellyfin.Api.Controllers /// The icon filename. /// Icon stream. [HttpGet("icons/{fileName}")] - public ActionResult GetIcon([FromRoute] string fileName) + [ProducesImageFile] + public ActionResult GetIcon([FromRoute] string fileName) { return GetIconInternal(fileName); } - private ActionResult GetIconInternal(string fileName) + private ActionResult GetIconInternal(string fileName) { var icon = _dlnaManager.GetIcon(fileName); if (icon == null) diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index b115ac6cd..230bb8295 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.PlaybackDtos; @@ -166,6 +167,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/master.m3u8")] [HttpHead("Videos/{itemId}/master.m3u8", Name = "HeadMasterHlsVideoPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesPlaylistFile] public async Task GetMasterHlsVideoPlaylist( [FromRoute] Guid itemId, [FromRoute] string? container, @@ -333,6 +335,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Audio/{itemId}/master.m3u8")] [HttpHead("Audio/{itemId}/master.m3u8", Name = "HeadMasterHlsAudioPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesPlaylistFile] public async Task GetMasterHlsAudioPlaylist( [FromRoute] Guid itemId, [FromRoute] string? container, @@ -498,6 +501,7 @@ namespace Jellyfin.Api.Controllers /// A containing the audio file. [HttpGet("Videos/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesPlaylistFile] public async Task GetVariantHlsVideoPlaylist( [FromRoute] Guid itemId, [FromRoute] string? container, @@ -663,6 +667,7 @@ namespace Jellyfin.Api.Controllers /// A containing the audio file. [HttpGet("Audio/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesPlaylistFile] public async Task GetVariantHlsAudioPlaylist( [FromRoute] Guid itemId, [FromRoute] string? container, @@ -830,6 +835,7 @@ namespace Jellyfin.Api.Controllers /// A containing the audio file. [HttpGet("Videos/{itemId}/hls1/{playlistId}/{segmentId}.{container}")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesVideoFile] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsVideoSegment( [FromRoute] Guid itemId, @@ -999,6 +1005,7 @@ namespace Jellyfin.Api.Controllers /// A containing the audio file. [HttpGet("Audio/{itemId}/hls1/{playlistId}/{segmentId}.{container}")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesAudioFile] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsAudioSegment( [FromRoute] Guid itemId, diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 816252f80..e534be50a 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Configuration; @@ -54,6 +55,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Audio/{itemId}/hls/{segmentId}/stream.mp3", Name = "GetHlsAudioSegmentLegacyMp3")] [HttpGet("Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesAudioFile] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsAudioSegmentLegacy([FromRoute] string itemId, [FromRoute] string segmentId) { @@ -74,6 +76,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/hls/{playlistId}/stream.m3u8")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesPlaylistFile] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsPlaylistLegacy([FromRoute] string itemId, [FromRoute] string playlistId) { @@ -112,6 +115,7 @@ namespace Jellyfin.Api.Controllers // [Authenticated] [HttpGet("Videos/{itemId}/hls/{playlistId}/{segmentId}.{segmentContainer}")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesVideoFile] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsVideoSegmentLegacy( [FromRoute] string itemId, diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index a204fe35c..dbd569e07 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -6,6 +6,7 @@ using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Controller.Configuration; @@ -351,6 +352,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("Items/{itemId}/Images/{imageType}/{imageIndex?}", Name = "HeadItemImage_2")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesImageFile] public async Task GetItemImage( [FromRoute] Guid itemId, [FromRoute] ImageType imageType, @@ -507,6 +509,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("Artists/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadArtistImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesImageFile] public async Task GetArtistImage( [FromRoute] string name, [FromRoute] ImageType imageType, @@ -585,6 +588,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("Genres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadGenreImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesImageFile] public async Task GetGenreImage( [FromRoute] string name, [FromRoute] ImageType imageType, @@ -663,6 +667,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("MusicGenres/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadMusicGenreImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesImageFile] public async Task GetMusicGenreImage( [FromRoute] string name, [FromRoute] ImageType imageType, @@ -741,6 +746,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("Persons/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadPersonImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesImageFile] public async Task GetPersonImage( [FromRoute] string name, [FromRoute] ImageType imageType, @@ -819,6 +825,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("Studios/{name}/Images/{imageType}/{imageIndex?}", Name = "HeadStudioImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesImageFile] public async Task GetStudioImage( [FromRoute] string name, [FromRoute] ImageType imageType, @@ -897,6 +904,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("Users/{userId}/Images/{imageType}/{imageIndex?}", Name = "HeadUserImage")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesImageFile] public async Task GetUserImage( [FromRoute] Guid userId, [FromRoute] ImageType imageType, @@ -1297,8 +1305,7 @@ namespace Jellyfin.Api.Controllers return NoContent(); } - var stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read); - return File(stream, imageContentType); + return PhysicalFile(imagePath, imageContentType); } } } diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index afde4a433..2bde3443a 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -7,6 +7,7 @@ using System.Net.Mime; using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller; @@ -18,6 +19,7 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.IO; +using MediaBrowser.Model.Net; using MediaBrowser.Model.Providers; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -248,6 +250,8 @@ namespace Jellyfin.Api.Controllers /// The task result contains an containing the images file stream. /// [HttpGet("Items/RemoteSearch/Image")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesImageFile] public async Task GetRemoteSearchImage( [FromQuery, Required] string imageUrl, [FromQuery, Required] string providerName) @@ -274,10 +278,7 @@ namespace Jellyfin.Api.Controllers } await DownloadImage(providerName, imageUrl, urlHash, pointerCachePath).ConfigureAwait(false); - - // Read the pointer file again - await using var fileStream = System.IO.File.OpenRead(pointerCachePath); - return new FileStreamResult(fileStream, MediaTypeNames.Application.Octet); + return PhysicalFile(pointerCachePath, MimeTypes.GetMimeType(pointerCachePath)); } /// @@ -293,6 +294,7 @@ namespace Jellyfin.Api.Controllers /// [HttpPost("Items/RemoteSearch/Apply/{id}")] [Authorize(Policy = Policies.RequiresElevation)] + [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task ApplySearchCriteria( [FromRoute] Guid itemId, [FromBody, Required] RemoteSearchResult searchResult, diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index a30873e9e..8c727cc59 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -8,6 +8,7 @@ using System.Net; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; @@ -104,6 +105,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesFile("video/*", "audio/*")] public ActionResult GetFile([FromRoute] Guid itemId) { var item = _libraryManager.GetItemById(itemId); @@ -618,6 +620,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.Download)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesFile("video/*", "audio/*")] public async Task GetDownload([FromRoute] Guid itemId) { var item = _libraryManager.GetItemById(itemId); diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 3ccfc826d..07a176edd 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -9,6 +9,7 @@ using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; @@ -1067,6 +1068,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("ListingProviders/SchedulesDirect/Countries")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesFile(MediaTypeNames.Application.Json)] public async Task GetSchedulesDirectCountries() { var client = _httpClientFactory.CreateClient(); @@ -1175,6 +1177,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("LiveRecordings/{recordingId}/stream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesVideoFile] public async Task GetLiveRecordingFile([FromRoute] string recordingId) { var path = _liveTvManager.GetEmbyTvActiveRecordingPath(recordingId); @@ -1205,6 +1208,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("LiveStreamFiles/{streamId}/stream.{container}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] + [ProducesVideoFile] public async Task GetLiveStreamFile([FromRoute] string streamId, [FromRoute] string container) { var liveStreamInfo = await _mediaSourceManager.GetDirectStreamProviderByUniqueId(streamId, CancellationToken.None).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 1e154a039..2a204e650 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -4,6 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Net.Mime; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.MediaInfoDtos; @@ -286,6 +287,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [Produces(MediaTypeNames.Application.Octet)] + [ProducesFile(MediaTypeNames.Application.Octet)] public ActionResult GetBitrateTestBytes([FromQuery] int size = 102400) { const int MaxSize = 10_000_000; diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 988acccc3..a82431623 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -9,6 +9,7 @@ using System.Net.Mime; using System.Text; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -162,6 +163,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [Produces(MediaTypeNames.Application.Octet)] + [ProducesFile("text/*")] public async Task GetRemoteSubtitles([FromRoute, Required] string? id) { var result = await _subtitleManager.GetRemoteSubtitles(id, CancellationToken.None).ConfigureAwait(false); @@ -185,6 +187,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")] [HttpGet("Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}", Name = "GetSubtitle_2")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesFile("text/*")] public async Task GetSubtitle( [FromRoute, Required] Guid itemId, [FromRoute, Required] string? mediaSourceId, @@ -251,6 +254,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/subtitles.m3u8")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesPlaylistFile] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] public async Task GetSubtitlePlaylist( [FromRoute] Guid itemId, diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index bbfd163de..256f39d0c 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -3,8 +3,10 @@ using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; using System.Linq; +using System.Net.Mime; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Net; @@ -190,16 +192,13 @@ namespace Jellyfin.Api.Controllers [HttpGet("Logs/Log")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesFile(MediaTypeNames.Text.Plain)] public ActionResult GetLogFile([FromQuery, Required] string? name) { var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath) .First(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)); - // For older files, assume fully static - var fileShare = file.LastWriteTimeUtc < DateTime.UtcNow.AddHours(-1) ? FileShare.Read : FileShare.ReadWrite; - - FileStream stream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, fileShare); - return File(stream, "text/plain"); + return File(file.FullName, MediaTypeNames.Text.Plain); } /// diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index b13cf9fa5..b00653d9b 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.StreamingDtos; @@ -91,6 +92,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status302Found)] + [ProducesAudioFile] public async Task GetUniversalAudioStream( [FromRoute] Guid itemId, [FromRoute] string? container, diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index d67f82219..746710475 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -125,7 +125,7 @@ namespace Jellyfin.Api.Controllers /// Deletes a user. /// /// The user id. - /// User deleted. + /// User deleted. /// User not found. /// A indicating success or a if the user was not found. [HttpDelete("{userId}")] @@ -255,7 +255,7 @@ namespace Jellyfin.Api.Controllers /// /// The user id. /// The request. - /// Password successfully reset. + /// Password successfully reset. /// User is not allowed to update the password. /// User not found. /// A indicating success or a or a on failure. @@ -313,7 +313,7 @@ namespace Jellyfin.Api.Controllers /// /// The user id. /// The request. - /// Password successfully reset. + /// Password successfully reset. /// User is not allowed to update the password. /// User not found. /// A indicating success or a or a on failure. diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 76188f46d..92e82727e 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.PlaybackDtos; @@ -161,6 +162,7 @@ namespace Jellyfin.Api.Controllers /// A containing the hls file. [HttpGet("Videos/{itemId}/live.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesPlaylistFile] public async Task GetLiveHlsStream( [FromRoute] Guid itemId, [FromQuery] string? container, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index f42810c94..18023664b 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Net.Http; using System.Threading; using System.Threading.Tasks; +using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; @@ -159,7 +160,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success, or a if the video doesn't exist. [HttpDelete("{itemId}/AlternateSources")] [Authorize(Policy = Policies.RequiresElevation)] - [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DeleteAlternateSources([FromRoute] Guid itemId) { @@ -326,6 +327,7 @@ namespace Jellyfin.Api.Controllers [HttpHead("{itemId}/{stream=stream}.{container?}", Name = "HeadVideoStream_2")] [HttpHead("{itemId}/stream", Name = "HeadVideoStream")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesVideoFile] public async Task GetVideoStream( [FromRoute] Guid itemId, [FromRoute] string? container, diff --git a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs index 0160a05f9..04b611123 100644 --- a/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs +++ b/Jellyfin.Server/Extensions/ApiServiceCollectionExtensions.cs @@ -16,6 +16,7 @@ using Jellyfin.Api.Auth.LocalAccessPolicy; using Jellyfin.Api.Auth.RequiresElevationPolicy; using Jellyfin.Api.Constants; using Jellyfin.Api.Controllers; +using Jellyfin.Server.Filters; using Jellyfin.Server.Formatters; using Jellyfin.Server.Models; using MediaBrowser.Common; @@ -249,6 +250,8 @@ namespace Jellyfin.Server.Extensions // TODO - remove when all types are supported in System.Text.Json c.AddSwaggerTypeMappings(); + + c.OperationFilter(); }); } diff --git a/Jellyfin.Server/Filters/FileResponseFilter.cs b/Jellyfin.Server/Filters/FileResponseFilter.cs new file mode 100644 index 000000000..8ea35c281 --- /dev/null +++ b/Jellyfin.Server/Filters/FileResponseFilter.cs @@ -0,0 +1,52 @@ +using System; +using System.Linq; +using Jellyfin.Api.Attributes; +using Microsoft.OpenApi.Models; +using Swashbuckle.AspNetCore.SwaggerGen; + +namespace Jellyfin.Server.Filters +{ + /// + public class FileResponseFilter : IOperationFilter + { + private const string SuccessCode = "200"; + private static readonly OpenApiMediaType _openApiMediaType = new OpenApiMediaType + { + Schema = new OpenApiSchema + { + Type = "file" + } + }; + + /// + public void Apply(OpenApiOperation operation, OperationFilterContext context) + { + foreach (var attribute in context.ApiDescription.ActionDescriptor.EndpointMetadata) + { + if (attribute is ProducesFileAttribute producesFileAttribute) + { + // Get operation response values. + var (_, value) = operation.Responses + .FirstOrDefault(o => o.Key.Equals(SuccessCode, StringComparison.Ordinal)); + + // Operation doesn't have a response. + if (value == null) + { + continue; + } + + // Clear existing responses. + value.Content.Clear(); + + // Add all content-types as file. + foreach (var contentType in producesFileAttribute.GetContentTypes()) + { + value.Content.Add(contentType, _openApiMediaType); + } + + break; + } + } + } + } +} -- cgit v1.2.3 From 59d47ec3f52d8592f6a2aac405ee214cfda10081 Mon Sep 17 00:00:00 2001 From: crobibero Date: Sat, 5 Sep 2020 17:07:25 -0600 Subject: Make all FromRoute required --- Jellyfin.Api/Controllers/AlbumsController.cs | 5 +- Jellyfin.Api/Controllers/ArtistsController.cs | 3 +- Jellyfin.Api/Controllers/AudioController.cs | 5 +- Jellyfin.Api/Controllers/ChannelsController.cs | 4 +- Jellyfin.Api/Controllers/CollectionController.cs | 4 +- .../Controllers/ConfigurationController.cs | 4 +- .../Controllers/DisplayPreferencesController.cs | 4 +- Jellyfin.Api/Controllers/DlnaController.cs | 6 +- Jellyfin.Api/Controllers/DlnaServerController.cs | 18 +-- Jellyfin.Api/Controllers/DynamicHlsController.cs | 32 ++--- Jellyfin.Api/Controllers/GenresController.cs | 2 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 12 +- Jellyfin.Api/Controllers/ImageController.cs | 156 ++++++++++----------- Jellyfin.Api/Controllers/InstantMixController.cs | 12 +- Jellyfin.Api/Controllers/ItemLookupController.cs | 4 +- Jellyfin.Api/Controllers/ItemRefreshController.cs | 2 +- Jellyfin.Api/Controllers/ItemUpdateController.cs | 6 +- Jellyfin.Api/Controllers/ItemsController.cs | 4 +- Jellyfin.Api/Controllers/LibraryController.cs | 16 +-- Jellyfin.Api/Controllers/LiveTvController.cs | 26 ++-- Jellyfin.Api/Controllers/MediaInfoController.cs | 4 +- Jellyfin.Api/Controllers/MusicGenresController.cs | 2 +- Jellyfin.Api/Controllers/PackageController.cs | 6 +- Jellyfin.Api/Controllers/PersonsController.cs | 3 +- Jellyfin.Api/Controllers/PlaylistsController.cs | 28 ++-- Jellyfin.Api/Controllers/PlaystateController.cs | 18 +-- Jellyfin.Api/Controllers/PluginsController.cs | 10 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 6 +- .../Controllers/ScheduledTasksController.cs | 2 +- Jellyfin.Api/Controllers/SessionController.cs | 6 +- Jellyfin.Api/Controllers/StudiosController.cs | 2 +- Jellyfin.Api/Controllers/SubtitleController.cs | 16 +-- Jellyfin.Api/Controllers/SuggestionsController.cs | 2 +- .../Controllers/UniversalAudioController.cs | 4 +- Jellyfin.Api/Controllers/UserController.cs | 14 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 20 +-- Jellyfin.Api/Controllers/UserViewsController.cs | 4 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 8 +- Jellyfin.Api/Controllers/YearsController.cs | 2 +- 40 files changed, 244 insertions(+), 240 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/AlbumsController.cs b/Jellyfin.Api/Controllers/AlbumsController.cs index 190d4bd07..9b68d056f 100644 --- a/Jellyfin.Api/Controllers/AlbumsController.cs +++ b/Jellyfin.Api/Controllers/AlbumsController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; @@ -52,7 +53,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Albums/{albumId}/Similar")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarAlbums( - [FromRoute] string albumId, + [FromRoute][Required] string albumId, [FromQuery] Guid? userId, [FromQuery] string? excludeArtistIds, [FromQuery] int? limit) @@ -84,7 +85,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Artists/{artistId}/Similar")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarArtists( - [FromRoute] string artistId, + [FromRoute][Required] string artistId, [FromQuery] Guid? userId, [FromQuery] string? excludeArtistIds, [FromQuery] int? limit) diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index 3f72830cd..b3dad14f3 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; @@ -469,7 +470,7 @@ namespace Jellyfin.Api.Controllers /// An containing the artist. [HttpGet("{name}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetArtistByName([FromRoute] string name, [FromQuery] Guid? userId) + public ActionResult GetArtistByName([FromRoute][Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions().AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index 802cd026e..a81efe966 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.StreamingDtos; @@ -89,8 +90,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("{itemId}/stream", Name = "HeadAudioStream")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetAudioStream( - [FromRoute] Guid itemId, - [FromRoute] string? container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs index bdd7dfd96..93d9a9d00 100644 --- a/Jellyfin.Api/Controllers/ChannelsController.cs +++ b/Jellyfin.Api/Controllers/ChannelsController.cs @@ -90,7 +90,7 @@ namespace Jellyfin.Api.Controllers /// Channel features returned. /// An containing the channel features. [HttpGet("{channelId}/Features")] - public ActionResult GetChannelFeatures([FromRoute] string channelId) + public ActionResult GetChannelFeatures([FromRoute][Required] string channelId) { return _channelManager.GetChannelFeatures(channelId); } @@ -114,7 +114,7 @@ namespace Jellyfin.Api.Controllers /// [HttpGet("{channelId}/Items")] public async Task>> GetChannelItems( - [FromRoute] Guid channelId, + [FromRoute][Required] Guid channelId, [FromQuery] Guid? folderId, [FromQuery] Guid? userId, [FromQuery] int? startIndex, diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index c5910d6e8..0b1f655da 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task AddToCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task AddToCollection([FromRoute][Required] Guid collectionId, [FromQuery, Required] string? itemIds) { await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true); return NoContent(); @@ -103,7 +103,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpDelete("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task RemoveFromCollection([FromRoute] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task RemoveFromCollection([FromRoute][Required] Guid collectionId, [FromQuery, Required] string? itemIds) { await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false); return NoContent(); diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index 20fb0ec87..f13b6d38d 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers /// Configuration. [HttpGet("Configuration/{key}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetNamedConfiguration([FromRoute] string? key) + public ActionResult GetNamedConfiguration([FromRoute][Required] string? key) { return _configurationManager.GetConfiguration(key); } @@ -87,7 +87,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Configuration/{key}")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task UpdateNamedConfiguration([FromRoute] string? key) + public async Task UpdateNamedConfiguration([FromRoute][Required] string? key) { var configurationType = _configurationManager.GetConfigurationType(key); var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType, _serializerOptions).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs index c3b67eec3..6422a45fd 100644 --- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs +++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs @@ -43,7 +43,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")] public ActionResult GetDisplayPreferences( - [FromRoute] string? displayPreferencesId, + [FromRoute][Required] string? displayPreferencesId, [FromQuery] [Required] Guid userId, [FromQuery] [Required] string? client) { @@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")] public ActionResult UpdateDisplayPreferences( - [FromRoute] string? displayPreferencesId, + [FromRoute][Required] string? displayPreferencesId, [FromQuery, Required] Guid userId, [FromQuery, Required] string? client, [FromBody, Required] DisplayPreferencesDto displayPreferences) diff --git a/Jellyfin.Api/Controllers/DlnaController.cs b/Jellyfin.Api/Controllers/DlnaController.cs index 397299a73..69c948174 100644 --- a/Jellyfin.Api/Controllers/DlnaController.cs +++ b/Jellyfin.Api/Controllers/DlnaController.cs @@ -59,7 +59,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Profiles/{profileId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetProfile([FromRoute] string profileId) + public ActionResult GetProfile([FromRoute][Required] string profileId) { var profile = _dlnaManager.GetProfile(profileId); if (profile == null) @@ -80,7 +80,7 @@ namespace Jellyfin.Api.Controllers [HttpDelete("Profiles/{profileId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteProfile([FromRoute] string profileId) + public ActionResult DeleteProfile([FromRoute][Required] string profileId) { var existingDeviceProfile = _dlnaManager.GetProfile(profileId); if (existingDeviceProfile == null) @@ -117,7 +117,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Profiles/{profileId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateProfile([FromRoute] string profileId, [FromBody] DeviceProfile deviceProfile) + public ActionResult UpdateProfile([FromRoute][Required] string profileId, [FromBody] DeviceProfile deviceProfile) { var existingDeviceProfile = _dlnaManager.GetProfile(profileId); if (existingDeviceProfile == null) diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs index 9ebd89819..832fcc8c6 100644 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ b/Jellyfin.Api/Controllers/DlnaServerController.cs @@ -45,7 +45,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{serverId}/description.xml", Name = "GetDescriptionXml_2")] [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetDescriptionXml([FromRoute] string serverId) + public ActionResult GetDescriptionXml([FromRoute][Required] string serverId) { var url = GetAbsoluteUri(); var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase)); @@ -65,7 +65,7 @@ namespace Jellyfin.Api.Controllers [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetContentDirectory([FromRoute] string serverId) + public ActionResult GetContentDirectory([FromRoute][Required] string serverId) { return Ok(_contentDirectory.GetServiceXml()); } @@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetMediaReceiverRegistrar([FromRoute] string serverId) + public ActionResult GetMediaReceiverRegistrar([FromRoute][Required] string serverId) { return Ok(_mediaReceiverRegistrar.GetServiceXml()); } @@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetConnectionManager([FromRoute] string serverId) + public ActionResult GetConnectionManager([FromRoute][Required] string serverId) { return Ok(_connectionManager.GetServiceXml()); } @@ -108,7 +108,7 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Control response. [HttpPost("{serverId}/ContentDirectory/Control")] - public async Task> ProcessContentDirectoryControlRequest([FromRoute] string serverId) + public async Task> ProcessContentDirectoryControlRequest([FromRoute][Required] string serverId) { return await ProcessControlRequestInternalAsync(serverId, Request.Body, _contentDirectory).ConfigureAwait(false); } @@ -119,7 +119,7 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Control response. [HttpPost("{serverId}/ConnectionManager/Control")] - public async Task> ProcessConnectionManagerControlRequest([FromRoute] string serverId) + public async Task> ProcessConnectionManagerControlRequest([FromRoute][Required] string serverId) { return await ProcessControlRequestInternalAsync(serverId, Request.Body, _connectionManager).ConfigureAwait(false); } @@ -130,7 +130,7 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Control response. [HttpPost("{serverId}/MediaReceiverRegistrar/Control")] - public async Task> ProcessMediaReceiverRegistrarControlRequest([FromRoute] string serverId) + public async Task> ProcessMediaReceiverRegistrarControlRequest([FromRoute][Required] string serverId) { return await ProcessControlRequestInternalAsync(serverId, Request.Body, _mediaReceiverRegistrar).ConfigureAwait(false); } @@ -185,7 +185,7 @@ namespace Jellyfin.Api.Controllers /// Icon stream. [HttpGet("{serverId}/icons/{fileName}")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetIconId([FromRoute] string serverId, [FromRoute] string fileName) + public ActionResult GetIconId([FromRoute][Required] string serverId, [FromRoute][Required] string fileName) { return GetIconInternal(fileName); } @@ -196,7 +196,7 @@ namespace Jellyfin.Api.Controllers /// The icon filename. /// Icon stream. [HttpGet("icons/{fileName}")] - public ActionResult GetIcon([FromRoute] string fileName) + public ActionResult GetIcon([FromRoute][Required] string fileName) { return GetIconInternal(fileName); } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 0c884d58d..ec711ce34 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -167,8 +167,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("Videos/{itemId}/master.m3u8", Name = "HeadMasterHlsVideoPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsVideoPlaylist( - [FromRoute] Guid itemId, - [FromRoute] string? container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -334,8 +334,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("Audio/{itemId}/master.m3u8", Name = "HeadMasterHlsAudioPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsAudioPlaylist( - [FromRoute] Guid itemId, - [FromRoute] string? container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -499,8 +499,8 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVariantHlsVideoPlaylist( - [FromRoute] Guid itemId, - [FromRoute] string? container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -664,8 +664,8 @@ namespace Jellyfin.Api.Controllers [HttpGet("Audio/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVariantHlsAudioPlaylist( - [FromRoute] Guid itemId, - [FromRoute] string? container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -832,10 +832,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsVideoSegment( - [FromRoute] Guid itemId, - [FromRoute] string playlistId, - [FromRoute] int segmentId, - [FromRoute] string container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string playlistId, + [FromRoute][Required] int segmentId, + [FromRoute][Required] string container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -1001,10 +1001,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsAudioSegment( - [FromRoute] Guid itemId, - [FromRoute] string playlistId, - [FromRoute] int segmentId, - [FromRoute] string container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string playlistId, + [FromRoute][Required] int segmentId, + [FromRoute][Required] string container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index 55ad71200..230aff417 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -260,7 +260,7 @@ namespace Jellyfin.Api.Controllers /// An containing the genre. [HttpGet("{genreName}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetGenre([FromRoute] string genreName, [FromQuery] Guid? userId) + public ActionResult GetGenre([FromRoute][Required] string genreName, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() .AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 816252f80..304b5ce82 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] - public ActionResult GetHlsAudioSegmentLegacy([FromRoute] string itemId, [FromRoute] string segmentId) + public ActionResult GetHlsAudioSegmentLegacy([FromRoute][Required] string itemId, [FromRoute][Required] string segmentId) { // TODO: Deprecate with new iOS app var file = segmentId + Path.GetExtension(Request.Path); @@ -75,7 +75,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] - public ActionResult GetHlsPlaylistLegacy([FromRoute] string itemId, [FromRoute] string playlistId) + public ActionResult GetHlsPlaylistLegacy([FromRoute][Required] string itemId, [FromRoute][Required] string playlistId) { var file = playlistId + Path.GetExtension(Request.Path); file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); @@ -114,10 +114,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsVideoSegmentLegacy( - [FromRoute] string itemId, - [FromRoute] string playlistId, - [FromRoute] string segmentId, - [FromRoute] string segmentContainer) + [FromRoute][Required] string itemId, + [FromRoute][Required] string playlistId, + [FromRoute][Required] string segmentId, + [FromRoute][Required] string segmentContainer) { var file = segmentId + Path.GetExtension(Request.Path); var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath(); diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index a204fe35c..3cde4062d 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -90,9 +90,9 @@ namespace Jellyfin.Api.Controllers [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] public async Task PostUserImage( - [FromRoute] Guid userId, - [FromRoute] ImageType imageType, - [FromRoute] int? index = null) + [FromRoute][Required] Guid userId, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] int? index = null) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) { @@ -137,9 +137,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult DeleteUserImage( - [FromRoute] Guid userId, - [FromRoute] ImageType imageType, - [FromRoute] int? index = null) + [FromRoute][Required] Guid userId, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] int? index = null) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) { @@ -175,9 +175,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DeleteItemImage( - [FromRoute] Guid itemId, - [FromRoute] ImageType imageType, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] Guid itemId, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -205,9 +205,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] public async Task SetItemImage( - [FromRoute] Guid itemId, - [FromRoute] ImageType imageType, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] Guid itemId, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -238,9 +238,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task UpdateItemImageIndex( - [FromRoute] Guid itemId, - [FromRoute] ImageType imageType, - [FromRoute] int imageIndex, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] int imageIndex, [FromQuery] int newIndex) { var item = _libraryManager.GetItemById(itemId); @@ -264,7 +264,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task>> GetItemImageInfos([FromRoute] Guid itemId) + public async Task>> GetItemImageInfos([FromRoute][Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -352,10 +352,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage( - [FromRoute] Guid itemId, - [FromRoute] ImageType imageType, - [FromRoute] int? maxWidth, - [FromRoute] int? maxHeight, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] int? maxWidth, + [FromRoute][Required] int? maxHeight, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -368,7 +368,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -430,23 +430,23 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage2( - [FromRoute] Guid itemId, - [FromRoute] ImageType imageType, - [FromRoute] int? maxWidth, - [FromRoute] int? maxHeight, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] int? maxWidth, + [FromRoute][Required] int? maxHeight, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, - [FromRoute] string tag, + [FromRoute][Required] string tag, [FromQuery] bool? cropWhitespace, - [FromRoute] string format, + [FromRoute][Required] string format, [FromQuery] bool? addPlayedIndicator, - [FromRoute] double? percentPlayed, - [FromRoute] int? unplayedCount, + [FromRoute][Required] double? percentPlayed, + [FromRoute][Required] int? unplayedCount, [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -508,14 +508,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetArtistImage( - [FromRoute] string name, - [FromRoute] ImageType imageType, - [FromRoute] string tag, - [FromRoute] string format, - [FromRoute] int? maxWidth, - [FromRoute] int? maxHeight, - [FromRoute] double? percentPlayed, - [FromRoute] int? unplayedCount, + [FromRoute][Required] string name, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] string tag, + [FromRoute][Required] string format, + [FromRoute][Required] int? maxWidth, + [FromRoute][Required] int? maxHeight, + [FromRoute][Required] double? percentPlayed, + [FromRoute][Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -524,7 +524,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetArtist(name); if (item == null) @@ -586,14 +586,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetGenreImage( - [FromRoute] string name, - [FromRoute] ImageType imageType, - [FromRoute] string tag, - [FromRoute] string format, - [FromRoute] int? maxWidth, - [FromRoute] int? maxHeight, - [FromRoute] double? percentPlayed, - [FromRoute] int? unplayedCount, + [FromRoute][Required] string name, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] string tag, + [FromRoute][Required] string format, + [FromRoute][Required] int? maxWidth, + [FromRoute][Required] int? maxHeight, + [FromRoute][Required] double? percentPlayed, + [FromRoute][Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -602,7 +602,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetGenre(name); if (item == null) @@ -664,14 +664,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetMusicGenreImage( - [FromRoute] string name, - [FromRoute] ImageType imageType, - [FromRoute] string tag, - [FromRoute] string format, - [FromRoute] int? maxWidth, - [FromRoute] int? maxHeight, - [FromRoute] double? percentPlayed, - [FromRoute] int? unplayedCount, + [FromRoute][Required] string name, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] string tag, + [FromRoute][Required] string format, + [FromRoute][Required] int? maxWidth, + [FromRoute][Required] int? maxHeight, + [FromRoute][Required] double? percentPlayed, + [FromRoute][Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -680,7 +680,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetMusicGenre(name); if (item == null) @@ -742,14 +742,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetPersonImage( - [FromRoute] string name, - [FromRoute] ImageType imageType, - [FromRoute] string tag, - [FromRoute] string format, - [FromRoute] int? maxWidth, - [FromRoute] int? maxHeight, - [FromRoute] double? percentPlayed, - [FromRoute] int? unplayedCount, + [FromRoute][Required] string name, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] string tag, + [FromRoute][Required] string format, + [FromRoute][Required] int? maxWidth, + [FromRoute][Required] int? maxHeight, + [FromRoute][Required] double? percentPlayed, + [FromRoute][Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -758,7 +758,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetPerson(name); if (item == null) @@ -820,14 +820,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetStudioImage( - [FromRoute] string name, - [FromRoute] ImageType imageType, - [FromRoute] string tag, - [FromRoute] string format, - [FromRoute] int? maxWidth, - [FromRoute] int? maxHeight, - [FromRoute] double? percentPlayed, - [FromRoute] int? unplayedCount, + [FromRoute][Required] string name, + [FromRoute][Required] ImageType imageType, + [FromRoute][Required] string tag, + [FromRoute][Required] string format, + [FromRoute][Required] int? maxWidth, + [FromRoute][Required] int? maxHeight, + [FromRoute][Required] double? percentPlayed, + [FromRoute][Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -836,7 +836,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var item = _libraryManager.GetStudio(name); if (item == null) @@ -898,8 +898,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetUserImage( - [FromRoute] Guid userId, - [FromRoute] ImageType imageType, + [FromRoute][Required] Guid userId, + [FromRoute][Required] ImageType imageType, [FromQuery] string? tag, [FromQuery] string? format, [FromQuery] int? maxWidth, @@ -914,7 +914,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute] int? imageIndex = null) + [FromRoute][Required] int? imageIndex = null) { var user = _userManager.GetUserById(userId); if (user == null) diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 73bd30c4d..11f2b2495 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -64,7 +64,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Songs/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromSong( - [FromRoute] Guid id, + [FromRoute][Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -101,7 +101,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Albums/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromAlbum( - [FromRoute] Guid id, + [FromRoute][Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -138,7 +138,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Playlists/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromPlaylist( - [FromRoute] Guid id, + [FromRoute][Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -211,7 +211,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Artists/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromArtists( - [FromRoute] Guid id, + [FromRoute][Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -248,7 +248,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("MusicGenres/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromMusicGenres( - [FromRoute] Guid id, + [FromRoute][Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -285,7 +285,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Items/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromItem( - [FromRoute] Guid id, + [FromRoute][Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index afde4a433..f1169f3d2 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -72,7 +72,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetExternalIdInfos([FromRoute] Guid itemId) + public ActionResult> GetExternalIdInfos([FromRoute][Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -294,7 +294,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/RemoteSearch/Apply/{id}")] [Authorize(Policy = Policies.RequiresElevation)] public async Task ApplySearchCriteria( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromBody, Required] RemoteSearchResult searchResult, [FromQuery] bool replaceAllImages = true) { diff --git a/Jellyfin.Api/Controllers/ItemRefreshController.cs b/Jellyfin.Api/Controllers/ItemRefreshController.cs index 3f5d305c1..0d1e02a78 100644 --- a/Jellyfin.Api/Controllers/ItemRefreshController.cs +++ b/Jellyfin.Api/Controllers/ItemRefreshController.cs @@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult Post( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] MetadataRefreshMode metadataRefreshMode = MetadataRefreshMode.None, [FromQuery] MetadataRefreshMode imageRefreshMode = MetadataRefreshMode.None, [FromQuery] bool replaceAllMetadata = false, diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index ec52f4996..0d064fffb 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task UpdateItem([FromRoute] Guid itemId, [FromBody, Required] BaseItemDto request) + public async Task UpdateItem([FromRoute][Required] Guid itemId, [FromBody, Required] BaseItemDto request) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -141,7 +141,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Items/{itemId}/MetadataEditor")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetMetadataEditorInfo([FromRoute] Guid itemId) + public ActionResult GetMetadataEditorInfo([FromRoute][Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); @@ -195,7 +195,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}/ContentType")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateItemContentType([FromRoute] Guid itemId, [FromQuery, Required] string? contentType) + public ActionResult UpdateItemContentType([FromRoute][Required] Guid itemId, [FromQuery, Required] string? contentType) { var item = _libraryManager.GetItemById(itemId); if (item == null) diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index f9273bad6..cc8051365 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -144,7 +144,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{uId}/Items", Name = "GetItems_2")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetItems( - [FromRoute] Guid? uId, + [FromRoute][Required] Guid? uId, [FromQuery] Guid? userId, [FromQuery] string? maxOfficialRating, [FromQuery] bool? hasThemeSong, @@ -529,7 +529,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Items/Resume")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetResumeItems( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromQuery] int? startIndex, [FromQuery] int? limit, [FromQuery] string? searchTerm, diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index a30873e9e..ac28fd6ca 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -104,7 +104,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetFile([FromRoute] Guid itemId) + public ActionResult GetFile([FromRoute][Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -144,7 +144,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetThemeSongs( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] bool inheritFromParent = false) { @@ -210,7 +210,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetThemeVideos( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] bool inheritFromParent = false) { @@ -275,7 +275,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetThemeMedia( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] bool inheritFromParent = false) { @@ -438,7 +438,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetAncestors([FromRoute] Guid itemId, [FromQuery] Guid? userId) + public ActionResult> GetAncestors([FromRoute][Required] Guid itemId, [FromQuery] Guid? userId) { var item = _libraryManager.GetItemById(itemId); @@ -555,7 +555,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Library/Movies/Updated")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult PostUpdatedMovies([FromRoute] string? tmdbId, [FromRoute] string? imdbId) + public ActionResult PostUpdatedMovies([FromRoute][Required] string? tmdbId, [FromRoute][Required] string? imdbId) { var movies = _libraryManager.GetItemList(new InternalItemsQuery { @@ -618,7 +618,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.Download)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetDownload([FromRoute] Guid itemId) + public async Task GetDownload([FromRoute][Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -687,7 +687,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarItems( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] string? excludeArtistIds, [FromQuery] Guid? userId, [FromQuery] int? limit, diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index eace0f911..e086e9029 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -209,7 +209,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Channels/{channelId}")] [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult GetChannel([FromRoute] Guid channelId, [FromQuery] Guid? userId) + public ActionResult GetChannel([FromRoute][Required] Guid channelId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId.Value) @@ -406,7 +406,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Recordings/{recordingId}")] [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult GetRecording([FromRoute] Guid recordingId, [FromQuery] Guid? userId) + public ActionResult GetRecording([FromRoute][Required] Guid recordingId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId.Value) @@ -428,7 +428,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Tuners/{tunerId}/Reset")] [ProducesResponseType(StatusCodes.Status204NoContent)] [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult ResetTuner([FromRoute] string tunerId) + public ActionResult ResetTuner([FromRoute][Required] string tunerId) { AssertUserCanManageLiveTv(); _liveTvManager.ResetTuner(tunerId, CancellationToken.None); @@ -744,7 +744,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetProgram( - [FromRoute] string programId, + [FromRoute][Required] string programId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) @@ -765,7 +765,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteRecording([FromRoute] Guid recordingId) + public ActionResult DeleteRecording([FromRoute][Required] Guid recordingId) { AssertUserCanManageLiveTv(); @@ -792,7 +792,7 @@ namespace Jellyfin.Api.Controllers [HttpDelete("Timers/{timerId}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CancelTimer([FromRoute] string timerId) + public async Task CancelTimer([FromRoute][Required] string timerId) { AssertUserCanManageLiveTv(); await _liveTvManager.CancelTimer(timerId).ConfigureAwait(false); @@ -810,7 +810,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] - public async Task UpdateTimer([FromRoute] string timerId, [FromBody] TimerInfoDto timerInfo) + public async Task UpdateTimer([FromRoute][Required] string timerId, [FromBody] TimerInfoDto timerInfo) { AssertUserCanManageLiveTv(); await _liveTvManager.UpdateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); @@ -844,7 +844,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task> GetSeriesTimer([FromRoute] string timerId) + public async Task> GetSeriesTimer([FromRoute][Required] string timerId) { var timer = await _liveTvManager.GetSeriesTimer(timerId, CancellationToken.None).ConfigureAwait(false); if (timer == null) @@ -884,7 +884,7 @@ namespace Jellyfin.Api.Controllers [HttpDelete("SeriesTimers/{timerId}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CancelSeriesTimer([FromRoute] string timerId) + public async Task CancelSeriesTimer([FromRoute][Required] string timerId) { AssertUserCanManageLiveTv(); await _liveTvManager.CancelSeriesTimer(timerId).ConfigureAwait(false); @@ -902,7 +902,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] - public async Task UpdateSeriesTimer([FromRoute] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo) + public async Task UpdateSeriesTimer([FromRoute][Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo) { AssertUserCanManageLiveTv(); await _liveTvManager.UpdateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); @@ -934,7 +934,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Obsolete("This endpoint is obsolete.")] - public ActionResult GetRecordingGroup([FromRoute] Guid? groupId) + public ActionResult GetRecordingGroup([FromRoute][Required] Guid? groupId) { return NotFound(); } @@ -1176,7 +1176,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("LiveRecordings/{recordingId}/stream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetLiveRecordingFile([FromRoute] string recordingId) + public async Task GetLiveRecordingFile([FromRoute][Required] string recordingId) { var path = _liveTvManager.GetEmbyTvActiveRecordingPath(recordingId); @@ -1206,7 +1206,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("LiveStreamFiles/{streamId}/stream.{container}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetLiveStreamFile([FromRoute] string streamId, [FromRoute] string container) + public async Task GetLiveStreamFile([FromRoute][Required] string streamId, [FromRoute][Required] string container) { var liveStreamInfo = await _mediaSourceManager.GetDirectStreamProviderByUniqueId(streamId, CancellationToken.None).ConfigureAwait(false); if (liveStreamInfo == null) diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 1e154a039..8bb0ace15 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers /// A containing a with the playback information. [HttpGet("Items/{itemId}/PlaybackInfo")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetPlaybackInfo([FromRoute] Guid itemId, [FromQuery, Required] Guid? userId) + public async Task> GetPlaybackInfo([FromRoute][Required] Guid itemId, [FromQuery, Required] Guid? userId) { return await _mediaInfoHelper.GetPlaybackInfo( itemId, @@ -100,7 +100,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}/PlaybackInfo")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPostedPlaybackInfo( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] long? maxStreamingBitrate, [FromQuery] long? startTimeTicks, diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 0d319137a..493386e93 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -258,7 +258,7 @@ namespace Jellyfin.Api.Controllers /// An containing a with the music genre. [HttpGet("{genreName}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetMusicGenre([FromRoute] string genreName, [FromQuery] Guid? userId) + public ActionResult GetMusicGenre([FromRoute][Required] string genreName, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions().AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index 3d6a87909..ea85e1909 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Packages/{name}")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPackageInfo( - [FromRoute] [Required] string? name, + [FromRoute][Required] string? name, [FromQuery] string? assemblyGuid) { var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Policy = Policies.RequiresElevation)] public async Task InstallPackage( - [FromRoute] [Required] string? name, + [FromRoute][Required] string? name, [FromQuery] string? assemblyGuid, [FromQuery] string? version) { @@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult CancelPackageInstallation( - [FromRoute] [Required] Guid packageId) + [FromRoute][Required] Guid packageId) { _installationManager.CancelInstallation(packageId); return NoContent(); diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index b6ccec666..be5fb7f7c 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Constants; @@ -262,7 +263,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{name}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetPerson([FromRoute] string name, [FromQuery] Guid? userId) + public ActionResult GetPerson([FromRoute][Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() .AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index f4c6a9253..07bb108e3 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task AddToPlaylist( - [FromRoute] Guid playlistId, + [FromRoute][Required] Guid playlistId, [FromQuery] string? ids, [FromQuery] Guid? userId) { @@ -103,9 +103,9 @@ namespace Jellyfin.Api.Controllers [HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task MoveItem( - [FromRoute] string? playlistId, - [FromRoute] string? itemId, - [FromRoute] int newIndex) + [FromRoute][Required] string? playlistId, + [FromRoute][Required] string? itemId, + [FromRoute][Required] int newIndex) { await _playlistManager.MoveItemAsync(playlistId, itemId, newIndex).ConfigureAwait(false); return NoContent(); @@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers /// An on success. [HttpDelete("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task RemoveFromPlaylist([FromRoute] string? playlistId, [FromQuery] string? entryIds) + public async Task RemoveFromPlaylist([FromRoute][Required] string? playlistId, [FromQuery] string? entryIds) { await _playlistManager.RemoveFromPlaylistAsync(playlistId, RequestHelpers.Split(entryIds, ',', true)).ConfigureAwait(false); return NoContent(); @@ -143,15 +143,15 @@ namespace Jellyfin.Api.Controllers /// The original playlist items. [HttpGet("{playlistId}/Items")] public ActionResult> GetPlaylistItems( - [FromRoute] Guid playlistId, - [FromRoute] Guid userId, - [FromRoute] int? startIndex, - [FromRoute] int? limit, - [FromRoute] string? fields, - [FromRoute] bool? enableImages, - [FromRoute] bool? enableUserData, - [FromRoute] int? imageTypeLimit, - [FromRoute] string? enableImageTypes) + [FromRoute][Required] Guid playlistId, + [FromRoute][Required] Guid userId, + [FromRoute][Required] int? startIndex, + [FromRoute][Required] int? limit, + [FromRoute][Required] string? fields, + [FromRoute][Required] bool? enableImages, + [FromRoute][Required] bool? enableUserData, + [FromRoute][Required] int? imageTypeLimit, + [FromRoute][Required] string? enableImageTypes) { var playlist = (Playlist)_libraryManager.GetItemById(playlistId); if (playlist == null) diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 22f2ca5c3..797c5aa36 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -71,8 +71,8 @@ namespace Jellyfin.Api.Controllers [HttpPost("Users/{userId}/PlayedItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult MarkPlayedItem( - [FromRoute] Guid userId, - [FromRoute] Guid itemId, + [FromRoute][Required] Guid userId, + [FromRoute][Required] Guid itemId, [FromQuery] DateTime? datePlayed) { var user = _userManager.GetUserById(userId); @@ -96,7 +96,7 @@ namespace Jellyfin.Api.Controllers /// A containing the . [HttpDelete("Users/{userId}/PlayedItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult MarkUnplayedItem([FromRoute] Guid userId, [FromRoute] Guid itemId) + public ActionResult MarkUnplayedItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { var user = _userManager.GetUserById(userId); var session = RequestHelpers.GetSession(_sessionManager, _authContext, Request); @@ -195,8 +195,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackStart( - [FromRoute] Guid userId, - [FromRoute] Guid itemId, + [FromRoute][Required] Guid userId, + [FromRoute][Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] int? audioStreamIndex, [FromQuery] int? subtitleStreamIndex, @@ -245,8 +245,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackProgress( - [FromRoute] Guid userId, - [FromRoute] Guid itemId, + [FromRoute][Required] Guid userId, + [FromRoute][Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] long? positionTicks, [FromQuery] int? audioStreamIndex, @@ -297,8 +297,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackStopped( - [FromRoute] Guid userId, - [FromRoute] Guid itemId, + [FromRoute][Required] Guid userId, + [FromRoute][Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] string? nextMediaType, [FromQuery] long? positionTicks, diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index a82f2621a..d0de1a422 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -64,7 +64,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UninstallPlugin([FromRoute] Guid pluginId) + public ActionResult UninstallPlugin([FromRoute][Required] Guid pluginId) { var plugin = _appHost.Plugins.FirstOrDefault(p => p.Id == pluginId); if (plugin == null) @@ -86,7 +86,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{pluginId}/Configuration")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetPluginConfiguration([FromRoute] Guid pluginId) + public ActionResult GetPluginConfiguration([FromRoute][Required] Guid pluginId) { if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin)) { @@ -113,7 +113,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("{pluginId}/Configuration")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task UpdatePluginConfiguration([FromRoute] Guid pluginId) + public async Task UpdatePluginConfiguration([FromRoute][Required] Guid pluginId) { if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin)) { @@ -172,7 +172,7 @@ namespace Jellyfin.Api.Controllers [Obsolete("This endpoint should not be used.")] [HttpPost("RegistrationRecords/{name}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetRegistrationStatus([FromRoute] string? name) + public ActionResult GetRegistrationStatus([FromRoute][Required] string? name) { return new MBRegistrationRecord { @@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers [Obsolete("Paid plugins are not supported")] [HttpGet("Registrations/{name}")] [ProducesResponseType(StatusCodes.Status501NotImplemented)] - public ActionResult GetRegistration([FromRoute] string? name) + public 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. diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 81aefd15c..597d3f2f6 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -70,7 +70,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> GetRemoteImages( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] ImageType? type, [FromQuery] int? startIndex, [FromQuery] int? limit, @@ -133,7 +133,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetRemoteImageProviders([FromRoute] Guid itemId) + public ActionResult> GetRemoteImageProviders([FromRoute][Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -209,7 +209,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DownloadRemoteImage( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery, Required] ImageType type, [FromQuery] string? imageUrl) { diff --git a/Jellyfin.Api/Controllers/ScheduledTasksController.cs b/Jellyfin.Api/Controllers/ScheduledTasksController.cs index e672070c0..ea6288de0 100644 --- a/Jellyfin.Api/Controllers/ScheduledTasksController.cs +++ b/Jellyfin.Api/Controllers/ScheduledTasksController.cs @@ -94,7 +94,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Running/{taskId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult StartTask([FromRoute] string? taskId) + public ActionResult StartTask([FromRoute][Required] string? taskId) { var task = _taskManager.ScheduledTasks.FirstOrDefault(o => o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase)); diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index ba8d51598..4f0f241c6 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -336,7 +336,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult AddUserToSession( [FromRoute, Required] string? sessionId, - [FromRoute] Guid userId) + [FromRoute][Required] Guid userId) { _sessionManager.AddAdditionalUser(sessionId, userId); return NoContent(); @@ -353,8 +353,8 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult RemoveUserFromSession( - [FromRoute] string? sessionId, - [FromRoute] Guid userId) + [FromRoute][Required] string? sessionId, + [FromRoute][Required] Guid userId) { _sessionManager.RemoveAdditionalUser(sessionId, userId); return NoContent(); diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index 6f2787d93..b3bb06500 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -259,7 +259,7 @@ namespace Jellyfin.Api.Controllers /// An containing the studio. [HttpGet("{name}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetStudio([FromRoute] string name, [FromQuery] Guid? userId) + public ActionResult GetStudio([FromRoute][Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions().AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 988acccc3..1096a06d2 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -86,8 +86,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult DeleteSubtitle( - [FromRoute] Guid itemId, - [FromRoute] int index) + [FromRoute][Required] Guid itemId, + [FromRoute][Required] int index) { var item = _libraryManager.GetItemById(itemId); @@ -112,7 +112,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task>> SearchRemoteSubtitles( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromRoute, Required] string? language, [FromQuery] bool? isPerfectMatch) { @@ -132,7 +132,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task DownloadRemoteSubtitles( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromRoute, Required] string? subtitleId) { var video = (Video)_libraryManager.GetItemById(itemId); @@ -193,7 +193,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] long? endPositionTicks, [FromQuery] bool copyTimestamps = false, [FromQuery] bool addVttTimeMap = false, - [FromRoute] long startPositionTicks = 0) + [FromRoute][Required] long startPositionTicks = 0) { if (string.Equals(format, "js", StringComparison.OrdinalIgnoreCase)) { @@ -253,9 +253,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] public async Task GetSubtitlePlaylist( - [FromRoute] Guid itemId, - [FromRoute] int index, - [FromRoute] string? mediaSourceId, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] int index, + [FromRoute][Required] string? mediaSourceId, [FromQuery, Required] int segmentLength) { var item = (Video)_libraryManager.GetItemById(itemId); diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index 42db6b6a1..4fff3cd3e 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Suggestions")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSuggestions( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromQuery] string? mediaType, [FromQuery] string? type, [FromQuery] int? startIndex, diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index b13cf9fa5..d57f23d9c 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -92,8 +92,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status302Found)] public async Task GetUniversalAudioStream( - [FromRoute] Guid itemId, - [FromRoute] string? container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string? container, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, [FromQuery] Guid? userId, diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index d67f82219..a9cab9cde 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -108,7 +108,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.IgnoreParentalControl)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetUserById([FromRoute] Guid userId) + public ActionResult GetUserById([FromRoute][Required] Guid userId) { var user = _userManager.GetUserById(userId); @@ -132,7 +132,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteUser([FromRoute] Guid userId) + public ActionResult DeleteUser([FromRoute][Required] Guid userId) { var user = _userManager.GetUserById(userId); _sessionManager.RevokeUserTokens(user.Id, null); @@ -265,7 +265,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task UpdateUserPassword( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromBody] UpdateUserPassword request) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) @@ -323,7 +323,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult UpdateUserEasyPassword( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromBody] UpdateUserEasyPassword request) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) @@ -365,7 +365,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task UpdateUser( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromBody] UserDto updateUser) { if (updateUser == null) @@ -409,7 +409,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult UpdateUserPolicy( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromBody] UserPolicy newPolicy) { if (newPolicy == null) @@ -464,7 +464,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult UpdateUserConfiguration( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromBody] UserConfiguration userConfig) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false)) diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index f55ff6f3d..809fbf43a 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -70,7 +70,7 @@ namespace Jellyfin.Api.Controllers /// An containing the d item. [HttpGet("Users/{userId}/Items/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetItem([FromRoute] Guid userId, [FromRoute] Guid itemId) + public async Task> GetItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -93,7 +93,7 @@ namespace Jellyfin.Api.Controllers /// An containing the user's root folder. [HttpGet("Users/{userId}/Items/Root")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetRootFolder([FromRoute] Guid userId) + public ActionResult GetRootFolder([FromRoute][Required] Guid userId) { var user = _userManager.GetUserById(userId); var item = _libraryManager.GetUserRootFolder(); @@ -110,7 +110,7 @@ namespace Jellyfin.Api.Controllers /// An containing the intros to play. [HttpGet("Users/{userId}/Items/{itemId}/Intros")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task>> GetIntros([FromRoute] Guid userId, [FromRoute] Guid itemId) + public async Task>> GetIntros([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -138,7 +138,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpPost("Users/{userId}/FavoriteItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult MarkFavoriteItem([FromRoute] Guid userId, [FromRoute] Guid itemId) + public ActionResult MarkFavoriteItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { return MarkFavorite(userId, itemId, true); } @@ -152,7 +152,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpDelete("Users/{userId}/FavoriteItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult UnmarkFavoriteItem([FromRoute] Guid userId, [FromRoute] Guid itemId) + public ActionResult UnmarkFavoriteItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { return MarkFavorite(userId, itemId, false); } @@ -166,7 +166,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpDelete("Users/{userId}/Items/{itemId}/Rating")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult DeleteUserItemRating([FromRoute] Guid userId, [FromRoute] Guid itemId) + public ActionResult DeleteUserItemRating([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { return UpdateUserItemRatingInternal(userId, itemId, null); } @@ -181,7 +181,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpPost("Users/{userId}/Items/{itemId}/Rating")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult UpdateUserItemRating([FromRoute] Guid userId, [FromRoute] Guid itemId, [FromQuery] bool? likes) + public ActionResult UpdateUserItemRating([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId, [FromQuery] bool? likes) { return UpdateUserItemRatingInternal(userId, itemId, likes); } @@ -195,7 +195,7 @@ namespace Jellyfin.Api.Controllers /// The items local trailers. [HttpGet("Users/{userId}/Items/{itemId}/LocalTrailers")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetLocalTrailers([FromRoute] Guid userId, [FromRoute] Guid itemId) + public ActionResult> GetLocalTrailers([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -230,7 +230,7 @@ namespace Jellyfin.Api.Controllers /// An containing the special features. [HttpGet("Users/{userId}/Items/{itemId}/SpecialFeatures")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetSpecialFeatures([FromRoute] Guid userId, [FromRoute] Guid itemId) + public ActionResult> GetSpecialFeatures([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -264,7 +264,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Items/Latest")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetLatestMedia( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromQuery] Guid? parentId, [FromQuery] string? fields, [FromQuery] string? includeItemTypes, diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 6df7cc779..fb78707f8 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -64,7 +64,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Views")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetUserViews( - [FromRoute] Guid userId, + [FromRoute][Required] Guid userId, [FromQuery] bool? includeExternalContent, [FromQuery] string? presetViews, [FromQuery] bool includeHidden = false) @@ -126,7 +126,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/GroupingOptions")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetGroupingOptions([FromRoute] Guid userId) + public ActionResult> GetGroupingOptions([FromRoute][Required] Guid userId) { var user = _userManager.GetUserById(userId); if (user == null) diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 76188f46d..77f21fcf3 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -162,7 +162,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/live.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetLiveHlsStream( - [FromRoute] Guid itemId, + [FromRoute][Required] Guid itemId, [FromQuery] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 83b03f965..224cc7b72 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{itemId}/AdditionalParts")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetAdditionalPart([FromRoute] Guid itemId, [FromQuery] Guid? userId) + public ActionResult> GetAdditionalPart([FromRoute][Required] Guid itemId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId.Value) @@ -162,7 +162,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task DeleteAlternateSources([FromRoute] Guid itemId) + public async Task DeleteAlternateSources([FromRoute][Required] Guid itemId) { var video = (Video)_libraryManager.GetItemById(itemId); @@ -331,8 +331,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("{itemId}/stream", Name = "HeadVideoStream")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVideoStream( - [FromRoute] Guid itemId, - [FromRoute] string? container, + [FromRoute][Required] Guid itemId, + [FromRoute][Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index eb91ac23e..620edf905 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{year}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetYear([FromRoute] int year, [FromQuery] Guid? userId) + public ActionResult GetYear([FromRoute][Required] int year, [FromQuery] Guid? userId) { var item = _libraryManager.GetYear(year); if (item == null) -- cgit v1.2.3 From b64108923aebd0f3e5a960462ad4cb2dbd74b6cc Mon Sep 17 00:00:00 2001 From: crobibero Date: Sat, 5 Sep 2020 17:11:44 -0600 Subject: Add missing references --- Jellyfin.Api/Controllers/ChannelsController.cs | 1 + Jellyfin.Api/Controllers/DlnaController.cs | 1 + Jellyfin.Api/Controllers/DlnaServerController.cs | 1 + Jellyfin.Api/Controllers/GenresController.cs | 1 + Jellyfin.Api/Controllers/HlsSegmentController.cs | 1 + Jellyfin.Api/Controllers/ImageController.cs | 1 + Jellyfin.Api/Controllers/ItemRefreshController.cs | 1 + Jellyfin.Api/Controllers/ItemsController.cs | 1 + Jellyfin.Api/Controllers/LiveTvController.cs | 1 + Jellyfin.Api/Controllers/MusicGenresController.cs | 1 + Jellyfin.Api/Controllers/PlaystateController.cs | 1 + Jellyfin.Api/Controllers/StudiosController.cs | 1 + Jellyfin.Api/Controllers/SuggestionsController.cs | 1 + Jellyfin.Api/Controllers/UniversalAudioController.cs | 1 + Jellyfin.Api/Controllers/UserLibraryController.cs | 1 + Jellyfin.Api/Controllers/UserViewsController.cs | 1 + Jellyfin.Api/Controllers/VideoHlsController.cs | 1 + Jellyfin.Api/Controllers/YearsController.cs | 1 + 18 files changed, 18 insertions(+) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs index 93d9a9d00..36dff2ad3 100644 --- a/Jellyfin.Api/Controllers/ChannelsController.cs +++ b/Jellyfin.Api/Controllers/ChannelsController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/Jellyfin.Api/Controllers/DlnaController.cs b/Jellyfin.Api/Controllers/DlnaController.cs index 69c948174..e6f0fb41e 100644 --- a/Jellyfin.Api/Controllers/DlnaController.cs +++ b/Jellyfin.Api/Controllers/DlnaController.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using Jellyfin.Api.Constants; using MediaBrowser.Controller.Dlna; using MediaBrowser.Model.Dlna; diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs index 832fcc8c6..2f93ca2c2 100644 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ b/Jellyfin.Api/Controllers/DlnaServerController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Net.Mime; diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index 230aff417..53be16370 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 304b5ce82..58c583d09 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 3cde4062d..e28957c9b 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; diff --git a/Jellyfin.Api/Controllers/ItemRefreshController.cs b/Jellyfin.Api/Controllers/ItemRefreshController.cs index 0d1e02a78..87086c681 100644 --- a/Jellyfin.Api/Controllers/ItemRefreshController.cs +++ b/Jellyfin.Api/Controllers/ItemRefreshController.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.ComponentModel.DataAnnotations; using Jellyfin.Api.Constants; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index cc8051365..170606b11 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index e086e9029..fb3f0f5f5 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 493386e93..df97c0ab9 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 797c5aa36..091f884d2 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index b3bb06500..0208ebfbb 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index 4fff3cd3e..52593b1ce 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -1,4 +1,5 @@ using System; +using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index d57f23d9c..a3678454f 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using System.Threading.Tasks; diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 809fbf43a..f93e80393 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading; using System.Threading.Tasks; diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index fb78707f8..8582a5a21 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Extensions; diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 77f21fcf3..cf667bf43 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Globalization; using System.IO; using System.Threading; diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 620edf905..b83b09c35 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; -- cgit v1.2.3 From 29fc882037162b8c7a79557556be9d535e94779f Mon Sep 17 00:00:00 2001 From: crobibero Date: Sun, 6 Sep 2020 09:07:27 -0600 Subject: merge all attributes --- Jellyfin.Api/Controllers/AlbumsController.cs | 4 +- Jellyfin.Api/Controllers/ArtistsController.cs | 2 +- Jellyfin.Api/Controllers/AudioController.cs | 4 +- Jellyfin.Api/Controllers/ChannelsController.cs | 4 +- Jellyfin.Api/Controllers/CollectionController.cs | 4 +- .../Controllers/ConfigurationController.cs | 4 +- .../Controllers/DisplayPreferencesController.cs | 4 +- Jellyfin.Api/Controllers/DlnaController.cs | 6 +- Jellyfin.Api/Controllers/DlnaServerController.cs | 18 +-- Jellyfin.Api/Controllers/DynamicHlsController.cs | 32 ++--- Jellyfin.Api/Controllers/GenresController.cs | 2 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 12 +- Jellyfin.Api/Controllers/ImageController.cs | 156 ++++++++++----------- Jellyfin.Api/Controllers/InstantMixController.cs | 12 +- Jellyfin.Api/Controllers/ItemLookupController.cs | 4 +- Jellyfin.Api/Controllers/ItemRefreshController.cs | 2 +- Jellyfin.Api/Controllers/ItemUpdateController.cs | 6 +- Jellyfin.Api/Controllers/ItemsController.cs | 4 +- Jellyfin.Api/Controllers/LibraryController.cs | 16 +-- Jellyfin.Api/Controllers/LiveTvController.cs | 26 ++-- Jellyfin.Api/Controllers/MediaInfoController.cs | 4 +- Jellyfin.Api/Controllers/MusicGenresController.cs | 2 +- Jellyfin.Api/Controllers/PackageController.cs | 6 +- Jellyfin.Api/Controllers/PersonsController.cs | 2 +- Jellyfin.Api/Controllers/PlaylistsController.cs | 28 ++-- Jellyfin.Api/Controllers/PlaystateController.cs | 18 +-- Jellyfin.Api/Controllers/PluginsController.cs | 10 +- Jellyfin.Api/Controllers/RemoteImageController.cs | 6 +- .../Controllers/ScheduledTasksController.cs | 2 +- Jellyfin.Api/Controllers/SessionController.cs | 6 +- Jellyfin.Api/Controllers/StudiosController.cs | 2 +- Jellyfin.Api/Controllers/SubtitleController.cs | 16 +-- Jellyfin.Api/Controllers/SuggestionsController.cs | 2 +- .../Controllers/UniversalAudioController.cs | 4 +- Jellyfin.Api/Controllers/UserController.cs | 14 +- Jellyfin.Api/Controllers/UserLibraryController.cs | 20 +-- Jellyfin.Api/Controllers/UserViewsController.cs | 4 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 8 +- Jellyfin.Api/Controllers/YearsController.cs | 2 +- 40 files changed, 240 insertions(+), 240 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/AlbumsController.cs b/Jellyfin.Api/Controllers/AlbumsController.cs index 9b68d056f..357f646a2 100644 --- a/Jellyfin.Api/Controllers/AlbumsController.cs +++ b/Jellyfin.Api/Controllers/AlbumsController.cs @@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Albums/{albumId}/Similar")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarAlbums( - [FromRoute][Required] string albumId, + [FromRoute, Required] string albumId, [FromQuery] Guid? userId, [FromQuery] string? excludeArtistIds, [FromQuery] int? limit) @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Artists/{artistId}/Similar")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarArtists( - [FromRoute][Required] string artistId, + [FromRoute, Required] string artistId, [FromQuery] Guid? userId, [FromQuery] string? excludeArtistIds, [FromQuery] int? limit) diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index b3dad14f3..d38214116 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -470,7 +470,7 @@ namespace Jellyfin.Api.Controllers /// An containing the artist. [HttpGet("{name}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetArtistByName([FromRoute][Required] string name, [FromQuery] Guid? userId) + public ActionResult GetArtistByName([FromRoute, Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions().AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index a81efe966..3bec43720 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -90,8 +90,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("{itemId}/stream", Name = "HeadAudioStream")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetAudioStream( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string? container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, diff --git a/Jellyfin.Api/Controllers/ChannelsController.cs b/Jellyfin.Api/Controllers/ChannelsController.cs index 36dff2ad3..33a969f85 100644 --- a/Jellyfin.Api/Controllers/ChannelsController.cs +++ b/Jellyfin.Api/Controllers/ChannelsController.cs @@ -91,7 +91,7 @@ namespace Jellyfin.Api.Controllers /// Channel features returned. /// An containing the channel features. [HttpGet("{channelId}/Features")] - public ActionResult GetChannelFeatures([FromRoute][Required] string channelId) + public ActionResult GetChannelFeatures([FromRoute, Required] string channelId) { return _channelManager.GetChannelFeatures(channelId); } @@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers /// [HttpGet("{channelId}/Items")] public async Task>> GetChannelItems( - [FromRoute][Required] Guid channelId, + [FromRoute, Required] Guid channelId, [FromQuery] Guid? folderId, [FromQuery] Guid? userId, [FromQuery] int? startIndex, diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 0b1f655da..f78690b06 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpPost("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task AddToCollection([FromRoute][Required] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task AddToCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string? itemIds) { await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true); return NoContent(); @@ -103,7 +103,7 @@ namespace Jellyfin.Api.Controllers /// A indicating success. [HttpDelete("{collectionId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task RemoveFromCollection([FromRoute][Required] Guid collectionId, [FromQuery, Required] string? itemIds) + public async Task RemoveFromCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string? itemIds) { await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false); return NoContent(); diff --git a/Jellyfin.Api/Controllers/ConfigurationController.cs b/Jellyfin.Api/Controllers/ConfigurationController.cs index f13b6d38d..5fd4c712a 100644 --- a/Jellyfin.Api/Controllers/ConfigurationController.cs +++ b/Jellyfin.Api/Controllers/ConfigurationController.cs @@ -73,7 +73,7 @@ namespace Jellyfin.Api.Controllers /// Configuration. [HttpGet("Configuration/{key}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetNamedConfiguration([FromRoute][Required] string? key) + public ActionResult GetNamedConfiguration([FromRoute, Required] string? key) { return _configurationManager.GetConfiguration(key); } @@ -87,7 +87,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Configuration/{key}")] [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task UpdateNamedConfiguration([FromRoute][Required] string? key) + public async Task UpdateNamedConfiguration([FromRoute, Required] string? key) { var configurationType = _configurationManager.GetConfigurationType(key); var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType, _serializerOptions).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs index 6422a45fd..6bb7b1910 100644 --- a/Jellyfin.Api/Controllers/DisplayPreferencesController.cs +++ b/Jellyfin.Api/Controllers/DisplayPreferencesController.cs @@ -43,7 +43,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")] public ActionResult GetDisplayPreferences( - [FromRoute][Required] string? displayPreferencesId, + [FromRoute, Required] string? displayPreferencesId, [FromQuery] [Required] Guid userId, [FromQuery] [Required] string? client) { @@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")] public ActionResult UpdateDisplayPreferences( - [FromRoute][Required] string? displayPreferencesId, + [FromRoute, Required] string? displayPreferencesId, [FromQuery, Required] Guid userId, [FromQuery, Required] string? client, [FromBody, Required] DisplayPreferencesDto displayPreferences) diff --git a/Jellyfin.Api/Controllers/DlnaController.cs b/Jellyfin.Api/Controllers/DlnaController.cs index e6f0fb41e..052a6aff2 100644 --- a/Jellyfin.Api/Controllers/DlnaController.cs +++ b/Jellyfin.Api/Controllers/DlnaController.cs @@ -60,7 +60,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Profiles/{profileId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetProfile([FromRoute][Required] string profileId) + public ActionResult GetProfile([FromRoute, Required] string profileId) { var profile = _dlnaManager.GetProfile(profileId); if (profile == null) @@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers [HttpDelete("Profiles/{profileId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteProfile([FromRoute][Required] string profileId) + public ActionResult DeleteProfile([FromRoute, Required] string profileId) { var existingDeviceProfile = _dlnaManager.GetProfile(profileId); if (existingDeviceProfile == null) @@ -118,7 +118,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Profiles/{profileId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateProfile([FromRoute][Required] string profileId, [FromBody] DeviceProfile deviceProfile) + public ActionResult UpdateProfile([FromRoute, Required] string profileId, [FromBody] DeviceProfile deviceProfile) { var existingDeviceProfile = _dlnaManager.GetProfile(profileId); if (existingDeviceProfile == null) diff --git a/Jellyfin.Api/Controllers/DlnaServerController.cs b/Jellyfin.Api/Controllers/DlnaServerController.cs index 2f93ca2c2..8cdea4367 100644 --- a/Jellyfin.Api/Controllers/DlnaServerController.cs +++ b/Jellyfin.Api/Controllers/DlnaServerController.cs @@ -46,7 +46,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{serverId}/description.xml", Name = "GetDescriptionXml_2")] [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetDescriptionXml([FromRoute][Required] string serverId) + public ActionResult GetDescriptionXml([FromRoute, Required] string serverId) { var url = GetAbsoluteUri(); var serverAddress = url.Substring(0, url.IndexOf("/dlna/", StringComparison.OrdinalIgnoreCase)); @@ -66,7 +66,7 @@ namespace Jellyfin.Api.Controllers [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetContentDirectory([FromRoute][Required] string serverId) + public ActionResult GetContentDirectory([FromRoute, Required] string serverId) { return Ok(_contentDirectory.GetServiceXml()); } @@ -82,7 +82,7 @@ namespace Jellyfin.Api.Controllers [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetMediaReceiverRegistrar([FromRoute][Required] string serverId) + public ActionResult GetMediaReceiverRegistrar([FromRoute, Required] string serverId) { return Ok(_mediaReceiverRegistrar.GetServiceXml()); } @@ -98,7 +98,7 @@ namespace Jellyfin.Api.Controllers [Produces(MediaTypeNames.Text.Xml)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetConnectionManager([FromRoute][Required] string serverId) + public ActionResult GetConnectionManager([FromRoute, Required] string serverId) { return Ok(_connectionManager.GetServiceXml()); } @@ -109,7 +109,7 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Control response. [HttpPost("{serverId}/ContentDirectory/Control")] - public async Task> ProcessContentDirectoryControlRequest([FromRoute][Required] string serverId) + public async Task> ProcessContentDirectoryControlRequest([FromRoute, Required] string serverId) { return await ProcessControlRequestInternalAsync(serverId, Request.Body, _contentDirectory).ConfigureAwait(false); } @@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Control response. [HttpPost("{serverId}/ConnectionManager/Control")] - public async Task> ProcessConnectionManagerControlRequest([FromRoute][Required] string serverId) + public async Task> ProcessConnectionManagerControlRequest([FromRoute, Required] string serverId) { return await ProcessControlRequestInternalAsync(serverId, Request.Body, _connectionManager).ConfigureAwait(false); } @@ -131,7 +131,7 @@ namespace Jellyfin.Api.Controllers /// Server UUID. /// Control response. [HttpPost("{serverId}/MediaReceiverRegistrar/Control")] - public async Task> ProcessMediaReceiverRegistrarControlRequest([FromRoute][Required] string serverId) + public async Task> ProcessMediaReceiverRegistrarControlRequest([FromRoute, Required] string serverId) { return await ProcessControlRequestInternalAsync(serverId, Request.Body, _mediaReceiverRegistrar).ConfigureAwait(false); } @@ -186,7 +186,7 @@ namespace Jellyfin.Api.Controllers /// Icon stream. [HttpGet("{serverId}/icons/{fileName}")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "serverId", Justification = "Required for DLNA")] - public ActionResult GetIconId([FromRoute][Required] string serverId, [FromRoute][Required] string fileName) + public ActionResult GetIconId([FromRoute, Required] string serverId, [FromRoute, Required] string fileName) { return GetIconInternal(fileName); } @@ -197,7 +197,7 @@ namespace Jellyfin.Api.Controllers /// The icon filename. /// Icon stream. [HttpGet("icons/{fileName}")] - public ActionResult GetIcon([FromRoute][Required] string fileName) + public ActionResult GetIcon([FromRoute, Required] string fileName) { return GetIconInternal(fileName); } diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index ec711ce34..d81c7996e 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -167,8 +167,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("Videos/{itemId}/master.m3u8", Name = "HeadMasterHlsVideoPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsVideoPlaylist( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string? container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -334,8 +334,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("Audio/{itemId}/master.m3u8", Name = "HeadMasterHlsAudioPlaylist")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetMasterHlsAudioPlaylist( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string? container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -499,8 +499,8 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVariantHlsVideoPlaylist( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string? container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -664,8 +664,8 @@ namespace Jellyfin.Api.Controllers [HttpGet("Audio/{itemId}/main.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVariantHlsAudioPlaylist( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string? container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -832,10 +832,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsVideoSegment( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string playlistId, - [FromRoute][Required] int segmentId, - [FromRoute][Required] string container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string playlistId, + [FromRoute, Required] int segmentId, + [FromRoute, Required] string container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, @@ -1001,10 +1001,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "playlistId", Justification = "Imported from ServiceStack")] public async Task GetHlsAudioSegment( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string playlistId, - [FromRoute][Required] int segmentId, - [FromRoute][Required] string container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string playlistId, + [FromRoute, Required] int segmentId, + [FromRoute, Required] string container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index 53be16370..de6aa86c9 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -261,7 +261,7 @@ namespace Jellyfin.Api.Controllers /// An containing the genre. [HttpGet("{genreName}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetGenre([FromRoute][Required] string genreName, [FromQuery] Guid? userId) + public ActionResult GetGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() .AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 58c583d09..e96df83fa 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -56,7 +56,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Audio/{itemId}/hls/{segmentId}/stream.aac", Name = "GetHlsAudioSegmentLegacyAac")] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] - public ActionResult GetHlsAudioSegmentLegacy([FromRoute][Required] string itemId, [FromRoute][Required] string segmentId) + public ActionResult GetHlsAudioSegmentLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string segmentId) { // TODO: Deprecate with new iOS app var file = segmentId + Path.GetExtension(Request.Path); @@ -76,7 +76,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] - public ActionResult GetHlsPlaylistLegacy([FromRoute][Required] string itemId, [FromRoute][Required] string playlistId) + public ActionResult GetHlsPlaylistLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string playlistId) { var file = playlistId + Path.GetExtension(Request.Path); file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); @@ -115,10 +115,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsVideoSegmentLegacy( - [FromRoute][Required] string itemId, - [FromRoute][Required] string playlistId, - [FromRoute][Required] string segmentId, - [FromRoute][Required] string segmentContainer) + [FromRoute, Required] string itemId, + [FromRoute, Required] string playlistId, + [FromRoute, Required] string segmentId, + [FromRoute, Required] string segmentContainer) { var file = segmentId + Path.GetExtension(Request.Path); var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath(); diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index e28957c9b..453da5711 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -91,9 +91,9 @@ namespace Jellyfin.Api.Controllers [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "imageType", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] public async Task PostUserImage( - [FromRoute][Required] Guid userId, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] int? index = null) + [FromRoute, Required] Guid userId, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] int? index = null) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) { @@ -138,9 +138,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult DeleteUserImage( - [FromRoute][Required] Guid userId, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] int? index = null) + [FromRoute, Required] Guid userId, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] int? index = null) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) { @@ -176,9 +176,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DeleteItemImage( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] Guid itemId, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -206,9 +206,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] public async Task SetItemImage( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] Guid itemId, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -239,9 +239,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task UpdateItemImageIndex( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] int imageIndex, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] int imageIndex, [FromQuery] int newIndex) { var item = _libraryManager.GetItemById(itemId); @@ -265,7 +265,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task>> GetItemImageInfos([FromRoute][Required] Guid itemId) + public async Task>> GetItemImageInfos([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -353,10 +353,10 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] int? maxWidth, - [FromRoute][Required] int? maxHeight, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] int? maxWidth, + [FromRoute, Required] int? maxHeight, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -369,7 +369,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -431,23 +431,23 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetItemImage2( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] int? maxWidth, - [FromRoute][Required] int? maxHeight, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] int? maxWidth, + [FromRoute, Required] int? maxHeight, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, - [FromRoute][Required] string tag, + [FromRoute, Required] string tag, [FromQuery] bool? cropWhitespace, - [FromRoute][Required] string format, + [FromRoute, Required] string format, [FromQuery] bool? addPlayedIndicator, - [FromRoute][Required] double? percentPlayed, - [FromRoute][Required] int? unplayedCount, + [FromRoute, Required] double? percentPlayed, + [FromRoute, Required] int? unplayedCount, [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -509,14 +509,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetArtistImage( - [FromRoute][Required] string name, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] string tag, - [FromRoute][Required] string format, - [FromRoute][Required] int? maxWidth, - [FromRoute][Required] int? maxHeight, - [FromRoute][Required] double? percentPlayed, - [FromRoute][Required] int? unplayedCount, + [FromRoute, Required] string name, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] string tag, + [FromRoute, Required] string format, + [FromRoute, Required] int? maxWidth, + [FromRoute, Required] int? maxHeight, + [FromRoute, Required] double? percentPlayed, + [FromRoute, Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -525,7 +525,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetArtist(name); if (item == null) @@ -587,14 +587,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetGenreImage( - [FromRoute][Required] string name, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] string tag, - [FromRoute][Required] string format, - [FromRoute][Required] int? maxWidth, - [FromRoute][Required] int? maxHeight, - [FromRoute][Required] double? percentPlayed, - [FromRoute][Required] int? unplayedCount, + [FromRoute, Required] string name, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] string tag, + [FromRoute, Required] string format, + [FromRoute, Required] int? maxWidth, + [FromRoute, Required] int? maxHeight, + [FromRoute, Required] double? percentPlayed, + [FromRoute, Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -603,7 +603,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetGenre(name); if (item == null) @@ -665,14 +665,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetMusicGenreImage( - [FromRoute][Required] string name, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] string tag, - [FromRoute][Required] string format, - [FromRoute][Required] int? maxWidth, - [FromRoute][Required] int? maxHeight, - [FromRoute][Required] double? percentPlayed, - [FromRoute][Required] int? unplayedCount, + [FromRoute, Required] string name, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] string tag, + [FromRoute, Required] string format, + [FromRoute, Required] int? maxWidth, + [FromRoute, Required] int? maxHeight, + [FromRoute, Required] double? percentPlayed, + [FromRoute, Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -681,7 +681,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetMusicGenre(name); if (item == null) @@ -743,14 +743,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetPersonImage( - [FromRoute][Required] string name, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] string tag, - [FromRoute][Required] string format, - [FromRoute][Required] int? maxWidth, - [FromRoute][Required] int? maxHeight, - [FromRoute][Required] double? percentPlayed, - [FromRoute][Required] int? unplayedCount, + [FromRoute, Required] string name, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] string tag, + [FromRoute, Required] string format, + [FromRoute, Required] int? maxWidth, + [FromRoute, Required] int? maxHeight, + [FromRoute, Required] double? percentPlayed, + [FromRoute, Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -759,7 +759,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetPerson(name); if (item == null) @@ -821,14 +821,14 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetStudioImage( - [FromRoute][Required] string name, - [FromRoute][Required] ImageType imageType, - [FromRoute][Required] string tag, - [FromRoute][Required] string format, - [FromRoute][Required] int? maxWidth, - [FromRoute][Required] int? maxHeight, - [FromRoute][Required] double? percentPlayed, - [FromRoute][Required] int? unplayedCount, + [FromRoute, Required] string name, + [FromRoute, Required] ImageType imageType, + [FromRoute, Required] string tag, + [FromRoute, Required] string format, + [FromRoute, Required] int? maxWidth, + [FromRoute, Required] int? maxHeight, + [FromRoute, Required] double? percentPlayed, + [FromRoute, Required] int? unplayedCount, [FromQuery] int? width, [FromQuery] int? height, [FromQuery] int? quality, @@ -837,7 +837,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var item = _libraryManager.GetStudio(name); if (item == null) @@ -899,8 +899,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetUserImage( - [FromRoute][Required] Guid userId, - [FromRoute][Required] ImageType imageType, + [FromRoute, Required] Guid userId, + [FromRoute, Required] ImageType imageType, [FromQuery] string? tag, [FromQuery] string? format, [FromQuery] int? maxWidth, @@ -915,7 +915,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? blur, [FromQuery] string? backgroundColor, [FromQuery] string? foregroundLayer, - [FromRoute][Required] int? imageIndex = null) + [FromRoute, Required] int? imageIndex = null) { var user = _userManager.GetUserById(userId); if (user == null) diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 11f2b2495..01bfbba4e 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -64,7 +64,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Songs/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromSong( - [FromRoute][Required] Guid id, + [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -101,7 +101,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Albums/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromAlbum( - [FromRoute][Required] Guid id, + [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -138,7 +138,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Playlists/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromPlaylist( - [FromRoute][Required] Guid id, + [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -211,7 +211,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Artists/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromArtists( - [FromRoute][Required] Guid id, + [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -248,7 +248,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("MusicGenres/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromMusicGenres( - [FromRoute][Required] Guid id, + [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, @@ -285,7 +285,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Items/{id}/InstantMix")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetInstantMixFromItem( - [FromRoute][Required] Guid id, + [FromRoute, Required] Guid id, [FromQuery] Guid? userId, [FromQuery] int? limit, [FromQuery] string? fields, diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index f1169f3d2..f7b515cec 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -72,7 +72,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetExternalIdInfos([FromRoute][Required] Guid itemId) + public ActionResult> GetExternalIdInfos([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -294,7 +294,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/RemoteSearch/Apply/{id}")] [Authorize(Policy = Policies.RequiresElevation)] public async Task ApplySearchCriteria( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromBody, Required] RemoteSearchResult searchResult, [FromQuery] bool replaceAllImages = true) { diff --git a/Jellyfin.Api/Controllers/ItemRefreshController.cs b/Jellyfin.Api/Controllers/ItemRefreshController.cs index 87086c681..49865eb5e 100644 --- a/Jellyfin.Api/Controllers/ItemRefreshController.cs +++ b/Jellyfin.Api/Controllers/ItemRefreshController.cs @@ -54,7 +54,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult Post( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] MetadataRefreshMode metadataRefreshMode = MetadataRefreshMode.None, [FromQuery] MetadataRefreshMode imageRefreshMode = MetadataRefreshMode.None, [FromQuery] bool replaceAllMetadata = false, diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index 0d064fffb..4308a434d 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task UpdateItem([FromRoute][Required] Guid itemId, [FromBody, Required] BaseItemDto request) + public async Task UpdateItem([FromRoute, Required] Guid itemId, [FromBody, Required] BaseItemDto request) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -141,7 +141,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Items/{itemId}/MetadataEditor")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetMetadataEditorInfo([FromRoute][Required] Guid itemId) + public ActionResult GetMetadataEditorInfo([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); @@ -195,7 +195,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}/ContentType")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateItemContentType([FromRoute][Required] Guid itemId, [FromQuery, Required] string? contentType) + public ActionResult UpdateItemContentType([FromRoute, Required] Guid itemId, [FromQuery, Required] string? contentType) { var item = _libraryManager.GetItemById(itemId); if (item == null) diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 170606b11..06ab176b2 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -145,7 +145,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{uId}/Items", Name = "GetItems_2")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetItems( - [FromRoute][Required] Guid? uId, + [FromRoute, Required] Guid? uId, [FromQuery] Guid? userId, [FromQuery] string? maxOfficialRating, [FromQuery] bool? hasThemeSong, @@ -530,7 +530,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Items/Resume")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetResumeItems( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromQuery] int? startIndex, [FromQuery] int? limit, [FromQuery] string? searchTerm, diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index ac28fd6ca..f1f52961d 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -104,7 +104,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetFile([FromRoute][Required] Guid itemId) + public ActionResult GetFile([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -144,7 +144,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetThemeSongs( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] bool inheritFromParent = false) { @@ -210,7 +210,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult GetThemeVideos( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] bool inheritFromParent = false) { @@ -275,7 +275,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetThemeMedia( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] bool inheritFromParent = false) { @@ -438,7 +438,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetAncestors([FromRoute][Required] Guid itemId, [FromQuery] Guid? userId) + public ActionResult> GetAncestors([FromRoute, Required] Guid itemId, [FromQuery] Guid? userId) { var item = _libraryManager.GetItemById(itemId); @@ -555,7 +555,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Library/Movies/Updated")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult PostUpdatedMovies([FromRoute][Required] string? tmdbId, [FromRoute][Required] string? imdbId) + public ActionResult PostUpdatedMovies([FromRoute, Required] string? tmdbId, [FromRoute, Required] string? imdbId) { var movies = _libraryManager.GetItemList(new InternalItemsQuery { @@ -618,7 +618,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.Download)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetDownload([FromRoute][Required] Guid itemId) + public async Task GetDownload([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -687,7 +687,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSimilarItems( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] string? excludeArtistIds, [FromQuery] Guid? userId, [FromQuery] int? limit, diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index fb3f0f5f5..8678844d2 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -210,7 +210,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Channels/{channelId}")] [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult GetChannel([FromRoute][Required] Guid channelId, [FromQuery] Guid? userId) + public ActionResult GetChannel([FromRoute, Required] Guid channelId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId.Value) @@ -407,7 +407,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Recordings/{recordingId}")] [ProducesResponseType(StatusCodes.Status200OK)] [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult GetRecording([FromRoute][Required] Guid recordingId, [FromQuery] Guid? userId) + public ActionResult GetRecording([FromRoute, Required] Guid recordingId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId.Value) @@ -429,7 +429,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Tuners/{tunerId}/Reset")] [ProducesResponseType(StatusCodes.Status204NoContent)] [Authorize(Policy = Policies.DefaultAuthorization)] - public ActionResult ResetTuner([FromRoute][Required] string tunerId) + public ActionResult ResetTuner([FromRoute, Required] string tunerId) { AssertUserCanManageLiveTv(); _liveTvManager.ResetTuner(tunerId, CancellationToken.None); @@ -745,7 +745,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetProgram( - [FromRoute][Required] string programId, + [FromRoute, Required] string programId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) @@ -766,7 +766,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteRecording([FromRoute][Required] Guid recordingId) + public ActionResult DeleteRecording([FromRoute, Required] Guid recordingId) { AssertUserCanManageLiveTv(); @@ -793,7 +793,7 @@ namespace Jellyfin.Api.Controllers [HttpDelete("Timers/{timerId}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CancelTimer([FromRoute][Required] string timerId) + public async Task CancelTimer([FromRoute, Required] string timerId) { AssertUserCanManageLiveTv(); await _liveTvManager.CancelTimer(timerId).ConfigureAwait(false); @@ -811,7 +811,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] - public async Task UpdateTimer([FromRoute][Required] string timerId, [FromBody] TimerInfoDto timerInfo) + public async Task UpdateTimer([FromRoute, Required] string timerId, [FromBody] TimerInfoDto timerInfo) { AssertUserCanManageLiveTv(); await _liveTvManager.UpdateTimer(timerInfo, CancellationToken.None).ConfigureAwait(false); @@ -845,7 +845,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task> GetSeriesTimer([FromRoute][Required] string timerId) + public async Task> GetSeriesTimer([FromRoute, Required] string timerId) { var timer = await _liveTvManager.GetSeriesTimer(timerId, CancellationToken.None).ConfigureAwait(false); if (timer == null) @@ -885,7 +885,7 @@ namespace Jellyfin.Api.Controllers [HttpDelete("SeriesTimers/{timerId}")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task CancelSeriesTimer([FromRoute][Required] string timerId) + public async Task CancelSeriesTimer([FromRoute, Required] string timerId) { AssertUserCanManageLiveTv(); await _liveTvManager.CancelSeriesTimer(timerId).ConfigureAwait(false); @@ -903,7 +903,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "timerId", Justification = "Imported from ServiceStack")] - public async Task UpdateSeriesTimer([FromRoute][Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo) + public async Task UpdateSeriesTimer([FromRoute, Required] string timerId, [FromBody] SeriesTimerInfoDto seriesTimerInfo) { AssertUserCanManageLiveTv(); await _liveTvManager.UpdateSeriesTimer(seriesTimerInfo, CancellationToken.None).ConfigureAwait(false); @@ -935,7 +935,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Obsolete("This endpoint is obsolete.")] - public ActionResult GetRecordingGroup([FromRoute][Required] Guid? groupId) + public ActionResult GetRecordingGroup([FromRoute, Required] Guid? groupId) { return NotFound(); } @@ -1177,7 +1177,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("LiveRecordings/{recordingId}/stream")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetLiveRecordingFile([FromRoute][Required] string recordingId) + public async Task GetLiveRecordingFile([FromRoute, Required] string recordingId) { var path = _liveTvManager.GetEmbyTvActiveRecordingPath(recordingId); @@ -1207,7 +1207,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("LiveStreamFiles/{streamId}/stream.{container}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task GetLiveStreamFile([FromRoute][Required] string streamId, [FromRoute][Required] string container) + public async Task GetLiveStreamFile([FromRoute, Required] string streamId, [FromRoute, Required] string container) { var liveStreamInfo = await _mediaSourceManager.GetDirectStreamProviderByUniqueId(streamId, CancellationToken.None).ConfigureAwait(false); if (liveStreamInfo == null) diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 8bb0ace15..cc6eba4ae 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers /// A containing a with the playback information. [HttpGet("Items/{itemId}/PlaybackInfo")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetPlaybackInfo([FromRoute][Required] Guid itemId, [FromQuery, Required] Guid? userId) + public async Task> GetPlaybackInfo([FromRoute, Required] Guid itemId, [FromQuery, Required] Guid? userId) { return await _mediaInfoHelper.GetPlaybackInfo( itemId, @@ -100,7 +100,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}/PlaybackInfo")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPostedPlaybackInfo( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] Guid? userId, [FromQuery] long? maxStreamingBitrate, [FromQuery] long? startTimeTicks, diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index df97c0ab9..570ae8fdc 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -259,7 +259,7 @@ namespace Jellyfin.Api.Controllers /// An containing a with the music genre. [HttpGet("{genreName}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetMusicGenre([FromRoute][Required] string genreName, [FromQuery] Guid? userId) + public ActionResult GetMusicGenre([FromRoute, Required] string genreName, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions().AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index ea85e1909..7e406b418 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Packages/{name}")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task> GetPackageInfo( - [FromRoute][Required] string? name, + [FromRoute, Required] string? name, [FromQuery] string? assemblyGuid) { var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Policy = Policies.RequiresElevation)] public async Task InstallPackage( - [FromRoute][Required] string? name, + [FromRoute, Required] string? name, [FromQuery] string? assemblyGuid, [FromQuery] string? version) { @@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult CancelPackageInstallation( - [FromRoute][Required] Guid packageId) + [FromRoute, Required] Guid packageId) { _installationManager.CancelInstallation(packageId); return NoContent(); diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index be5fb7f7c..8bd610dad 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -263,7 +263,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{name}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetPerson([FromRoute][Required] string name, [FromQuery] Guid? userId) + public ActionResult GetPerson([FromRoute, Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions() .AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index 07bb108e3..69e0b8e07 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -84,7 +84,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task AddToPlaylist( - [FromRoute][Required] Guid playlistId, + [FromRoute, Required] Guid playlistId, [FromQuery] string? ids, [FromQuery] Guid? userId) { @@ -103,9 +103,9 @@ namespace Jellyfin.Api.Controllers [HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task MoveItem( - [FromRoute][Required] string? playlistId, - [FromRoute][Required] string? itemId, - [FromRoute][Required] int newIndex) + [FromRoute, Required] string? playlistId, + [FromRoute, Required] string? itemId, + [FromRoute, Required] int newIndex) { await _playlistManager.MoveItemAsync(playlistId, itemId, newIndex).ConfigureAwait(false); return NoContent(); @@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers /// An on success. [HttpDelete("{playlistId}/Items")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public async Task RemoveFromPlaylist([FromRoute][Required] string? playlistId, [FromQuery] string? entryIds) + public async Task RemoveFromPlaylist([FromRoute, Required] string? playlistId, [FromQuery] string? entryIds) { await _playlistManager.RemoveFromPlaylistAsync(playlistId, RequestHelpers.Split(entryIds, ',', true)).ConfigureAwait(false); return NoContent(); @@ -143,15 +143,15 @@ namespace Jellyfin.Api.Controllers /// The original playlist items. [HttpGet("{playlistId}/Items")] public ActionResult> GetPlaylistItems( - [FromRoute][Required] Guid playlistId, - [FromRoute][Required] Guid userId, - [FromRoute][Required] int? startIndex, - [FromRoute][Required] int? limit, - [FromRoute][Required] string? fields, - [FromRoute][Required] bool? enableImages, - [FromRoute][Required] bool? enableUserData, - [FromRoute][Required] int? imageTypeLimit, - [FromRoute][Required] string? enableImageTypes) + [FromRoute, Required] Guid playlistId, + [FromRoute, Required] Guid userId, + [FromRoute, Required] int? startIndex, + [FromRoute, Required] int? limit, + [FromRoute, Required] string? fields, + [FromRoute, Required] bool? enableImages, + [FromRoute, Required] bool? enableUserData, + [FromRoute, Required] int? imageTypeLimit, + [FromRoute, Required] string? enableImageTypes) { var playlist = (Playlist)_libraryManager.GetItemById(playlistId); if (playlist == null) diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 091f884d2..5c15e9a0d 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -72,8 +72,8 @@ namespace Jellyfin.Api.Controllers [HttpPost("Users/{userId}/PlayedItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult MarkPlayedItem( - [FromRoute][Required] Guid userId, - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, [FromQuery] DateTime? datePlayed) { var user = _userManager.GetUserById(userId); @@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers /// A containing the . [HttpDelete("Users/{userId}/PlayedItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult MarkUnplayedItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public ActionResult MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); var session = RequestHelpers.GetSession(_sessionManager, _authContext, Request); @@ -196,8 +196,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackStart( - [FromRoute][Required] Guid userId, - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] int? audioStreamIndex, [FromQuery] int? subtitleStreamIndex, @@ -246,8 +246,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackProgress( - [FromRoute][Required] Guid userId, - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] long? positionTicks, [FromQuery] int? audioStreamIndex, @@ -298,8 +298,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task OnPlaybackStopped( - [FromRoute][Required] Guid userId, - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] string? nextMediaType, [FromQuery] long? positionTicks, diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index d0de1a422..342b0328d 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -64,7 +64,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UninstallPlugin([FromRoute][Required] Guid pluginId) + public ActionResult UninstallPlugin([FromRoute, Required] Guid pluginId) { var plugin = _appHost.Plugins.FirstOrDefault(p => p.Id == pluginId); if (plugin == null) @@ -86,7 +86,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{pluginId}/Configuration")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetPluginConfiguration([FromRoute][Required] Guid pluginId) + public ActionResult GetPluginConfiguration([FromRoute, Required] Guid pluginId) { if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin)) { @@ -113,7 +113,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("{pluginId}/Configuration")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task UpdatePluginConfiguration([FromRoute][Required] Guid pluginId) + public async Task UpdatePluginConfiguration([FromRoute, Required] Guid pluginId) { if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin)) { @@ -172,7 +172,7 @@ namespace Jellyfin.Api.Controllers [Obsolete("This endpoint should not be used.")] [HttpPost("RegistrationRecords/{name}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetRegistrationStatus([FromRoute][Required] string? name) + public ActionResult GetRegistrationStatus([FromRoute, Required] string? name) { return new MBRegistrationRecord { @@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers [Obsolete("Paid plugins are not supported")] [HttpGet("Registrations/{name}")] [ProducesResponseType(StatusCodes.Status501NotImplemented)] - public ActionResult GetRegistration([FromRoute][Required] string? name) + public 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. diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 597d3f2f6..bdc817126 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -70,7 +70,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task> GetRemoteImages( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] ImageType? type, [FromQuery] int? startIndex, [FromQuery] int? limit, @@ -133,7 +133,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetRemoteImageProviders([FromRoute][Required] Guid itemId) + public ActionResult> GetRemoteImageProviders([FromRoute, Required] Guid itemId) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -209,7 +209,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task DownloadRemoteImage( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery, Required] ImageType type, [FromQuery] string? imageUrl) { diff --git a/Jellyfin.Api/Controllers/ScheduledTasksController.cs b/Jellyfin.Api/Controllers/ScheduledTasksController.cs index ea6288de0..3206f2734 100644 --- a/Jellyfin.Api/Controllers/ScheduledTasksController.cs +++ b/Jellyfin.Api/Controllers/ScheduledTasksController.cs @@ -94,7 +94,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Running/{taskId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult StartTask([FromRoute][Required] string? taskId) + public ActionResult StartTask([FromRoute, Required] string? taskId) { var task = _taskManager.ScheduledTasks.FirstOrDefault(o => o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase)); diff --git a/Jellyfin.Api/Controllers/SessionController.cs b/Jellyfin.Api/Controllers/SessionController.cs index 4f0f241c6..cff7c1501 100644 --- a/Jellyfin.Api/Controllers/SessionController.cs +++ b/Jellyfin.Api/Controllers/SessionController.cs @@ -336,7 +336,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult AddUserToSession( [FromRoute, Required] string? sessionId, - [FromRoute][Required] Guid userId) + [FromRoute, Required] Guid userId) { _sessionManager.AddAdditionalUser(sessionId, userId); return NoContent(); @@ -353,8 +353,8 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public ActionResult RemoveUserFromSession( - [FromRoute][Required] string? sessionId, - [FromRoute][Required] Guid userId) + [FromRoute, Required] string? sessionId, + [FromRoute, Required] Guid userId) { _sessionManager.RemoveAdditionalUser(sessionId, userId); return NoContent(); diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index 0208ebfbb..cdd5f958e 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -260,7 +260,7 @@ namespace Jellyfin.Api.Controllers /// An containing the studio. [HttpGet("{name}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetStudio([FromRoute][Required] string name, [FromQuery] Guid? userId) + public ActionResult GetStudio([FromRoute, Required] string name, [FromQuery] Guid? userId) { var dtoOptions = new DtoOptions().AddClientFields(Request); diff --git a/Jellyfin.Api/Controllers/SubtitleController.cs b/Jellyfin.Api/Controllers/SubtitleController.cs index 1096a06d2..2c82b5423 100644 --- a/Jellyfin.Api/Controllers/SubtitleController.cs +++ b/Jellyfin.Api/Controllers/SubtitleController.cs @@ -86,8 +86,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult DeleteSubtitle( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] int index) + [FromRoute, Required] Guid itemId, + [FromRoute, Required] int index) { var item = _libraryManager.GetItemById(itemId); @@ -112,7 +112,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] public async Task>> SearchRemoteSubtitles( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromRoute, Required] string? language, [FromQuery] bool? isPerfectMatch) { @@ -132,7 +132,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] public async Task DownloadRemoteSubtitles( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromRoute, Required] string? subtitleId) { var video = (Video)_libraryManager.GetItemById(itemId); @@ -193,7 +193,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] long? endPositionTicks, [FromQuery] bool copyTimestamps = false, [FromQuery] bool addVttTimeMap = false, - [FromRoute][Required] long startPositionTicks = 0) + [FromRoute, Required] long startPositionTicks = 0) { if (string.Equals(format, "js", StringComparison.OrdinalIgnoreCase)) { @@ -253,9 +253,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "index", Justification = "Imported from ServiceStack")] public async Task GetSubtitlePlaylist( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] int index, - [FromRoute][Required] string? mediaSourceId, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] int index, + [FromRoute, Required] string? mediaSourceId, [FromQuery, Required] int segmentLength) { var item = (Video)_libraryManager.GetItemById(itemId); diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index 52593b1ce..d7c81a3ab 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -54,7 +54,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Suggestions")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetSuggestions( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromQuery] string? mediaType, [FromQuery] string? type, [FromQuery] int? startIndex, diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index a3678454f..f7f2d0174 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -93,8 +93,8 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status302Found)] public async Task GetUniversalAudioStream( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string? container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string? container, [FromQuery] string? mediaSourceId, [FromQuery] string? deviceId, [FromQuery] Guid? userId, diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index a9cab9cde..95067bc17 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -108,7 +108,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.IgnoreParentalControl)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetUserById([FromRoute][Required] Guid userId) + public ActionResult GetUserById([FromRoute, Required] Guid userId) { var user = _userManager.GetUserById(userId); @@ -132,7 +132,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult DeleteUser([FromRoute][Required] Guid userId) + public ActionResult DeleteUser([FromRoute, Required] Guid userId) { var user = _userManager.GetUserById(userId); _sessionManager.RevokeUserTokens(user.Id, null); @@ -265,7 +265,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task UpdateUserPassword( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromBody] UpdateUserPassword request) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) @@ -323,7 +323,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public ActionResult UpdateUserEasyPassword( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromBody] UpdateUserEasyPassword request) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) @@ -365,7 +365,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task UpdateUser( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromBody] UserDto updateUser) { if (updateUser == null) @@ -409,7 +409,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult UpdateUserPolicy( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromBody] UserPolicy newPolicy) { if (newPolicy == null) @@ -464,7 +464,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public ActionResult UpdateUserConfiguration( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromBody] UserConfiguration userConfig) { if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false)) diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index f93e80393..48262f062 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -71,7 +71,7 @@ namespace Jellyfin.Api.Controllers /// An containing the d item. [HttpGet("Users/{userId}/Items/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task> GetItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public async Task> GetItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -94,7 +94,7 @@ namespace Jellyfin.Api.Controllers /// An containing the user's root folder. [HttpGet("Users/{userId}/Items/Root")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult GetRootFolder([FromRoute][Required] Guid userId) + public ActionResult GetRootFolder([FromRoute, Required] Guid userId) { var user = _userManager.GetUserById(userId); var item = _libraryManager.GetUserRootFolder(); @@ -111,7 +111,7 @@ namespace Jellyfin.Api.Controllers /// An containing the intros to play. [HttpGet("Users/{userId}/Items/{itemId}/Intros")] [ProducesResponseType(StatusCodes.Status200OK)] - public async Task>> GetIntros([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public async Task>> GetIntros([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -139,7 +139,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpPost("Users/{userId}/FavoriteItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult MarkFavoriteItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public ActionResult MarkFavoriteItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { return MarkFavorite(userId, itemId, true); } @@ -153,7 +153,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpDelete("Users/{userId}/FavoriteItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult UnmarkFavoriteItem([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public ActionResult UnmarkFavoriteItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { return MarkFavorite(userId, itemId, false); } @@ -167,7 +167,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpDelete("Users/{userId}/Items/{itemId}/Rating")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult DeleteUserItemRating([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public ActionResult DeleteUserItemRating([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { return UpdateUserItemRatingInternal(userId, itemId, null); } @@ -182,7 +182,7 @@ namespace Jellyfin.Api.Controllers /// An containing the . [HttpPost("Users/{userId}/Items/{itemId}/Rating")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult UpdateUserItemRating([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId, [FromQuery] bool? likes) + public ActionResult UpdateUserItemRating([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId, [FromQuery] bool? likes) { return UpdateUserItemRatingInternal(userId, itemId, likes); } @@ -196,7 +196,7 @@ namespace Jellyfin.Api.Controllers /// The items local trailers. [HttpGet("Users/{userId}/Items/{itemId}/LocalTrailers")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetLocalTrailers([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public ActionResult> GetLocalTrailers([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -231,7 +231,7 @@ namespace Jellyfin.Api.Controllers /// An containing the special features. [HttpGet("Users/{userId}/Items/{itemId}/SpecialFeatures")] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetSpecialFeatures([FromRoute][Required] Guid userId, [FromRoute][Required] Guid itemId) + public ActionResult> GetSpecialFeatures([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) { var user = _userManager.GetUserById(userId); @@ -265,7 +265,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Items/Latest")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetLatestMedia( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromQuery] Guid? parentId, [FromQuery] string? fields, [FromQuery] string? includeItemTypes, diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 8582a5a21..d575bfc3b 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -65,7 +65,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/Views")] [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult> GetUserViews( - [FromRoute][Required] Guid userId, + [FromRoute, Required] Guid userId, [FromQuery] bool? includeExternalContent, [FromQuery] string? presetViews, [FromQuery] bool includeHidden = false) @@ -127,7 +127,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Users/{userId}/GroupingOptions")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult> GetGroupingOptions([FromRoute][Required] Guid userId) + public ActionResult> GetGroupingOptions([FromRoute, Required] Guid userId) { var user = _userManager.GetUserById(userId); if (user == null) diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index cf667bf43..dabf04dee 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -163,7 +163,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("Videos/{itemId}/live.m3u8")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetLiveHlsStream( - [FromRoute][Required] Guid itemId, + [FromRoute, Required] Guid itemId, [FromQuery] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 224cc7b72..5c65399cb 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -115,7 +115,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{itemId}/AdditionalParts")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status200OK)] - public ActionResult> GetAdditionalPart([FromRoute][Required] Guid itemId, [FromQuery] Guid? userId) + public ActionResult> GetAdditionalPart([FromRoute, Required] Guid itemId, [FromQuery] Guid? userId) { var user = userId.HasValue && !userId.Equals(Guid.Empty) ? _userManager.GetUserById(userId.Value) @@ -162,7 +162,7 @@ namespace Jellyfin.Api.Controllers [Authorize(Policy = Policies.RequiresElevation)] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task DeleteAlternateSources([FromRoute][Required] Guid itemId) + public async Task DeleteAlternateSources([FromRoute, Required] Guid itemId) { var video = (Video)_libraryManager.GetItemById(itemId); @@ -331,8 +331,8 @@ namespace Jellyfin.Api.Controllers [HttpHead("{itemId}/stream", Name = "HeadVideoStream")] [ProducesResponseType(StatusCodes.Status200OK)] public async Task GetVideoStream( - [FromRoute][Required] Guid itemId, - [FromRoute][Required] string? container, + [FromRoute, Required] Guid itemId, + [FromRoute, Required] string? container, [FromQuery] bool? @static, [FromQuery] string? @params, [FromQuery] string? tag, diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index b83b09c35..4ecf0407b 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -180,7 +180,7 @@ namespace Jellyfin.Api.Controllers [HttpGet("{year}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult GetYear([FromRoute][Required] int year, [FromQuery] Guid? userId) + public ActionResult GetYear([FromRoute, Required] int year, [FromQuery] Guid? userId) { var item = _libraryManager.GetYear(year); if (item == null) -- cgit v1.2.3 From 01355e049855a21b69e7e258599c3fa35965375a Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 13 Nov 2020 09:04:31 -0700 Subject: Fix nullability errors in Jellyfin.Api (part 1) --- Jellyfin.Api/Controllers/DynamicHlsController.cs | 12 +++++++++- Jellyfin.Api/Controllers/EnvironmentController.cs | 5 ++++ Jellyfin.Api/Controllers/GenresController.cs | 2 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 5 ++++ Jellyfin.Api/Controllers/ImageByNameController.cs | 2 +- Jellyfin.Api/Controllers/ImageController.cs | 3 ++- Jellyfin.Api/Controllers/ItemLookupController.cs | 21 ++++++++++++++-- Jellyfin.Api/Controllers/LibraryController.cs | 6 ++--- Jellyfin.Api/Controllers/LiveTvController.cs | 2 +- Jellyfin.Api/Controllers/MusicGenresController.cs | 4 ++-- Jellyfin.Api/Controllers/PackageController.cs | 5 ++++ Jellyfin.Api/Controllers/RemoteImageController.cs | 28 ++++++++++++++++++---- Jellyfin.Api/Controllers/SearchController.cs | 2 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 8 ++++++- Jellyfin.Api/Helpers/AudioHelper.cs | 8 ++++++- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 11 ++++++--- Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs | 4 ++-- Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs | 6 ++--- Jellyfin.Api/Helpers/HlsHelpers.cs | 4 ++++ Jellyfin.Api/Helpers/ProgressiveFileCopier.cs | 5 ++++ Jellyfin.Api/Helpers/StreamingHelpers.cs | 4 ++++ Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 26 +++++++++++++------- .../Models/PlaybackDtos/TranscodingJobDto.cs | 4 ++-- .../Models/PlaybackDtos/TranscodingThrottler.cs | 2 +- .../ActivityLogWebSocketListener.cs | 2 +- .../ScheduledTasksWebSocketListener.cs | 6 ++--- .../SessionInfoWebSocketListener.cs | 14 +++++------ .../Subtitles/SubtitleEncoder.cs | 2 +- MediaBrowser.Model/Net/MimeTypes.cs | 6 ++--- 29 files changed, 155 insertions(+), 54 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index e07690e11..b0d5a7cd8 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1347,7 +1347,13 @@ namespace Jellyfin.Api.Controllers var mapArgs = state.IsOutputVideo ? _encodingHelper.GetMapArgs(state) : string.Empty; - var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request.SegmentContainer); + var directory = Path.GetDirectoryName(outputPath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request.SegmentContainer); var segmentFormat = GetSegmentFileExtension(state.Request.SegmentContainer).TrimStart('.'); if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase)) @@ -1566,6 +1572,10 @@ namespace Jellyfin.Api.Controllers private string GetSegmentPath(StreamState state, string playlist, int index) { var folder = Path.GetDirectoryName(playlist); + if (folder == null) + { + throw new NullReferenceException(nameof(folder)); + } var filename = Path.GetFileNameWithoutExtension(playlist); diff --git a/Jellyfin.Api/Controllers/EnvironmentController.cs b/Jellyfin.Api/Controllers/EnvironmentController.cs index ce88b0b99..8de217bbf 100644 --- a/Jellyfin.Api/Controllers/EnvironmentController.cs +++ b/Jellyfin.Api/Controllers/EnvironmentController.cs @@ -103,6 +103,11 @@ namespace Jellyfin.Api.Controllers if (validatePathDto.ValidateWritable) { + if (validatePathDto.Path == null) + { + throw new NullReferenceException(nameof(validatePathDto.Path)); + } + var file = Path.Combine(validatePathDto.Path, Guid.NewGuid().ToString()); try { diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index f6e0772ec..9c009d784 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -177,7 +177,7 @@ namespace Jellyfin.Api.Controllers return _dtoService.GetBaseItemDto(item, dtoOptions); } - private T GetItemFromSlugName(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) + private T? GetItemFromSlugName(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) where T : BaseItem, new() { var result = libraryManager.GetItemList(new InternalItemsQuery diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 054e586ce..2cee0e9ef 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -136,6 +136,11 @@ namespace Jellyfin.Api.Controllers string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1); + if (playlistPath == null) + { + throw new NullReferenceException(nameof(playlistPath)); + } + return GetFileResult(file, playlistPath); } diff --git a/Jellyfin.Api/Controllers/ImageByNameController.cs b/Jellyfin.Api/Controllers/ImageByNameController.cs index 980c3273d..198dbc51f 100644 --- a/Jellyfin.Api/Controllers/ImageByNameController.cs +++ b/Jellyfin.Api/Controllers/ImageByNameController.cs @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers /// Theme to search. /// File name to search for. /// A containing the image contents on success, or a if the image could not be found. - private ActionResult GetImageFile(string basePath, string? theme, string? name) + private ActionResult GetImageFile(string basePath, string theme, string? name) { var themeFolder = Path.Combine(basePath, theme); if (Directory.Exists(themeFolder)) diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 4a67c1aed..76e53b9a5 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Linq; +using System.Net.Mime; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Attributes; @@ -1268,7 +1269,7 @@ namespace Jellyfin.Api.Controllers Response.Headers.Add(key, value); } - Response.ContentType = imageContentType; + Response.ContentType = imageContentType ?? MediaTypeNames.Text.Plain; Response.Headers.Add(HeaderNames.Age, Convert.ToInt64((DateTime.UtcNow - dateImageModified).TotalSeconds).ToString(CultureInfo.InvariantCulture)); Response.Headers.Add(HeaderNames.Vary, HeaderNames.Accept); diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index ab73aa428..b6cb79716 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -334,10 +334,21 @@ namespace Jellyfin.Api.Controllers private async Task DownloadImage(string providerName, string url, Guid urlHash, string pointerCachePath) { using var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false); + if (result.Content.Headers.ContentType?.MediaType == null) + { + throw new NullReferenceException(nameof(result.Content.Headers.ContentType)); + } + var ext = result.Content.Headers.ContentType.MediaType.Split('/')[^1]; var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + var directory = Path.GetDirectoryName(fullCachePath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + Directory.CreateDirectory(directory); using (var stream = result.Content) { await using var fileStream = new FileStream( @@ -351,7 +362,13 @@ namespace Jellyfin.Api.Controllers await stream.CopyToAsync(fileStream).ConfigureAwait(false); } - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); + if (pointerCacheDirectory == null) + { + throw new NullReferenceException(nameof(pointerCacheDirectory)); + } + + Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath).ConfigureAwait(false); } diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 8a872ae13..60bbc5022 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -455,7 +455,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions().AddClientFields(Request); - BaseItem parent = item.GetParent(); + BaseItem? parent = item.GetParent(); while (parent != null) { @@ -466,7 +466,7 @@ namespace Jellyfin.Api.Controllers baseItemDtos.Add(_dtoService.GetBaseItemDto(parent, dtoOptions, user)); - parent = parent.GetParent(); + parent = parent?.GetParent(); } return baseItemDtos; @@ -854,7 +854,7 @@ namespace Jellyfin.Api.Controllers return _libraryManager.GetItemsResult(query).TotalRecordCount; } - private BaseItem TranslateParentItem(BaseItem item, User user) + private BaseItem? TranslateParentItem(BaseItem item, User user) { return item.GetParent() is AggregateFolder ? _libraryManager.GetUserRootFolder().GetChildren(user, true) diff --git a/Jellyfin.Api/Controllers/LiveTvController.cs b/Jellyfin.Api/Controllers/LiveTvController.cs index 31253cbbc..384a48705 100644 --- a/Jellyfin.Api/Controllers/LiveTvController.cs +++ b/Jellyfin.Api/Controllers/LiveTvController.cs @@ -1078,7 +1078,7 @@ namespace Jellyfin.Api.Controllers var client = _httpClientFactory.CreateClient(NamedClient.Default); // https://json.schedulesdirect.org/20141201/available/countries // Can't dispose the response as it's required up the call chain. - var response = await client.GetAsync("https://json.schedulesdirect.org/20141201/available/countries") + var response = await client.GetAsync(new Uri("https://json.schedulesdirect.org/20141201/available/countries")) .ConfigureAwait(false); return File(await response.Content.ReadAsStreamAsync().ConfigureAwait(false), MediaTypeNames.Application.Json); diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index e434f190a..989c383fd 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -140,7 +140,7 @@ namespace Jellyfin.Api.Controllers { var dtoOptions = new DtoOptions().AddClientFields(Request); - MusicGenre item; + MusicGenre? item; if (genreName.IndexOf(BaseItem.SlugChar, StringComparison.OrdinalIgnoreCase) != -1) { @@ -161,7 +161,7 @@ namespace Jellyfin.Api.Controllers return _dtoService.GetBaseItemDto(item, dtoOptions); } - private T GetItemFromSlugName(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) + private T? GetItemFromSlugName(ILibraryManager libraryManager, string name, DtoOptions dtoOptions) where T : BaseItem, new() { var result = libraryManager.GetItemList(new InternalItemsQuery diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index 1d9de14d2..a104af4e6 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -54,6 +54,11 @@ namespace Jellyfin.Api.Controllers string.IsNullOrEmpty(assemblyGuid) ? default : Guid.Parse(assemblyGuid)) .FirstOrDefault(); + if (result == null) + { + return NotFound(); + } + return result; } diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 5f095443b..ad76b3984 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -157,9 +157,9 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesImageFile] - public async Task GetRemoteImage([FromQuery, Required] string imageUrl) + public async Task GetRemoteImage([FromQuery, Required] Uri imageUrl) { - var urlHash = imageUrl.GetMD5(); + var urlHash = imageUrl.ToString().GetMD5(); var pointerCachePath = GetFullCachePath(urlHash.ToString()); string? contentPath = null; @@ -245,17 +245,35 @@ namespace Jellyfin.Api.Controllers /// The URL hash. /// The pointer cache path. /// Task. - private async Task DownloadImage(string url, Guid urlHash, string pointerCachePath) + private async Task DownloadImage(Uri url, Guid urlHash, string pointerCachePath) { var httpClient = _httpClientFactory.CreateClient(NamedClient.Default); using var response = await httpClient.GetAsync(url).ConfigureAwait(false); + if (response.Content.Headers.ContentType?.MediaType == null) + { + throw new NullReferenceException(nameof(response.Content.Headers.ContentType)); + } + var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last(); var fullCachePath = GetFullCachePath(urlHash + "." + ext); - Directory.CreateDirectory(Path.GetDirectoryName(fullCachePath)); + var fullCacheDirectory = Path.GetDirectoryName(fullCachePath); + if (fullCacheDirectory == null) + { + throw new NullReferenceException(nameof(fullCacheDirectory)); + } + + Directory.CreateDirectory(fullCacheDirectory); await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); - Directory.CreateDirectory(Path.GetDirectoryName(pointerCachePath)); + + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); + if (pointerCacheDirectory == null) + { + throw new NullReferenceException(nameof(pointerCacheDirectory)); + } + + Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None) .ConfigureAwait(false); } diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 62c870cb1..e75f0d06b 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -260,7 +260,7 @@ namespace Jellyfin.Api.Controllers } } - private T GetParentWithImage(BaseItem item, ImageType type) + private T? GetParentWithImage(BaseItem item, ImageType type) where T : BaseItem { return item.GetParents().OfType().FirstOrDefault(i => i.HasImage(type)); diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index d7bcf79c1..517239966 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -361,7 +361,13 @@ namespace Jellyfin.Api.Controllers var threads = _encodingHelper.GetNumberOfThreads(state, _encodingOptions, videoCodec); var inputModifier = _encodingHelper.GetInputModifier(state, _encodingOptions); var format = !string.IsNullOrWhiteSpace(state.Request.SegmentContainer) ? "." + state.Request.SegmentContainer : ".ts"; - var outputTsArg = Path.Combine(Path.GetDirectoryName(outputPath), Path.GetFileNameWithoutExtension(outputPath)) + "%d" + format; + var directory = Path.GetDirectoryName(outputPath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + format; var segmentFormat = format.TrimStart('.'); if (string.Equals(segmentFormat, "ts", StringComparison.OrdinalIgnoreCase)) diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index a3f2d88ce..c6d577b19 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -1,4 +1,5 @@ -using System.Net.Http; +using System; +using System.Net.Http; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; @@ -98,6 +99,11 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, StreamingRequestDto streamingRequest) { + if (_httpContextAccessor.HttpContext == null) + { + throw new NullReferenceException(nameof(_httpContextAccessor.HttpContext)); + } + bool isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == System.Net.WebRequestMethods.Http.Head; var cancellationTokenSource = new CancellationTokenSource(); diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index ea012f837..20bca731f 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -113,7 +113,7 @@ namespace Jellyfin.Api.Helpers StreamingRequestDto streamingRequest, bool enableAdaptiveBitrateStreaming) { - var isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == WebRequestMethods.Http.Head; + var isHeadRequest = _httpContextAccessor.HttpContext?.Request.Method == WebRequestMethods.Http.Head; var cancellationTokenSource = new CancellationTokenSource(); return await GetMasterPlaylistInternal( streamingRequest, @@ -130,6 +130,11 @@ namespace Jellyfin.Api.Helpers TranscodingJobType transcodingJobType, CancellationTokenSource cancellationTokenSource) { + if (_httpContextAccessor.HttpContext == null) + { + throw new NullReferenceException(nameof(_httpContextAccessor.HttpContext)); + } + using var state = await StreamingHelpers.GetStreamingState( streamingRequest, _httpContextAccessor.HttpContext.Request, @@ -487,14 +492,14 @@ namespace Jellyfin.Api.Helpers if (string.Equals(codec, "h264", StringComparison.OrdinalIgnoreCase)) { - string profile = state.GetRequestedProfiles("h264").FirstOrDefault(); + string? profile = state.GetRequestedProfiles("h264").FirstOrDefault(); return HlsCodecStringHelpers.GetH264String(profile, level); } if (string.Equals(codec, "h265", StringComparison.OrdinalIgnoreCase) || string.Equals(codec, "hevc", StringComparison.OrdinalIgnoreCase)) { - string profile = state.GetRequestedProfiles("h265").FirstOrDefault(); + string? profile = state.GetRequestedProfiles("h265").FirstOrDefault(); return HlsCodecStringHelpers.GetH265String(profile, level); } diff --git a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs index 366301d3e..20c94cdda 100644 --- a/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs +++ b/Jellyfin.Api/Helpers/FileStreamResponseHelpers.cs @@ -37,8 +37,8 @@ namespace Jellyfin.Api.Helpers } // Can't dispose the response as it's required up the call chain. - var response = await httpClient.GetAsync(state.MediaPath).ConfigureAwait(false); - var contentType = response.Content.Headers.ContentType.ToString(); + var response = await httpClient.GetAsync(new Uri(state.MediaPath)).ConfigureAwait(false); + var contentType = response.Content.Headers.ContentType?.ToString(); httpContext.Response.Headers[HeaderNames.AcceptRanges] = "none"; diff --git a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs index 95f1906ef..1bd3d67ff 100644 --- a/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs @@ -23,7 +23,7 @@ namespace Jellyfin.Api.Helpers /// /// AAC profile. /// AAC codec string. - public static string GetAACString(string profile) + public static string GetAACString(string? profile) { StringBuilder result = new StringBuilder("mp4a", 9); @@ -46,7 +46,7 @@ namespace Jellyfin.Api.Helpers /// H.264 profile. /// H.264 level. /// H.264 string. - public static string GetH264String(string profile, int level) + public static string GetH264String(string? profile, int level) { StringBuilder result = new StringBuilder("avc1", 11); @@ -80,7 +80,7 @@ namespace Jellyfin.Api.Helpers /// H.265 profile. /// H.265 level. /// H.265 string. - public static string GetH265String(string profile, int level) + public static string GetH265String(string? profile, int level) { // The h265 syntax is a bit of a mystery at the time this comment was written. // This is what I've found through various sources: diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index 242496697..16fbac7ae 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -45,6 +45,10 @@ namespace Jellyfin.Api.Helpers while (!reader.EndOfStream) { var line = await reader.ReadLineAsync().ConfigureAwait(false); + if (line == null) + { + throw new NullReferenceException(nameof(line)); + } if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) { diff --git a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs index e00ed3304..65c03c710 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs @@ -90,6 +90,11 @@ namespace Jellyfin.Api.Helpers allowAsyncFileRead = true; } + if (_path == null) + { + throw new NullReferenceException(nameof(_path)); + } + await using var inputStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); var eofCount = 0; diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index f4ec29bde..1d102071c 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -83,6 +83,10 @@ namespace Jellyfin.Api.Helpers } streamingRequest.StreamOptions = ParseStreamOptions(httpRequest.Query); + if (httpRequest.Path.Value == null) + { + throw new NullReferenceException(nameof(httpRequest.Path)); + } var url = httpRequest.Path.Value.Split('.').Last(); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 0db1fabff..b72e33af3 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -102,7 +102,7 @@ namespace Jellyfin.Api.Helpers /// /// Playback session id. /// The transcoding job. - public TranscodingJobDto GetTranscodingJob(string playSessionId) + public TranscodingJobDto? GetTranscodingJob(string playSessionId) { lock (_activeTranscodingJobs) { @@ -116,7 +116,7 @@ namespace Jellyfin.Api.Helpers /// Path to the transcoding file. /// The . /// The transcoding job. - public TranscodingJobDto GetTranscodingJob(string path, TranscodingJobType type) + public TranscodingJobDto? GetTranscodingJob(string path, TranscodingJobType type) { lock (_activeTranscodingJobs) { @@ -193,9 +193,13 @@ namespace Jellyfin.Api.Helpers /// Called when [transcode kill timer stopped]. /// /// The state. - private async void OnTranscodeKillTimerStopped(object state) + private async void OnTranscodeKillTimerStopped(object? state) { - var job = (TranscodingJobDto)state; + var job = (TranscodingJobDto?)state; + if (job == null) + { + throw new NullReferenceException(nameof(job)); + } if (!job.HasExited && job.Type != TranscodingJobType.Progressive) { @@ -489,7 +493,13 @@ namespace Jellyfin.Api.Helpers CancellationTokenSource cancellationTokenSource, string? workingDirectory = null) { - Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); + var directory = Path.GetDirectoryName(outputPath); + if (directory == null) + { + throw new NullReferenceException(nameof(directory)); + } + + Directory.CreateDirectory(directory); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); @@ -523,7 +533,7 @@ namespace Jellyfin.Api.Helpers RedirectStandardInput = true, FileName = _mediaEncoder.EncoderPath, Arguments = commandLineArguments, - WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? null : workingDirectory, + WorkingDirectory = string.IsNullOrWhiteSpace(workingDirectory) ? string.Empty : workingDirectory, ErrorDialog = false }, EnableRaisingEvents = true @@ -827,7 +837,7 @@ namespace Jellyfin.Api.Helpers { lock (_transcodingLocks) { - if (!_transcodingLocks.TryGetValue(outputPath, out SemaphoreSlim result)) + if (!_transcodingLocks.TryGetValue(outputPath, out SemaphoreSlim? result)) { result = new SemaphoreSlim(1, 1); _transcodingLocks[outputPath] = result; @@ -837,7 +847,7 @@ namespace Jellyfin.Api.Helpers } } - private void OnPlaybackProgress(object sender, PlaybackProgressEventArgs e) + private void OnPlaybackProgress(object? sender, PlaybackProgressEventArgs e) { if (!string.IsNullOrWhiteSpace(e.PlaySessionId)) { diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs index b9507a4e5..9edc19bb6 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingJobDto.cs @@ -196,7 +196,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos /// Start kill timer. /// /// Callback action. - public void StartKillTimer(Action callback) + public void StartKillTimer(Action callback) { StartKillTimer(callback, PingTimeout); } @@ -206,7 +206,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos /// /// Callback action. /// Callback interval. - public void StartKillTimer(Action callback, int intervalMs) + public void StartKillTimer(Action callback, int intervalMs) { if (HasExited) { diff --git a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs index b5e42ea29..872a46824 100644 --- a/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs +++ b/Jellyfin.Api/Models/PlaybackDtos/TranscodingThrottler.cs @@ -101,7 +101,7 @@ namespace Jellyfin.Api.Models.PlaybackDtos return _config.GetConfiguration("encoding"); } - private async void TimerCallback(object state) + private async void TimerCallback(object? state) { if (_job.HasExited) { diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs index 77d55828d..ce5465116 100644 --- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs @@ -56,7 +56,7 @@ namespace Jellyfin.Api.WebSocketListeners base.Dispose(dispose); } - private void OnEntryCreated(object sender, GenericEventArgs e) + private void OnEntryCreated(object? sender, GenericEventArgs e) { SendData(true); } diff --git a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs index 80314b923..94df23e56 100644 --- a/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/ScheduledTasksWebSocketListener.cs @@ -64,19 +64,19 @@ namespace Jellyfin.Api.WebSocketListeners base.Dispose(dispose); } - private void OnTaskCompleted(object sender, TaskCompletionEventArgs e) + private void OnTaskCompleted(object? sender, TaskCompletionEventArgs e) { SendData(true); e.Task.TaskProgress -= OnTaskProgress; } - private void OnTaskExecuting(object sender, GenericEventArgs e) + private void OnTaskExecuting(object? sender, GenericEventArgs e) { SendData(true); e.Argument.TaskProgress += OnTaskProgress; } - private void OnTaskProgress(object sender, GenericEventArgs e) + private void OnTaskProgress(object? sender, GenericEventArgs e) { SendData(false); } diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs index 1cf43a005..d996ac69f 100644 --- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs +++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs @@ -66,37 +66,37 @@ namespace Jellyfin.Api.WebSocketListeners base.Dispose(dispose); } - private async void OnSessionManagerSessionActivity(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionActivity(object? sender, SessionEventArgs e) { await SendData(false).ConfigureAwait(false); } - private async void OnSessionManagerCapabilitiesChanged(object sender, SessionEventArgs e) + private async void OnSessionManagerCapabilitiesChanged(object? sender, SessionEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerPlaybackProgress(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackProgress(object? sender, PlaybackProgressEventArgs e) { await SendData(!e.IsAutomated).ConfigureAwait(false); } - private async void OnSessionManagerPlaybackStopped(object sender, PlaybackStopEventArgs e) + private async void OnSessionManagerPlaybackStopped(object? sender, PlaybackStopEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerPlaybackStart(object sender, PlaybackProgressEventArgs e) + private async void OnSessionManagerPlaybackStart(object? sender, PlaybackProgressEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerSessionEnded(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionEnded(object? sender, SessionEventArgs e) { await SendData(true).ConfigureAwait(false); } - private async void OnSessionManagerSessionStarted(object sender, SessionEventArgs e) + private async void OnSessionManagerSessionStarted(object? sender, SessionEventArgs e) { await SendData(true).ConfigureAwait(false); } diff --git a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs index 0a9958b9e..8b3c6b2e6 100644 --- a/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs +++ b/MediaBrowser.MediaEncoding/Subtitles/SubtitleEncoder.cs @@ -758,7 +758,7 @@ namespace MediaBrowser.MediaEncoding.Subtitles case MediaProtocol.Http: { using var response = await _httpClientFactory.CreateClient(NamedClient.Default) - .GetAsync(path, cancellationToken) + .GetAsync(new Uri(path), cancellationToken) .ConfigureAwait(false); return await response.Content.ReadAsStreamAsync().ConfigureAwait(false); } diff --git a/MediaBrowser.Model/Net/MimeTypes.cs b/MediaBrowser.Model/Net/MimeTypes.cs index afe7351d3..55c0e6c9a 100644 --- a/MediaBrowser.Model/Net/MimeTypes.cs +++ b/MediaBrowser.Model/Net/MimeTypes.cs @@ -210,9 +210,9 @@ namespace MediaBrowser.Model.Net return enableStreamDefault ? "application/octet-stream" : null; } - public static string? ToExtension(string mimeType) + public static string? ToExtension(string? mimeType) { - if (mimeType.Length == 0) + if (string.IsNullOrEmpty(mimeType)) { throw new ArgumentException("String can't be empty.", nameof(mimeType)); } @@ -220,7 +220,7 @@ namespace MediaBrowser.Model.Net // handle text/html; charset=UTF-8 mimeType = mimeType.Split(';')[0]; - if (_extensionLookup.TryGetValue(mimeType, out string result)) + if (_extensionLookup.TryGetValue(mimeType, out string? result)) { return result; } -- cgit v1.2.3 From 5f52a58e785fa4ae06fa07a93b81c1e7547ac9f3 Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 13 Nov 2020 11:14:44 -0700 Subject: Convert NullReferenceException to ResourceNotFoundException --- Emby.Server.Implementations/AppBase/ConfigurationHelper.cs | 5 +++-- Emby.Server.Implementations/Cryptography/CryptographyProvider.cs | 3 ++- Emby.Server.Implementations/Session/WebSocketController.cs | 3 ++- Jellyfin.Api/Controllers/DynamicHlsController.cs | 5 +++-- Jellyfin.Api/Controllers/EnvironmentController.cs | 3 ++- Jellyfin.Api/Controllers/HlsSegmentController.cs | 3 ++- Jellyfin.Api/Controllers/ItemLookupController.cs | 6 +++--- Jellyfin.Api/Controllers/RemoteImageController.cs | 6 +++--- Jellyfin.Api/Controllers/VideoHlsController.cs | 3 ++- Jellyfin.Api/Helpers/AudioHelper.cs | 3 ++- Jellyfin.Api/Helpers/DynamicHlsHelper.cs | 2 +- Jellyfin.Api/Helpers/HlsHelpers.cs | 3 ++- Jellyfin.Api/Helpers/ProgressiveFileCopier.cs | 3 ++- Jellyfin.Api/Helpers/StreamingHelpers.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 5 +++-- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 7 ++++--- .../Users/DefaultPasswordResetProvider.cs | 2 +- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 3 ++- 18 files changed, 40 insertions(+), 27 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index e19ce5edf..8cca5cc77 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -3,6 +3,7 @@ using System; using System.IO; using System.Linq; +using MediaBrowser.Common.Extensions; using MediaBrowser.Model.Serialization; namespace Emby.Server.Implementations.AppBase @@ -36,7 +37,7 @@ namespace Emby.Server.Implementations.AppBase catch (Exception) { var instanceConfiguration = Activator.CreateInstance(type); - configuration = instanceConfiguration ?? throw new NullReferenceException(nameof(instanceConfiguration)); + configuration = instanceConfiguration ?? throw new ResourceNotFoundException(nameof(instanceConfiguration)); } using var stream = new MemoryStream(buffer?.Length ?? 0); @@ -52,7 +53,7 @@ namespace Emby.Server.Implementations.AppBase var directory = Path.GetDirectoryName(path); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } Directory.CreateDirectory(directory); diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs index a48b6f356..8d7f73b3c 100644 --- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Security.Cryptography; +using MediaBrowser.Common.Extensions; using MediaBrowser.Model.Cryptography; using static MediaBrowser.Common.Cryptography.Constants; @@ -83,7 +84,7 @@ namespace Emby.Server.Implementations.Cryptography using var h = HashAlgorithm.Create(hashMethod); if (h == null) { - throw new NullReferenceException(nameof(h)); + throw new ResourceNotFoundException(nameof(h)); } if (salt.Length == 0) diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index 7559ccb78..78f83e337 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net.WebSockets; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Net; using MediaBrowser.Controller.Session; using MediaBrowser.Model.Net; @@ -59,7 +60,7 @@ namespace Emby.Server.Implementations.Session { if (sender == null) { - throw new NullReferenceException(nameof(sender)); + throw new ResourceNotFoundException(nameof(sender)); } var connection = (IWebSocketConnection)sender; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index b0d5a7cd8..64bea999f 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -14,6 +14,7 @@ using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -1350,7 +1351,7 @@ namespace Jellyfin.Api.Controllers var directory = Path.GetDirectoryName(outputPath); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request.SegmentContainer); @@ -1574,7 +1575,7 @@ namespace Jellyfin.Api.Controllers var folder = Path.GetDirectoryName(playlist); if (folder == null) { - throw new NullReferenceException(nameof(folder)); + throw new ResourceNotFoundException(nameof(folder)); } var filename = Path.GetFileNameWithoutExtension(playlist); diff --git a/Jellyfin.Api/Controllers/EnvironmentController.cs b/Jellyfin.Api/Controllers/EnvironmentController.cs index 8de217bbf..6dd536254 100644 --- a/Jellyfin.Api/Controllers/EnvironmentController.cs +++ b/Jellyfin.Api/Controllers/EnvironmentController.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Models.EnvironmentDtos; +using MediaBrowser.Common.Extensions; using MediaBrowser.Model.IO; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; @@ -105,7 +106,7 @@ namespace Jellyfin.Api.Controllers { if (validatePathDto.Path == null) { - throw new NullReferenceException(nameof(validatePathDto.Path)); + throw new ResourceNotFoundException(nameof(validatePathDto.Path)); } var file = Path.Combine(validatePathDto.Path, Guid.NewGuid().ToString()); diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 2cee0e9ef..fe1ffacb0 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -8,6 +8,7 @@ using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; @@ -138,7 +139,7 @@ namespace Jellyfin.Api.Controllers if (playlistPath == null) { - throw new NullReferenceException(nameof(playlistPath)); + throw new ResourceNotFoundException(nameof(playlistPath)); } return GetFileResult(file, playlistPath); diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index b6cb79716..b14840f80 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -336,7 +336,7 @@ namespace Jellyfin.Api.Controllers using var result = await _providerManager.GetSearchImage(providerName, url, CancellationToken.None).ConfigureAwait(false); if (result.Content.Headers.ContentType?.MediaType == null) { - throw new NullReferenceException(nameof(result.Content.Headers.ContentType)); + throw new ResourceNotFoundException(nameof(result.Content.Headers.ContentType)); } var ext = result.Content.Headers.ContentType.MediaType.Split('/')[^1]; @@ -345,7 +345,7 @@ namespace Jellyfin.Api.Controllers var directory = Path.GetDirectoryName(fullCachePath); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } Directory.CreateDirectory(directory); @@ -365,7 +365,7 @@ namespace Jellyfin.Api.Controllers var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); if (pointerCacheDirectory == null) { - throw new NullReferenceException(nameof(pointerCacheDirectory)); + throw new ResourceNotFoundException(nameof(pointerCacheDirectory)); } Directory.CreateDirectory(pointerCacheDirectory); diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index ad76b3984..2566f574c 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -251,7 +251,7 @@ namespace Jellyfin.Api.Controllers using var response = await httpClient.GetAsync(url).ConfigureAwait(false); if (response.Content.Headers.ContentType?.MediaType == null) { - throw new NullReferenceException(nameof(response.Content.Headers.ContentType)); + throw new ResourceNotFoundException(nameof(response.Content.Headers.ContentType)); } var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last(); @@ -260,7 +260,7 @@ namespace Jellyfin.Api.Controllers var fullCacheDirectory = Path.GetDirectoryName(fullCachePath); if (fullCacheDirectory == null) { - throw new NullReferenceException(nameof(fullCacheDirectory)); + throw new ResourceNotFoundException(nameof(fullCacheDirectory)); } Directory.CreateDirectory(fullCacheDirectory); @@ -270,7 +270,7 @@ namespace Jellyfin.Api.Controllers var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); if (pointerCacheDirectory == null) { - throw new NullReferenceException(nameof(pointerCacheDirectory)); + throw new ResourceNotFoundException(nameof(pointerCacheDirectory)); } Directory.CreateDirectory(pointerCacheDirectory); diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 517239966..c47876beb 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -11,6 +11,7 @@ using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; @@ -364,7 +365,7 @@ namespace Jellyfin.Api.Controllers var directory = Path.GetDirectoryName(outputPath); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + format; diff --git a/Jellyfin.Api/Helpers/AudioHelper.cs b/Jellyfin.Api/Helpers/AudioHelper.cs index c6d577b19..21ec2d32f 100644 --- a/Jellyfin.Api/Helpers/AudioHelper.cs +++ b/Jellyfin.Api/Helpers/AudioHelper.cs @@ -4,6 +4,7 @@ using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Common.Net; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; @@ -101,7 +102,7 @@ namespace Jellyfin.Api.Helpers { if (_httpContextAccessor.HttpContext == null) { - throw new NullReferenceException(nameof(_httpContextAccessor.HttpContext)); + throw new ResourceNotFoundException(nameof(_httpContextAccessor.HttpContext)); } bool isHeadRequest = _httpContextAccessor.HttpContext.Request.Method == System.Net.WebRequestMethods.Http.Head; diff --git a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs index 20bca731f..e7fac50c6 100644 --- a/Jellyfin.Api/Helpers/DynamicHlsHelper.cs +++ b/Jellyfin.Api/Helpers/DynamicHlsHelper.cs @@ -132,7 +132,7 @@ namespace Jellyfin.Api.Helpers { if (_httpContextAccessor.HttpContext == null) { - throw new NullReferenceException(nameof(_httpContextAccessor.HttpContext)); + throw new ResourceNotFoundException(nameof(_httpContextAccessor.HttpContext)); } using var state = await StreamingHelpers.GetStreamingState( diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index 16fbac7ae..707d1cd10 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; +using MediaBrowser.Common.Extensions; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; @@ -47,7 +48,7 @@ namespace Jellyfin.Api.Helpers var line = await reader.ReadLineAsync().ConfigureAwait(false); if (line == null) { - throw new NullReferenceException(nameof(line)); + throw new ResourceNotFoundException(nameof(line)); } if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) diff --git a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs index 65c03c710..8bddf00d5 100644 --- a/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs +++ b/Jellyfin.Api/Helpers/ProgressiveFileCopier.cs @@ -5,6 +5,7 @@ using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Models.PlaybackDtos; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Library; using MediaBrowser.Model.IO; @@ -92,7 +93,7 @@ namespace Jellyfin.Api.Helpers if (_path == null) { - throw new NullReferenceException(nameof(_path)); + throw new ResourceNotFoundException(nameof(_path)); } await using var inputStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, IODefaults.FileStreamBufferSize, fileOptions); diff --git a/Jellyfin.Api/Helpers/StreamingHelpers.cs b/Jellyfin.Api/Helpers/StreamingHelpers.cs index 1d102071c..04b107727 100644 --- a/Jellyfin.Api/Helpers/StreamingHelpers.cs +++ b/Jellyfin.Api/Helpers/StreamingHelpers.cs @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Helpers streamingRequest.StreamOptions = ParseStreamOptions(httpRequest.Query); if (httpRequest.Path.Value == null) { - throw new NullReferenceException(nameof(httpRequest.Path)); + throw new ResourceNotFoundException(nameof(httpRequest.Path)); } var url = httpRequest.Path.Value.Split('.').Last(); diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index b72e33af3..4ec0c576a 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -12,6 +12,7 @@ using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using Jellyfin.Data.Enums; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.MediaEncoding; @@ -198,7 +199,7 @@ namespace Jellyfin.Api.Helpers var job = (TranscodingJobDto?)state; if (job == null) { - throw new NullReferenceException(nameof(job)); + throw new ResourceNotFoundException(nameof(job)); } if (!job.HasExited && job.Type != TranscodingJobType.Progressive) @@ -496,7 +497,7 @@ namespace Jellyfin.Api.Helpers var directory = Path.GetDirectoryName(outputPath); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } Directory.CreateDirectory(directory); diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index ad066c524..1570d247b 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -4,6 +4,7 @@ using System.Globalization; using System.IO; using BlurHashSharp.SkiaSharp; using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Extensions; using MediaBrowser.Model.Drawing; @@ -230,7 +231,7 @@ namespace Jellyfin.Drawing.Skia var directory = Path.GetDirectoryName(tempPath); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } Directory.CreateDirectory(directory); @@ -501,7 +502,7 @@ namespace Jellyfin.Drawing.Skia var outputDirectory = Path.GetDirectoryName(outputPath); if (outputDirectory == null) { - throw new NullReferenceException(nameof(outputDirectory)); + throw new ResourceNotFoundException(nameof(outputDirectory)); } Directory.CreateDirectory(outputDirectory); @@ -554,7 +555,7 @@ namespace Jellyfin.Drawing.Skia var directory = Path.GetDirectoryName(outputPath); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } Directory.CreateDirectory(directory); diff --git a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs index ced25524e..465fb09cd 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs @@ -62,7 +62,7 @@ namespace Jellyfin.Server.Implementations.Users if (spr == null) { - throw new NullReferenceException(nameof(spr)); + throw new ResourceNotFoundException(nameof(spr)); } if (spr.ExpirationDate < DateTime.UtcNow) diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 11ad69d91..da04203e0 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; +using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Movies; @@ -130,7 +131,7 @@ namespace MediaBrowser.LocalMetadata.Savers var directory = Path.GetDirectoryName(path); if (directory == null) { - throw new NullReferenceException(nameof(directory)); + throw new ResourceNotFoundException(nameof(directory)); } Directory.CreateDirectory(directory); -- cgit v1.2.3 From 95ebb9a55ace6c544fa7fa15d0a255a5cee752a8 Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 13 Nov 2020 11:24:46 -0700 Subject: Use null coalescing when possible --- .../AppBase/ConfigurationHelper.cs | 6 +----- .../Cryptography/CryptographyProvider.cs | 7 +------ .../Session/WebSocketController.cs | 7 +------ Jellyfin.Api/Controllers/DynamicHlsController.cs | 13 ++----------- Jellyfin.Api/Controllers/HlsSegmentController.cs | 8 ++------ Jellyfin.Api/Controllers/ItemLookupController.cs | 13 ++----------- Jellyfin.Api/Controllers/RemoteImageController.cs | 14 ++------------ Jellyfin.Api/Controllers/VideoHlsController.cs | 7 +------ Jellyfin.Api/Helpers/HlsHelpers.cs | 7 ++----- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 14 ++------------ Jellyfin.Drawing.Skia/SkiaEncoder.cs | 21 +++------------------ .../Users/DefaultPasswordResetProvider.cs | 8 ++------ MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 7 +------ 13 files changed, 22 insertions(+), 110 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 8cca5cc77..b0a14f43d 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -50,11 +50,7 @@ namespace Emby.Server.Implementations.AppBase // If the file didn't exist before, or if something has changed, re-save if (buffer == null || !newBytes.AsSpan(0, newBytesLen).SequenceEqual(buffer)) { - var directory = Path.GetDirectoryName(path); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } + var directory = Path.GetDirectoryName(path) ?? throw new ResourceNotFoundException(nameof(path)); Directory.CreateDirectory(directory); // Save it after load in case we got new items diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs index 8d7f73b3c..42db18396 100644 --- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs @@ -81,12 +81,7 @@ namespace Emby.Server.Implementations.Cryptography throw new CryptographicException($"Requested hash method is not supported: {hashMethod}"); } - using var h = HashAlgorithm.Create(hashMethod); - if (h == null) - { - throw new ResourceNotFoundException(nameof(h)); - } - + using var h = HashAlgorithm.Create(hashMethod) ?? throw new ResourceNotFoundException(nameof(hashMethod)); if (salt.Length == 0) { return h.ComputeHash(bytes); diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index 78f83e337..5268ea1b9 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -58,12 +58,7 @@ namespace Emby.Server.Implementations.Session private void OnConnectionClosed(object? sender, EventArgs e) { - if (sender == null) - { - throw new ResourceNotFoundException(nameof(sender)); - } - - var connection = (IWebSocketConnection)sender; + var connection = sender as IWebSocketConnection ?? throw new ResourceNotFoundException(nameof(sender)); _logger.LogDebug("Removing websocket from session {Session}", _session.Id); _sockets.Remove(connection); connection.Closed -= OnConnectionClosed; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 64bea999f..783deebdc 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1348,11 +1348,7 @@ namespace Jellyfin.Api.Controllers var mapArgs = state.IsOutputVideo ? _encodingHelper.GetMapArgs(state) : string.Empty; - var directory = Path.GetDirectoryName(outputPath); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } + var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request.SegmentContainer); @@ -1572,12 +1568,7 @@ namespace Jellyfin.Api.Controllers private string GetSegmentPath(StreamState state, string playlist, int index) { - var folder = Path.GetDirectoryName(playlist); - if (folder == null) - { - throw new ResourceNotFoundException(nameof(folder)); - } - + var folder = Path.GetDirectoryName(playlist) ?? throw new ResourceNotFoundException(nameof(playlist)); var filename = Path.GetFileNameWithoutExtension(playlist); return Path.Combine(folder, filename + index.ToString(CultureInfo.InvariantCulture) + GetSegmentFileExtension(state.Request.SegmentContainer)); diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index fe1ffacb0..b9adcd380 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -135,12 +135,8 @@ namespace Jellyfin.Api.Controllers var playlistPath = _fileSystem.GetFilePaths(transcodeFolderPath) .FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) - && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1); - - if (playlistPath == null) - { - throw new ResourceNotFoundException(nameof(playlistPath)); - } + && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1) + ?? throw new ResourceNotFoundException(nameof(transcodeFolderPath)); return GetFileResult(file, playlistPath); } diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index b14840f80..a0d9bfb54 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -342,12 +342,7 @@ namespace Jellyfin.Api.Controllers var ext = result.Content.Headers.ContentType.MediaType.Split('/')[^1]; var fullCachePath = GetFullCachePath(urlHash + "." + ext); - var directory = Path.GetDirectoryName(fullCachePath); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } - + var directory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException(nameof(fullCachePath)); Directory.CreateDirectory(directory); using (var stream = result.Content) { @@ -362,11 +357,7 @@ namespace Jellyfin.Api.Controllers await stream.CopyToAsync(fileStream).ConfigureAwait(false); } - var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); - if (pointerCacheDirectory == null) - { - throw new ResourceNotFoundException(nameof(pointerCacheDirectory)); - } + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ResourceNotFoundException(nameof(pointerCachePath)); Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index 2566f574c..b4a9e5582 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -257,22 +257,12 @@ namespace Jellyfin.Api.Controllers var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last(); var fullCachePath = GetFullCachePath(urlHash + "." + ext); - var fullCacheDirectory = Path.GetDirectoryName(fullCachePath); - if (fullCacheDirectory == null) - { - throw new ResourceNotFoundException(nameof(fullCacheDirectory)); - } - + var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException(nameof(fullCachePath)); Directory.CreateDirectory(fullCacheDirectory); await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); - var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath); - if (pointerCacheDirectory == null) - { - throw new ResourceNotFoundException(nameof(pointerCacheDirectory)); - } - + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ResourceNotFoundException(nameof(pointerCachePath)); Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None) .ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index c47876beb..cc538f15e 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -362,12 +362,7 @@ namespace Jellyfin.Api.Controllers var threads = _encodingHelper.GetNumberOfThreads(state, _encodingOptions, videoCodec); var inputModifier = _encodingHelper.GetInputModifier(state, _encodingOptions); var format = !string.IsNullOrWhiteSpace(state.Request.SegmentContainer) ? "." + state.Request.SegmentContainer : ".ts"; - var directory = Path.GetDirectoryName(outputPath); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } - + var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + format; var segmentFormat = format.TrimStart('.'); diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index 707d1cd10..bcf0da319 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -45,11 +45,8 @@ namespace Jellyfin.Api.Helpers while (!reader.EndOfStream) { - var line = await reader.ReadLineAsync().ConfigureAwait(false); - if (line == null) - { - throw new ResourceNotFoundException(nameof(line)); - } + var line = await reader.ReadLineAsync().ConfigureAwait(false) + ?? throw new ResourceNotFoundException(nameof(reader)); if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) { diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 4ec0c576a..846624183 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -196,12 +196,7 @@ namespace Jellyfin.Api.Helpers /// The state. private async void OnTranscodeKillTimerStopped(object? state) { - var job = (TranscodingJobDto?)state; - if (job == null) - { - throw new ResourceNotFoundException(nameof(job)); - } - + var job = state as TranscodingJobDto ?? throw new ResourceNotFoundException(nameof(state)); if (!job.HasExited && job.Type != TranscodingJobType.Progressive) { var timeSinceLastPing = (DateTime.UtcNow - job.LastPingDate).TotalMilliseconds; @@ -494,12 +489,7 @@ namespace Jellyfin.Api.Helpers CancellationTokenSource cancellationTokenSource, string? workingDirectory = null) { - var directory = Path.GetDirectoryName(outputPath); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } - + var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); Directory.CreateDirectory(directory); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 1570d247b..0c90d04a7 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -228,12 +228,7 @@ namespace Jellyfin.Drawing.Skia } var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path)); - var directory = Path.GetDirectoryName(tempPath); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } - + var directory = Path.GetDirectoryName(tempPath) ?? throw new ResourceNotFoundException(nameof(tempPath)); Directory.CreateDirectory(directory); File.Copy(path, tempPath, true); @@ -499,12 +494,7 @@ namespace Jellyfin.Drawing.Skia // If all we're doing is resizing then we can stop now if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator) { - var outputDirectory = Path.GetDirectoryName(outputPath); - if (outputDirectory == null) - { - throw new ResourceNotFoundException(nameof(outputDirectory)); - } - + var outputDirectory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); Directory.CreateDirectory(outputDirectory); using var outputStream = new SKFileWStream(outputPath); using var pixmap = new SKPixmap(new SKImageInfo(width, height), resizedBitmap.GetPixels()); @@ -552,12 +542,7 @@ namespace Jellyfin.Drawing.Skia DrawIndicator(canvas, width, height, options); } - var directory = Path.GetDirectoryName(outputPath); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } - + var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); Directory.CreateDirectory(directory); using (var outputStream = new SKFileWStream(outputPath)) { diff --git a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs index 465fb09cd..7f2490404 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs @@ -57,12 +57,8 @@ namespace Jellyfin.Server.Implementations.Users SerializablePasswordReset? spr; await using (var str = File.OpenRead(resetFile)) { - spr = await JsonSerializer.DeserializeAsync(str).ConfigureAwait(false); - } - - if (spr == null) - { - throw new ResourceNotFoundException(nameof(spr)); + spr = await JsonSerializer.DeserializeAsync(str).ConfigureAwait(false) + ?? throw new ResourceNotFoundException(nameof(spr)); } if (spr.ExpirationDate < DateTime.UtcNow) diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index da04203e0..2c9c9ccaa 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -128,12 +128,7 @@ namespace MediaBrowser.LocalMetadata.Savers private void SaveToFile(Stream stream, string path) { - var directory = Path.GetDirectoryName(path); - if (directory == null) - { - throw new ResourceNotFoundException(nameof(directory)); - } - + var directory = Path.GetDirectoryName(path) ?? throw new ResourceNotFoundException(nameof(path)); Directory.CreateDirectory(directory); // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); -- cgit v1.2.3 From 73d2cb1c2a3a7cd1a30840a2b52921a3b81c6809 Mon Sep 17 00:00:00 2001 From: crobibero Date: Fri, 13 Nov 2020 18:04:06 -0700 Subject: Updated based on review feedback --- Emby.Server.Implementations/AppBase/ConfigurationHelper.cs | 4 ++-- Emby.Server.Implementations/Cryptography/CryptographyProvider.cs | 2 +- Emby.Server.Implementations/Session/WebSocketController.cs | 2 +- Jellyfin.Api/Controllers/DynamicHlsController.cs | 4 ++-- Jellyfin.Api/Controllers/HlsSegmentController.cs | 2 +- Jellyfin.Api/Controllers/ItemLookupController.cs | 4 ++-- Jellyfin.Api/Controllers/RemoteImageController.cs | 4 ++-- Jellyfin.Api/Controllers/VideoHlsController.cs | 2 +- Jellyfin.Api/Helpers/HlsHelpers.cs | 9 ++++++--- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 4 ++-- Jellyfin.Drawing.Skia/SkiaEncoder.cs | 6 +++--- .../Users/DefaultPasswordResetProvider.cs | 2 +- MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs | 2 +- 13 files changed, 25 insertions(+), 22 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs index 6c425c7fb..77819c764 100644 --- a/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs +++ b/Emby.Server.Implementations/AppBase/ConfigurationHelper.cs @@ -36,7 +36,7 @@ namespace Emby.Server.Implementations.AppBase } catch (Exception) { - configuration = Activator.CreateInstance(type) ?? throw new ResourceNotFoundException(nameof(type)); + configuration = Activator.CreateInstance(type) ?? throw new ArgumentException($"Provided path ({type}) is not valid.", nameof(type)); } using var stream = new MemoryStream(buffer?.Length ?? 0); @@ -49,7 +49,7 @@ namespace Emby.Server.Implementations.AppBase // If the file didn't exist before, or if something has changed, re-save if (buffer == null || !newBytes.AsSpan(0, newBytesLen).SequenceEqual(buffer)) { - var directory = Path.GetDirectoryName(path) ?? throw new ResourceNotFoundException(nameof(path)); + var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); Directory.CreateDirectory(directory); // Save it after load in case we got new items diff --git a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs index 42db18396..12a9e44e7 100644 --- a/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs +++ b/Emby.Server.Implementations/Cryptography/CryptographyProvider.cs @@ -81,7 +81,7 @@ namespace Emby.Server.Implementations.Cryptography throw new CryptographicException($"Requested hash method is not supported: {hashMethod}"); } - using var h = HashAlgorithm.Create(hashMethod) ?? throw new ResourceNotFoundException(nameof(hashMethod)); + using var h = HashAlgorithm.Create(hashMethod) ?? throw new ResourceNotFoundException($"Unknown hash method: {hashMethod}."); if (salt.Length == 0) { return h.ComputeHash(bytes); diff --git a/Emby.Server.Implementations/Session/WebSocketController.cs b/Emby.Server.Implementations/Session/WebSocketController.cs index 5268ea1b9..f9c6a13c6 100644 --- a/Emby.Server.Implementations/Session/WebSocketController.cs +++ b/Emby.Server.Implementations/Session/WebSocketController.cs @@ -58,7 +58,7 @@ namespace Emby.Server.Implementations.Session private void OnConnectionClosed(object? sender, EventArgs e) { - var connection = sender as IWebSocketConnection ?? throw new ResourceNotFoundException(nameof(sender)); + var connection = sender as IWebSocketConnection ?? throw new ArgumentException($"{nameof(sender)} is not of type {nameof(IWebSocketConnection)}", nameof(sender)); _logger.LogDebug("Removing websocket from session {Session}", _session.Id); _sockets.Remove(connection); connection.Closed -= OnConnectionClosed; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 783deebdc..6e59da798 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1348,7 +1348,7 @@ namespace Jellyfin.Api.Controllers var mapArgs = state.IsOutputVideo ? _encodingHelper.GetMapArgs(state) : string.Empty; - var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); + var directory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath)); var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + GetSegmentFileExtension(state.Request.SegmentContainer); @@ -1568,7 +1568,7 @@ namespace Jellyfin.Api.Controllers private string GetSegmentPath(StreamState state, string playlist, int index) { - var folder = Path.GetDirectoryName(playlist) ?? throw new ResourceNotFoundException(nameof(playlist)); + var folder = Path.GetDirectoryName(playlist) ?? throw new ArgumentException($"Provided path ({playlist}) is not valid.", nameof(playlist)); var filename = Path.GetFileNameWithoutExtension(playlist); return Path.Combine(folder, filename + index.ToString(CultureInfo.InvariantCulture) + GetSegmentFileExtension(state.Request.SegmentContainer)); diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index b9adcd380..3b75e8d43 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -136,7 +136,7 @@ namespace Jellyfin.Api.Controllers .FirstOrDefault(i => string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1) - ?? throw new ResourceNotFoundException(nameof(transcodeFolderPath)); + ?? throw new ResourceNotFoundException($"Provided path ({transcodeFolderPath}) is not valid."); return GetFileResult(file, playlistPath); } diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index a0d9bfb54..a7c1a6388 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -342,7 +342,7 @@ namespace Jellyfin.Api.Controllers var ext = result.Content.Headers.ContentType.MediaType.Split('/')[^1]; var fullCachePath = GetFullCachePath(urlHash + "." + ext); - var directory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException(nameof(fullCachePath)); + var directory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); Directory.CreateDirectory(directory); using (var stream = result.Content) { @@ -357,7 +357,7 @@ namespace Jellyfin.Api.Controllers await stream.CopyToAsync(fileStream).ConfigureAwait(false); } - var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ResourceNotFoundException(nameof(pointerCachePath)); + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath).ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/RemoteImageController.cs b/Jellyfin.Api/Controllers/RemoteImageController.cs index b4a9e5582..c2bfab175 100644 --- a/Jellyfin.Api/Controllers/RemoteImageController.cs +++ b/Jellyfin.Api/Controllers/RemoteImageController.cs @@ -257,12 +257,12 @@ namespace Jellyfin.Api.Controllers var ext = response.Content.Headers.ContentType.MediaType.Split('/').Last(); var fullCachePath = GetFullCachePath(urlHash + "." + ext); - var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException(nameof(fullCachePath)); + var fullCacheDirectory = Path.GetDirectoryName(fullCachePath) ?? throw new ResourceNotFoundException($"Provided path ({fullCachePath}) is not valid."); Directory.CreateDirectory(fullCacheDirectory); await using var fileStream = new FileStream(fullCachePath, FileMode.Create, FileAccess.Write, FileShare.Read, IODefaults.FileStreamBufferSize, true); await response.Content.CopyToAsync(fileStream).ConfigureAwait(false); - var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ResourceNotFoundException(nameof(pointerCachePath)); + var pointerCacheDirectory = Path.GetDirectoryName(pointerCachePath) ?? throw new ArgumentException($"Provided path ({pointerCachePath}) is not valid.", nameof(pointerCachePath)); Directory.CreateDirectory(pointerCacheDirectory); await System.IO.File.WriteAllTextAsync(pointerCachePath, fullCachePath, CancellationToken.None) .ConfigureAwait(false); diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index cc538f15e..389dc8a08 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -362,7 +362,7 @@ namespace Jellyfin.Api.Controllers var threads = _encodingHelper.GetNumberOfThreads(state, _encodingOptions, videoCodec); var inputModifier = _encodingHelper.GetInputModifier(state, _encodingOptions); var format = !string.IsNullOrWhiteSpace(state.Request.SegmentContainer) ? "." + state.Request.SegmentContainer : ".ts"; - var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); + var directory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath)); var outputTsArg = Path.Combine(directory, Path.GetFileNameWithoutExtension(outputPath)) + "%d" + format; var segmentFormat = format.TrimStart('.'); diff --git a/Jellyfin.Api/Helpers/HlsHelpers.cs b/Jellyfin.Api/Helpers/HlsHelpers.cs index bcf0da319..7fd784806 100644 --- a/Jellyfin.Api/Helpers/HlsHelpers.cs +++ b/Jellyfin.Api/Helpers/HlsHelpers.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using System.Threading; using System.Threading.Tasks; -using MediaBrowser.Common.Extensions; using MediaBrowser.Model.IO; using Microsoft.Extensions.Logging; @@ -45,8 +44,12 @@ namespace Jellyfin.Api.Helpers while (!reader.EndOfStream) { - var line = await reader.ReadLineAsync().ConfigureAwait(false) - ?? throw new ResourceNotFoundException(nameof(reader)); + var line = await reader.ReadLineAsync().ConfigureAwait(false); + if (line == null) + { + // Nothing currently in buffer. + continue; + } if (line.IndexOf("#EXTINF:", StringComparison.OrdinalIgnoreCase) != -1) { diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 846624183..168dc27a8 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -196,7 +196,7 @@ namespace Jellyfin.Api.Helpers /// The state. private async void OnTranscodeKillTimerStopped(object? state) { - var job = state as TranscodingJobDto ?? throw new ResourceNotFoundException(nameof(state)); + var job = state as TranscodingJobDto ?? throw new ArgumentException($"{nameof(state)} is not of type {nameof(TranscodingJobDto)}", nameof(state)); if (!job.HasExited && job.Type != TranscodingJobType.Progressive) { var timeSinceLastPing = (DateTime.UtcNow - job.LastPingDate).TotalMilliseconds; @@ -489,7 +489,7 @@ namespace Jellyfin.Api.Helpers CancellationTokenSource cancellationTokenSource, string? workingDirectory = null) { - var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); + var directory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath)); Directory.CreateDirectory(directory); await AcquireResources(state, cancellationTokenSource).ConfigureAwait(false); diff --git a/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/Jellyfin.Drawing.Skia/SkiaEncoder.cs index 0c90d04a7..ee60748c7 100644 --- a/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -228,7 +228,7 @@ namespace Jellyfin.Drawing.Skia } var tempPath = Path.Combine(_appPaths.TempDirectory, Guid.NewGuid() + Path.GetExtension(path)); - var directory = Path.GetDirectoryName(tempPath) ?? throw new ResourceNotFoundException(nameof(tempPath)); + var directory = Path.GetDirectoryName(tempPath) ?? throw new ResourceNotFoundException($"Provided path ({tempPath}) is not valid."); Directory.CreateDirectory(directory); File.Copy(path, tempPath, true); @@ -494,7 +494,7 @@ namespace Jellyfin.Drawing.Skia // If all we're doing is resizing then we can stop now if (!hasBackgroundColor && !hasForegroundColor && blur == 0 && !hasIndicator) { - var outputDirectory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); + var outputDirectory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath)); Directory.CreateDirectory(outputDirectory); using var outputStream = new SKFileWStream(outputPath); using var pixmap = new SKPixmap(new SKImageInfo(width, height), resizedBitmap.GetPixels()); @@ -542,7 +542,7 @@ namespace Jellyfin.Drawing.Skia DrawIndicator(canvas, width, height, options); } - var directory = Path.GetDirectoryName(outputPath) ?? throw new ResourceNotFoundException(nameof(outputPath)); + var directory = Path.GetDirectoryName(outputPath) ?? throw new ArgumentException($"Provided path ({outputPath}) is not valid.", nameof(outputPath)); Directory.CreateDirectory(directory); using (var outputStream = new SKFileWStream(outputPath)) { diff --git a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs index 7f2490404..e71d419e0 100644 --- a/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs +++ b/Jellyfin.Server.Implementations/Users/DefaultPasswordResetProvider.cs @@ -58,7 +58,7 @@ namespace Jellyfin.Server.Implementations.Users await using (var str = File.OpenRead(resetFile)) { spr = await JsonSerializer.DeserializeAsync(str).ConfigureAwait(false) - ?? throw new ResourceNotFoundException(nameof(spr)); + ?? throw new ResourceNotFoundException($"Provided path ({resetFile}) is not valid."); } if (spr.ExpirationDate < DateTime.UtcNow) diff --git a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs index 2c9c9ccaa..396206658 100644 --- a/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs +++ b/MediaBrowser.LocalMetadata/Savers/BaseXmlSaver.cs @@ -128,7 +128,7 @@ namespace MediaBrowser.LocalMetadata.Savers private void SaveToFile(Stream stream, string path) { - var directory = Path.GetDirectoryName(path) ?? throw new ResourceNotFoundException(nameof(path)); + var directory = Path.GetDirectoryName(path) ?? throw new ArgumentException($"Provided path ({path}) is not valid.", nameof(path)); Directory.CreateDirectory(directory); // On Windows, savint the file will fail if the file is hidden or readonly FileSystem.SetAttributes(path, false, false); -- cgit v1.2.3 From fe8531f74e1152086673026840e244d66054acd4 Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 19 Nov 2020 16:15:20 -0700 Subject: Fix live tv hls playback --- Jellyfin.Api/Controllers/HlsSegmentController.cs | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 3b75e8d43..f6359f8e4 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -132,13 +132,25 @@ namespace Jellyfin.Api.Controllers var normalizedPlaylistId = playlistId; - var playlistPath = _fileSystem.GetFilePaths(transcodeFolderPath) - .FirstOrDefault(i => - string.Equals(Path.GetExtension(i), ".m3u8", StringComparison.OrdinalIgnoreCase) - && i.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1) - ?? throw new ResourceNotFoundException($"Provided path ({transcodeFolderPath}) is not valid."); + var filePaths = _fileSystem.GetFilePaths(transcodeFolderPath); + // Add . to start of segment container for future use. + segmentContainer = segmentContainer.Insert(0, "."); + string? playlistPath = null; + foreach (var path in filePaths) + { + var pathExtension = Path.GetExtension(path); + if ((string.Equals(pathExtension, segmentContainer, StringComparison.OrdinalIgnoreCase) + || string.Equals(pathExtension, ".m3u8", StringComparison.OrdinalIgnoreCase)) + && path.IndexOf(normalizedPlaylistId, StringComparison.OrdinalIgnoreCase) != -1) + { + playlistPath = path; + break; + } + } - return GetFileResult(file, playlistPath); + return playlistPath == null + ? NotFound("Hls segment not found.") + : GetFileResult(file, playlistPath); } private ActionResult GetFileResult(string path, string playlistPath) -- cgit v1.2.3 From d58e435409afc013ff6d31c2d99c9b32078bbe96 Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 19 Nov 2020 16:16:23 -0700 Subject: Add response code documentation --- Jellyfin.Api/Controllers/HlsSegmentController.cs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index f6359f8e4..ccdbbb297 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -112,11 +112,13 @@ namespace Jellyfin.Api.Controllers /// The segment id. /// The segment container. /// Hls video segment returned. + /// Hls segment not found. /// A containing the video segment. // Can't require authentication just yet due to seeing some requests come from Chrome without full query string // [Authenticated] [HttpGet("Videos/{itemId}/hls/{playlistId}/{segmentId}.{segmentContainer}")] [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesVideoFile] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "itemId", Justification = "Required for ServiceStack")] public ActionResult GetHlsVideoSegmentLegacy( -- cgit v1.2.3 From f5973d57e8c070692450f0e04e01615c78c954d9 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sat, 21 Nov 2020 14:26:03 +0100 Subject: Remove UTF8 bom from some files --- Jellyfin.Api/Controllers/ApiKeyController.cs | 2 +- Jellyfin.Api/Controllers/ArtistsController.cs | 2 +- Jellyfin.Api/Controllers/BrandingController.cs | 2 +- Jellyfin.Api/Controllers/CollectionController.cs | 2 +- Jellyfin.Api/Controllers/DashboardController.cs | 2 +- Jellyfin.Api/Controllers/FilterController.cs | 2 +- Jellyfin.Api/Controllers/GenresController.cs | 2 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 2 +- Jellyfin.Api/Controllers/ImageController.cs | 2 +- Jellyfin.Api/Controllers/InstantMixController.cs | 2 +- Jellyfin.Api/Controllers/ItemLookupController.cs | 2 +- Jellyfin.Api/Controllers/ItemUpdateController.cs | 2 +- Jellyfin.Api/Controllers/LocalizationController.cs | 2 +- Jellyfin.Api/Controllers/MediaInfoController.cs | 2 +- Jellyfin.Api/Controllers/MoviesController.cs | 2 +- Jellyfin.Api/Controllers/MusicGenresController.cs | 2 +- Jellyfin.Api/Controllers/PersonsController.cs | 2 +- Jellyfin.Api/Controllers/PlaylistsController.cs | 2 +- Jellyfin.Api/Controllers/PlaystateController.cs | 2 +- Jellyfin.Api/Controllers/PluginsController.cs | 2 +- Jellyfin.Api/Controllers/StudiosController.cs | 2 +- Jellyfin.Api/Controllers/SuggestionsController.cs | 2 +- Jellyfin.Api/Controllers/SyncPlayController.cs | 2 +- Jellyfin.Api/Controllers/SystemController.cs | 2 +- Jellyfin.Api/Controllers/TimeSyncController.cs | 2 +- Jellyfin.Api/Controllers/UniversalAudioController.cs | 2 +- Jellyfin.Api/Controllers/UserController.cs | 2 +- Jellyfin.Api/Controllers/UserViewsController.cs | 2 +- Jellyfin.Api/Controllers/YearsController.cs | 2 +- 29 files changed, 29 insertions(+), 29 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/ApiKeyController.cs b/Jellyfin.Api/Controllers/ApiKeyController.cs index e8d6ccdf2..8c43d786a 100644 --- a/Jellyfin.Api/Controllers/ApiKeyController.cs +++ b/Jellyfin.Api/Controllers/ApiKeyController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Globalization; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index f684c649a..c65dc8620 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/BrandingController.cs b/Jellyfin.Api/Controllers/BrandingController.cs index 1d4836f27..d3ea41201 100644 --- a/Jellyfin.Api/Controllers/BrandingController.cs +++ b/Jellyfin.Api/Controllers/BrandingController.cs @@ -1,4 +1,4 @@ -using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Configuration; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Branding; using Microsoft.AspNetCore.Http; diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 2a342c2cb..2a7b2b5c6 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index a859ac114..ccc81dfc5 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index c97a1ed14..31cb9e273 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.ModelBinders; diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index 2dd504770..d2b41e0a8 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index ccdbbb297..f51987732 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.IO; diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index 366f70163..f48c1df72 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index d17a26db4..6913afd0f 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index a7c1a6388..6c38f77ce 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index 0a6ed31ae..9e1a39853 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Jellyfin.Api/Controllers/LocalizationController.cs b/Jellyfin.Api/Controllers/LocalizationController.cs index ef2e7e8b1..3d8b9e0ca 100644 --- a/Jellyfin.Api/Controllers/LocalizationController.cs +++ b/Jellyfin.Api/Controllers/LocalizationController.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Jellyfin.Api.Constants; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Globalization; diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 186024585..b42e6686e 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Buffers; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Jellyfin.Api/Controllers/MoviesController.cs b/Jellyfin.Api/Controllers/MoviesController.cs index ebc148fe5..75dfd4e68 100644 --- a/Jellyfin.Api/Controllers/MoviesController.cs +++ b/Jellyfin.Api/Controllers/MoviesController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Globalization; using System.Linq; diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 8c6104302..e7d0a61c5 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index 9dc79b388..aaad36551 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index bc47ecbd1..3e55434c0 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index 5c15e9a0d..7a60b0deb 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index 0f8ceba29..98f1bc2d2 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index af28b4f59..5090bf1de 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index 69292186e..9f1dec712 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs index e16a10ba4..346431e60 100644 --- a/Jellyfin.Api/Controllers/SyncPlayController.cs +++ b/Jellyfin.Api/Controllers/SyncPlayController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index 4cb1984a2..92875d735 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; diff --git a/Jellyfin.Api/Controllers/TimeSyncController.cs b/Jellyfin.Api/Controllers/TimeSyncController.cs index 2dc744e7c..27c7186fc 100644 --- a/Jellyfin.Api/Controllers/TimeSyncController.cs +++ b/Jellyfin.Api/Controllers/TimeSyncController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Globalization; using MediaBrowser.Model.SyncPlay; using Microsoft.AspNetCore.Http; diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 255532307..34c9f32fa 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; diff --git a/Jellyfin.Api/Controllers/UserController.cs b/Jellyfin.Api/Controllers/UserController.cs index 0f7c25d0e..9805b84b1 100644 --- a/Jellyfin.Api/Controllers/UserController.cs +++ b/Jellyfin.Api/Controllers/UserController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index 60fd1df01..e1483ce9d 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Globalization; diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 9c3ecb4ce..ec7c3de97 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; -- cgit v1.2.3 From 223b42aed3395f7d01ea513bf352cdf4fd3e7002 Mon Sep 17 00:00:00 2001 From: crobibero Date: Wed, 10 Feb 2021 17:09:23 -0700 Subject: Create BaseItemKind enum --- Emby.Server.Implementations/Dto/DtoService.cs | 4 +- Jellyfin.Api/Controllers/ArtistsController.cs | 18 +- Jellyfin.Api/Controllers/CollectionController.cs | 1 - Jellyfin.Api/Controllers/DashboardController.cs | 6 - Jellyfin.Api/Controllers/DynamicHlsController.cs | 1 - Jellyfin.Api/Controllers/FilterController.cs | 37 ++--- Jellyfin.Api/Controllers/GenresController.cs | 9 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 2 - Jellyfin.Api/Controllers/InstantMixController.cs | 1 - Jellyfin.Api/Controllers/ItemLookupController.cs | 2 - Jellyfin.Api/Controllers/ItemsController.cs | 27 ++- Jellyfin.Api/Controllers/LibraryController.cs | 1 - Jellyfin.Api/Controllers/MusicGenresController.cs | 9 +- Jellyfin.Api/Controllers/PackageController.cs | 1 - Jellyfin.Api/Controllers/PersonsController.cs | 1 - Jellyfin.Api/Controllers/PlaylistsController.cs | 1 - Jellyfin.Api/Controllers/PluginsController.cs | 2 - Jellyfin.Api/Controllers/SearchController.cs | 9 +- Jellyfin.Api/Controllers/StudiosController.cs | 9 +- Jellyfin.Api/Controllers/SuggestionsController.cs | 1 - Jellyfin.Api/Controllers/SyncPlayController.cs | 1 - Jellyfin.Api/Controllers/SystemController.cs | 1 - Jellyfin.Api/Controllers/TimeSyncController.cs | 1 - Jellyfin.Api/Controllers/TrailersController.cs | 4 +- Jellyfin.Api/Controllers/TvShowsController.cs | 1 - Jellyfin.Api/Controllers/UserLibraryController.cs | 5 +- Jellyfin.Api/Controllers/UserViewsController.cs | 1 - Jellyfin.Api/Controllers/VideoHlsController.cs | 1 - Jellyfin.Api/Controllers/YearsController.cs | 15 +- Jellyfin.Api/Helpers/RequestHelpers.cs | 16 ++ Jellyfin.Data/Enums/BaseItemKind.cs | 190 ++++++++++++++++++++++ MediaBrowser.Controller/Entities/BaseItem.cs | 5 + MediaBrowser.Model/Dto/BaseItemDto.cs | 3 +- 33 files changed, 289 insertions(+), 97 deletions(-) create mode 100644 Jellyfin.Data/Enums/BaseItemKind.cs (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index e3ab0d6ea..54b18a8c8 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -249,7 +249,7 @@ namespace Emby.Server.Implementations.Dto var activeRecording = liveTvManager.GetActiveRecordingInfo(item.Path); if (activeRecording != null) { - dto.Type = "Recording"; + dto.Type = BaseItemKind.Recording; dto.CanDownload = false; dto.RunTimeTicks = null; @@ -904,7 +904,7 @@ namespace Emby.Server.Implementations.Dto } } - dto.Type = item.GetClientTypeName(); + dto.Type = item.GetBaseItemKind(); if ((item.CommunityRating ?? 0) > 0) { dto.CommunityRating = item.CommunityRating; diff --git a/Jellyfin.Api/Controllers/ArtistsController.cs b/Jellyfin.Api/Controllers/ArtistsController.cs index fed7ed3e5..4b2e5e7ea 100644 --- a/Jellyfin.Api/Controllers/ArtistsController.cs +++ b/Jellyfin.Api/Controllers/ArtistsController.cs @@ -3,8 +3,10 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; +using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -88,8 +90,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? searchTerm, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters, [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, @@ -127,8 +129,8 @@ namespace Jellyfin.Api.Controllers var query = new InternalItemsQuery(user) { - ExcludeItemTypes = excludeItemTypes, - IncludeItemTypes = includeItemTypes, + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), MediaTypes = mediaTypes, StartIndex = startIndex, Limit = limit, @@ -287,8 +289,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? searchTerm, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters, [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, @@ -326,8 +328,8 @@ namespace Jellyfin.Api.Controllers var query = new InternalItemsQuery(user) { - ExcludeItemTypes = excludeItemTypes, - IncludeItemTypes = includeItemTypes, + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), MediaTypes = mediaTypes, StartIndex = startIndex, Limit = limit, diff --git a/Jellyfin.Api/Controllers/CollectionController.cs b/Jellyfin.Api/Controllers/CollectionController.cs index 2a7b2b5c6..852d1e9cb 100644 --- a/Jellyfin.Api/Controllers/CollectionController.cs +++ b/Jellyfin.Api/Controllers/CollectionController.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using MediaBrowser.Controller.Collections; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index ff7895373..b2baa9cea 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -7,17 +7,11 @@ using Jellyfin.Api.Attributes; using Jellyfin.Api.Models; using MediaBrowser.Common.Plugins; using MediaBrowser.Controller; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Extensions; -using MediaBrowser.Controller.Plugins; using MediaBrowser.Model.Net; using MediaBrowser.Model.Plugins; using Microsoft.AspNetCore.Http; -using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Mvc; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; -using Microsoft.Net.Http.Headers; namespace Jellyfin.Api.Controllers { diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index 6e85737d2..e375645cf 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -15,7 +15,6 @@ using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; diff --git a/Jellyfin.Api/Controllers/FilterController.cs b/Jellyfin.Api/Controllers/FilterController.cs index 9220b988f..223b2a2b6 100644 --- a/Jellyfin.Api/Controllers/FilterController.cs +++ b/Jellyfin.Api/Controllers/FilterController.cs @@ -1,13 +1,12 @@ using System; using System.Linq; using Jellyfin.Api.Constants; +using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Entities.Movies; using MediaBrowser.Controller.Library; -using MediaBrowser.Controller.Playlists; using MediaBrowser.Model.Dto; using MediaBrowser.Model.Querying; using Microsoft.AspNetCore.Authorization; @@ -51,7 +50,7 @@ namespace Jellyfin.Api.Controllers public ActionResult GetQueryFiltersLegacy( [FromQuery] Guid? userId, [FromQuery] Guid? parentId, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes) { var user = userId.HasValue && !userId.Equals(Guid.Empty) @@ -60,10 +59,10 @@ namespace Jellyfin.Api.Controllers BaseItem? item = null; if (includeItemTypes.Length != 1 - || !(string.Equals(includeItemTypes[0], nameof(BoxSet), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], nameof(Playlist), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], nameof(Trailer), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], "Program", StringComparison.OrdinalIgnoreCase))) + || !(includeItemTypes[0] == BaseItemKind.BoxSet + || includeItemTypes[0] == BaseItemKind.Playlist + || includeItemTypes[0] == BaseItemKind.Trailer + || includeItemTypes[0] == BaseItemKind.Program)) { item = _libraryManager.GetParentItem(parentId, user?.Id); } @@ -72,7 +71,7 @@ namespace Jellyfin.Api.Controllers { User = user, MediaTypes = mediaTypes, - IncludeItemTypes = includeItemTypes, + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), Recursive = true, EnableTotalRecordCount = false, DtoOptions = new DtoOptions @@ -137,7 +136,7 @@ namespace Jellyfin.Api.Controllers public ActionResult GetQueryFilters( [FromQuery] Guid? userId, [FromQuery] Guid? parentId, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery] bool? isAiring, [FromQuery] bool? isMovie, [FromQuery] bool? isSports, @@ -152,10 +151,10 @@ namespace Jellyfin.Api.Controllers BaseItem? parentItem = null; if (includeItemTypes.Length == 1 - && (string.Equals(includeItemTypes[0], nameof(BoxSet), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], nameof(Playlist), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], nameof(Trailer), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], "Program", StringComparison.OrdinalIgnoreCase))) + && (includeItemTypes[0] == BaseItemKind.BoxSet + || includeItemTypes[0] == BaseItemKind.Playlist + || includeItemTypes[0] == BaseItemKind.Trailer + || includeItemTypes[0] == BaseItemKind.Program)) { parentItem = null; } @@ -167,7 +166,7 @@ namespace Jellyfin.Api.Controllers var filters = new QueryFilters(); var genreQuery = new InternalItemsQuery(user) { - IncludeItemTypes = includeItemTypes, + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), DtoOptions = new DtoOptions { Fields = Array.Empty(), @@ -192,10 +191,10 @@ namespace Jellyfin.Api.Controllers } if (includeItemTypes.Length == 1 - && (string.Equals(includeItemTypes[0], nameof(MusicAlbum), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], nameof(MusicVideo), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], nameof(MusicArtist), StringComparison.OrdinalIgnoreCase) - || string.Equals(includeItemTypes[0], nameof(Audio), StringComparison.OrdinalIgnoreCase))) + && (includeItemTypes[0] == BaseItemKind.MusicAlbum + || includeItemTypes[0] == BaseItemKind.MusicVideo + || includeItemTypes[0] == BaseItemKind.MusicArtist + || includeItemTypes[0] == BaseItemKind.Audio)) { filters.Genres = _libraryManager.GetMusicGenres(genreQuery).Items.Select(i => new NameGuidPair { diff --git a/Jellyfin.Api/Controllers/GenresController.cs b/Jellyfin.Api/Controllers/GenresController.cs index b6755ed5e..7bcf4674c 100644 --- a/Jellyfin.Api/Controllers/GenresController.cs +++ b/Jellyfin.Api/Controllers/GenresController.cs @@ -6,6 +6,7 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -74,8 +75,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? searchTerm, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery] bool? isFavorite, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, @@ -96,8 +97,8 @@ namespace Jellyfin.Api.Controllers var query = new InternalItemsQuery(user) { - ExcludeItemTypes = excludeItemTypes, - IncludeItemTypes = includeItemTypes, + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), StartIndex = startIndex, Limit = limit, IsFavorite = isFavorite, diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index f51987732..25abe73ed 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -2,13 +2,11 @@ using System; using System.ComponentModel.DataAnnotations; using System.Diagnostics.CodeAnalysis; using System.IO; -using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.MediaEncoding; using MediaBrowser.Model.IO; diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 244625752..f061755c3 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.ModelBinders; diff --git a/Jellyfin.Api/Controllers/ItemLookupController.cs b/Jellyfin.Api/Controllers/ItemLookupController.cs index 6c38f77ce..dfc68ffce 100644 --- a/Jellyfin.Api/Controllers/ItemLookupController.cs +++ b/Jellyfin.Api/Controllers/ItemLookupController.cs @@ -2,8 +2,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.IO; -using System.Linq; -using System.Net.Mime; using System.Text.Json; using System.Threading; using System.Threading.Tasks; diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 7d7747495..2c9760f6d 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -1,6 +1,5 @@ using System; using System.ComponentModel.DataAnnotations; -using System.Globalization; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; @@ -178,8 +177,8 @@ namespace Jellyfin.Api.Controllers [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters, [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, @@ -233,8 +232,8 @@ namespace Jellyfin.Api.Controllers .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); if (includeItemTypes.Length == 1 - && (includeItemTypes[0].Equals("Playlist", StringComparison.OrdinalIgnoreCase) - || includeItemTypes[0].Equals("BoxSet", StringComparison.OrdinalIgnoreCase))) + && (includeItemTypes[0] == BaseItemKind.Playlist + || includeItemTypes[0] == BaseItemKind.BoxSet)) { parentId = null; } @@ -251,7 +250,7 @@ namespace Jellyfin.Api.Controllers && string.Equals(hasCollectionType.CollectionType, CollectionType.Playlists, StringComparison.OrdinalIgnoreCase)) { recursive = true; - includeItemTypes = new[] { "Playlist" }; + includeItemTypes = new[] { BaseItemKind.Playlist }; } var enabledChannels = user!.GetPreferenceValues(PreferenceKind.EnabledChannels); @@ -286,8 +285,8 @@ namespace Jellyfin.Api.Controllers { IsPlayed = isPlayed, MediaTypes = mediaTypes, - IncludeItemTypes = includeItemTypes, - ExcludeItemTypes = excludeItemTypes, + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), Recursive = recursive ?? false, OrderBy = RequestHelpers.GetOrderBy(sortBy, sortOrder), IsFavorite = isFavorite, @@ -611,8 +610,8 @@ namespace Jellyfin.Api.Controllers [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters, [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, @@ -773,8 +772,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery] bool enableTotalRecordCount = true, [FromQuery] bool? enableImages = true) { @@ -810,8 +809,8 @@ namespace Jellyfin.Api.Controllers CollapseBoxSetItems = false, EnableTotalRecordCount = enableTotalRecordCount, AncestorIds = ancestorIds, - IncludeItemTypes = includeItemTypes, - ExcludeItemTypes = excludeItemTypes, + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), SearchTerm = searchTerm }); diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index 28d359ac3..db4aa9668 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -11,7 +11,6 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.LibraryDtos; using Jellyfin.Data.Entities; diff --git a/Jellyfin.Api/Controllers/MusicGenresController.cs b/Jellyfin.Api/Controllers/MusicGenresController.cs index 2608a9cd0..7f7058b5e 100644 --- a/Jellyfin.Api/Controllers/MusicGenresController.cs +++ b/Jellyfin.Api/Controllers/MusicGenresController.cs @@ -6,6 +6,7 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.Audio; @@ -74,8 +75,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? searchTerm, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery] bool? isFavorite, [FromQuery] int? imageTypeLimit, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ImageType[] enableImageTypes, @@ -96,8 +97,8 @@ namespace Jellyfin.Api.Controllers var query = new InternalItemsQuery(user) { - ExcludeItemTypes = excludeItemTypes, - IncludeItemTypes = includeItemTypes, + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), StartIndex = startIndex, Limit = limit, IsFavorite = isFavorite, diff --git a/Jellyfin.Api/Controllers/PackageController.cs b/Jellyfin.Api/Controllers/PackageController.cs index c589f54ac..5dd49ef2f 100644 --- a/Jellyfin.Api/Controllers/PackageController.cs +++ b/Jellyfin.Api/Controllers/PackageController.cs @@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; using Jellyfin.Api.Constants; -using MediaBrowser.Common.Json; using MediaBrowser.Common.Updates; using MediaBrowser.Controller.Configuration; using MediaBrowser.Model.Updates; diff --git a/Jellyfin.Api/Controllers/PersonsController.cs b/Jellyfin.Api/Controllers/PersonsController.cs index 17e631197..70a94e27c 100644 --- a/Jellyfin.Api/Controllers/PersonsController.cs +++ b/Jellyfin.Api/Controllers/PersonsController.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Controllers/PlaylistsController.cs b/Jellyfin.Api/Controllers/PlaylistsController.cs index a55e4ad2f..1667d6ede 100644 --- a/Jellyfin.Api/Controllers/PlaylistsController.cs +++ b/Jellyfin.Api/Controllers/PlaylistsController.cs @@ -6,7 +6,6 @@ using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.PlaylistDtos; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Controllers/PluginsController.cs b/Jellyfin.Api/Controllers/PluginsController.cs index b73611c97..b2e8bee91 100644 --- a/Jellyfin.Api/Controllers/PluginsController.cs +++ b/Jellyfin.Api/Controllers/PluginsController.cs @@ -1,10 +1,8 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Globalization; using System.IO; using System.Linq; -using System.Net.Mime; using System.Text.Json; using System.Threading.Tasks; using Jellyfin.Api.Attributes; diff --git a/Jellyfin.Api/Controllers/SearchController.cs b/Jellyfin.Api/Controllers/SearchController.cs index 08255ff8f..6c22050a7 100644 --- a/Jellyfin.Api/Controllers/SearchController.cs +++ b/Jellyfin.Api/Controllers/SearchController.cs @@ -6,6 +6,7 @@ using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Drawing; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -83,8 +84,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? limit, [FromQuery] Guid? userId, [FromQuery, Required] string searchTerm, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, [FromQuery] Guid? parentId, [FromQuery] bool? isMovie, @@ -109,8 +110,8 @@ namespace Jellyfin.Api.Controllers IncludeStudios = includeStudios, StartIndex = startIndex, UserId = userId ?? Guid.Empty, - IncludeItemTypes = includeItemTypes, - ExcludeItemTypes = excludeItemTypes, + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), MediaTypes = mediaTypes, ParentId = parentId, diff --git a/Jellyfin.Api/Controllers/StudiosController.cs b/Jellyfin.Api/Controllers/StudiosController.cs index bb54c59f6..da8f8b199 100644 --- a/Jellyfin.Api/Controllers/StudiosController.cs +++ b/Jellyfin.Api/Controllers/StudiosController.cs @@ -5,6 +5,7 @@ using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Entities; +using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; @@ -73,8 +74,8 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? searchTerm, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery] bool? isFavorite, [FromQuery] bool? enableUserData, [FromQuery] int? imageTypeLimit, @@ -96,8 +97,8 @@ namespace Jellyfin.Api.Controllers var query = new InternalItemsQuery(user) { - ExcludeItemTypes = excludeItemTypes, - IncludeItemTypes = includeItemTypes, + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), StartIndex = startIndex, Limit = limit, IsFavorite = isFavorite, diff --git a/Jellyfin.Api/Controllers/SuggestionsController.cs b/Jellyfin.Api/Controllers/SuggestionsController.cs index 9f1dec712..a55f13e66 100644 --- a/Jellyfin.Api/Controllers/SuggestionsController.cs +++ b/Jellyfin.Api/Controllers/SuggestionsController.cs @@ -3,7 +3,6 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Data.Enums; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Controllers/SyncPlayController.cs b/Jellyfin.Api/Controllers/SyncPlayController.cs index 82cbe58df..f878f2329 100644 --- a/Jellyfin.Api/Controllers/SyncPlayController.cs +++ b/Jellyfin.Api/Controllers/SyncPlayController.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading; diff --git a/Jellyfin.Api/Controllers/SystemController.cs b/Jellyfin.Api/Controllers/SystemController.cs index e67a27ae3..bbbe5fb8d 100644 --- a/Jellyfin.Api/Controllers/SystemController.cs +++ b/Jellyfin.Api/Controllers/SystemController.cs @@ -5,7 +5,6 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Mime; -using System.Threading; using System.Threading.Tasks; using Jellyfin.Api.Attributes; using Jellyfin.Api.Constants; diff --git a/Jellyfin.Api/Controllers/TimeSyncController.cs b/Jellyfin.Api/Controllers/TimeSyncController.cs index c730ac12b..7df51c7af 100644 --- a/Jellyfin.Api/Controllers/TimeSyncController.cs +++ b/Jellyfin.Api/Controllers/TimeSyncController.cs @@ -1,5 +1,4 @@ using System; -using System.Globalization; using MediaBrowser.Model.SyncPlay; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; diff --git a/Jellyfin.Api/Controllers/TrailersController.cs b/Jellyfin.Api/Controllers/TrailersController.cs index 242b8f068..dd3836551 100644 --- a/Jellyfin.Api/Controllers/TrailersController.cs +++ b/Jellyfin.Api/Controllers/TrailersController.cs @@ -148,7 +148,7 @@ namespace Jellyfin.Api.Controllers [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFilter[] filters, [FromQuery] bool? isFavorite, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, @@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] bool enableTotalRecordCount = true, [FromQuery] bool? enableImages = true) { - var includeItemTypes = new[] { "Trailer" }; + var includeItemTypes = new[] { BaseItemKind.Trailer }; return _itemsController .GetItems( diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index 223f58859..e1c67f830 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; -using System.Globalization; using System.Linq; using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; diff --git a/Jellyfin.Api/Controllers/UserLibraryController.cs b/Jellyfin.Api/Controllers/UserLibraryController.cs index 0e65591cc..1d70406ac 100644 --- a/Jellyfin.Api/Controllers/UserLibraryController.cs +++ b/Jellyfin.Api/Controllers/UserLibraryController.cs @@ -8,6 +8,7 @@ using Jellyfin.Api.Constants; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; +using Jellyfin.Data.Enums; using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Dto; using MediaBrowser.Controller.Entities; @@ -269,7 +270,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid userId, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery] bool? isPlayed, [FromQuery] bool? enableImages, [FromQuery] int? imageTypeLimit, @@ -296,7 +297,7 @@ namespace Jellyfin.Api.Controllers new LatestItemsQuery { GroupItems = groupItems, - IncludeItemTypes = includeItemTypes, + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), IsPlayed = isPlayed, Limit = limit, ParentId = parentId ?? Guid.Empty, diff --git a/Jellyfin.Api/Controllers/UserViewsController.cs b/Jellyfin.Api/Controllers/UserViewsController.cs index e1483ce9d..7bc5ecdf1 100644 --- a/Jellyfin.Api/Controllers/UserViewsController.cs +++ b/Jellyfin.Api/Controllers/UserViewsController.cs @@ -4,7 +4,6 @@ using System.ComponentModel.DataAnnotations; using System.Globalization; using System.Linq; using Jellyfin.Api.Extensions; -using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; using Jellyfin.Api.Models.UserViewDtos; using MediaBrowser.Controller.Dto; diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index 7e743ee0c..ba51aa43e 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -12,7 +12,6 @@ using Jellyfin.Api.Helpers; using Jellyfin.Api.Models.PlaybackDtos; using Jellyfin.Api.Models.StreamingDtos; using MediaBrowser.Common.Configuration; -using MediaBrowser.Common.Extensions; using MediaBrowser.Controller.Configuration; using MediaBrowser.Controller.Devices; using MediaBrowser.Controller.Dlna; diff --git a/Jellyfin.Api/Controllers/YearsController.cs b/Jellyfin.Api/Controllers/YearsController.cs index 7c27752f7..d6dc6650c 100644 --- a/Jellyfin.Api/Controllers/YearsController.cs +++ b/Jellyfin.Api/Controllers/YearsController.cs @@ -74,8 +74,8 @@ namespace Jellyfin.Api.Controllers [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] SortOrder[] sortOrder, [FromQuery] Guid? parentId, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] ItemFields[] fields, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] excludeItemTypes, - [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] includeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] excludeItemTypes, + [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] BaseItemKind[] includeItemTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] mediaTypes, [FromQuery, ModelBinder(typeof(CommaDelimitedArrayModelBinder))] string[] sortBy, [FromQuery] bool? enableUserData, @@ -101,8 +101,8 @@ namespace Jellyfin.Api.Controllers var query = new InternalItemsQuery(user) { - ExcludeItemTypes = excludeItemTypes, - IncludeItemTypes = includeItemTypes, + ExcludeItemTypes = RequestHelpers.GetItemTypeStrings(excludeItemTypes), + IncludeItemTypes = RequestHelpers.GetItemTypeStrings(includeItemTypes), MediaTypes = mediaTypes, DtoOptions = dtoOptions }; @@ -193,16 +193,17 @@ namespace Jellyfin.Api.Controllers return _dtoService.GetBaseItemDto(item, dtoOptions); } - private bool FilterItem(BaseItem f, IReadOnlyCollection excludeItemTypes, IReadOnlyCollection includeItemTypes, IReadOnlyCollection mediaTypes) + private bool FilterItem(BaseItem f, IReadOnlyCollection excludeItemTypes, IReadOnlyCollection includeItemTypes, IReadOnlyCollection mediaTypes) { + var baseItemKind = f.GetBaseItemKind(); // Exclude item types - if (excludeItemTypes.Count > 0 && excludeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)) + if (excludeItemTypes.Count > 0 && excludeItemTypes.Contains(baseItemKind)) { return false; } // Include item types - if (includeItemTypes.Count > 0 && !includeItemTypes.Contains(f.GetType().Name, StringComparer.OrdinalIgnoreCase)) + if (includeItemTypes.Count > 0 && !includeItemTypes.Contains(baseItemKind)) { return false; } diff --git a/Jellyfin.Api/Helpers/RequestHelpers.cs b/Jellyfin.Api/Helpers/RequestHelpers.cs index db0ccc657..94856e03e 100644 --- a/Jellyfin.Api/Helpers/RequestHelpers.cs +++ b/Jellyfin.Api/Helpers/RequestHelpers.cs @@ -129,5 +129,21 @@ namespace Jellyfin.Api.Helpers TotalRecordCount = result.TotalRecordCount }; } + + internal static string[] GetItemTypeStrings(IReadOnlyList itemKinds) + { + if (itemKinds.Count == 0) + { + return Array.Empty(); + } + + var itemTypes = new string[itemKinds.Count]; + for (var i = 0; i < itemKinds.Count; i++) + { + itemTypes[i] = itemKinds[i].ToString(); + } + + return itemTypes; + } } } diff --git a/Jellyfin.Data/Enums/BaseItemKind.cs b/Jellyfin.Data/Enums/BaseItemKind.cs new file mode 100644 index 000000000..aac30279e --- /dev/null +++ b/Jellyfin.Data/Enums/BaseItemKind.cs @@ -0,0 +1,190 @@ +namespace Jellyfin.Data.Enums +{ + /// + /// The base item kind. + /// + /// + /// This enum is generated from all classes that inherit from BaseItem. + /// + public enum BaseItemKind + { + /// + /// Item is aggregate folder. + /// + AggregateFolder, + + /// + /// Item is audio. + /// + Audio, + + /// + /// Item is audio book. + /// + AudioBook, + + /// + /// Item is base plugin folder. + /// + BasePluginFolder, + + /// + /// Item is book. + /// + Book, + + /// + /// Item is box set. + /// + BoxSet, + + /// + /// Item is channel. + /// + Channel, + + /// + /// Item is channel folder item. + /// + ChannelFolderItem, + + /// + /// Item is collection folder. + /// + CollectionFolder, + + /// + /// Item is episode. + /// + Episode, + + /// + /// Item is folder. + /// + Folder, + + /// + /// Item is genre. + /// + Genre, + + /// + /// Item is manual playlists folder. + /// + ManualPlaylistsFolder, + + /// + /// Item is movie. + /// + Movie, + + /// + /// Item is music album. + /// + MusicAlbum, + + /// + /// Item is music artist. + /// + MusicArtist, + + /// + /// Item is music genre. + /// + MusicGenre, + + /// + /// Item is music video. + /// + MusicVideo, + + /// + /// Item is person. + /// + Person, + + /// + /// Item is photo. + /// + Photo, + + /// + /// Item is photo album. + /// + PhotoAlbum, + + /// + /// Item is playlist. + /// + Playlist, + + /// + /// Item is program + /// + Program, + + /// + /// Item is recording. + /// + /// + /// Manually added. + /// + Recording, + + /// + /// Item is season. + /// + Season, + + /// + /// Item is series. + /// + Series, + + /// + /// Item is studio. + /// + Studio, + + /// + /// Item is trailer. + /// + Trailer, + + /// + /// Item is live tv channel. + /// + /// + /// Type is overridden. + /// + TvChannel, + + /// + /// Item is live tv program. + /// + /// + /// Type is overridden. + /// + TvProgram, + + /// + /// Item is user root folder. + /// + UserRootFolder, + + /// + /// Item is user view. + /// + UserView, + + /// + /// Item is video. + /// + Video, + + /// + /// Item is year. + /// + Year + } +} \ No newline at end of file diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index cbb02aabd..7598b29e6 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1998,6 +1998,11 @@ namespace MediaBrowser.Controller.Entities return GetType().Name; } + public BaseItemKind GetBaseItemKind() + { + return Enum.Parse(GetClientTypeName()); + } + /// /// Gets the linked child. /// diff --git a/MediaBrowser.Model/Dto/BaseItemDto.cs b/MediaBrowser.Model/Dto/BaseItemDto.cs index 3f7aac9cd..2f9f9d3cd 100644 --- a/MediaBrowser.Model/Dto/BaseItemDto.cs +++ b/MediaBrowser.Model/Dto/BaseItemDto.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using Jellyfin.Data.Enums; using MediaBrowser.Model.Drawing; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Library; @@ -276,7 +277,7 @@ namespace MediaBrowser.Model.Dto /// Gets or sets the type. /// /// The type. - public string Type { get; set; } + public BaseItemKind Type { get; set; } /// /// Gets or sets the people. -- cgit v1.2.3 From 858c91ab485f79648aa625e89378c6de9e19df4b Mon Sep 17 00:00:00 2001 From: crobibero Date: Thu, 4 Mar 2021 18:25:52 -0700 Subject: Specify defaults or set query parameter to nullable --- Jellyfin.Api/Controllers/AudioController.cs | 8 ++-- Jellyfin.Api/Controllers/DynamicHlsController.cs | 48 +++++++++++----------- Jellyfin.Api/Controllers/HlsSegmentController.cs | 4 +- Jellyfin.Api/Controllers/ImageController.cs | 16 ++++---- Jellyfin.Api/Controllers/ItemUpdateController.cs | 2 +- Jellyfin.Api/Controllers/LibraryController.cs | 2 +- Jellyfin.Api/Controllers/PlaystateController.cs | 20 ++++----- .../Controllers/UniversalAudioController.cs | 2 +- Jellyfin.Api/Controllers/VideoHlsController.cs | 8 ++-- Jellyfin.Api/Controllers/VideosController.cs | 12 +++--- 10 files changed, 62 insertions(+), 60 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/AudioController.cs b/Jellyfin.Api/Controllers/AudioController.cs index 616fe5b91..8b1813b20 100644 --- a/Jellyfin.Api/Controllers/AudioController.cs +++ b/Jellyfin.Api/Controllers/AudioController.cs @@ -122,7 +122,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -174,7 +174,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -287,7 +287,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -339,7 +339,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index e375645cf..f6c23c5aa 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -203,7 +203,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -218,7 +218,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions, [FromQuery] bool enableAdaptiveBitrateStreaming = true) { @@ -255,7 +255,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -270,7 +270,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions, EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming }; @@ -370,7 +370,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -385,7 +385,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions, [FromQuery] bool enableAdaptiveBitrateStreaming = true) { @@ -422,7 +422,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -437,7 +437,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions, EnableAdaptiveBitrateStreaming = enableAdaptiveBitrateStreaming }; @@ -533,7 +533,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -548,7 +548,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions) { var cancellationTokenSource = new CancellationTokenSource(); @@ -585,7 +585,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -600,7 +600,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions }; @@ -698,7 +698,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -713,7 +713,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions) { var cancellationTokenSource = new CancellationTokenSource(); @@ -750,7 +750,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -765,7 +765,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions }; @@ -868,7 +868,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -883,7 +883,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions) { var streamingRequest = new VideoRequestDto @@ -920,7 +920,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -935,7 +935,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions }; @@ -1040,7 +1040,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -1055,7 +1055,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions) { var streamingRequest = new StreamingRequestDto @@ -1092,7 +1092,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -1107,7 +1107,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions }; diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 25abe73ed..d0ed45acb 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -96,7 +96,9 @@ namespace Jellyfin.Api.Controllers [HttpDelete("Videos/ActiveEncodings")] [Authorize(Policy = Policies.DefaultAuthorization)] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult StopEncodingProcess([FromQuery] string deviceId, [FromQuery] string playSessionId) + public ActionResult StopEncodingProcess( + [FromQuery, Required] string deviceId, + [FromQuery, Required] string playSessionId) { _transcodingJobHelper.KillTranscodingJobs(deviceId, playSessionId, path => true); return NoContent(); diff --git a/Jellyfin.Api/Controllers/ImageController.cs b/Jellyfin.Api/Controllers/ImageController.cs index a50d6e46b..cfc038f23 100644 --- a/Jellyfin.Api/Controllers/ImageController.cs +++ b/Jellyfin.Api/Controllers/ImageController.cs @@ -392,7 +392,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] Guid itemId, [FromRoute, Required] ImageType imageType, [FromRoute, Required] int imageIndex, - [FromQuery] int newIndex) + [FromQuery, Required] int newIndex) { var item = _libraryManager.GetItemById(itemId); if (item == null) @@ -741,7 +741,7 @@ namespace Jellyfin.Api.Controllers public async Task GetArtistImage( [FromRoute, Required] string name, [FromRoute, Required] ImageType imageType, - [FromQuery] string tag, + [FromQuery] string? tag, [FromQuery] ImageFormat? format, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, @@ -820,7 +820,7 @@ namespace Jellyfin.Api.Controllers public async Task GetGenreImage( [FromRoute, Required] string name, [FromRoute, Required] ImageType imageType, - [FromQuery] string tag, + [FromQuery] string? tag, [FromQuery] ImageFormat? format, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, @@ -900,7 +900,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string name, [FromRoute, Required] ImageType imageType, [FromRoute, Required] int imageIndex, - [FromQuery] string tag, + [FromQuery] string? tag, [FromQuery] ImageFormat? format, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, @@ -978,7 +978,7 @@ namespace Jellyfin.Api.Controllers public async Task GetMusicGenreImage( [FromRoute, Required] string name, [FromRoute, Required] ImageType imageType, - [FromQuery] string tag, + [FromQuery] string? tag, [FromQuery] ImageFormat? format, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, @@ -1058,7 +1058,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string name, [FromRoute, Required] ImageType imageType, [FromRoute, Required] int imageIndex, - [FromQuery] string tag, + [FromQuery] string? tag, [FromQuery] ImageFormat? format, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, @@ -1136,7 +1136,7 @@ namespace Jellyfin.Api.Controllers public async Task GetPersonImage( [FromRoute, Required] string name, [FromRoute, Required] ImageType imageType, - [FromQuery] string tag, + [FromQuery] string? tag, [FromQuery] ImageFormat? format, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, @@ -1216,7 +1216,7 @@ namespace Jellyfin.Api.Controllers [FromRoute, Required] string name, [FromRoute, Required] ImageType imageType, [FromRoute, Required] int imageIndex, - [FromQuery] string tag, + [FromQuery] string? tag, [FromQuery] ImageFormat? format, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, diff --git a/Jellyfin.Api/Controllers/ItemUpdateController.cs b/Jellyfin.Api/Controllers/ItemUpdateController.cs index 9e1a39853..a9f4a5a58 100644 --- a/Jellyfin.Api/Controllers/ItemUpdateController.cs +++ b/Jellyfin.Api/Controllers/ItemUpdateController.cs @@ -195,7 +195,7 @@ namespace Jellyfin.Api.Controllers [HttpPost("Items/{itemId}/ContentType")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public ActionResult UpdateItemContentType([FromRoute, Required] Guid itemId, [FromQuery] string contentType) + public ActionResult UpdateItemContentType([FromRoute, Required] Guid itemId, [FromQuery] string? contentType) { var item = _libraryManager.GetItemById(itemId); if (item == null) diff --git a/Jellyfin.Api/Controllers/LibraryController.cs b/Jellyfin.Api/Controllers/LibraryController.cs index db4aa9668..3443ebd72 100644 --- a/Jellyfin.Api/Controllers/LibraryController.cs +++ b/Jellyfin.Api/Controllers/LibraryController.cs @@ -777,7 +777,7 @@ namespace Jellyfin.Api.Controllers [ProducesResponseType(StatusCodes.Status200OK)] public ActionResult GetLibraryOptionsInfo( [FromQuery] string? libraryContentType, - [FromQuery] bool isNewLibrary) + [FromQuery] bool isNewLibrary = false) { var result = new LibraryOptionsResultDto(); diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index ec7b84ff6..f256c8c25 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -152,7 +152,7 @@ namespace Jellyfin.Api.Controllers /// A . [HttpPost("Sessions/Playing/Ping")] [ProducesResponseType(StatusCodes.Status204NoContent)] - public ActionResult PingPlaybackSession([FromQuery] string playSessionId) + public ActionResult PingPlaybackSession([FromQuery, Required] string playSessionId) { _transcodingJobHelper.PingTranscodingJob(playSessionId, null); return NoContent(); @@ -202,9 +202,9 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? mediaSourceId, [FromQuery] int? audioStreamIndex, [FromQuery] int? subtitleStreamIndex, - [FromQuery] PlayMethod playMethod, + [FromQuery] PlayMethod? playMethod, [FromQuery] string? liveStreamId, - [FromQuery] string playSessionId, + [FromQuery] string? playSessionId, [FromQuery] bool canSeek = false) { var playbackStartInfo = new PlaybackStartInfo @@ -214,7 +214,7 @@ namespace Jellyfin.Api.Controllers MediaSourceId = mediaSourceId, AudioStreamIndex = audioStreamIndex, SubtitleStreamIndex = subtitleStreamIndex, - PlayMethod = playMethod, + PlayMethod = playMethod ?? PlayMethod.Transcode, PlaySessionId = playSessionId, LiveStreamId = liveStreamId }; @@ -254,10 +254,10 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? audioStreamIndex, [FromQuery] int? subtitleStreamIndex, [FromQuery] int? volumeLevel, - [FromQuery] PlayMethod playMethod, + [FromQuery] PlayMethod? playMethod, [FromQuery] string? liveStreamId, - [FromQuery] string playSessionId, - [FromQuery] RepeatMode repeatMode, + [FromQuery] string? playSessionId, + [FromQuery] RepeatMode? repeatMode, [FromQuery] bool isPaused = false, [FromQuery] bool isMuted = false) { @@ -271,10 +271,10 @@ namespace Jellyfin.Api.Controllers AudioStreamIndex = audioStreamIndex, SubtitleStreamIndex = subtitleStreamIndex, VolumeLevel = volumeLevel, - PlayMethod = playMethod, + PlayMethod = playMethod ?? PlayMethod.Transcode, PlaySessionId = playSessionId, LiveStreamId = liveStreamId, - RepeatMode = repeatMode + RepeatMode = repeatMode ?? RepeatMode.RepeatNone }; playbackProgressInfo.PlayMethod = ValidatePlayMethod(playbackProgressInfo.PlayMethod, playbackProgressInfo.PlaySessionId); @@ -352,7 +352,7 @@ namespace Jellyfin.Api.Controllers return _userDataRepository.GetUserDataDto(item, user); } - private PlayMethod ValidatePlayMethod(PlayMethod method, string playSessionId) + private PlayMethod ValidatePlayMethod(PlayMethod method, string? playSessionId) { if (method == PlayMethod.Transcode) { diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 5aa033ccf..0c2e6f19f 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -112,7 +112,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? maxAudioSampleRate, [FromQuery] int? maxAudioBitDepth, [FromQuery] bool? enableRemoteMedia, - [FromQuery] bool breakOnNonKeyFrames, + [FromQuery] bool breakOnNonKeyFrames = false, [FromQuery] bool enableRedirection = true) { var deviceProfile = GetDeviceProfile(container, transcodingContainer, audioCodec, transcodingProtocol, breakOnNonKeyFrames, transcodingAudioChannels, maxAudioSampleRate, maxAudioBitDepth, maxAudioChannels); diff --git a/Jellyfin.Api/Controllers/VideoHlsController.cs b/Jellyfin.Api/Controllers/VideoHlsController.cs index ba51aa43e..620eef568 100644 --- a/Jellyfin.Api/Controllers/VideoHlsController.cs +++ b/Jellyfin.Api/Controllers/VideoHlsController.cs @@ -198,7 +198,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -213,7 +213,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions, [FromQuery] int? maxWidth, [FromQuery] int? maxHeight, @@ -253,7 +253,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -268,7 +268,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions, MaxHeight = maxHeight, MaxWidth = maxWidth, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 44dc63952..8c7aa7325 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -364,7 +364,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -379,7 +379,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions) { var isHeadRequest = Request.Method == System.Net.WebRequestMethods.Http.Head; @@ -418,7 +418,7 @@ namespace Jellyfin.Api.Controllers Height = height, VideoBitRate = videoBitRate, SubtitleStreamIndex = subtitleStreamIndex, - SubtitleMethod = subtitleMethod, + SubtitleMethod = subtitleMethod ?? SubtitleDeliveryMethod.Encode, MaxRefFrames = maxRefFrames, MaxVideoBitDepth = maxVideoBitDepth, RequireAvc = requireAvc ?? true, @@ -433,7 +433,7 @@ namespace Jellyfin.Api.Controllers TranscodeReasons = transcodeReasons, AudioStreamIndex = audioStreamIndex, VideoStreamIndex = videoStreamIndex, - Context = context, + Context = context ?? EncodingContext.Streaming, StreamOptions = streamOptions }; @@ -620,7 +620,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] int? height, [FromQuery] int? videoBitRate, [FromQuery] int? subtitleStreamIndex, - [FromQuery] SubtitleDeliveryMethod subtitleMethod, + [FromQuery] SubtitleDeliveryMethod? subtitleMethod, [FromQuery] int? maxRefFrames, [FromQuery] int? maxVideoBitDepth, [FromQuery] bool? requireAvc, @@ -635,7 +635,7 @@ namespace Jellyfin.Api.Controllers [FromQuery] string? transcodeReasons, [FromQuery] int? audioStreamIndex, [FromQuery] int? videoStreamIndex, - [FromQuery] EncodingContext context, + [FromQuery] EncodingContext? context, [FromQuery] Dictionary streamOptions) { return GetVideoStream( -- cgit v1.2.3 From f61d18612b2e6c6e9a5dd4510331ac8d89a337d5 Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sat, 20 Mar 2021 00:38:58 +0100 Subject: Fix directory traversal in the HlsSegmentController in a fairly rudimentary but working way. GHSL-2021-050: Issue 1,2,3 Arbitrary file read and directory traversal. The segment id's can probably just be verified to be an actual ID or to not contain any forward or backward slashes --- Jellyfin.Api/Controllers/HlsSegmentController.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index d0ed45acb..5a8542048 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -62,6 +62,13 @@ namespace Jellyfin.Api.Controllers // TODO: Deprecate with new iOS app var file = segmentId + Path.GetExtension(Request.Path); file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); + var transcodePath = _serverConfigurationManager.GetTranscodePath(); + file = Path.GetFullPath(Path.Combine(transcodePath, file)); + var fileDir = Path.GetDirectoryName(file); + if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodePath)) + { + return BadRequest("Invalid segment."); + } return FileStreamResponseHelpers.GetStaticFileResult(file, MimeTypes.GetMimeType(file)!, false, HttpContext); } @@ -82,6 +89,13 @@ namespace Jellyfin.Api.Controllers { var file = playlistId + Path.GetExtension(Request.Path); file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); + var transcodePath = _serverConfigurationManager.GetTranscodePath(); + file = Path.GetFullPath(Path.Combine(transcodePath, file)); + var fileDir = Path.GetDirectoryName(file); + if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodePath) || Path.GetExtension(file) != ".m3u8") + { + return BadRequest("Invalid segment."); + } return GetFileResult(file, file); } @@ -131,6 +145,12 @@ namespace Jellyfin.Api.Controllers var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath(); file = Path.Combine(transcodeFolderPath, file); + file = Path.GetFullPath(Path.Combine(transcodeFolderPath, file)); + var fileDir = Path.GetDirectoryName(file); + if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodeFolderPath)) + { + return BadRequest("Invalid segment."); + } var normalizedPlaylistId = playlistId; -- cgit v1.2.3 From 1f3aa3fe6f72f9b745dac7de5b6f8b877590017c Mon Sep 17 00:00:00 2001 From: Erwin de Haan Date: Sat, 20 Mar 2021 01:28:14 +0100 Subject: Apply review suggestions --- Jellyfin.Api/Controllers/HlsSegmentController.cs | 3 --- 1 file changed, 3 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 5a8542048..473bdc523 100644 --- a/Jellyfin.Api/Controllers/HlsSegmentController.cs +++ b/Jellyfin.Api/Controllers/HlsSegmentController.cs @@ -61,7 +61,6 @@ namespace Jellyfin.Api.Controllers { // TODO: Deprecate with new iOS app var file = segmentId + Path.GetExtension(Request.Path); - file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); var transcodePath = _serverConfigurationManager.GetTranscodePath(); file = Path.GetFullPath(Path.Combine(transcodePath, file)); var fileDir = Path.GetDirectoryName(file); @@ -88,7 +87,6 @@ namespace Jellyfin.Api.Controllers public ActionResult GetHlsPlaylistLegacy([FromRoute, Required] string itemId, [FromRoute, Required] string playlistId) { var file = playlistId + Path.GetExtension(Request.Path); - file = Path.Combine(_serverConfigurationManager.GetTranscodePath(), file); var transcodePath = _serverConfigurationManager.GetTranscodePath(); file = Path.GetFullPath(Path.Combine(transcodePath, file)); var fileDir = Path.GetDirectoryName(file); @@ -144,7 +142,6 @@ namespace Jellyfin.Api.Controllers var file = segmentId + Path.GetExtension(Request.Path); var transcodeFolderPath = _serverConfigurationManager.GetTranscodePath(); - file = Path.Combine(transcodeFolderPath, file); file = Path.GetFullPath(Path.Combine(transcodeFolderPath, file)); var fileDir = Path.GetDirectoryName(file); if (string.IsNullOrEmpty(fileDir) || !fileDir.StartsWith(transcodeFolderPath)) -- cgit v1.2.3 From 7c282ec3694d8e6a127588c41cd0c68f8ee4e93b Mon Sep 17 00:00:00 2001 From: KonH Date: Sun, 3 Oct 2021 10:43:05 +0700 Subject: Fix warning: The nullable warning suppression expression is redundant (#2149) --- .../Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs | 4 ++-- Jellyfin.Api/Controllers/DashboardController.cs | 2 +- Jellyfin.Api/Controllers/DynamicHlsController.cs | 2 +- Jellyfin.Api/Controllers/HlsSegmentController.cs | 4 ++-- Jellyfin.Api/Controllers/InstantMixController.cs | 14 +++++++------- Jellyfin.Api/Controllers/ItemsController.cs | 2 +- Jellyfin.Api/Controllers/MediaInfoController.cs | 2 +- Jellyfin.Api/Controllers/TvShowsController.cs | 8 ++++---- Jellyfin.Api/Controllers/UniversalAudioController.cs | 2 +- Jellyfin.Api/Controllers/VideosController.cs | 2 +- Jellyfin.Api/Helpers/TranscodingJobHelper.cs | 8 ++++---- Jellyfin.Api/Models/StreamingDtos/StreamState.cs | 2 +- .../Security/AuthorizationContext.cs | 2 +- 13 files changed, 27 insertions(+), 27 deletions(-) (limited to 'Jellyfin.Api/Controllers/HlsSegmentController.cs') diff --git a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs index b898ac76c..e6c04eb08 100644 --- a/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs +++ b/Jellyfin.Api/Auth/SyncPlayAccessPolicy/SyncPlayAccessHandler.cs @@ -51,7 +51,7 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy { if (user.SyncPlayAccess == SyncPlayUserAccessType.CreateAndJoinGroups || user.SyncPlayAccess == SyncPlayUserAccessType.JoinGroups - || _syncPlayManager.IsUserActive(userId!.Value)) + || _syncPlayManager.IsUserActive(userId.Value)) { context.Succeed(requirement); } @@ -85,7 +85,7 @@ namespace Jellyfin.Api.Auth.SyncPlayAccessPolicy } else if (requirement.RequiredAccess == SyncPlayAccessRequirementType.IsInGroup) { - if (_syncPlayManager.IsUserActive(userId!.Value)) + if (_syncPlayManager.IsUserActive(userId.Value)) { context.Succeed(requirement); } diff --git a/Jellyfin.Api/Controllers/DashboardController.cs b/Jellyfin.Api/Controllers/DashboardController.cs index 445733c24..87cb418d9 100644 --- a/Jellyfin.Api/Controllers/DashboardController.cs +++ b/Jellyfin.Api/Controllers/DashboardController.cs @@ -53,7 +53,7 @@ namespace Jellyfin.Api.Controllers if (enableInMainMenu.HasValue) { - configPages = configPages.Where(p => p!.EnableInMainMenu == enableInMainMenu.Value).ToList(); + configPages = configPages.Where(p => p.EnableInMainMenu == enableInMainMenu.Value).ToList(); } return configPages; diff --git a/Jellyfin.Api/Controllers/DynamicHlsController.cs b/Jellyfin.Api/Controllers/DynamicHlsController.cs index a54003357..42e82dd5b 100644 --- a/Jellyfin.Api/Controllers/DynamicHlsController.cs +++ b/Jellyfin.Api/Controllers/DynamicHlsController.cs @@ -1709,7 +1709,7 @@ namespace Jellyfin.Api.Controllers return Task.CompletedTask; }); - return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath)!, false, HttpContext); + return FileStreamResponseHelpers.GetStaticFileResult(segmentPath, MimeTypes.GetMimeType(segmentPath), false, HttpContext); } private long GetEndPositionTicks(StreamState state, int requestedIndex) diff --git a/Jellyfin.Api/Controllers/HlsSegmentController.cs b/Jellyfin.Api/Controllers/HlsSegmentController.cs index 473bdc523..71caa0fe0 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), false, HttpContext); } /// @@ -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), false, HttpContext); } } } diff --git a/Jellyfin.Api/Controllers/InstantMixController.cs b/Jellyfin.Api/Controllers/InstantMixController.cs index 4774ed4ef..a6c2e07c9 100644 --- a/Jellyfin.Api/Controllers/InstantMixController.cs +++ b/Jellyfin.Api/Controllers/InstantMixController.cs @@ -80,7 +80,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -116,7 +116,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(album, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -152,7 +152,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(playlist, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -187,7 +187,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromGenres(new[] { name }, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -259,7 +259,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } @@ -332,7 +332,7 @@ namespace Jellyfin.Api.Controllers : null; var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var items = _musicManager.GetInstantMixFromItem(item, user, dtoOptions); return GetResult(items, user, limit, dtoOptions); } diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 52eefc5c2..f0d44e5cc 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -287,7 +287,7 @@ namespace Jellyfin.Api.Controllers if ((recursive.HasValue && recursive.Value) || ids.Length != 0 || item is not UserRootFolder) { - var query = new InternalItemsQuery(user!) + var query = new InternalItemsQuery(user) { IsPlayed = isPlayed, MediaTypes = mediaTypes, diff --git a/Jellyfin.Api/Controllers/MediaInfoController.cs b/Jellyfin.Api/Controllers/MediaInfoController.cs index 7c78928f7..96ef2d678 100644 --- a/Jellyfin.Api/Controllers/MediaInfoController.cs +++ b/Jellyfin.Api/Controllers/MediaInfoController.cs @@ -184,7 +184,7 @@ namespace Jellyfin.Api.Controllers audioStreamIndex, subtitleStreamIndex, maxAudioChannels, - info!.PlaySessionId!, + info.PlaySessionId!, userId ?? Guid.Empty, enableDirectPlay.Value, enableDirectStream.Value, diff --git a/Jellyfin.Api/Controllers/TvShowsController.cs b/Jellyfin.Api/Controllers/TvShowsController.cs index 6eada67cf..5dd773331 100644 --- a/Jellyfin.Api/Controllers/TvShowsController.cs +++ b/Jellyfin.Api/Controllers/TvShowsController.cs @@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers { var options = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes); var result = _tvSeriesManager.GetNextUp( new NextUpQuery @@ -153,7 +153,7 @@ namespace Jellyfin.Api.Controllers var options = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImges, enableUserData, imageTypeLimit, enableImageTypes); var itemsResult = _libraryManager.GetItemList(new InternalItemsQuery(user) { @@ -223,7 +223,7 @@ namespace Jellyfin.Api.Controllers var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); if (seasonId.HasValue) // Season id was supplied. Get episodes by season id. { @@ -350,7 +350,7 @@ namespace Jellyfin.Api.Controllers var dtoOptions = new DtoOptions { Fields = fields } .AddClientFields(Request) - .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes!); + .AddAdditionalDtoOptions(enableImages, enableUserData, imageTypeLimit, enableImageTypes); var returnItems = _dtoService.GetBaseItemDtos(seasons, dtoOptions, user); diff --git a/Jellyfin.Api/Controllers/UniversalAudioController.cs b/Jellyfin.Api/Controllers/UniversalAudioController.cs index 20a02bf4a..bc9527a0b 100644 --- a/Jellyfin.Api/Controllers/UniversalAudioController.cs +++ b/Jellyfin.Api/Controllers/UniversalAudioController.cs @@ -155,7 +155,7 @@ namespace Jellyfin.Api.Controllers null, null, maxAudioChannels, - info!.PlaySessionId!, + info.PlaySessionId!, userId ?? Guid.Empty, true, true, diff --git a/Jellyfin.Api/Controllers/VideosController.cs b/Jellyfin.Api/Controllers/VideosController.cs index 150f22d1b..e1cbc6f33 100644 --- a/Jellyfin.Api/Controllers/VideosController.cs +++ b/Jellyfin.Api/Controllers/VideosController.cs @@ -461,7 +461,7 @@ namespace Jellyfin.Api.Controllers var liveStream = new ProgressiveFileStream(liveStreamInfo.GetStream()); // TODO (moved from MediaBrowser.Api): Don't hardcode contentType - return File(liveStream, MimeTypes.GetMimeType("file.ts")!); + return File(liveStream, MimeTypes.GetMimeType("file.ts")); } // Static remote stream diff --git a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs index 14f287aef..488856c4e 100644 --- a/Jellyfin.Api/Helpers/TranscodingJobHelper.cs +++ b/Jellyfin.Api/Helpers/TranscodingJobHelper.cs @@ -86,8 +86,8 @@ namespace Jellyfin.Api.Helpers DeleteEncodedMediaCache(); - sessionManager!.PlaybackProgress += OnPlaybackProgress; - sessionManager!.PlaybackStart += OnPlaybackProgress; + sessionManager.PlaybackProgress += OnPlaybackProgress; + sessionManager.PlaybackStart += OnPlaybackProgress; } /// @@ -878,8 +878,8 @@ namespace Jellyfin.Api.Helpers if (disposing) { _loggerFactory.Dispose(); - _sessionManager!.PlaybackProgress -= OnPlaybackProgress; - _sessionManager!.PlaybackStart -= OnPlaybackProgress; + _sessionManager.PlaybackProgress -= OnPlaybackProgress; + _sessionManager.PlaybackStart -= OnPlaybackProgress; } } } diff --git a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs index 0f84faeaf..cbabf087b 100644 --- a/Jellyfin.Api/Models/StreamingDtos/StreamState.cs +++ b/Jellyfin.Api/Models/StreamingDtos/StreamState.cs @@ -55,7 +55,7 @@ namespace Jellyfin.Api.Models.StreamingDtos /// /// Gets the video request. /// - public VideoRequestDto? VideoRequest => Request! as VideoRequestDto; + public VideoRequestDto? VideoRequest => Request as VideoRequestDto; /// /// Gets or sets the direct stream provicer. diff --git a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs index 244abf469..ba2cfc724 100644 --- a/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs +++ b/Jellyfin.Server.Implementations/Security/AuthorizationContext.cs @@ -27,7 +27,7 @@ namespace Jellyfin.Server.Implementations.Security { if (requestContext.Request.HttpContext.Items.TryGetValue("AuthorizationInfo", out var cached) && cached != null) { - return Task.FromResult((AuthorizationInfo)cached!); // Cache should never contain null + return Task.FromResult((AuthorizationInfo)cached); // Cache should never contain null } return GetAuthorization(requestContext); -- cgit v1.2.3