diff --git a/Jellyfin.Api/Controllers/ItemsController.cs b/Jellyfin.Api/Controllers/ItemsController.cs index 4e46e808ae..38a7d115e5 100644 --- a/Jellyfin.Api/Controllers/ItemsController.cs +++ b/Jellyfin.Api/Controllers/ItemsController.cs @@ -1,6 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; using System.Linq; +using System.Threading; using Jellyfin.Api.Extensions; using Jellyfin.Api.Helpers; using Jellyfin.Api.ModelBinders; @@ -34,6 +35,7 @@ public class ItemsController : BaseJellyfinApiController private readonly IDtoService _dtoService; private readonly ILogger _logger; private readonly ISessionManager _sessionManager; + private readonly IUserDataManager _userDataRepository; /// /// Initializes a new instance of the class. @@ -44,13 +46,15 @@ public class ItemsController : BaseJellyfinApiController /// Instance of the interface. /// Instance of the interface. /// Instance of the interface. + /// Instance of the interface. public ItemsController( IUserManager userManager, ILibraryManager libraryManager, ILocalizationManager localization, IDtoService dtoService, ILogger logger, - ISessionManager sessionManager) + ISessionManager sessionManager, + IUserDataManager userDataRepository) { _userManager = userManager; _libraryManager = libraryManager; @@ -58,6 +62,7 @@ public class ItemsController : BaseJellyfinApiController _dtoService = dtoService; _logger = logger; _sessionManager = sessionManager; + _userDataRepository = userDataRepository; } /// @@ -881,4 +886,103 @@ public class ItemsController : BaseJellyfinApiController itemsResult.TotalRecordCount, returnItems); } + + /// + /// Get Item User Data. + /// + /// The user id. + /// The item id. + /// item user data returned. + /// When item is not found. + /// Return Item . + [HttpGet("Users/{userId}/Items/{itemId}/UserData")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public ActionResult GetItemUserData( + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId) + { + var user = _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException(); + var item = _libraryManager.GetItemById(itemId); + + return (item == null) ? NotFound() : _userDataRepository.GetUserDataDto(item, user); + } + + /// + /// Update Item User Data. + /// + /// The user id. + /// The item id. + /// Optional. Whether to mark the item as played. + /// Optional. Whether to mark the item as favorite. + /// Optional. Whether mark the item as liked. + /// Optional. User item rating. + /// Optional. User Item playback Position Ticks. 1 tick = 10000 ms. + /// Item user data. + /// Optional. The date the item was played. + /// update user data returned. + /// When item is not found. + /// . + [HttpPost("Users/{userId}/Items/{itemId}/UserData")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status404NotFound)] + public ActionResult UpdateItemUserData( + [FromRoute, Required] Guid userId, + [FromRoute, Required] Guid itemId, + [FromQuery] bool? played, + [FromQuery] bool? favorite, + [FromQuery] bool? likes, + [FromQuery] double? rating, + [FromQuery] long? playbackPositionTicks, + [FromQuery] int? playCount, + [FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? lastPlayedDate) + { + var user = _userManager.GetUserById(userId) ?? throw new ResourceNotFoundException(); + var item = _libraryManager.GetItemById(itemId); + if (item == null) + { + return NotFound(); + } + + var userData = _userDataRepository.GetUserData(user, item); + + if (played.HasValue) + { + userData.Played = played.Value; + } + + if (favorite.HasValue) + { + userData.IsFavorite = favorite.Value; + } + + if (likes.HasValue) + { + userData.Likes = likes.Value; + } + + if (rating.HasValue) + { + userData.Rating = rating.Value; + } + + if (playbackPositionTicks.HasValue) + { + userData.PlaybackPositionTicks = playbackPositionTicks.Value; + } + + if (playCount.HasValue) + { + userData.PlayCount = playCount.Value; + } + + if (lastPlayedDate.HasValue) + { + userData.LastPlayedDate = lastPlayedDate.Value; + } + + _userDataRepository.SaveUserData(user.Id, item, userData, UserDataSaveReason.UpdateUserData, CancellationToken.None); + + return _userDataRepository.GetUserDataDto(item, user); + } } diff --git a/MediaBrowser.Model/Entities/UserDataSaveReason.cs b/MediaBrowser.Model/Entities/UserDataSaveReason.cs index 20404e6f4d..b8e73a98cd 100644 --- a/MediaBrowser.Model/Entities/UserDataSaveReason.cs +++ b/MediaBrowser.Model/Entities/UserDataSaveReason.cs @@ -33,6 +33,11 @@ namespace MediaBrowser.Model.Entities /// /// The import. /// - Import = 6 + Import = 6, + + /// + /// API call updated item user data. + /// + UpdateUserData = 7, } }