mirror of
				https://github.com/jellyfin/jellyfin.git
				synced 2025-10-31 10:37:22 -04:00 
			
		
		
		
	Add missing attributes, fix response codes, fix route parameter casing
This commit is contained in:
		
							parent
							
								
									deac459b62
								
							
						
					
					
						commit
						10ddbc34ec
					
				| @ -68,7 +68,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="key">Configuration key.</param> | ||||
|         /// <response code="200">Configuration returned.</response> | ||||
|         /// <returns>Configuration.</returns> | ||||
|         [HttpGet("Configuration/{Key}")] | ||||
|         [HttpGet("Configuration/{key}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult<object> GetNamedConfiguration([FromRoute] string key) | ||||
|         { | ||||
| @ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="key">Configuration key.</param> | ||||
|         /// <response code="204">Named configuration updated.</response> | ||||
|         /// <returns>Update status.</returns> | ||||
|         [HttpPost("Configuration/{Key}")] | ||||
|         [HttpPost("Configuration/{key}")] | ||||
|         [Authorize(Policy = Policies.RequiresElevation)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public async Task<ActionResult> UpdateNamedConfiguration([FromRoute] string key) | ||||
|  | ||||
| @ -133,6 +133,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the device could not be found.</returns> | ||||
|         [HttpDelete] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult DeleteDevice([FromQuery, BindRequired] string id) | ||||
|         { | ||||
|             var existingDevice = _deviceManager.GetDevice(id); | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| using System.ComponentModel.DataAnnotations; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using System.Threading; | ||||
| using MediaBrowser.Controller.Persistence; | ||||
| using MediaBrowser.Model.Entities; | ||||
| @ -34,9 +35,8 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="client">Client.</param> | ||||
|         /// <response code="200">Display preferences retrieved.</response> | ||||
|         /// <returns>An <see cref="OkResult"/> containing the display preferences on success, or a <see cref="NotFoundResult"/> if the display preferences could not be found.</returns> | ||||
|         [HttpGet("{DisplayPreferencesId}")] | ||||
|         [HttpGet("{displayPreferencesId}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult<DisplayPreferences> GetDisplayPreferences( | ||||
|             [FromRoute] string displayPreferencesId, | ||||
|             [FromQuery] [Required] string userId, | ||||
| @ -52,30 +52,24 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="userId">User Id.</param> | ||||
|         /// <param name="client">Client.</param> | ||||
|         /// <param name="displayPreferences">New Display Preferences object.</param> | ||||
|         /// <response code="200">Display preferences updated.</response> | ||||
|         /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the display preferences could not be found.</returns> | ||||
|         [HttpPost("{DisplayPreferencesId}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(typeof(ModelStateDictionary), StatusCodes.Status400BadRequest)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         /// <response code="204">Display preferences updated.</response> | ||||
|         /// <returns>An <see cref="OkResult"/> on success.</returns> | ||||
|         [HttpPost("{displayPreferencesId}")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")] | ||||
|         public ActionResult UpdateDisplayPreferences( | ||||
|             [FromRoute] string displayPreferencesId, | ||||
|             [FromQuery, BindRequired] string userId, | ||||
|             [FromQuery, BindRequired] string client, | ||||
|             [FromBody, BindRequired] DisplayPreferences displayPreferences) | ||||
|         { | ||||
|             if (displayPreferencesId == null) | ||||
|             { | ||||
|                 // TODO - refactor so parameter doesn't exist or is actually used. | ||||
|             } | ||||
| 
 | ||||
|             _displayPreferencesRepository.SaveDisplayPreferences( | ||||
|                 displayPreferences, | ||||
|                 userId, | ||||
|                 client, | ||||
|                 CancellationToken.None); | ||||
| 
 | ||||
|             return Ok(); | ||||
|             return NoContent(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -58,7 +58,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="200">Image stream retrieved.</response> | ||||
|         /// <response code="404">Image not found.</response> | ||||
|         /// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns> | ||||
|         [HttpGet("General/{Name}/{Type}")] | ||||
|         [HttpGet("General/{name}/{type}")] | ||||
|         [AllowAnonymous] | ||||
|         [Produces(MediaTypeNames.Application.Octet)] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
| @ -103,7 +103,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="200">Image stream retrieved.</response> | ||||
|         /// <response code="404">Image not found.</response> | ||||
|         /// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns> | ||||
|         [HttpGet("Ratings/{Theme}/{Name}")] | ||||
|         [HttpGet("Ratings/{theme}/{name}")] | ||||
|         [AllowAnonymous] | ||||
|         [Produces(MediaTypeNames.Application.Octet)] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
| @ -136,7 +136,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="200">Image stream retrieved.</response> | ||||
|         /// <response code="404">Image not found.</response> | ||||
|         /// <returns>A <see cref="FileStreamResult"/> containing the image contents on success, or a <see cref="NotFoundResult"/> if the image could not be found.</returns> | ||||
|         [HttpGet("MediaInfo/{Theme}/{Name}")] | ||||
|         [HttpGet("MediaInfo/{theme}/{name}")] | ||||
|         [AllowAnonymous] | ||||
|         [Produces(MediaTypeNames.Application.Octet)] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| using System; | ||||
| using System.ComponentModel; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using MediaBrowser.Controller.Library; | ||||
| @ -40,29 +41,29 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Refreshes metadata for an item. | ||||
|         /// </summary> | ||||
|         /// <param name="id">Item id.</param> | ||||
|         /// <param name="itemId">Item id.</param> | ||||
|         /// <param name="metadataRefreshMode">(Optional) Specifies the metadata refresh mode.</param> | ||||
|         /// <param name="imageRefreshMode">(Optional) Specifies the image refresh mode.</param> | ||||
|         /// <param name="replaceAllMetadata">(Optional) Determines if metadata should be replaced. Only applicable if mode is FullRefresh.</param> | ||||
|         /// <param name="replaceAllImages">(Optional) Determines if images should be replaced. Only applicable if mode is FullRefresh.</param> | ||||
|         /// <param name="recursive">(Unused) Indicates if the refresh should occur recursively.</param> | ||||
|         /// <response code="200">Item metadata refresh queued.</response> | ||||
|         /// <response code="204">Item metadata refresh queued.</response> | ||||
|         /// <response code="404">Item to refresh not found.</response> | ||||
|         /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the item could not be found.</returns> | ||||
|         [HttpPost("{Id}/Refresh")] | ||||
|         [HttpPost("{itemId}/Refresh")] | ||||
|         [Description("Refreshes metadata for an item.")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "recursive", Justification = "Imported from ServiceStack")] | ||||
|         public ActionResult Post( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] Guid itemId, | ||||
|             [FromQuery] MetadataRefreshMode metadataRefreshMode = MetadataRefreshMode.None, | ||||
|             [FromQuery] MetadataRefreshMode imageRefreshMode = MetadataRefreshMode.None, | ||||
|             [FromQuery] bool replaceAllMetadata = false, | ||||
|             [FromQuery] bool replaceAllImages = false, | ||||
|             [FromQuery] bool recursive = false) | ||||
|         { | ||||
|             var item = _libraryManager.GetItemById(id); | ||||
|             var item = _libraryManager.GetItemById(itemId); | ||||
|             if (item == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
| @ -82,7 +83,7 @@ namespace Jellyfin.Api.Controllers | ||||
|             }; | ||||
| 
 | ||||
|             _providerManager.QueueRefresh(item.Id, refreshOptions, RefreshPriority.High); | ||||
|             return Ok(); | ||||
|             return NoContent(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -42,7 +42,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="limit">An optional limit on the number of notifications returned.</param> | ||||
|         /// <response code="200">Notifications returned.</response> | ||||
|         /// <returns>An <see cref="OkResult"/> containing a list of notifications.</returns> | ||||
|         [HttpGet("{UserID}")] | ||||
|         [HttpGet("{userId}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isRead", Justification = "Imported from ServiceStack")] | ||||
| @ -63,7 +63,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="userId">The user's ID.</param> | ||||
|         /// <response code="200">Summary of user's notifications returned.</response> | ||||
|         /// <returns>An <cref see="OkResult"/> containing a summary of the users notifications.</returns> | ||||
|         [HttpGet("{UserID}/Summary")] | ||||
|         [HttpGet("{userId}/Summary")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] | ||||
|         public ActionResult<NotificationsSummaryDto> GetNotificationsSummary( | ||||
| @ -138,7 +138,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="ids">A comma-separated list of the IDs of notifications which should be set as read.</param> | ||||
|         /// <response code="204">Notifications set as read.</response> | ||||
|         /// <returns>A <cref see="NoContentResult"/>.</returns> | ||||
|         [HttpPost("{UserID}/Read")] | ||||
|         [HttpPost("{userId}/Read")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "ids", Justification = "Imported from ServiceStack")] | ||||
| @ -156,7 +156,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <param name="ids">A comma-separated list of the IDs of notifications which should be set as unread.</param> | ||||
|         /// <response code="204">Notifications set as unread.</response> | ||||
|         /// <returns>A <cref see="NoContentResult"/>.</returns> | ||||
|         [HttpPost("{UserID}/Unread")] | ||||
|         [HttpPost("{userId}/Unread")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Imported from ServiceStack")] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "ids", Justification = "Imported from ServiceStack")] | ||||
|  | ||||
| @ -35,9 +35,10 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// </summary> | ||||
|         /// <param name="name">The name of the package.</param> | ||||
|         /// <param name="assemblyGuid">The GUID of the associated assembly.</param> | ||||
|         /// <response code="200">Package retrieved.</response> | ||||
|         /// <returns>A <see cref="PackageInfo"/> containing package information.</returns> | ||||
|         [HttpGet("/{Name}")] | ||||
|         [ProducesResponseType(typeof(PackageInfo), StatusCodes.Status200OK)] | ||||
|         [HttpGet("/{name}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public async Task<ActionResult<PackageInfo>> GetPackageInfo( | ||||
|             [FromRoute] [Required] string name, | ||||
|             [FromQuery] string? assemblyGuid) | ||||
| @ -54,9 +55,10 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Gets available packages. | ||||
|         /// </summary> | ||||
|         /// <response code="200">Available packages returned.</response> | ||||
|         /// <returns>An <see cref="PackageInfo"/> containing available packages information.</returns> | ||||
|         [HttpGet] | ||||
|         [ProducesResponseType(typeof(PackageInfo[]), StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public async Task<IEnumerable<PackageInfo>> GetPackages() | ||||
|         { | ||||
|             IEnumerable<PackageInfo> packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); | ||||
| @ -73,7 +75,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="204">Package found.</response> | ||||
|         /// <response code="404">Package not found.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> on success, or a <see cref="NotFoundResult"/> if the package could not be found.</returns> | ||||
|         [HttpPost("/Installed/{Name}")] | ||||
|         [HttpPost("/Installed/{name}")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         [Authorize(Policy = Policies.RequiresElevation)] | ||||
| @ -102,17 +104,16 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Cancels a package installation. | ||||
|         /// </summary> | ||||
|         /// <param name="id">Installation Id.</param> | ||||
|         /// <param name="packageId">Installation Id.</param> | ||||
|         /// <response code="204">Installation cancelled.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> on successfully cancelling a package installation.</returns> | ||||
|         [HttpDelete("/Installing/{id}")] | ||||
|         [HttpDelete("/Installing/{packageId}")] | ||||
|         [Authorize(Policy = Policies.RequiresElevation)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public IActionResult CancelPackageInstallation( | ||||
|             [FromRoute] [Required] string id) | ||||
|             [FromRoute] [Required] Guid packageId) | ||||
|         { | ||||
|             _installationManager.CancelInstallation(new Guid(id)); | ||||
| 
 | ||||
|             _installationManager.CancelInstallation(packageId); | ||||
|             return NoContent(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -11,6 +11,7 @@ using MediaBrowser.Common.Plugins; | ||||
| using MediaBrowser.Common.Updates; | ||||
| using MediaBrowser.Model.Plugins; | ||||
| using Microsoft.AspNetCore.Authorization; | ||||
| using Microsoft.AspNetCore.Http; | ||||
| using Microsoft.AspNetCore.Mvc; | ||||
| using Microsoft.AspNetCore.Mvc.ModelBinding; | ||||
| 
 | ||||
| @ -45,6 +46,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="200">Installed plugins returned.</response> | ||||
|         /// <returns>List of currently installed plugins.</returns> | ||||
|         [HttpGet] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isAppStoreEnabled", Justification = "Imported from ServiceStack")] | ||||
|         public ActionResult<IEnumerable<PluginInfo>> GetPlugins([FromRoute] bool? isAppStoreEnabled) | ||||
|         { | ||||
| @ -55,11 +57,13 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// Uninstalls a plugin. | ||||
|         /// </summary> | ||||
|         /// <param name="pluginId">Plugin id.</param> | ||||
|         /// <response code="200">Plugin uninstalled.</response> | ||||
|         /// <response code="204">Plugin uninstalled.</response> | ||||
|         /// <response code="404">Plugin not found.</response> | ||||
|         /// <returns>An <see cref="OkResult"/> on success, or a <see cref="NotFoundResult"/> if the file could not be found.</returns> | ||||
|         [HttpDelete("{pluginId}")] | ||||
|         [Authorize(Policy = Policies.RequiresElevation)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult UninstallPlugin([FromRoute] Guid pluginId) | ||||
|         { | ||||
|             var plugin = _appHost.Plugins.FirstOrDefault(p => p.Id == pluginId); | ||||
| @ -69,7 +73,7 @@ namespace Jellyfin.Api.Controllers | ||||
|             } | ||||
| 
 | ||||
|             _installationManager.UninstallPlugin(plugin); | ||||
|             return Ok(); | ||||
|             return NoContent(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
| @ -80,6 +84,8 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="404">Plugin not found or plugin configuration not found.</response> | ||||
|         /// <returns>Plugin configuration.</returns> | ||||
|         [HttpGet("{pluginId}/Configuration")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult<BasePluginConfiguration> GetPluginConfiguration([FromRoute] Guid pluginId) | ||||
|         { | ||||
|             if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin)) | ||||
| @ -97,14 +103,16 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// Accepts plugin configuration as JSON body. | ||||
|         /// </remarks> | ||||
|         /// <param name="pluginId">Plugin id.</param> | ||||
|         /// <response code="200">Plugin configuration updated.</response> | ||||
|         /// <response code="200">Plugin not found or plugin does not have configuration.</response> | ||||
|         /// <response code="204">Plugin configuration updated.</response> | ||||
|         /// <response code="404">Plugin not found or plugin does not have configuration.</response> | ||||
|         /// <returns> | ||||
|         /// A <see cref="Task" /> that represents the asynchronous operation to update plugin configuration. | ||||
|         ///    The task result contains an <see cref="OkResult"/> indicating success, or <see cref="NotFoundResult"/> | ||||
|         ///    when plugin not found or plugin doesn't have configuration. | ||||
|         /// </returns> | ||||
|         [HttpPost("{pluginId}/Configuration")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public async Task<ActionResult> UpdatePluginConfiguration([FromRoute] Guid pluginId) | ||||
|         { | ||||
|             if (!(_appHost.Plugins.FirstOrDefault(p => p.Id == pluginId) is IHasPluginConfiguration plugin)) | ||||
| @ -116,7 +124,7 @@ namespace Jellyfin.Api.Controllers | ||||
|                 .ConfigureAwait(false); | ||||
| 
 | ||||
|             plugin.UpdateConfiguration(configuration); | ||||
|             return Ok(); | ||||
|             return NoContent(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
| @ -126,6 +134,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <returns>Plugin security info.</returns> | ||||
|         [Obsolete("This endpoint should not be used.")] | ||||
|         [HttpGet("SecurityInfo")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult<PluginSecurityInfo> GetPluginSecurityInfo() | ||||
|         { | ||||
|             return new PluginSecurityInfo | ||||
| @ -139,14 +148,15 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// Updates plugin security info. | ||||
|         /// </summary> | ||||
|         /// <param name="pluginSecurityInfo">Plugin security info.</param> | ||||
|         /// <response code="200">Plugin security info updated.</response> | ||||
|         /// <returns>An <see cref="OkResult"/>.</returns> | ||||
|         /// <response code="204">Plugin security info updated.</response> | ||||
|         /// <returns>An <see cref="NoContentResult"/>.</returns> | ||||
|         [Obsolete("This endpoint should not be used.")] | ||||
|         [HttpPost("SecurityInfo")] | ||||
|         [Authorize(Policy = Policies.RequiresElevation)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult UpdatePluginSecurityInfo([FromBody, BindRequired] PluginSecurityInfo pluginSecurityInfo) | ||||
|         { | ||||
|             return Ok(); | ||||
|             return NoContent(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
| @ -157,6 +167,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <returns>Mb registration record.</returns> | ||||
|         [Obsolete("This endpoint should not be used.")] | ||||
|         [HttpPost("RegistrationRecords/{name}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public ActionResult<MBRegistrationRecord> GetRegistrationStatus([FromRoute] string name) | ||||
|         { | ||||
|             return new MBRegistrationRecord | ||||
| @ -178,6 +189,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <exception cref="NotImplementedException">This endpoint is not implemented.</exception> | ||||
|         [Obsolete("Paid plugins are not supported")] | ||||
|         [HttpGet("/Registrations/{name}")] | ||||
|         [ProducesResponseType(StatusCodes.Status501NotImplemented)] | ||||
|         public ActionResult GetRegistration([FromRoute] string name) | ||||
|         { | ||||
|             // TODO Once we have proper apps and plugins and decide to break compatibility with paid plugins, | ||||
|  | ||||
| @ -55,7 +55,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Gets available remote images for an item. | ||||
|         /// </summary> | ||||
|         /// <param name="id">Item Id.</param> | ||||
|         /// <param name="itemId">Item Id.</param> | ||||
|         /// <param name="type">The image type.</param> | ||||
|         /// <param name="startIndex">Optional. The record index to start at. All items with a lower index will be dropped from the results.</param> | ||||
|         /// <param name="limit">Optional. The maximum number of records to return.</param> | ||||
| @ -64,18 +64,18 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="200">Remote Images returned.</response> | ||||
|         /// <response code="404">Item not found.</response> | ||||
|         /// <returns>Remote Image Result.</returns> | ||||
|         [HttpGet("{Id}/RemoteImages")] | ||||
|         [HttpGet("{itemId}/RemoteImages")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public async Task<ActionResult<RemoteImageResult>> GetRemoteImages( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] Guid itemId, | ||||
|             [FromQuery] ImageType? type, | ||||
|             [FromQuery] int? startIndex, | ||||
|             [FromQuery] int? limit, | ||||
|             [FromQuery] string providerName, | ||||
|             [FromQuery] bool includeAllLanguages) | ||||
|         { | ||||
|             var item = _libraryManager.GetItemById(id); | ||||
|             var item = _libraryManager.GetItemById(itemId); | ||||
|             if (item == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
| @ -123,16 +123,16 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Gets available remote image providers for an item. | ||||
|         /// </summary> | ||||
|         /// <param name="id">Item Id.</param> | ||||
|         /// <param name="itemId">Item Id.</param> | ||||
|         /// <response code="200">Returned remote image providers.</response> | ||||
|         /// <response code="404">Item not found.</response> | ||||
|         /// <returns>List of remote image providers.</returns> | ||||
|         [HttpGet("{Id}/RemoteImages/Providers")] | ||||
|         [HttpGet("{itemId}/RemoteImages/Providers")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult<IEnumerable<ImageProviderInfo>> GetRemoteImageProviders([FromRoute] string id) | ||||
|         public ActionResult<IEnumerable<ImageProviderInfo>> GetRemoteImageProviders([FromRoute] Guid itemId) | ||||
|         { | ||||
|             var item = _libraryManager.GetItemById(id); | ||||
|             var item = _libraryManager.GetItemById(itemId); | ||||
|             if (item == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
| @ -195,21 +195,21 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Downloads a remote image for an item. | ||||
|         /// </summary> | ||||
|         /// <param name="id">Item Id.</param> | ||||
|         /// <param name="itemId">Item Id.</param> | ||||
|         /// <param name="type">The image type.</param> | ||||
|         /// <param name="imageUrl">The image url.</param> | ||||
|         /// <response code="200">Remote image downloaded.</response> | ||||
|         /// <response code="204">Remote image downloaded.</response> | ||||
|         /// <response code="404">Remote image not found.</response> | ||||
|         /// <returns>Download status.</returns> | ||||
|         [HttpPost("{Id}/RemoteImages/Download")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [HttpPost("{itemId}/RemoteImages/Download")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public async Task<ActionResult> DownloadRemoteImage( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] Guid itemId, | ||||
|             [FromQuery, BindRequired] ImageType type, | ||||
|             [FromQuery] string imageUrl) | ||||
|         { | ||||
|             var item = _libraryManager.GetItemById(id); | ||||
|             var item = _libraryManager.GetItemById(itemId); | ||||
|             if (item == null) | ||||
|             { | ||||
|                 return NotFound(); | ||||
| @ -219,7 +219,7 @@ namespace Jellyfin.Api.Controllers | ||||
|                 .ConfigureAwait(false); | ||||
| 
 | ||||
|             item.UpdateToRepository(ItemUpdateType.ImageUpdate, CancellationToken.None); | ||||
|             return Ok(); | ||||
|             return NoContent(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|  | ||||
| @ -113,16 +113,16 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Instructs a session to browse to an item or view. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session Id.</param> | ||||
|         /// <param name="sessionId">The session Id.</param> | ||||
|         /// <param name="itemType">The type of item to browse to.</param> | ||||
|         /// <param name="itemId">The Id of the item.</param> | ||||
|         /// <param name="itemName">The name of the item.</param> | ||||
|         /// <response code="204">Instruction sent to session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/Viewing")] | ||||
|         [HttpPost("/Sessions/{sessionId}/Viewing")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult DisplayContent( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromQuery] string itemType, | ||||
|             [FromQuery] string itemId, | ||||
|             [FromQuery] string itemName) | ||||
| @ -136,7 +136,7 @@ namespace Jellyfin.Api.Controllers | ||||
| 
 | ||||
|             _sessionManager.SendBrowseCommand( | ||||
|                 RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, | ||||
|                 id, | ||||
|                 sessionId, | ||||
|                 command, | ||||
|                 CancellationToken.None); | ||||
| 
 | ||||
| @ -146,17 +146,17 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Instructs a session to play an item. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="itemIds">The ids of the items to play, comma delimited.</param> | ||||
|         /// <param name="startPositionTicks">The starting position of the first item.</param> | ||||
|         /// <param name="playCommand">The type of play command to issue (PlayNow, PlayNext, PlayLast). Clients who have not yet implemented play next and play last may play now.</param> | ||||
|         /// <param name="playRequest">The <see cref="PlayRequest"/>.</param> | ||||
|         /// <response code="204">Instruction sent to session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/Playing")] | ||||
|         [HttpPost("/Sessions/{sessionId}/Playing")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult Play( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromQuery] Guid[] itemIds, | ||||
|             [FromQuery] long? startPositionTicks, | ||||
|             [FromQuery] PlayCommand playCommand, | ||||
| @ -173,7 +173,7 @@ namespace Jellyfin.Api.Controllers | ||||
| 
 | ||||
|             _sessionManager.SendPlayCommand( | ||||
|                 RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, | ||||
|                 id, | ||||
|                 sessionId, | ||||
|                 playRequest, | ||||
|                 CancellationToken.None); | ||||
| 
 | ||||
| @ -183,19 +183,19 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Issues a playstate command to a client. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="playstateRequest">The <see cref="PlaystateRequest"/>.</param> | ||||
|         /// <response code="204">Playstate command sent to session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/Playing/{command}")] | ||||
|         [HttpPost("/Sessions/{sessionId}/Playing/{command}")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult SendPlaystateCommand( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromBody] PlaystateRequest playstateRequest) | ||||
|         { | ||||
|             _sessionManager.SendPlaystateCommand( | ||||
|                 RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, | ||||
|                 id, | ||||
|                 sessionId, | ||||
|                 playstateRequest, | ||||
|                 CancellationToken.None); | ||||
| 
 | ||||
| @ -205,14 +205,14 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Issues a system command to a client. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="command">The command to send.</param> | ||||
|         /// <response code="204">System command sent to session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/System/{Command}")] | ||||
|         [HttpPost("/Sessions/{sessionId}/System/{command}")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult SendSystemCommand( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromRoute] string command) | ||||
|         { | ||||
|             var name = command; | ||||
| @ -228,7 +228,7 @@ namespace Jellyfin.Api.Controllers | ||||
|                 ControllingUserId = currentSession.UserId | ||||
|             }; | ||||
| 
 | ||||
|             _sessionManager.SendGeneralCommand(currentSession.Id, id, generalCommand, CancellationToken.None); | ||||
|             _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None); | ||||
| 
 | ||||
|             return NoContent(); | ||||
|         } | ||||
| @ -236,14 +236,14 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Issues a general command to a client. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="command">The command to send.</param> | ||||
|         /// <response code="204">General command sent to session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/Command/{Command}")] | ||||
|         [HttpPost("/Sessions/{sessionId}/Command/{Command}")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult SendGeneralCommand( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromRoute] string command) | ||||
|         { | ||||
|             var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request); | ||||
| @ -254,7 +254,7 @@ namespace Jellyfin.Api.Controllers | ||||
|                 ControllingUserId = currentSession.UserId | ||||
|             }; | ||||
| 
 | ||||
|             _sessionManager.SendGeneralCommand(currentSession.Id, id, generalCommand, CancellationToken.None); | ||||
|             _sessionManager.SendGeneralCommand(currentSession.Id, sessionId, generalCommand, CancellationToken.None); | ||||
| 
 | ||||
|             return NoContent(); | ||||
|         } | ||||
| @ -262,14 +262,14 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Issues a full general command to a client. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="command">The <see cref="GeneralCommand"/>.</param> | ||||
|         /// <response code="204">Full general command sent to session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/Command")] | ||||
|         [HttpPost("/Sessions/{sessionId}/Command")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult SendFullGeneralCommand( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromBody, Required] GeneralCommand command) | ||||
|         { | ||||
|             var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request); | ||||
| @ -283,7 +283,7 @@ namespace Jellyfin.Api.Controllers | ||||
| 
 | ||||
|             _sessionManager.SendGeneralCommand( | ||||
|                 currentSession.Id, | ||||
|                 id, | ||||
|                 sessionId, | ||||
|                 command, | ||||
|                 CancellationToken.None); | ||||
| 
 | ||||
| @ -293,16 +293,16 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Issues a command to a client to display a message to the user. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="text">The message test.</param> | ||||
|         /// <param name="header">The message header.</param> | ||||
|         /// <param name="timeoutMs">The message timeout. If omitted the user will have to confirm viewing the message.</param> | ||||
|         /// <response code="204">Message sent.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/Message")] | ||||
|         [HttpPost("/Sessions/{sessionId}/Message")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult SendMessageCommand( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromQuery] string text, | ||||
|             [FromQuery] string header, | ||||
|             [FromQuery] long? timeoutMs) | ||||
| @ -314,7 +314,7 @@ namespace Jellyfin.Api.Controllers | ||||
|                 Text = text | ||||
|             }; | ||||
| 
 | ||||
|             _sessionManager.SendMessageCommand(RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, id, command, CancellationToken.None); | ||||
|             _sessionManager.SendMessageCommand(RequestHelpers.GetSession(_sessionManager, _authContext, Request).Id, sessionId, command, CancellationToken.None); | ||||
| 
 | ||||
|             return NoContent(); | ||||
|         } | ||||
| @ -322,34 +322,34 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Adds an additional user to a session. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <response code="204">User added to session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Sessions/{id}/User/{userId}")] | ||||
|         [HttpPost("/Sessions/{sessionId}/User/{userId}")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult AddUserToSession( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromRoute] Guid userId) | ||||
|         { | ||||
|             _sessionManager.AddAdditionalUser(id, userId); | ||||
|             _sessionManager.AddAdditionalUser(sessionId, userId); | ||||
|             return NoContent(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Removes an additional user from a session. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The session id.</param> | ||||
|         /// <param name="sessionId">The session id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <response code="204">User removed from session.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpDelete("/Sessions/{id}/User/{userId}")] | ||||
|         [HttpDelete("/Sessions/{sessionId}/User/{userId}")] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public ActionResult RemoveUserFromSession( | ||||
|             [FromRoute] string id, | ||||
|             [FromRoute] string sessionId, | ||||
|             [FromRoute] Guid userId) | ||||
|         { | ||||
|             _sessionManager.RemoveAdditionalUser(id, userId); | ||||
|             _sessionManager.RemoveAdditionalUser(sessionId, userId); | ||||
|             return NoContent(); | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -75,20 +75,20 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Deletes an external subtitle file. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The item id.</param> | ||||
|         /// <param name="itemId">The item id.</param> | ||||
|         /// <param name="index">The index of the subtitle file.</param> | ||||
|         /// <response code="204">Subtitle deleted.</response> | ||||
|         /// <response code="404">Item not found.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpDelete("/Videos/{id}/Subtitles/{index}")] | ||||
|         [HttpDelete("/Videos/{itemId}/Subtitles/{index}")] | ||||
|         [Authorize(Policy = Policies.RequiresElevation)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult<Task> DeleteSubtitle( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid itemId, | ||||
|             [FromRoute] int index) | ||||
|         { | ||||
|             var item = _libraryManager.GetItemById(id); | ||||
|             var item = _libraryManager.GetItemById(itemId); | ||||
| 
 | ||||
|             if (item == null) | ||||
|             { | ||||
| @ -102,20 +102,20 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Search remote subtitles. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The item id.</param> | ||||
|         /// <param name="itemId">The item id.</param> | ||||
|         /// <param name="language">The language of the subtitles.</param> | ||||
|         /// <param name="isPerfectMatch">Optional. Only show subtitles which are a perfect match.</param> | ||||
|         /// <response code="200">Subtitles retrieved.</response> | ||||
|         /// <returns>An array of <see cref="RemoteSubtitleInfo"/>.</returns> | ||||
|         [HttpGet("/Items/{id}/RemoteSearch/Subtitles/{language}")] | ||||
|         [HttpGet("/Items/{itemId}/RemoteSearch/Subtitles/{language}")] | ||||
|         [Authorize(Policy = Policies.DefaultAuthorization)] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public async Task<ActionResult<IEnumerable<RemoteSubtitleInfo>>> SearchRemoteSubtitles( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid itemId, | ||||
|             [FromRoute] string language, | ||||
|             [FromQuery] bool? isPerfectMatch) | ||||
|         { | ||||
|             var video = (Video)_libraryManager.GetItemById(id); | ||||
|             var video = (Video)_libraryManager.GetItemById(itemId); | ||||
| 
 | ||||
|             return await _subtitleManager.SearchSubtitles(video, language, isPerfectMatch, CancellationToken.None).ConfigureAwait(false); | ||||
|         } | ||||
| @ -123,18 +123,18 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Downloads a remote subtitle. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The item id.</param> | ||||
|         /// <param name="itemId">The item id.</param> | ||||
|         /// <param name="subtitleId">The subtitle id.</param> | ||||
|         /// <response code="204">Subtitle downloaded.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/>.</returns> | ||||
|         [HttpPost("/Items/{id}/RemoteSearch/Subtitles/{subtitleId}")] | ||||
|         [HttpPost("/Items/{itemId}/RemoteSearch/Subtitles/{subtitleId}")] | ||||
|         [Authorize(Policy = Policies.DefaultAuthorization)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         public async Task<ActionResult> DownloadRemoteSubtitles( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid itemId, | ||||
|             [FromRoute] string subtitleId) | ||||
|         { | ||||
|             var video = (Video)_libraryManager.GetItemById(id); | ||||
|             var video = (Video)_libraryManager.GetItemById(itemId); | ||||
| 
 | ||||
|             try | ||||
|             { | ||||
| @ -171,28 +171,28 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Gets subtitles in a specified format. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The item id.</param> | ||||
|         /// <param name="itemId">The item id.</param> | ||||
|         /// <param name="mediaSourceId">The media source id.</param> | ||||
|         /// <param name="index">The subtitle stream index.</param> | ||||
|         /// <param name="format">The format of the returned subtitle.</param> | ||||
|         /// <param name="startPositionTicks">Optional. The start position of the subtitle in ticks.</param> | ||||
|         /// <param name="endPositionTicks">Optional. The end position of the subtitle in ticks.</param> | ||||
|         /// <param name="copyTimestamps">Optional. Whether to copy the timestamps.</param> | ||||
|         /// <param name="addVttTimeMap">Optional. Whether to add a VTT time map.</param> | ||||
|         /// <param name="startPositionTicks">Optional. The start position of the subtitle in ticks.</param> | ||||
|         /// <response code="200">File returned.</response> | ||||
|         /// <returns>A <see cref="FileContentResult"/> with the subtitle file.</returns> | ||||
|         [HttpGet("/Videos/{id}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")] | ||||
|         [HttpGet("/Videos/{id}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks}/Stream.{format}")] | ||||
|         [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/Stream.{format}")] | ||||
|         [HttpGet("/Videos/{itemId}/{mediaSourceId}/Subtitles/{index}/{startPositionTicks?}/Stream.{format}")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         public async Task<ActionResult> GetSubtitle( | ||||
|             [FromRoute, Required] Guid id, | ||||
|             [FromRoute, Required] Guid itemId, | ||||
|             [FromRoute, Required] string mediaSourceId, | ||||
|             [FromRoute, Required] int index, | ||||
|             [FromRoute, Required] string format, | ||||
|             [FromRoute] long startPositionTicks, | ||||
|             [FromQuery] long? endPositionTicks, | ||||
|             [FromQuery] bool copyTimestamps, | ||||
|             [FromQuery] bool addVttTimeMap) | ||||
|             [FromQuery] bool addVttTimeMap, | ||||
|             [FromRoute] long startPositionTicks = 0) | ||||
|         { | ||||
|             if (string.Equals(format, "js", StringComparison.OrdinalIgnoreCase)) | ||||
|             { | ||||
| @ -201,9 +201,9 @@ namespace Jellyfin.Api.Controllers | ||||
| 
 | ||||
|             if (string.IsNullOrEmpty(format)) | ||||
|             { | ||||
|                 var item = (Video)_libraryManager.GetItemById(id); | ||||
|                 var item = (Video)_libraryManager.GetItemById(itemId); | ||||
| 
 | ||||
|                 var idString = id.ToString("N", CultureInfo.InvariantCulture); | ||||
|                 var idString = itemId.ToString("N", CultureInfo.InvariantCulture); | ||||
|                 var mediaSource = _mediaSourceManager.GetStaticMediaSources(item, false) | ||||
|                     .First(i => string.Equals(i.Id, mediaSourceId ?? idString, StringComparison.Ordinal)); | ||||
| 
 | ||||
| @ -216,7 +216,7 @@ namespace Jellyfin.Api.Controllers | ||||
| 
 | ||||
|             if (string.Equals(format, "vtt", StringComparison.OrdinalIgnoreCase) && addVttTimeMap) | ||||
|             { | ||||
|                 await using Stream stream = await EncodeSubtitles(id, mediaSourceId, index, format, startPositionTicks, endPositionTicks, copyTimestamps).ConfigureAwait(false); | ||||
|                 await using Stream stream = await EncodeSubtitles(itemId, mediaSourceId, index, format, startPositionTicks, endPositionTicks, copyTimestamps).ConfigureAwait(false); | ||||
|                 using var reader = new StreamReader(stream); | ||||
| 
 | ||||
|                 var text = await reader.ReadToEndAsync().ConfigureAwait(false); | ||||
| @ -228,7 +228,7 @@ namespace Jellyfin.Api.Controllers | ||||
| 
 | ||||
|             return File( | ||||
|                 await EncodeSubtitles( | ||||
|                     id, | ||||
|                     itemId, | ||||
|                     mediaSourceId, | ||||
|                     index, | ||||
|                     format, | ||||
| @ -241,23 +241,23 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Gets an HLS subtitle playlist. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The item id.</param> | ||||
|         /// <param name="itemId">The item id.</param> | ||||
|         /// <param name="index">The subtitle stream index.</param> | ||||
|         /// <param name="mediaSourceId">The media source id.</param> | ||||
|         /// <param name="segmentLength">The subtitle segment length.</param> | ||||
|         /// <response code="200">Subtitle playlist retrieved.</response> | ||||
|         /// <returns>A <see cref="FileContentResult"/> with the HLS subtitle playlist.</returns> | ||||
|         [HttpGet("/Videos/{id}/{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")] | ||||
|         public async Task<ActionResult> GetSubtitlePlaylist( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid itemId, | ||||
|             [FromRoute] int index, | ||||
|             [FromRoute] string mediaSourceId, | ||||
|             [FromQuery, Required] int segmentLength) | ||||
|         { | ||||
|             var item = (Video)_libraryManager.GetItemById(id); | ||||
|             var item = (Video)_libraryManager.GetItemById(itemId); | ||||
| 
 | ||||
|             var mediaSource = await _mediaSourceManager.GetMediaSource(item, mediaSourceId, null, false, CancellationToken.None).ConfigureAwait(false); | ||||
| 
 | ||||
|  | ||||
| @ -105,17 +105,17 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Gets a user by Id. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <response code="200">User returned.</response> | ||||
|         /// <response code="404">User not found.</response> | ||||
|         /// <returns>An <see cref="UserDto"/> with information about the user or a <see cref="NotFoundResult"/> if the user was not found.</returns> | ||||
|         [HttpGet("{id}")] | ||||
|         [HttpGet("{userId}")] | ||||
|         [Authorize(Policy = Policies.IgnoreSchedule)] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult<UserDto> GetUserById([FromRoute] Guid id) | ||||
|         public ActionResult<UserDto> GetUserById([FromRoute] Guid userId) | ||||
|         { | ||||
|             var user = _userManager.GetUserById(id); | ||||
|             var user = _userManager.GetUserById(userId); | ||||
| 
 | ||||
|             if (user == null) | ||||
|             { | ||||
| @ -129,17 +129,17 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Deletes a user. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <response code="200">User deleted.</response> | ||||
|         /// <response code="404">User not found.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="NotFoundResult"/> if the user was not found.</returns> | ||||
|         [HttpDelete("{id}")] | ||||
|         [HttpDelete("{userId}")] | ||||
|         [Authorize(Policy = Policies.RequiresElevation)] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult DeleteUser([FromRoute] Guid id) | ||||
|         public ActionResult DeleteUser([FromRoute] Guid userId) | ||||
|         { | ||||
|             var user = _userManager.GetUserById(id); | ||||
|             var user = _userManager.GetUserById(userId); | ||||
| 
 | ||||
|             if (user == null) | ||||
|             { | ||||
| @ -154,23 +154,23 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Authenticates a user. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <param name="pw">The password as plain text.</param> | ||||
|         /// <param name="password">The password sha1-hash.</param> | ||||
|         /// <response code="200">User authenticated.</response> | ||||
|         /// <response code="403">Sha1-hashed password only is not allowed.</response> | ||||
|         /// <response code="404">User not found.</response> | ||||
|         /// <returns>A <see cref="Task"/> containing an <see cref="AuthenticationResult"/>.</returns> | ||||
|         [HttpPost("{id}/Authenticate")] | ||||
|         [HttpPost("{userId}/Authenticate")] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public async Task<ActionResult<AuthenticationResult>> AuthenticateUser( | ||||
|             [FromRoute, Required] Guid id, | ||||
|             [FromRoute, Required] Guid userId, | ||||
|             [FromQuery, BindRequired] string pw, | ||||
|             [FromQuery, BindRequired] string password) | ||||
|         { | ||||
|             var user = _userManager.GetUserById(id); | ||||
|             var user = _userManager.GetUserById(userId); | ||||
| 
 | ||||
|             if (user == null) | ||||
|             { | ||||
| @ -230,27 +230,27 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Updates a user's password. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <param name="request">The <see cref="UpdateUserPassword"/> request.</param> | ||||
|         /// <response code="200">Password successfully reset.</response> | ||||
|         /// <response code="403">User is not allowed to update the password.</response> | ||||
|         /// <response code="404">User not found.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="ForbidResult"/> or a <see cref="NotFoundResult"/> on failure.</returns> | ||||
|         [HttpPost("{id}/Password")] | ||||
|         [HttpPost("{userId}/Password")] | ||||
|         [Authorize] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public async Task<ActionResult> UpdateUserPassword( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid userId, | ||||
|             [FromBody] UpdateUserPassword request) | ||||
|         { | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, true)) | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) | ||||
|             { | ||||
|                 return Forbid("User is not allowed to update the password."); | ||||
|             } | ||||
| 
 | ||||
|             var user = _userManager.GetUserById(id); | ||||
|             var user = _userManager.GetUserById(userId); | ||||
| 
 | ||||
|             if (user == null) | ||||
|             { | ||||
| @ -288,27 +288,27 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Updates a user's easy password. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <param name="request">The <see cref="UpdateUserEasyPassword"/> request.</param> | ||||
|         /// <response code="200">Password successfully reset.</response> | ||||
|         /// <response code="403">User is not allowed to update the password.</response> | ||||
|         /// <response code="404">User not found.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="ForbidResult"/> or a <see cref="NotFoundResult"/> on failure.</returns> | ||||
|         [HttpPost("{id}/EasyPassword")] | ||||
|         [HttpPost("{userId}/EasyPassword")] | ||||
|         [Authorize] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|         public ActionResult UpdateUserEasyPassword( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid userId, | ||||
|             [FromBody] UpdateUserEasyPassword request) | ||||
|         { | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, true)) | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) | ||||
|             { | ||||
|                 return Forbid("User is not allowed to update the easy password."); | ||||
|             } | ||||
| 
 | ||||
|             var user = _userManager.GetUserById(id); | ||||
|             var user = _userManager.GetUserById(userId); | ||||
| 
 | ||||
|             if (user == null) | ||||
|             { | ||||
| @ -330,19 +330,19 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Updates a user. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <param name="updateUser">The updated user model.</param> | ||||
|         /// <response code="204">User updated.</response> | ||||
|         /// <response code="400">User information was not supplied.</response> | ||||
|         /// <response code="403">User update forbidden.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="BadRequestResult"/> or a <see cref="ForbidResult"/> on failure.</returns> | ||||
|         [HttpPost("{id}")] | ||||
|         [HttpPost("{userId}")] | ||||
|         [Authorize] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||
|         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||
|         public async Task<ActionResult> UpdateUser( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid userId, | ||||
|             [FromBody] UserDto updateUser) | ||||
|         { | ||||
|             if (updateUser == null) | ||||
| @ -350,12 +350,12 @@ namespace Jellyfin.Api.Controllers | ||||
|                 return BadRequest(); | ||||
|             } | ||||
| 
 | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, false)) | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false)) | ||||
|             { | ||||
|                 return Forbid("User update not allowed."); | ||||
|             } | ||||
| 
 | ||||
|             var user = _userManager.GetUserById(id); | ||||
|             var user = _userManager.GetUserById(userId); | ||||
| 
 | ||||
|             if (string.Equals(user.Username, updateUser.Name, StringComparison.Ordinal)) | ||||
|             { | ||||
| @ -374,19 +374,19 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Updates a user policy. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <param name="newPolicy">The new user policy.</param> | ||||
|         /// <response code="204">User policy updated.</response> | ||||
|         /// <response code="400">User policy was not supplied.</response> | ||||
|         /// <response code="403">User policy update forbidden.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> indicating success or a <see cref="BadRequestResult"/> or a <see cref="ForbidResult"/> on failure..</returns> | ||||
|         [HttpPost("{id}/Policy")] | ||||
|         [HttpPost("{userId}/Policy")] | ||||
|         [Authorize] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status400BadRequest)] | ||||
|         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||
|         public ActionResult UpdateUserPolicy( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid userId, | ||||
|             [FromBody] UserPolicy newPolicy) | ||||
|         { | ||||
|             if (newPolicy == null) | ||||
| @ -394,7 +394,7 @@ namespace Jellyfin.Api.Controllers | ||||
|                 return BadRequest(); | ||||
|             } | ||||
| 
 | ||||
|             var user = _userManager.GetUserById(id); | ||||
|             var user = _userManager.GetUserById(userId); | ||||
| 
 | ||||
|             // If removing admin access | ||||
|             if (!(newPolicy.IsAdministrator && user.HasPermission(PermissionKind.IsAdministrator))) | ||||
| @ -423,7 +423,7 @@ namespace Jellyfin.Api.Controllers | ||||
|                 _sessionManager.RevokeUserTokens(user.Id, currentToken); | ||||
|             } | ||||
| 
 | ||||
|             _userManager.UpdatePolicy(id, newPolicy); | ||||
|             _userManager.UpdatePolicy(userId, newPolicy); | ||||
| 
 | ||||
|             return NoContent(); | ||||
|         } | ||||
| @ -431,25 +431,25 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <summary> | ||||
|         /// Updates a user configuration. | ||||
|         /// </summary> | ||||
|         /// <param name="id">The user id.</param> | ||||
|         /// <param name="userId">The user id.</param> | ||||
|         /// <param name="userConfig">The new user configuration.</param> | ||||
|         /// <response code="204">User configuration updated.</response> | ||||
|         /// <response code="403">User configuration update forbidden.</response> | ||||
|         /// <returns>A <see cref="NoContentResult"/> indicating success.</returns> | ||||
|         [HttpPost("{id}/Configuration")] | ||||
|         [HttpPost("{userId}/Configuration")] | ||||
|         [Authorize] | ||||
|         [ProducesResponseType(StatusCodes.Status204NoContent)] | ||||
|         [ProducesResponseType(StatusCodes.Status403Forbidden)] | ||||
|         public ActionResult UpdateUserConfiguration( | ||||
|             [FromRoute] Guid id, | ||||
|             [FromRoute] Guid userId, | ||||
|             [FromBody] UserConfiguration userConfig) | ||||
|         { | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, id, false)) | ||||
|             if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, false)) | ||||
|             { | ||||
|                 return Forbid("User configuration update not allowed"); | ||||
|             } | ||||
| 
 | ||||
|             _userManager.UpdateConfiguration(id, userConfig); | ||||
|             _userManager.UpdateConfiguration(userId, userConfig); | ||||
| 
 | ||||
|             return NoContent(); | ||||
|         } | ||||
|  | ||||
| @ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers | ||||
|         /// <response code="200">Attachment retrieved.</response> | ||||
|         /// <response code="404">Video or attachment not found.</response> | ||||
|         /// <returns>An <see cref="FileStreamResult"/> containing the attachment stream on success, or a <see cref="NotFoundResult"/> if the attachment could not be found.</returns> | ||||
|         [HttpGet("{VideoID}/{MediaSourceID}/Attachments/{Index}")] | ||||
|         [HttpGet("{videoId}/{mediaSourceId}/Attachments/{index}")] | ||||
|         [Produces(MediaTypeNames.Application.Octet)] | ||||
|         [ProducesResponseType(StatusCodes.Status200OK)] | ||||
|         [ProducesResponseType(StatusCodes.Status404NotFound)] | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user