Merge pull request #4093 from crobibero/bad-route

Fix api routes
This commit is contained in:
Bond-009 2020-09-11 09:10:16 +00:00 committed by GitHub
commit 1d633aac0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 143 additions and 143 deletions

View File

@ -65,7 +65,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Keys")] [HttpPost("Keys")]
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult CreateKey([FromQuery, Required] string? app) public ActionResult CreateKey([FromQuery, Required] string app)
{ {
_authRepo.Create(new AuthenticationInfo _authRepo.Create(new AuthenticationInfo
{ {
@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers
[HttpDelete("Keys/{key}")] [HttpDelete("Keys/{key}")]
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult RevokeKey([FromRoute, Required] string? key) public ActionResult RevokeKey([FromRoute, Required] string key)
{ {
_sessionManager.RevokeToken(key); _sessionManager.RevokeToken(key);
return NoContent(); return NoContent();

View File

@ -85,15 +85,15 @@ namespace Jellyfin.Api.Controllers
/// <param name="streamOptions">Optional. The streaming options.</param> /// <param name="streamOptions">Optional. The streaming options.</param>
/// <response code="200">Audio stream returned.</response> /// <response code="200">Audio stream returned.</response>
/// <returns>A <see cref="FileResult"/> containing the audio file.</returns> /// <returns>A <see cref="FileResult"/> containing the audio file.</returns>
[HttpGet("{itemId}/stream.{container}", Name = "GetAudioStreamByContainer")] [HttpGet("{itemId}/stream.{container:required}", Name = "GetAudioStreamByContainer")]
[HttpGet("{itemId}/stream", Name = "GetAudioStream")] [HttpGet("{itemId}/stream", Name = "GetAudioStream")]
[HttpHead("{itemId}/stream.{container}", Name = "HeadAudioStreamByContainer")] [HttpHead("{itemId}/stream.{container:required}", Name = "HeadAudioStreamByContainer")]
[HttpHead("{itemId}/stream", Name = "HeadAudioStream")] [HttpHead("{itemId}/stream", Name = "HeadAudioStream")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesAudioFile] [ProducesAudioFile]
public async Task<ActionResult> GetAudioStream( public async Task<ActionResult> GetAudioStream(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? container, [FromRoute] string? container,
[FromQuery] bool? @static, [FromQuery] bool? @static,
[FromQuery] string? @params, [FromQuery] string? @params,
[FromQuery] string? tag, [FromQuery] string? tag,

View File

@ -88,7 +88,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns> /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
[HttpPost("{collectionId}/Items")] [HttpPost("{collectionId}/Items")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> AddToCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string? itemIds) public async Task<ActionResult> AddToCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string itemIds)
{ {
await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true); await _collectionManager.AddToCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(true);
return NoContent(); return NoContent();
@ -103,7 +103,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns> /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
[HttpDelete("{collectionId}/Items")] [HttpDelete("{collectionId}/Items")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> RemoveFromCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string? itemIds) public async Task<ActionResult> RemoveFromCollection([FromRoute, Required] Guid collectionId, [FromQuery, Required] string itemIds)
{ {
await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false); await _collectionManager.RemoveFromCollectionAsync(collectionId, RequestHelpers.GetGuids(itemIds)).ConfigureAwait(false);
return NoContent(); return NoContent();

View File

@ -76,7 +76,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Configuration/{key}")] [HttpGet("Configuration/{key}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesFile(MediaTypeNames.Application.Json)] [ProducesFile(MediaTypeNames.Application.Json)]
public ActionResult<object> GetNamedConfiguration([FromRoute, Required] string? key) public ActionResult<object> GetNamedConfiguration([FromRoute, Required] string key)
{ {
return _configurationManager.GetConfiguration(key); return _configurationManager.GetConfiguration(key);
} }
@ -90,7 +90,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Configuration/{key}")] [HttpPost("Configuration/{key}")]
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> UpdateNamedConfiguration([FromRoute, Required] string? key) public async Task<ActionResult> UpdateNamedConfiguration([FromRoute, Required] string key)
{ {
var configurationType = _configurationManager.GetConfigurationType(key); var configurationType = _configurationManager.GetConfigurationType(key);
var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType, _serializerOptions).ConfigureAwait(false); var configuration = await JsonSerializer.DeserializeAsync(Request.Body, configurationType, _serializerOptions).ConfigureAwait(false);

View File

@ -65,7 +65,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<DeviceInfo> GetDeviceInfo([FromQuery, Required] string? id) public ActionResult<DeviceInfo> GetDeviceInfo([FromQuery, Required] string id)
{ {
var deviceInfo = _deviceManager.GetDevice(id); var deviceInfo = _deviceManager.GetDevice(id);
if (deviceInfo == null) if (deviceInfo == null)
@ -87,7 +87,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<DeviceOptions> GetDeviceOptions([FromQuery, Required] string? id) public ActionResult<DeviceOptions> GetDeviceOptions([FromQuery, Required] string id)
{ {
var deviceInfo = _deviceManager.GetDeviceOptions(id); var deviceInfo = _deviceManager.GetDeviceOptions(id);
if (deviceInfo == null) if (deviceInfo == null)
@ -111,7 +111,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult UpdateDeviceOptions( public ActionResult UpdateDeviceOptions(
[FromQuery, Required] string? id, [FromQuery, Required] string id,
[FromBody, Required] DeviceOptions deviceOptions) [FromBody, Required] DeviceOptions deviceOptions)
{ {
var existingDeviceOptions = _deviceManager.GetDeviceOptions(id); var existingDeviceOptions = _deviceManager.GetDeviceOptions(id);
@ -134,7 +134,7 @@ namespace Jellyfin.Api.Controllers
[HttpDelete] [HttpDelete]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult DeleteDevice([FromQuery, Required] string? id) public ActionResult DeleteDevice([FromQuery, Required] string id)
{ {
var existingDevice = _deviceManager.GetDevice(id); var existingDevice = _deviceManager.GetDevice(id);
if (existingDevice == null) if (existingDevice == null)

View File

@ -43,9 +43,9 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")]
public ActionResult<DisplayPreferencesDto> GetDisplayPreferences( public ActionResult<DisplayPreferencesDto> GetDisplayPreferences(
[FromRoute, Required] string? displayPreferencesId, [FromRoute, Required] string displayPreferencesId,
[FromQuery] [Required] Guid userId, [FromQuery, Required] Guid userId,
[FromQuery] [Required] string? client) [FromQuery, Required] string client)
{ {
var displayPreferences = _displayPreferencesManager.GetDisplayPreferences(userId, client); var displayPreferences = _displayPreferencesManager.GetDisplayPreferences(userId, client);
var itemPreferences = _displayPreferencesManager.GetItemDisplayPreferences(displayPreferences.UserId, Guid.Empty, displayPreferences.Client); var itemPreferences = _displayPreferencesManager.GetItemDisplayPreferences(displayPreferences.UserId, Guid.Empty, displayPreferences.Client);
@ -97,9 +97,9 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")] [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "displayPreferencesId", Justification = "Imported from ServiceStack")]
public ActionResult UpdateDisplayPreferences( public ActionResult UpdateDisplayPreferences(
[FromRoute, Required] string? displayPreferencesId, [FromRoute, Required] string displayPreferencesId,
[FromQuery, Required] Guid userId, [FromQuery, Required] Guid userId,
[FromQuery, Required] string? client, [FromQuery, Required] string client,
[FromBody, Required] DisplayPreferencesDto displayPreferences) [FromBody, Required] DisplayPreferencesDto displayPreferences)
{ {
HomeSectionType[] defaults = HomeSectionType[] defaults =

View File

@ -170,7 +170,7 @@ namespace Jellyfin.Api.Controllers
[ProducesPlaylistFile] [ProducesPlaylistFile]
public async Task<ActionResult> GetMasterHlsVideoPlaylist( public async Task<ActionResult> GetMasterHlsVideoPlaylist(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? container, [FromRoute, Required] string container,
[FromQuery] bool? @static, [FromQuery] bool? @static,
[FromQuery] string? @params, [FromQuery] string? @params,
[FromQuery] string? tag, [FromQuery] string? tag,
@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? segmentContainer, [FromQuery] string? segmentContainer,
[FromQuery] int? segmentLength, [FromQuery] int? segmentLength,
[FromQuery] int? minSegments, [FromQuery] int? minSegments,
[FromQuery, Required] string? mediaSourceId, [FromQuery, Required] string mediaSourceId,
[FromQuery] string? deviceId, [FromQuery] string? deviceId,
[FromQuery] string? audioCodec, [FromQuery] string? audioCodec,
[FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? enableAutoStreamCopy,
@ -338,7 +338,7 @@ namespace Jellyfin.Api.Controllers
[ProducesPlaylistFile] [ProducesPlaylistFile]
public async Task<ActionResult> GetMasterHlsAudioPlaylist( public async Task<ActionResult> GetMasterHlsAudioPlaylist(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? container, [FromQuery, Required] string container,
[FromQuery] bool? @static, [FromQuery] bool? @static,
[FromQuery] string? @params, [FromQuery] string? @params,
[FromQuery] string? tag, [FromQuery] string? tag,
@ -347,7 +347,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] string? segmentContainer, [FromQuery] string? segmentContainer,
[FromQuery] int? segmentLength, [FromQuery] int? segmentLength,
[FromQuery] int? minSegments, [FromQuery] int? minSegments,
[FromQuery, Required] string? mediaSourceId, [FromQuery, Required] string mediaSourceId,
[FromQuery] string? deviceId, [FromQuery] string? deviceId,
[FromQuery] string? audioCodec, [FromQuery] string? audioCodec,
[FromQuery] bool? enableAutoStreamCopy, [FromQuery] bool? enableAutoStreamCopy,
@ -504,7 +504,7 @@ namespace Jellyfin.Api.Controllers
[ProducesPlaylistFile] [ProducesPlaylistFile]
public async Task<ActionResult> GetVariantHlsVideoPlaylist( public async Task<ActionResult> GetVariantHlsVideoPlaylist(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? container, [FromQuery, Required] string container,
[FromQuery] bool? @static, [FromQuery] bool? @static,
[FromQuery] string? @params, [FromQuery] string? @params,
[FromQuery] string? tag, [FromQuery] string? tag,
@ -670,7 +670,7 @@ namespace Jellyfin.Api.Controllers
[ProducesPlaylistFile] [ProducesPlaylistFile]
public async Task<ActionResult> GetVariantHlsAudioPlaylist( public async Task<ActionResult> GetVariantHlsAudioPlaylist(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? container, [FromQuery, Required] string container,
[FromQuery] bool? @static, [FromQuery] bool? @static,
[FromQuery] string? @params, [FromQuery] string? @params,
[FromQuery] string? tag, [FromQuery] string? tag,

View File

@ -67,7 +67,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesImageFile] [ProducesImageFile]
public ActionResult GetGeneralImage([FromRoute, Required] string? name, [FromRoute, Required] string? type) public ActionResult GetGeneralImage([FromRoute, Required] string name, [FromRoute, Required] string type)
{ {
var filename = string.Equals(type, "primary", StringComparison.OrdinalIgnoreCase) var filename = string.Equals(type, "primary", StringComparison.OrdinalIgnoreCase)
? "folder" ? "folder"
@ -114,8 +114,8 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesImageFile] [ProducesImageFile]
public ActionResult GetRatingImage( public ActionResult GetRatingImage(
[FromRoute, Required] string? theme, [FromRoute, Required] string theme,
[FromRoute, Required] string? name) [FromRoute, Required] string name)
{ {
return GetImageFile(_applicationPaths.RatingsPath, theme, name); return GetImageFile(_applicationPaths.RatingsPath, theme, name);
} }
@ -148,8 +148,8 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesImageFile] [ProducesImageFile]
public ActionResult GetMediaInfoImage( public ActionResult GetMediaInfoImage(
[FromRoute, Required] string? theme, [FromRoute, Required] string theme,
[FromRoute, Required] string? name) [FromRoute, Required] string name)
{ {
return GetImageFile(_applicationPaths.MediaInfoImagesPath, theme, name); return GetImageFile(_applicationPaths.MediaInfoImagesPath, theme, name);
} }

View File

@ -94,7 +94,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> PostUserImage( public async Task<ActionResult> PostUserImage(
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] int? index = null) [FromRoute] int? index = null)
{ {
if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
{ {
@ -141,7 +141,7 @@ namespace Jellyfin.Api.Controllers
public ActionResult DeleteUserImage( public ActionResult DeleteUserImage(
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] int? index = null) [FromRoute] int? index = null)
{ {
if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true)) if (!RequestHelpers.AssertCanUpdateUser(_authContext, HttpContext.Request, userId, true))
{ {
@ -179,7 +179,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> DeleteItemImage( public async Task<ActionResult> DeleteItemImage(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
if (item == null) if (item == null)
@ -209,7 +209,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> SetItemImage( public async Task<ActionResult> SetItemImage(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
if (item == null) if (item == null)
@ -357,8 +357,8 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> GetItemImage( public async Task<ActionResult> GetItemImage(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] int? maxWidth, [FromQuery] int? maxWidth,
[FromRoute, Required] int? maxHeight, [FromQuery] int? maxHeight,
[FromQuery] int? width, [FromQuery] int? width,
[FromQuery] int? height, [FromQuery] int? height,
[FromQuery] int? quality, [FromQuery] int? quality,
@ -371,7 +371,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
if (item == null) if (item == null)
@ -436,8 +436,8 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> GetItemImage2( public async Task<ActionResult> GetItemImage2(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] int? maxWidth, [FromRoute, Required] int maxWidth,
[FromRoute, Required] int? maxHeight, [FromRoute, Required] int maxHeight,
[FromQuery] int? width, [FromQuery] int? width,
[FromQuery] int? height, [FromQuery] int? height,
[FromQuery] int? quality, [FromQuery] int? quality,
@ -445,12 +445,12 @@ namespace Jellyfin.Api.Controllers
[FromQuery] bool? cropWhitespace, [FromQuery] bool? cropWhitespace,
[FromRoute, Required] string format, [FromRoute, Required] string format,
[FromQuery] bool? addPlayedIndicator, [FromQuery] bool? addPlayedIndicator,
[FromRoute, Required] double? percentPlayed, [FromRoute, Required] double percentPlayed,
[FromRoute, Required] int? unplayedCount, [FromRoute, Required] int unplayedCount,
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute, Required] int imageIndex)
{ {
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
if (item == null) if (item == null)
@ -515,12 +515,12 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> GetArtistImage( public async Task<ActionResult> GetArtistImage(
[FromRoute, Required] string name, [FromRoute, Required] string name,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] string tag, [FromQuery] string tag,
[FromRoute, Required] string format, [FromQuery] string format,
[FromRoute, Required] int? maxWidth, [FromQuery] int? maxWidth,
[FromRoute, Required] int? maxHeight, [FromQuery] int? maxHeight,
[FromRoute, Required] double? percentPlayed, [FromQuery] double? percentPlayed,
[FromRoute, Required] int? unplayedCount, [FromQuery] int? unplayedCount,
[FromQuery] int? width, [FromQuery] int? width,
[FromQuery] int? height, [FromQuery] int? height,
[FromQuery] int? quality, [FromQuery] int? quality,
@ -529,7 +529,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute, Required] int imageIndex)
{ {
var item = _libraryManager.GetArtist(name); var item = _libraryManager.GetArtist(name);
if (item == null) if (item == null)
@ -594,12 +594,12 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> GetGenreImage( public async Task<ActionResult> GetGenreImage(
[FromRoute, Required] string name, [FromRoute, Required] string name,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] string tag, [FromQuery] string tag,
[FromRoute, Required] string format, [FromQuery] string format,
[FromRoute, Required] int? maxWidth, [FromQuery] int? maxWidth,
[FromRoute, Required] int? maxHeight, [FromQuery] int? maxHeight,
[FromRoute, Required] double? percentPlayed, [FromQuery] double? percentPlayed,
[FromRoute, Required] int? unplayedCount, [FromQuery] int? unplayedCount,
[FromQuery] int? width, [FromQuery] int? width,
[FromQuery] int? height, [FromQuery] int? height,
[FromQuery] int? quality, [FromQuery] int? quality,
@ -608,7 +608,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var item = _libraryManager.GetGenre(name); var item = _libraryManager.GetGenre(name);
if (item == null) if (item == null)
@ -673,12 +673,12 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> GetMusicGenreImage( public async Task<ActionResult> GetMusicGenreImage(
[FromRoute, Required] string name, [FromRoute, Required] string name,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] string tag, [FromQuery] string tag,
[FromRoute, Required] string format, [FromQuery] string format,
[FromRoute, Required] int? maxWidth, [FromQuery] int? maxWidth,
[FromRoute, Required] int? maxHeight, [FromQuery] int? maxHeight,
[FromRoute, Required] double? percentPlayed, [FromQuery] double? percentPlayed,
[FromRoute, Required] int? unplayedCount, [FromQuery] int? unplayedCount,
[FromQuery] int? width, [FromQuery] int? width,
[FromQuery] int? height, [FromQuery] int? height,
[FromQuery] int? quality, [FromQuery] int? quality,
@ -687,7 +687,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var item = _libraryManager.GetMusicGenre(name); var item = _libraryManager.GetMusicGenre(name);
if (item == null) if (item == null)
@ -752,12 +752,12 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> GetPersonImage( public async Task<ActionResult> GetPersonImage(
[FromRoute, Required] string name, [FromRoute, Required] string name,
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] string tag, [FromQuery] string tag,
[FromRoute, Required] string format, [FromQuery] string format,
[FromRoute, Required] int? maxWidth, [FromQuery] int? maxWidth,
[FromRoute, Required] int? maxHeight, [FromQuery] int? maxHeight,
[FromRoute, Required] double? percentPlayed, [FromQuery] double? percentPlayed,
[FromRoute, Required] int? unplayedCount, [FromQuery] int? unplayedCount,
[FromQuery] int? width, [FromQuery] int? width,
[FromQuery] int? height, [FromQuery] int? height,
[FromQuery] int? quality, [FromQuery] int? quality,
@ -766,7 +766,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var item = _libraryManager.GetPerson(name); var item = _libraryManager.GetPerson(name);
if (item == null) if (item == null)
@ -833,10 +833,10 @@ namespace Jellyfin.Api.Controllers
[FromRoute, Required] ImageType imageType, [FromRoute, Required] ImageType imageType,
[FromRoute, Required] string tag, [FromRoute, Required] string tag,
[FromRoute, Required] string format, [FromRoute, Required] string format,
[FromRoute, Required] int? maxWidth, [FromQuery] int? maxWidth,
[FromRoute, Required] int? maxHeight, [FromQuery] int? maxHeight,
[FromRoute, Required] double? percentPlayed, [FromQuery] double? percentPlayed,
[FromRoute, Required] int? unplayedCount, [FromQuery] int? unplayedCount,
[FromQuery] int? width, [FromQuery] int? width,
[FromQuery] int? height, [FromQuery] int? height,
[FromQuery] int? quality, [FromQuery] int? quality,
@ -845,7 +845,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var item = _libraryManager.GetStudio(name); var item = _libraryManager.GetStudio(name);
if (item == null) if (item == null)
@ -924,7 +924,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? blur, [FromQuery] int? blur,
[FromQuery] string? backgroundColor, [FromQuery] string? backgroundColor,
[FromQuery] string? foregroundLayer, [FromQuery] string? foregroundLayer,
[FromRoute, Required] int? imageIndex = null) [FromRoute] int? imageIndex = null)
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);
if (user == null) if (user == null)

View File

@ -175,7 +175,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("MusicGenres/{name}/InstantMix")] [HttpGet("MusicGenres/{name}/InstantMix")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryResult<BaseItemDto>> GetInstantMixFromMusicGenre( public ActionResult<QueryResult<BaseItemDto>> GetInstantMixFromMusicGenre(
[FromRoute, Required] string? name, [FromRoute, Required] string name,
[FromQuery] Guid? userId, [FromQuery] Guid? userId,
[FromQuery] int? limit, [FromQuery] int? limit,
[FromQuery] string? fields, [FromQuery] string? fields,

View File

@ -195,7 +195,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Items/{itemId}/ContentType")] [HttpPost("Items/{itemId}/ContentType")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult UpdateItemContentType([FromRoute, Required] Guid itemId, [FromQuery, Required] string? contentType) public ActionResult UpdateItemContentType([FromRoute, Required] Guid itemId, [FromQuery] string contentType)
{ {
var item = _libraryManager.GetItemById(itemId); var item = _libraryManager.GetItemById(itemId);
if (item == null) if (item == null)

View File

@ -145,7 +145,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Users/{uId}/Items", Name = "GetItems_2")] [HttpGet("Users/{uId}/Items", Name = "GetItems_2")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryResult<BaseItemDto>> GetItems( public ActionResult<QueryResult<BaseItemDto>> GetItems(
[FromRoute, Required] Guid? uId, [FromRoute] Guid? uId,
[FromQuery] Guid? userId, [FromQuery] Guid? userId,
[FromQuery] string? maxOfficialRating, [FromQuery] string? maxOfficialRating,
[FromQuery] bool? hasThemeSong, [FromQuery] bool? hasThemeSong,

View File

@ -556,7 +556,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Library/Movies/Updated")] [HttpPost("Library/Movies/Updated")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostUpdatedMovies([FromRoute, Required] string? tmdbId, [FromRoute, Required] string? imdbId) public ActionResult PostUpdatedMovies([FromQuery] string? tmdbId, [FromQuery] string? imdbId)
{ {
var movies = _libraryManager.GetItemList(new InternalItemsQuery var movies = _libraryManager.GetItemList(new InternalItemsQuery
{ {

View File

@ -936,7 +936,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[Obsolete("This endpoint is obsolete.")] [Obsolete("This endpoint is obsolete.")]
public ActionResult<BaseItemDto> GetRecordingGroup([FromRoute, Required] Guid? groupId) public ActionResult<BaseItemDto> GetRecordingGroup([FromRoute, Required] Guid groupId)
{ {
return NotFound(); return NotFound();
} }

View File

@ -70,7 +70,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="Task"/> containing a <see cref="PlaybackInfoResponse"/> with the playback information.</returns> /// <returns>A <see cref="Task"/> containing a <see cref="PlaybackInfoResponse"/> with the playback information.</returns>
[HttpGet("Items/{itemId}/PlaybackInfo")] [HttpGet("Items/{itemId}/PlaybackInfo")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<PlaybackInfoResponse>> GetPlaybackInfo([FromRoute, Required] Guid itemId, [FromQuery, Required] Guid? userId) public async Task<ActionResult<PlaybackInfoResponse>> GetPlaybackInfo([FromRoute, Required] Guid itemId, [FromQuery, Required] Guid userId)
{ {
return await _mediaInfoHelper.GetPlaybackInfo( return await _mediaInfoHelper.GetPlaybackInfo(
itemId, itemId,
@ -271,7 +271,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>A <see cref="NoContentResult"/> indicating success.</returns> /// <returns>A <see cref="NoContentResult"/> indicating success.</returns>
[HttpPost("LiveStreams/Close")] [HttpPost("LiveStreams/Close")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> CloseLiveStream([FromQuery, Required] string? liveStreamId) public async Task<ActionResult> CloseLiveStream([FromQuery, Required] string liveStreamId)
{ {
await _mediaSourceManager.CloseLiveStream(liveStreamId).ConfigureAwait(false); await _mediaSourceManager.CloseLiveStream(liveStreamId).ConfigureAwait(false);
return NoContent(); return NoContent();

View File

@ -44,7 +44,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Packages/{name}")] [HttpGet("Packages/{name}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<PackageInfo>> GetPackageInfo( public async Task<ActionResult<PackageInfo>> GetPackageInfo(
[FromRoute, Required] string? name, [FromRoute, Required] string name,
[FromQuery] string? assemblyGuid) [FromQuery] string? assemblyGuid)
{ {
var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false); var packages = await _installationManager.GetAvailablePackages().ConfigureAwait(false);
@ -85,7 +85,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
public async Task<ActionResult> InstallPackage( public async Task<ActionResult> InstallPackage(
[FromRoute, Required] string? name, [FromRoute, Required] string name,
[FromQuery] string? assemblyGuid, [FromQuery] string? assemblyGuid,
[FromQuery] string? version) [FromQuery] string? version)
{ {

View File

@ -103,8 +103,8 @@ namespace Jellyfin.Api.Controllers
[HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")] [HttpPost("{playlistId}/Items/{itemId}/Move/{newIndex}")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> MoveItem( public async Task<ActionResult> MoveItem(
[FromRoute, Required] string? playlistId, [FromRoute, Required] string playlistId,
[FromRoute, Required] string? itemId, [FromRoute, Required] string itemId,
[FromRoute, Required] int newIndex) [FromRoute, Required] int newIndex)
{ {
await _playlistManager.MoveItemAsync(playlistId, itemId, newIndex).ConfigureAwait(false); await _playlistManager.MoveItemAsync(playlistId, itemId, newIndex).ConfigureAwait(false);
@ -120,7 +120,7 @@ namespace Jellyfin.Api.Controllers
/// <returns>An <see cref="NoContentResult"/> on success.</returns> /// <returns>An <see cref="NoContentResult"/> on success.</returns>
[HttpDelete("{playlistId}/Items")] [HttpDelete("{playlistId}/Items")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> RemoveFromPlaylist([FromRoute, Required] string? playlistId, [FromQuery] string? entryIds) public async Task<ActionResult> RemoveFromPlaylist([FromRoute, Required] string playlistId, [FromQuery] string? entryIds)
{ {
await _playlistManager.RemoveFromPlaylistAsync(playlistId, RequestHelpers.Split(entryIds, ',', true)).ConfigureAwait(false); await _playlistManager.RemoveFromPlaylistAsync(playlistId, RequestHelpers.Split(entryIds, ',', true)).ConfigureAwait(false);
return NoContent(); return NoContent();
@ -144,14 +144,14 @@ namespace Jellyfin.Api.Controllers
[HttpGet("{playlistId}/Items")] [HttpGet("{playlistId}/Items")]
public ActionResult<QueryResult<BaseItemDto>> GetPlaylistItems( public ActionResult<QueryResult<BaseItemDto>> GetPlaylistItems(
[FromRoute, Required] Guid playlistId, [FromRoute, Required] Guid playlistId,
[FromRoute, Required] Guid userId, [FromQuery, Required] Guid userId,
[FromRoute, Required] int? startIndex, [FromQuery] int? startIndex,
[FromRoute, Required] int? limit, [FromQuery] int? limit,
[FromRoute, Required] string? fields, [FromQuery] string? fields,
[FromRoute, Required] bool? enableImages, [FromQuery] bool? enableImages,
[FromRoute, Required] bool? enableUserData, [FromQuery] bool? enableUserData,
[FromRoute, Required] int? imageTypeLimit, [FromQuery] int? imageTypeLimit,
[FromRoute, Required] string? enableImageTypes) [FromQuery] string? enableImageTypes)
{ {
var playlist = (Playlist)_libraryManager.GetItemById(playlistId); var playlist = (Playlist)_libraryManager.GetItemById(playlistId);
if (playlist == null) if (playlist == null)

View File

@ -172,7 +172,7 @@ namespace Jellyfin.Api.Controllers
[Obsolete("This endpoint should not be used.")] [Obsolete("This endpoint should not be used.")]
[HttpPost("RegistrationRecords/{name}")] [HttpPost("RegistrationRecords/{name}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<MBRegistrationRecord> GetRegistrationStatus([FromRoute, Required] string? name) public ActionResult<MBRegistrationRecord> GetRegistrationStatus([FromRoute, Required] string name)
{ {
return new MBRegistrationRecord return new MBRegistrationRecord
{ {
@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers
[Obsolete("Paid plugins are not supported")] [Obsolete("Paid plugins are not supported")]
[HttpGet("Registrations/{name}")] [HttpGet("Registrations/{name}")]
[ProducesResponseType(StatusCodes.Status501NotImplemented)] [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, // 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. // delete all these registration endpoints. They are only kept for compatibility.

View File

@ -71,7 +71,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("{taskId}")] [HttpGet("{taskId}")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<TaskInfo> GetTask([FromRoute, Required] string? taskId) public ActionResult<TaskInfo> GetTask([FromRoute, Required] string taskId)
{ {
var task = _taskManager.ScheduledTasks.FirstOrDefault(i => var task = _taskManager.ScheduledTasks.FirstOrDefault(i =>
string.Equals(i.Id, taskId, StringComparison.OrdinalIgnoreCase)); string.Equals(i.Id, taskId, StringComparison.OrdinalIgnoreCase));
@ -94,7 +94,7 @@ namespace Jellyfin.Api.Controllers
[HttpPost("Running/{taskId}")] [HttpPost("Running/{taskId}")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult StartTask([FromRoute, Required] string? taskId) public ActionResult StartTask([FromRoute, Required] string taskId)
{ {
var task = _taskManager.ScheduledTasks.FirstOrDefault(o => var task = _taskManager.ScheduledTasks.FirstOrDefault(o =>
o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase)); o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase));
@ -118,7 +118,7 @@ namespace Jellyfin.Api.Controllers
[HttpDelete("Running/{taskId}")] [HttpDelete("Running/{taskId}")]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult StopTask([FromRoute, Required] string? taskId) public ActionResult StopTask([FromRoute, Required] string taskId)
{ {
var task = _taskManager.ScheduledTasks.FirstOrDefault(o => var task = _taskManager.ScheduledTasks.FirstOrDefault(o =>
o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase)); o.Id.Equals(taskId, StringComparison.OrdinalIgnoreCase));
@ -144,7 +144,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult UpdateTask( public ActionResult UpdateTask(
[FromRoute, Required] string? taskId, [FromRoute, Required] string taskId,
[FromBody, Required] TaskTriggerInfo[] triggerInfos) [FromBody, Required] TaskTriggerInfo[] triggerInfos)
{ {
var task = _taskManager.ScheduledTasks.FirstOrDefault(o => var task = _taskManager.ScheduledTasks.FirstOrDefault(o =>

View File

@ -81,7 +81,7 @@ namespace Jellyfin.Api.Controllers
[FromQuery] int? startIndex, [FromQuery] int? startIndex,
[FromQuery] int? limit, [FromQuery] int? limit,
[FromQuery] Guid? userId, [FromQuery] Guid? userId,
[FromQuery, Required] string? searchTerm, [FromQuery, Required] string searchTerm,
[FromQuery] string? includeItemTypes, [FromQuery] string? includeItemTypes,
[FromQuery] string? excludeItemTypes, [FromQuery] string? excludeItemTypes,
[FromQuery] string? mediaTypes, [FromQuery] string? mediaTypes,

View File

@ -125,10 +125,10 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult DisplayContent( public ActionResult DisplayContent(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromQuery, Required] string? itemType, [FromQuery, Required] string itemType,
[FromQuery, Required] string? itemId, [FromQuery, Required] string itemId,
[FromQuery, Required] string? itemName) [FromQuery, Required] string itemName)
{ {
var command = new BrowseRequest var command = new BrowseRequest
{ {
@ -150,25 +150,25 @@ namespace Jellyfin.Api.Controllers
/// Instructs a session to play an item. /// Instructs a session to play an item.
/// </summary> /// </summary>
/// <param name="sessionId">The session id.</param> /// <param name="sessionId">The session id.</param>
/// <param name="command">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="itemIds">The ids of the items to play, comma delimited.</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="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>
/// <response code="204">Instruction sent to session.</response> /// <response code="204">Instruction sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns> /// <returns>A <see cref="NoContentResult"/>.</returns>
[HttpPost("Sessions/{sessionId}/Playing")] [HttpPost("Sessions/{sessionId}/Playing/{command}")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult Play( public ActionResult Play(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] PlayCommand command,
[FromQuery] Guid[] itemIds, [FromQuery] Guid[] itemIds,
[FromQuery] long? startPositionTicks, [FromQuery] long? startPositionTicks)
[FromQuery] PlayCommand playCommand)
{ {
var playRequest = new PlayRequest var playRequest = new PlayRequest
{ {
ItemIds = itemIds, ItemIds = itemIds,
StartPositionTicks = startPositionTicks, StartPositionTicks = startPositionTicks,
PlayCommand = playCommand PlayCommand = command
}; };
_sessionManager.SendPlayCommand( _sessionManager.SendPlayCommand(
@ -187,11 +187,11 @@ namespace Jellyfin.Api.Controllers
/// <param name="playstateRequest">The <see cref="PlaystateRequest"/>.</param> /// <param name="playstateRequest">The <see cref="PlaystateRequest"/>.</param>
/// <response code="204">Playstate command sent to session.</response> /// <response code="204">Playstate command sent to session.</response>
/// <returns>A <see cref="NoContentResult"/>.</returns> /// <returns>A <see cref="NoContentResult"/>.</returns>
[HttpPost("Sessions/{sessionId}/Playing/{command}")] [HttpPost("Sessions/{sessionId}/Playing")]
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendPlaystateCommand( public ActionResult SendPlaystateCommand(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromBody] PlaystateRequest playstateRequest) [FromBody] PlaystateRequest playstateRequest)
{ {
_sessionManager.SendPlaystateCommand( _sessionManager.SendPlaystateCommand(
@ -214,8 +214,8 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendSystemCommand( public ActionResult SendSystemCommand(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] string? command) [FromRoute, Required] string command)
{ {
var name = command; var name = command;
if (Enum.TryParse(name, true, out GeneralCommandType commandType)) if (Enum.TryParse(name, true, out GeneralCommandType commandType))
@ -246,8 +246,8 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendGeneralCommand( public ActionResult SendGeneralCommand(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] string? command) [FromRoute, Required] string command)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request); var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request);
@ -273,7 +273,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendFullGeneralCommand( public ActionResult SendFullGeneralCommand(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromBody, Required] GeneralCommand command) [FromBody, Required] GeneralCommand command)
{ {
var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request); var currentSession = RequestHelpers.GetSession(_sessionManager, _authContext, Request);
@ -307,9 +307,9 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult SendMessageCommand( public ActionResult SendMessageCommand(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromQuery, Required] string? text, [FromQuery, Required] string text,
[FromQuery, Required] string? header, [FromQuery] string? header,
[FromQuery] long? timeoutMs) [FromQuery] long? timeoutMs)
{ {
var command = new MessageCommand var command = new MessageCommand
@ -335,7 +335,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult AddUserToSession( public ActionResult AddUserToSession(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] Guid userId) [FromRoute, Required] Guid userId)
{ {
_sessionManager.AddAdditionalUser(sessionId, userId); _sessionManager.AddAdditionalUser(sessionId, userId);
@ -353,7 +353,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult RemoveUserFromSession( public ActionResult RemoveUserFromSession(
[FromRoute, Required] string? sessionId, [FromRoute, Required] string sessionId,
[FromRoute, Required] Guid userId) [FromRoute, Required] Guid userId)
{ {
_sessionManager.RemoveAdditionalUser(sessionId, userId); _sessionManager.RemoveAdditionalUser(sessionId, userId);
@ -375,7 +375,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.DefaultAuthorization)] [Authorize(Policy = Policies.DefaultAuthorization)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public ActionResult PostCapabilities( public ActionResult PostCapabilities(
[FromQuery, Required] string? id, [FromQuery] string? id,
[FromQuery] string? playableMediaTypes, [FromQuery] string? playableMediaTypes,
[FromQuery] string? supportedCommands, [FromQuery] string? supportedCommands,
[FromQuery] bool supportsMediaControl = false, [FromQuery] bool supportsMediaControl = false,

View File

@ -114,7 +114,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public async Task<ActionResult<IEnumerable<RemoteSubtitleInfo>>> SearchRemoteSubtitles( public async Task<ActionResult<IEnumerable<RemoteSubtitleInfo>>> SearchRemoteSubtitles(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? language, [FromRoute, Required] string language,
[FromQuery] bool? isPerfectMatch) [FromQuery] bool? isPerfectMatch)
{ {
var video = (Video)_libraryManager.GetItemById(itemId); var video = (Video)_libraryManager.GetItemById(itemId);
@ -134,7 +134,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
public async Task<ActionResult> DownloadRemoteSubtitles( public async Task<ActionResult> DownloadRemoteSubtitles(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? subtitleId) [FromRoute, Required] string subtitleId)
{ {
var video = (Video)_libraryManager.GetItemById(itemId); var video = (Video)_libraryManager.GetItemById(itemId);
@ -164,7 +164,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[Produces(MediaTypeNames.Application.Octet)] [Produces(MediaTypeNames.Application.Octet)]
[ProducesFile("text/*")] [ProducesFile("text/*")]
public async Task<ActionResult> GetRemoteSubtitles([FromRoute, Required] string? id) public async Task<ActionResult> GetRemoteSubtitles([FromRoute, Required] string id)
{ {
var result = await _subtitleManager.GetRemoteSubtitles(id, CancellationToken.None).ConfigureAwait(false); var result = await _subtitleManager.GetRemoteSubtitles(id, CancellationToken.None).ConfigureAwait(false);
@ -190,13 +190,13 @@ namespace Jellyfin.Api.Controllers
[ProducesFile("text/*")] [ProducesFile("text/*")]
public async Task<ActionResult> GetSubtitle( public async Task<ActionResult> GetSubtitle(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? mediaSourceId, [FromRoute, Required] string mediaSourceId,
[FromRoute, Required] int index, [FromRoute, Required] int index,
[FromRoute, Required] string? format, [FromRoute, Required] string format,
[FromQuery] long? endPositionTicks, [FromQuery] long? endPositionTicks,
[FromQuery] bool copyTimestamps = false, [FromQuery] bool copyTimestamps = false,
[FromQuery] bool addVttTimeMap = false, [FromQuery] bool addVttTimeMap = false,
[FromRoute, Required] long startPositionTicks = 0) [FromRoute] long startPositionTicks = 0)
{ {
if (string.Equals(format, "js", StringComparison.OrdinalIgnoreCase)) if (string.Equals(format, "js", StringComparison.OrdinalIgnoreCase))
{ {
@ -258,7 +258,7 @@ namespace Jellyfin.Api.Controllers
public async Task<ActionResult> GetSubtitlePlaylist( public async Task<ActionResult> GetSubtitlePlaylist(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] int index, [FromRoute, Required] int index,
[FromRoute, Required] string? mediaSourceId, [FromRoute, Required] string mediaSourceId,
[FromQuery, Required] int segmentLength) [FromQuery, Required] int segmentLength)
{ {
var item = (Video)_libraryManager.GetItemById(itemId); var item = (Video)_libraryManager.GetItemById(itemId);

View File

@ -194,7 +194,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesFile(MediaTypeNames.Text.Plain)] [ProducesFile(MediaTypeNames.Text.Plain)]
public ActionResult GetLogFile([FromQuery, Required] string? name) public ActionResult GetLogFile([FromQuery, Required] string name)
{ {
var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath) var file = _fileSystem.GetFiles(_appPaths.LogDirectoryPath)
.First(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase)); .First(i => string.Equals(i.Name, name, StringComparison.OrdinalIgnoreCase));

View File

@ -69,7 +69,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("NextUp")] [HttpGet("NextUp")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryResult<BaseItemDto>> GetNextUp( public ActionResult<QueryResult<BaseItemDto>> GetNextUp(
[FromQuery, Required] Guid? userId, [FromQuery] Guid? userId,
[FromQuery] int? startIndex, [FromQuery] int? startIndex,
[FromQuery] int? limit, [FromQuery] int? limit,
[FromQuery] string? fields, [FromQuery] string? fields,
@ -127,7 +127,7 @@ namespace Jellyfin.Api.Controllers
[HttpGet("Upcoming")] [HttpGet("Upcoming")]
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
public ActionResult<QueryResult<BaseItemDto>> GetUpcomingEpisodes( public ActionResult<QueryResult<BaseItemDto>> GetUpcomingEpisodes(
[FromQuery, Required] Guid? userId, [FromQuery] Guid? userId,
[FromQuery] int? startIndex, [FromQuery] int? startIndex,
[FromQuery] int? limit, [FromQuery] int? limit,
[FromQuery] string? fields, [FromQuery] string? fields,
@ -194,8 +194,8 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<QueryResult<BaseItemDto>> GetEpisodes( public ActionResult<QueryResult<BaseItemDto>> GetEpisodes(
[FromRoute, Required] string? seriesId, [FromRoute, Required] string seriesId,
[FromQuery, Required] Guid? userId, [FromQuery] Guid? userId,
[FromQuery] string? fields, [FromQuery] string? fields,
[FromQuery] int? season, [FromQuery] int? season,
[FromQuery] string? seasonId, [FromQuery] string? seasonId,
@ -317,8 +317,8 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public ActionResult<QueryResult<BaseItemDto>> GetSeasons( public ActionResult<QueryResult<BaseItemDto>> GetSeasons(
[FromRoute, Required] string? seriesId, [FromRoute, Required] string seriesId,
[FromQuery, Required] Guid? userId, [FromQuery] Guid? userId,
[FromQuery] string? fields, [FromQuery] string? fields,
[FromQuery] bool? isSpecialSeason, [FromQuery] bool? isSpecialSeason,
[FromQuery] bool? isMissing, [FromQuery] bool? isMissing,

View File

@ -97,7 +97,7 @@ namespace Jellyfin.Api.Controllers
[ProducesAudioFile] [ProducesAudioFile]
public async Task<ActionResult> GetUniversalAudioStream( public async Task<ActionResult> GetUniversalAudioStream(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? container, [FromRoute] string? container,
[FromQuery] string? mediaSourceId, [FromQuery] string? mediaSourceId,
[FromQuery] string? deviceId, [FromQuery] string? deviceId,
[FromQuery] Guid? userId, [FromQuery] Guid? userId,

View File

@ -157,7 +157,7 @@ namespace Jellyfin.Api.Controllers
[ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<ActionResult<AuthenticationResult>> AuthenticateUser( public async Task<ActionResult<AuthenticationResult>> AuthenticateUser(
[FromRoute, Required] Guid userId, [FromRoute, Required] Guid userId,
[FromQuery, Required] string? pw, [FromQuery, Required] string pw,
[FromQuery] string? password) [FromQuery] string? password)
{ {
var user = _userManager.GetUserById(userId); var user = _userManager.GetUserById(userId);

View File

@ -203,7 +203,7 @@ namespace Jellyfin.Api.Controllers
[Authorize(Policy = Policies.RequiresElevation)] [Authorize(Policy = Policies.RequiresElevation)]
[ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task<ActionResult> MergeVersions([FromQuery, Required] string? itemIds) public async Task<ActionResult> MergeVersions([FromQuery, Required] string itemIds)
{ {
var items = RequestHelpers.Split(itemIds, ',', true) var items = RequestHelpers.Split(itemIds, ',', true)
.Select(i => _libraryManager.GetItemById(i)) .Select(i => _libraryManager.GetItemById(i))
@ -334,7 +334,7 @@ namespace Jellyfin.Api.Controllers
[ProducesVideoFile] [ProducesVideoFile]
public async Task<ActionResult> GetVideoStream( public async Task<ActionResult> GetVideoStream(
[FromRoute, Required] Guid itemId, [FromRoute, Required] Guid itemId,
[FromRoute, Required] string? container, [FromRoute] string? container,
[FromQuery] bool? @static, [FromQuery] bool? @static,
[FromQuery] string? @params, [FromQuery] string? @params,
[FromQuery] string? tag, [FromQuery] string? tag,