mirror of
https://github.com/jellyfin/jellyfin.git
synced 2026-07-06 06:12:52 +01:00
Merge pull request #12798 from JPVenson/feature/EFUserData
Refactor library.db into jellyfin.db and EFCore
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Jellyfin.Api.Extensions;
|
||||
using Jellyfin.Api.Helpers;
|
||||
using Jellyfin.Api.ModelBinders;
|
||||
@@ -389,23 +391,19 @@ public class InstantMixController : BaseJellyfinApiController
|
||||
return GetResult(items, user, limit, dtoOptions);
|
||||
}
|
||||
|
||||
private QueryResult<BaseItemDto> GetResult(List<BaseItem> items, User? user, int? limit, DtoOptions dtoOptions)
|
||||
private QueryResult<BaseItemDto> GetResult(IReadOnlyList<BaseItem> items, User? user, int? limit, DtoOptions dtoOptions)
|
||||
{
|
||||
var list = items;
|
||||
var totalCount = items.Count;
|
||||
|
||||
var totalCount = list.Count;
|
||||
|
||||
if (limit.HasValue && limit < list.Count)
|
||||
if (limit.HasValue && limit < items.Count)
|
||||
{
|
||||
list = list.GetRange(0, limit.Value);
|
||||
items = items.Take(limit.Value).ToArray();
|
||||
}
|
||||
|
||||
var returnList = _dtoService.GetBaseItemDtos(list, dtoOptions, user);
|
||||
|
||||
var result = new QueryResult<BaseItemDto>(
|
||||
0,
|
||||
totalCount,
|
||||
returnList);
|
||||
_dtoService.GetBaseItemDtos(items, dtoOptions, user));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -967,7 +967,7 @@ public class ItemsController : BaseJellyfinApiController
|
||||
[HttpGet("UserItems/{itemId}/UserData")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult<UserItemDataDto> GetItemUserData(
|
||||
public ActionResult<UserItemDataDto?> GetItemUserData(
|
||||
[FromQuery] Guid? userId,
|
||||
[FromRoute, Required] Guid itemId)
|
||||
{
|
||||
@@ -1005,7 +1005,7 @@ public class ItemsController : BaseJellyfinApiController
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[Obsolete("Kept for backwards compatibility")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public ActionResult<UserItemDataDto> GetItemUserDataLegacy(
|
||||
public ActionResult<UserItemDataDto?> GetItemUserDataLegacy(
|
||||
[FromRoute, Required] Guid userId,
|
||||
[FromRoute, Required] Guid itemId)
|
||||
=> GetItemUserData(userId, itemId);
|
||||
@@ -1022,7 +1022,7 @@ public class ItemsController : BaseJellyfinApiController
|
||||
[HttpPost("UserItems/{itemId}/UserData")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public ActionResult<UserItemDataDto> UpdateItemUserData(
|
||||
public ActionResult<UserItemDataDto?> UpdateItemUserData(
|
||||
[FromQuery] Guid? userId,
|
||||
[FromRoute, Required] Guid itemId,
|
||||
[FromBody, Required] UpdateUserItemDataDto userDataDto)
|
||||
@@ -1064,7 +1064,7 @@ public class ItemsController : BaseJellyfinApiController
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[Obsolete("Kept for backwards compatibility")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public ActionResult<UserItemDataDto> UpdateItemUserDataLegacy(
|
||||
public ActionResult<UserItemDataDto?> UpdateItemUserDataLegacy(
|
||||
[FromRoute, Required] Guid userId,
|
||||
[FromRoute, Required] Guid itemId,
|
||||
[FromBody, Required] UpdateUserItemDataDto userDataDto)
|
||||
|
||||
@@ -780,11 +780,9 @@ public class LibraryController : BaseJellyfinApiController
|
||||
Genres = item.Genres,
|
||||
Limit = limit,
|
||||
IncludeItemTypes = includeItemTypes.ToArray(),
|
||||
SimilarTo = item,
|
||||
DtoOptions = dtoOptions,
|
||||
EnableTotalRecordCount = !isMovie ?? true,
|
||||
EnableGroupByMetadataKey = isMovie ?? false,
|
||||
MinSimilarityScore = 2 // A remnant from album/artist scoring
|
||||
};
|
||||
|
||||
// ExcludeArtistIds
|
||||
@@ -793,7 +791,7 @@ public class LibraryController : BaseJellyfinApiController
|
||||
query.ExcludeArtistIds = excludeArtistIds;
|
||||
}
|
||||
|
||||
List<BaseItem> itemsResult = _libraryManager.GetItemList(query);
|
||||
var itemsResult = _libraryManager.GetItemList(query);
|
||||
|
||||
var returnList = _dtoService.GetBaseItemDtos(itemsResult, dtoOptions, user);
|
||||
|
||||
|
||||
@@ -99,6 +99,7 @@ public class LibraryStructureController : BaseJellyfinApiController
|
||||
/// <param name="name">The name of the folder.</param>
|
||||
/// <param name="refreshLibrary">Whether to refresh the library.</param>
|
||||
/// <response code="204">Folder removed.</response>
|
||||
/// <response code="404">Folder not found.</response>
|
||||
/// <returns>A <see cref="NoContentResult"/>.</returns>
|
||||
[HttpDelete]
|
||||
[ProducesResponseType(StatusCodes.Status204NoContent)]
|
||||
@@ -106,7 +107,9 @@ public class LibraryStructureController : BaseJellyfinApiController
|
||||
[FromQuery] string name,
|
||||
[FromQuery] bool refreshLibrary = false)
|
||||
{
|
||||
// TODO: refactor! this relies on an FileNotFound exception to return NotFound when attempting to remove a library that does not exist.
|
||||
await _libraryManager.RemoveVirtualFolder(name, refreshLibrary).ConfigureAwait(false);
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@ public class MoviesController : BaseJellyfinApiController
|
||||
DtoOptions = dtoOptions
|
||||
});
|
||||
|
||||
var mostRecentMovies = recentlyPlayedMovies.GetRange(0, Math.Min(recentlyPlayedMovies.Count, 6));
|
||||
var mostRecentMovies = recentlyPlayedMovies.Take(Math.Min(recentlyPlayedMovies.Count, 6)).ToList();
|
||||
// Get recently played directors
|
||||
var recentDirectors = GetDirectors(mostRecentMovies)
|
||||
.ToList();
|
||||
@@ -276,7 +276,6 @@ public class MoviesController : BaseJellyfinApiController
|
||||
Limit = itemLimit,
|
||||
IncludeItemTypes = itemTypes.ToArray(),
|
||||
IsMovie = true,
|
||||
SimilarTo = item,
|
||||
EnableGroupByMetadataKey = true,
|
||||
DtoOptions = dtoOptions
|
||||
});
|
||||
|
||||
@@ -72,7 +72,7 @@ public class PlaystateController : BaseJellyfinApiController
|
||||
[HttpPost("UserPlayedItems/{itemId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<UserItemDataDto>> MarkPlayedItem(
|
||||
public async Task<ActionResult<UserItemDataDto?>> MarkPlayedItem(
|
||||
[FromQuery] Guid? userId,
|
||||
[FromRoute, Required] Guid itemId,
|
||||
[FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed)
|
||||
@@ -121,7 +121,7 @@ public class PlaystateController : BaseJellyfinApiController
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[Obsolete("Kept for backwards compatibility")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public Task<ActionResult<UserItemDataDto>> MarkPlayedItemLegacy(
|
||||
public Task<ActionResult<UserItemDataDto?>> MarkPlayedItemLegacy(
|
||||
[FromRoute, Required] Guid userId,
|
||||
[FromRoute, Required] Guid itemId,
|
||||
[FromQuery, ModelBinder(typeof(LegacyDateTimeModelBinder))] DateTime? datePlayed)
|
||||
@@ -138,7 +138,7 @@ public class PlaystateController : BaseJellyfinApiController
|
||||
[HttpDelete("UserPlayedItems/{itemId}")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
public async Task<ActionResult<UserItemDataDto>> MarkUnplayedItem(
|
||||
public async Task<ActionResult<UserItemDataDto?>> MarkUnplayedItem(
|
||||
[FromQuery] Guid? userId,
|
||||
[FromRoute, Required] Guid itemId)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ public class PlaystateController : BaseJellyfinApiController
|
||||
[ProducesResponseType(StatusCodes.Status404NotFound)]
|
||||
[Obsolete("Kept for backwards compatibility")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public Task<ActionResult<UserItemDataDto>> MarkUnplayedItemLegacy(
|
||||
public Task<ActionResult<UserItemDataDto?>> MarkUnplayedItemLegacy(
|
||||
[FromRoute, Required] Guid userId,
|
||||
[FromRoute, Required] Guid itemId)
|
||||
=> MarkUnplayedItem(userId, itemId);
|
||||
@@ -502,7 +502,7 @@ public class PlaystateController : BaseJellyfinApiController
|
||||
/// <param name="wasPlayed">if set to <c>true</c> [was played].</param>
|
||||
/// <param name="datePlayed">The date played.</param>
|
||||
/// <returns>Task.</returns>
|
||||
private UserItemDataDto UpdatePlayedStatus(User user, BaseItem item, bool wasPlayed, DateTime? datePlayed)
|
||||
private UserItemDataDto? UpdatePlayedStatus(User user, BaseItem item, bool wasPlayed, DateTime? datePlayed)
|
||||
{
|
||||
if (wasPlayed)
|
||||
{
|
||||
|
||||
@@ -305,7 +305,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
||||
/// <returns>An <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>.</returns>
|
||||
[HttpDelete("UserItems/{itemId}/Rating")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult<UserItemDataDto> DeleteUserItemRating(
|
||||
public ActionResult<UserItemDataDto?> DeleteUserItemRating(
|
||||
[FromQuery] Guid? userId,
|
||||
[FromRoute, Required] Guid itemId)
|
||||
{
|
||||
@@ -338,7 +338,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[Obsolete("Kept for backwards compatibility")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public ActionResult<UserItemDataDto> DeleteUserItemRatingLegacy(
|
||||
public ActionResult<UserItemDataDto?> DeleteUserItemRatingLegacy(
|
||||
[FromRoute, Required] Guid userId,
|
||||
[FromRoute, Required] Guid itemId)
|
||||
=> DeleteUserItemRating(userId, itemId);
|
||||
@@ -353,7 +353,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
||||
/// <returns>An <see cref="OkResult"/> containing the <see cref="UserItemDataDto"/>.</returns>
|
||||
[HttpPost("UserItems/{itemId}/Rating")]
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
public ActionResult<UserItemDataDto> UpdateUserItemRating(
|
||||
public ActionResult<UserItemDataDto?> UpdateUserItemRating(
|
||||
[FromQuery] Guid? userId,
|
||||
[FromRoute, Required] Guid itemId,
|
||||
[FromQuery] bool? likes)
|
||||
@@ -388,7 +388,7 @@ public class UserLibraryController : BaseJellyfinApiController
|
||||
[ProducesResponseType(StatusCodes.Status200OK)]
|
||||
[Obsolete("Kept for backwards compatibility")]
|
||||
[ApiExplorerSettings(IgnoreApi = true)]
|
||||
public ActionResult<UserItemDataDto> UpdateUserItemRatingLegacy(
|
||||
public ActionResult<UserItemDataDto?> UpdateUserItemRatingLegacy(
|
||||
[FromRoute, Required] Guid userId,
|
||||
[FromRoute, Required] Guid itemId,
|
||||
[FromQuery] bool? likes)
|
||||
@@ -662,12 +662,15 @@ public class UserLibraryController : BaseJellyfinApiController
|
||||
// Get the user data for this item
|
||||
var data = _userDataRepository.GetUserData(user, item);
|
||||
|
||||
// Set favorite status
|
||||
data.IsFavorite = isFavorite;
|
||||
if (data is not null)
|
||||
{
|
||||
// Set favorite status
|
||||
data.IsFavorite = isFavorite;
|
||||
|
||||
_userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
|
||||
_userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
|
||||
}
|
||||
|
||||
return _userDataRepository.GetUserDataDto(item, user);
|
||||
return _userDataRepository.GetUserDataDto(item, user)!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -676,14 +679,17 @@ public class UserLibraryController : BaseJellyfinApiController
|
||||
/// <param name="user">The user.</param>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="likes">if set to <c>true</c> [likes].</param>
|
||||
private UserItemDataDto UpdateUserItemRatingInternal(User user, BaseItem item, bool? likes)
|
||||
private UserItemDataDto? UpdateUserItemRatingInternal(User user, BaseItem item, bool? likes)
|
||||
{
|
||||
// Get the user data for this item
|
||||
var data = _userDataRepository.GetUserData(user, item);
|
||||
|
||||
data.Likes = likes;
|
||||
if (data is not null)
|
||||
{
|
||||
data.Likes = likes;
|
||||
|
||||
_userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
|
||||
_userDataRepository.SaveUserData(user, item, data, UserDataSaveReason.UpdateUserRating, CancellationToken.None);
|
||||
}
|
||||
|
||||
return _userDataRepository.GetUserDataDto(item, user);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using Jellyfin.Api.Extensions;
|
||||
@@ -105,18 +106,18 @@ public class YearsController : BaseJellyfinApiController
|
||||
|
||||
bool Filter(BaseItem i) => FilterItem(i, excludeItemTypes, includeItemTypes, mediaTypes);
|
||||
|
||||
IList<BaseItem> items;
|
||||
IReadOnlyList<BaseItem> items;
|
||||
if (parentItem.IsFolder)
|
||||
{
|
||||
var folder = (Folder)parentItem;
|
||||
|
||||
if (userId.IsNullOrEmpty())
|
||||
{
|
||||
items = recursive ? folder.GetRecursiveChildren(Filter) : folder.Children.Where(Filter).ToList();
|
||||
items = recursive ? folder.GetRecursiveChildren(Filter) : folder.Children.Where(Filter).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
items = recursive ? folder.GetRecursiveChildren(user, query).ToList() : folder.GetChildren(user, true).Where(Filter).ToList();
|
||||
items = recursive ? folder.GetRecursiveChildren(user, query) : folder.GetChildren(user, true).Where(Filter).ToArray();
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user