diff options
| author | Cody Robibero <cody@robibe.ro> | 2024-03-03 13:51:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-03 13:51:31 -0700 |
| commit | 6e5ec99ea10557c141ed8d755e672cef628d35f0 (patch) | |
| tree | dc3aff5d566811d7f52030c10b25fdb1a02b9b5e /Jellyfin.Api/Controllers/PlaystateController.cs | |
| parent | 8d40d431e8e5b067a535e564362b902480a13259 (diff) | |
Move userId in API from route to optional query parameter (#11074)
* Move userId in API from route to optional query parameter
* Standardize UserViewsController
* Move userId to query in ImageController
* Move userId to query in ItemsController
* Move userId to query in PlaystateController
* Move userId to query in SuggestionsController
* Move userId from route to query in UserLibraryController
* Clean up routes
* Move userId to query in UserController
* fix bad merge
---------
Co-authored-by: Niels van Velzen <git@ndat.nl>
Diffstat (limited to 'Jellyfin.Api/Controllers/PlaystateController.cs')
| -rw-r--r-- | Jellyfin.Api/Controllers/PlaystateController.cs | 168 |
1 files changed, 149 insertions, 19 deletions
diff --git a/Jellyfin.Api/Controllers/PlaystateController.cs b/Jellyfin.Api/Controllers/PlaystateController.cs index bde2f4d1a..949d101dc 100644 --- a/Jellyfin.Api/Controllers/PlaystateController.cs +++ b/Jellyfin.Api/Controllers/PlaystateController.cs @@ -68,15 +68,16 @@ public class PlaystateController : BaseJellyfinApiController /// <response code="200">Item marked as played.</response> /// <response code="404">Item not found.</response> /// <returns>An <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>, or a <see cref="NotFoundResult"/> if item was not found.</returns> - [HttpPost("Users/{userId}/PlayedItems/{itemId}")] + [HttpPost("UserPlayedItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task<ActionResult<UserItemDataDto>> MarkPlayedItem( - [FromRoute, Required] Guid userId, + [FromQuery] Guid? userId, [FromRoute, Required] Guid itemId, [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed) { - var user = _userManager.GetUserById(userId); + var requestUserId = RequestHelpers.GetUserId(User, userId); + var user = _userManager.GetUserById(requestUserId); if (user is null) { return NotFound(); @@ -106,6 +107,26 @@ public class PlaystateController : BaseJellyfinApiController } /// <summary> + /// Marks an item as played for user. + /// </summary> + /// <param name="userId">User id.</param> + /// <param name="itemId">Item id.</param> + /// <param name="datePlayed">Optional. The date the item was played.</param> + /// <response code="200">Item marked as played.</response> + /// <response code="404">Item not found.</response> + /// <returns>An <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>, or a <see cref="NotFoundResult"/> if item was not found.</returns> + [HttpPost("Users/{userId}/PlayedItems/{itemId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [Obsolete("Kept for backwards compatibility")] + [ApiExplorerSettings(IgnoreApi = true)] + public Task<ActionResult<UserItemDataDto>> MarkPlayedItemLegacy( + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, + [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed) + => MarkPlayedItem(userId, itemId, datePlayed); + + /// <summary> /// Marks an item as unplayed for user. /// </summary> /// <param name="userId">User id.</param> @@ -113,12 +134,15 @@ public class PlaystateController : BaseJellyfinApiController /// <response code="200">Item marked as unplayed.</response> /// <response code="404">Item not found.</response> /// <returns>A <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>, or a <see cref="NotFoundResult"/> if item was not found.</returns> - [HttpDelete("Users/{userId}/PlayedItems/{itemId}")] + [HttpDelete("UserPlayedItems/{itemId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] - public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem([FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId) + public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem( + [FromQuery] Guid? userId, + [FromRoute, Required] Guid itemId) { - var user = _userManager.GetUserById(userId); + var requestUserId = RequestHelpers.GetUserId(User, userId); + var user = _userManager.GetUserById(requestUserId); if (user is null) { return NotFound(); @@ -148,6 +172,24 @@ public class PlaystateController : BaseJellyfinApiController } /// <summary> + /// Marks an item as unplayed for user. + /// </summary> + /// <param name="userId">User id.</param> + /// <param name="itemId">Item id.</param> + /// <response code="200">Item marked as unplayed.</response> + /// <response code="404">Item not found.</response> + /// <returns>A <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>, or a <see cref="NotFoundResult"/> if item was not found.</returns> + [HttpDelete("Users/{userId}/PlayedItems/{itemId}")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + [Obsolete("Kept for backwards compatibility")] + [ApiExplorerSettings(IgnoreApi = true)] + public Task<ActionResult<UserItemDataDto>> MarkUnplayedItemLegacy( + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId) + => MarkUnplayedItem(userId, itemId); + + /// <summary> /// Reports playback has started within a session. /// </summary> /// <param name="playbackStartInfo">The playback start info.</param> @@ -215,9 +257,8 @@ public class PlaystateController : BaseJellyfinApiController } /// <summary> - /// Reports that a user has begun playing an item. + /// Reports that a session has begun playing an item. /// </summary> - /// <param name="userId">User id.</param> /// <param name="itemId">Item id.</param> /// <param name="mediaSourceId">The id of the MediaSource.</param> /// <param name="audioStreamIndex">The audio stream index.</param> @@ -228,11 +269,9 @@ public class PlaystateController : BaseJellyfinApiController /// <param name="canSeek">Indicates if the client can seek.</param> /// <response code="204">Play start recorded.</response> /// <returns>A <see cref="NoContentResult"/>.</returns> - [HttpPost("Users/{userId}/PlayingItems/{itemId}")] + [HttpPost("PlayingItems/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task<ActionResult> OnPlaybackStart( - [FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] int? audioStreamIndex, @@ -261,11 +300,41 @@ public class PlaystateController : BaseJellyfinApiController } /// <summary> - /// Reports a user's playback progress. + /// Reports that a user has begun playing an item. /// </summary> /// <param name="userId">User id.</param> /// <param name="itemId">Item id.</param> /// <param name="mediaSourceId">The id of the MediaSource.</param> + /// <param name="audioStreamIndex">The audio stream index.</param> + /// <param name="subtitleStreamIndex">The subtitle stream index.</param> + /// <param name="playMethod">The play method.</param> + /// <param name="liveStreamId">The live stream id.</param> + /// <param name="playSessionId">The play session id.</param> + /// <param name="canSeek">Indicates if the client can seek.</param> + /// <response code="204">Play start recorded.</response> + /// <returns>A <see cref="NoContentResult"/>.</returns> + [HttpPost("Users/{userId}/PlayingItems/{itemId}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [Obsolete("Kept for backwards compatibility")] + [ApiExplorerSettings(IgnoreApi = true)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] + public Task<ActionResult> OnPlaybackStartLegacy( + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, + [FromQuery] string? mediaSourceId, + [FromQuery] int? audioStreamIndex, + [FromQuery] int? subtitleStreamIndex, + [FromQuery] PlayMethod? playMethod, + [FromQuery] string? liveStreamId, + [FromQuery] string? playSessionId, + [FromQuery] bool canSeek = false) + => OnPlaybackStart(itemId, mediaSourceId, audioStreamIndex, subtitleStreamIndex, playMethod, liveStreamId, playSessionId, canSeek); + + /// <summary> + /// Reports a session's playback progress. + /// </summary> + /// <param name="itemId">Item id.</param> + /// <param name="mediaSourceId">The id of the MediaSource.</param> /// <param name="positionTicks">Optional. The current position, in ticks. 1 tick = 10000 ms.</param> /// <param name="audioStreamIndex">The audio stream index.</param> /// <param name="subtitleStreamIndex">The subtitle stream index.</param> @@ -278,11 +347,9 @@ public class PlaystateController : BaseJellyfinApiController /// <param name="isMuted">Indicates if the player is muted.</param> /// <response code="204">Play progress recorded.</response> /// <returns>A <see cref="NoContentResult"/>.</returns> - [HttpPost("Users/{userId}/PlayingItems/{itemId}/Progress")] + [HttpPost("PlayingItems/{itemId}/Progress")] [ProducesResponseType(StatusCodes.Status204NoContent)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task<ActionResult> OnPlaybackProgress( - [FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] long? positionTicks, @@ -319,22 +386,58 @@ public class PlaystateController : BaseJellyfinApiController } /// <summary> - /// Reports that a user has stopped playing an item. + /// Reports a user's playback progress. /// </summary> /// <param name="userId">User id.</param> /// <param name="itemId">Item id.</param> /// <param name="mediaSourceId">The id of the MediaSource.</param> + /// <param name="positionTicks">Optional. The current position, in ticks. 1 tick = 10000 ms.</param> + /// <param name="audioStreamIndex">The audio stream index.</param> + /// <param name="subtitleStreamIndex">The subtitle stream index.</param> + /// <param name="volumeLevel">Scale of 0-100.</param> + /// <param name="playMethod">The play method.</param> + /// <param name="liveStreamId">The live stream id.</param> + /// <param name="playSessionId">The play session id.</param> + /// <param name="repeatMode">The repeat mode.</param> + /// <param name="isPaused">Indicates if the player is paused.</param> + /// <param name="isMuted">Indicates if the player is muted.</param> + /// <response code="204">Play progress recorded.</response> + /// <returns>A <see cref="NoContentResult"/>.</returns> + [HttpPost("Users/{userId}/PlayingItems/{itemId}/Progress")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [Obsolete("Kept for backwards compatibility")] + [ApiExplorerSettings(IgnoreApi = true)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] + public Task<ActionResult> OnPlaybackProgressLegacy( + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, + [FromQuery] string? mediaSourceId, + [FromQuery] long? positionTicks, + [FromQuery] int? audioStreamIndex, + [FromQuery] int? subtitleStreamIndex, + [FromQuery] int? volumeLevel, + [FromQuery] PlayMethod? playMethod, + [FromQuery] string? liveStreamId, + [FromQuery] string? playSessionId, + [FromQuery] RepeatMode? repeatMode, + [FromQuery] bool isPaused = false, + [FromQuery] bool isMuted = false) + => OnPlaybackProgress(itemId, mediaSourceId, positionTicks, audioStreamIndex, subtitleStreamIndex, volumeLevel, playMethod, liveStreamId, playSessionId, repeatMode, isPaused, isMuted); + + /// <summary> + /// Reports that a session has stopped playing an item. + /// </summary> + /// <param name="itemId">Item id.</param> + /// <param name="mediaSourceId">The id of the MediaSource.</param> /// <param name="nextMediaType">The next media type that will play.</param> /// <param name="positionTicks">Optional. The position, in ticks, where playback stopped. 1 tick = 10000 ms.</param> /// <param name="liveStreamId">The live stream id.</param> /// <param name="playSessionId">The play session id.</param> /// <response code="204">Playback stop recorded.</response> /// <returns>A <see cref="NoContentResult"/>.</returns> - [HttpDelete("Users/{userId}/PlayingItems/{itemId}")] + [HttpDelete("PlayingItems/{itemId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] - [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] public async Task<ActionResult> OnPlaybackStopped( - [FromRoute, Required] Guid userId, [FromRoute, Required] Guid itemId, [FromQuery] string? mediaSourceId, [FromQuery] string? nextMediaType, @@ -364,6 +467,33 @@ public class PlaystateController : BaseJellyfinApiController } /// <summary> + /// Reports that a user has stopped playing an item. + /// </summary> + /// <param name="userId">User id.</param> + /// <param name="itemId">Item id.</param> + /// <param name="mediaSourceId">The id of the MediaSource.</param> + /// <param name="nextMediaType">The next media type that will play.</param> + /// <param name="positionTicks">Optional. The position, in ticks, where playback stopped. 1 tick = 10000 ms.</param> + /// <param name="liveStreamId">The live stream id.</param> + /// <param name="playSessionId">The play session id.</param> + /// <response code="204">Playback stop recorded.</response> + /// <returns>A <see cref="NoContentResult"/>.</returns> + [HttpDelete("Users/{userId}/PlayingItems/{itemId}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [Obsolete("Kept for backwards compatibility")] + [ApiExplorerSettings(IgnoreApi = true)] + [SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "userId", Justification = "Required for ServiceStack")] + public Task<ActionResult> OnPlaybackStoppedLegacy( + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, + [FromQuery] string? mediaSourceId, + [FromQuery] string? nextMediaType, + [FromQuery] long? positionTicks, + [FromQuery] string? liveStreamId, + [FromQuery] string? playSessionId) + => OnPlaybackStopped(itemId, mediaSourceId, nextMediaType, positionTicks, liveStreamId, playSessionId); + + /// <summary> /// Updates the played status. /// </summary> /// <param name="user">The user.</param> |
