aboutsummaryrefslogtreecommitdiff
path: root/Jellyfin.Server.Implementations
diff options
context:
space:
mode:
authorJPVenson <github@jpb.email>2025-03-25 15:12:48 +0000
committerJPVenson <github@jpb.email>2025-03-25 15:12:48 +0000
commit850f1c79f1319de56a300c1d62565c9b2793b7d8 (patch)
treef307a380c63d80809fed23c7ce2c8a0d0aba5de8 /Jellyfin.Server.Implementations
parentef7f6fc8a97118df7f410a7afa2f501f3f4ca3e2 (diff)
parent671d801d9f734665d0acbd441246712ad2e3d91f (diff)
Merge branch 'master' into feature/DatabaseRefactor
Diffstat (limited to 'Jellyfin.Server.Implementations')
-rw-r--r--Jellyfin.Server.Implementations/Item/BaseItemRepository.cs72
-rw-r--r--Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs14
2 files changed, 56 insertions, 30 deletions
diff --git a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
index 392b7de74..bea69b282 100644
--- a/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
+++ b/Jellyfin.Server.Implementations/Item/BaseItemRepository.cs
@@ -101,16 +101,23 @@ public sealed class BaseItemRepository
using var context = _dbProvider.CreateDbContext();
using var transaction = context.Database.BeginTransaction();
- context.PeopleBaseItemMap.Where(e => e.ItemId == id).ExecuteDelete();
- context.Peoples.Where(e => e.BaseItems!.Count == 0).ExecuteDelete();
- context.Chapters.Where(e => e.ItemId == id).ExecuteDelete();
- context.MediaStreamInfos.Where(e => e.ItemId == id).ExecuteDelete();
context.AncestorIds.Where(e => e.ItemId == id || e.ParentItemId == id).ExecuteDelete();
- context.ItemValuesMap.Where(e => e.ItemId == id).ExecuteDelete();
- context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDelete();
+ context.AttachmentStreamInfos.Where(e => e.ItemId == id).ExecuteDelete();
context.BaseItemImageInfos.Where(e => e.ItemId == id).ExecuteDelete();
+ context.BaseItemMetadataFields.Where(e => e.ItemId == id).ExecuteDelete();
context.BaseItemProviders.Where(e => e.ItemId == id).ExecuteDelete();
+ context.BaseItemTrailerTypes.Where(e => e.ItemId == id).ExecuteDelete();
context.BaseItems.Where(e => e.Id == id).ExecuteDelete();
+ context.Chapters.Where(e => e.ItemId == id).ExecuteDelete();
+ context.CustomItemDisplayPreferences.Where(e => e.ItemId == id).ExecuteDelete();
+ context.ItemDisplayPreferences.Where(e => e.ItemId == id).ExecuteDelete();
+ context.ItemValues.Where(e => e.BaseItemsMap!.Count == 0).ExecuteDelete();
+ context.ItemValuesMap.Where(e => e.ItemId == id).ExecuteDelete();
+ context.MediaSegments.Where(e => e.ItemId == id).ExecuteDelete();
+ context.MediaStreamInfos.Where(e => e.ItemId == id).ExecuteDelete();
+ context.PeopleBaseItemMap.Where(e => e.ItemId == id).ExecuteDelete();
+ context.Peoples.Where(e => e.BaseItems!.Count == 0).ExecuteDelete();
+ context.TrickplayInfos.Where(e => e.ItemId == id).ExecuteDelete();
context.SaveChanges();
transaction.Commit();
}
@@ -255,6 +262,37 @@ public sealed class BaseItemRepository
return dbQuery.AsEnumerable().Where(e => e is not null).Select(w => DeserialiseBaseItem(w, filter.SkipDeserialization)).ToArray();
}
+ /// <inheritdoc />
+ public IReadOnlyList<string> GetNextUpSeriesKeys(InternalItemsQuery filter, DateTime dateCutoff)
+ {
+ ArgumentNullException.ThrowIfNull(filter);
+ ArgumentNullException.ThrowIfNull(filter.User);
+
+ using var context = _dbProvider.CreateDbContext();
+
+ var query = context.BaseItems
+ .AsNoTracking()
+ .Where(i => filter.TopParentIds.Contains(i.TopParentId!.Value))
+ .Where(i => i.Type == _itemTypeLookup.BaseItemKindNames[BaseItemKind.Episode])
+ .Join(
+ context.UserData.AsNoTracking(),
+ i => new { UserId = filter.User.Id, ItemId = i.Id },
+ u => new { UserId = u.UserId, ItemId = u.ItemId },
+ (entity, data) => new { Item = entity, UserData = data })
+ .GroupBy(g => g.Item.SeriesPresentationUniqueKey)
+ .Select(g => new { g.Key, LastPlayedDate = g.Max(u => u.UserData.LastPlayedDate) })
+ .Where(g => g.Key != null && g.LastPlayedDate != null && g.LastPlayedDate >= dateCutoff)
+ .OrderByDescending(g => g.LastPlayedDate)
+ .Select(g => g.Key!);
+
+ if (filter.Limit.HasValue)
+ {
+ query = query.Take(filter.Limit.Value);
+ }
+
+ return query.ToArray();
+ }
+
private IQueryable<BaseItemEntity> ApplyGroupingFilter(IQueryable<BaseItemEntity> dbQuery, InternalItemsQuery filter)
{
// This whole block is needed to filter duplicate entries on request
@@ -925,25 +963,11 @@ public sealed class BaseItemRepository
using var context = _dbProvider.CreateDbContext();
- var innerQuery = new InternalItemsQuery(filter.User)
- {
- ExcludeItemTypes = filter.ExcludeItemTypes,
- IncludeItemTypes = filter.IncludeItemTypes,
- MediaTypes = filter.MediaTypes,
- AncestorIds = filter.AncestorIds,
- ItemIds = filter.ItemIds,
- TopParentIds = filter.TopParentIds,
- ParentId = filter.ParentId,
- IsAiring = filter.IsAiring,
- IsMovie = filter.IsMovie,
- IsSports = filter.IsSports,
- IsKids = filter.IsKids,
- IsNews = filter.IsNews,
- IsSeries = filter.IsSeries
- };
- var query = TranslateQuery(context.BaseItems.AsNoTracking(), context, innerQuery);
+ var query = TranslateQuery(context.BaseItems.AsNoTracking(), context, filter);
- query = query.Where(e => e.Type == returnType && e.ItemValues!.Any(f => e.CleanName == f.ItemValue.CleanValue && itemValueTypes.Any(w => (ItemValueType)w == f.ItemValue.Type)));
+ query = query.Where(e => e.Type == returnType);
+ // this does not seem to be nesseary but it does not make any sense why this isn't working.
+ // && e.ItemValues!.Any(f => e.CleanName == f.ItemValue.CleanValue && itemValueTypes.Any(w => (ItemValueType)w == f.ItemValue.Type)));
if (filter.OrderBy.Count != 0
|| !string.IsNullOrEmpty(filter.SearchTerm))
diff --git a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs
index 5d209b0af..6949ec1a8 100644
--- a/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs
+++ b/Jellyfin.Server.Implementations/Trickplay/TrickplayManager.cs
@@ -12,6 +12,7 @@ using MediaBrowser.Common.Configuration;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Entities;
+using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.MediaEncoding;
using MediaBrowser.Controller.Trickplay;
@@ -37,9 +38,10 @@ public class TrickplayManager : ITrickplayManager
private readonly IImageEncoder _imageEncoder;
private readonly IDbContextFactory<JellyfinDbContext> _dbProvider;
private readonly IApplicationPaths _appPaths;
+ private readonly IPathManager _pathManager;
private static readonly AsyncNonKeyedLocker _resourcePool = new(1);
- private static readonly string[] _trickplayImgExtensions = { ".jpg" };
+ private static readonly string[] _trickplayImgExtensions = [".jpg"];
/// <summary>
/// Initializes a new instance of the <see cref="TrickplayManager"/> class.
@@ -53,6 +55,7 @@ public class TrickplayManager : ITrickplayManager
/// <param name="imageEncoder">The image encoder.</param>
/// <param name="dbProvider">The database provider.</param>
/// <param name="appPaths">The application paths.</param>
+ /// <param name="pathManager">The path manager.</param>
public TrickplayManager(
ILogger<TrickplayManager> logger,
IMediaEncoder mediaEncoder,
@@ -62,7 +65,8 @@ public class TrickplayManager : ITrickplayManager
IServerConfigurationManager config,
IImageEncoder imageEncoder,
IDbContextFactory<JellyfinDbContext> dbProvider,
- IApplicationPaths appPaths)
+ IApplicationPaths appPaths,
+ IPathManager pathManager)
{
_logger = logger;
_mediaEncoder = mediaEncoder;
@@ -73,6 +77,7 @@ public class TrickplayManager : ITrickplayManager
_imageEncoder = imageEncoder;
_dbProvider = dbProvider;
_appPaths = appPaths;
+ _pathManager = pathManager;
}
/// <inheritdoc />
@@ -610,10 +615,7 @@ public class TrickplayManager : ITrickplayManager
/// <inheritdoc />
public string GetTrickplayDirectory(BaseItem item, int tileWidth, int tileHeight, int width, bool saveWithMedia = false)
{
- var path = saveWithMedia
- ? Path.Combine(item.ContainingFolderPath, Path.ChangeExtension(item.Path, ".trickplay"))
- : Path.Combine(item.GetInternalMetadataPath(), "trickplay");
-
+ var path = _pathManager.GetTrickplayDirectory(item, saveWithMedia);
var subdirectory = string.Format(
CultureInfo.InvariantCulture,
"{0} - {1}x{2}",