diff options
4 files changed, 68 insertions, 3 deletions
diff --git a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs index b9f9f29723..6ba4a7bce6 100644 --- a/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/ExtraResolver.cs @@ -32,8 +32,8 @@ namespace Emby.Server.Implementations.Library.Resolvers : base(logger, namingOptions, directoryService) { _namingOptions = namingOptions; - _trailerResolvers = new IItemResolver[] { new GenericVideoResolver<Trailer>(logger, namingOptions, directoryService) }; - _videoResolvers = new IItemResolver[] { this }; + _trailerResolvers = [new GenericVideoResolver<Trailer>(logger, namingOptions, directoryService, parseName: true)]; + _videoResolvers = [this]; } protected override Video Resolve(ItemResolveArgs args) diff --git a/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs index ba320266a4..b3bdea704a 100644 --- a/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs +++ b/Emby.Server.Implementations/Library/Resolvers/GenericVideoResolver.cs @@ -2,6 +2,7 @@ using Emby.Naming.Common; using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using Microsoft.Extensions.Logging; @@ -14,15 +15,25 @@ namespace Emby.Server.Implementations.Library.Resolvers public class GenericVideoResolver<T> : BaseVideoResolver<T> where T : Video, new() { + private readonly bool _parseName; + /// <summary> /// Initializes a new instance of the <see cref="GenericVideoResolver{T}"/> class. /// </summary> /// <param name="logger">The logger.</param> /// <param name="namingOptions">The naming options.</param> /// <param name="directoryService">The directory service.</param> - public GenericVideoResolver(ILogger logger, NamingOptions namingOptions, IDirectoryService directoryService) + /// <param name="parseName">Whether to parse the file name for metadata such as the year.</param> + public GenericVideoResolver(ILogger logger, NamingOptions namingOptions, IDirectoryService directoryService, bool parseName = false) : base(logger, namingOptions, directoryService) { + _parseName = parseName; + } + + /// <inheritdoc /> + protected override T Resolve(ItemResolveArgs args) + { + return ResolveVideo<T>(args, _parseName); } } } diff --git a/MediaBrowser.Controller/Entities/BaseItem.cs b/MediaBrowser.Controller/Entities/BaseItem.cs index 49a4ed4bf6..cc2a425a4d 100644 --- a/MediaBrowser.Controller/Entities/BaseItem.cs +++ b/MediaBrowser.Controller/Entities/BaseItem.cs @@ -1557,6 +1557,19 @@ namespace MediaBrowser.Controller.Entities i.OwnerId = ownerId; i.ParentId = Guid.Empty; + + // Extras (e.g. trailers) frequently have no reliable date metadata of their own and + // would otherwise fall back to the file's container creation date. Inherit the owner's + // year/premiere date when the extra doesn't have one, so it stays consistent with the + // media it belongs to. Setting it before the refresh means the media info provider + // won't overwrite it from the file creation date. + if (!i.ProductionYear.HasValue && item.ProductionYear.HasValue) + { + i.ProductionYear = item.ProductionYear; + i.PremiereDate ??= item.PremiereDate; + subOptions.ForceSave = true; + } + return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken); }); diff --git a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs index 562711337f..07c537aee1 100644 --- a/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs +++ b/tests/Jellyfin.Server.Implementations.Tests/Library/LibraryManager/FindExtrasTests.cs @@ -306,6 +306,47 @@ public class FindExtrasTests } [Fact] + public void FindExtras_TrailerWithYearInFilename_SetsProductionYearFromFilename() + { + var owner = new Movie { Name = "Up", Path = "/movies/Up/Up.mkv" }; + var paths = new List<string> + { + "/movies/Up/Up.mkv", + "/movies/Up/trailers" + }; + + _fileSystemMock.Setup(f => f.GetFiles( + "/movies/Up/trailers", + It.IsAny<string[]>(), + false, + false)) + .Returns(new List<FileSystemMetadata> + { + new() + { + FullName = "/movies/Up/trailers/Trailer 1 (2013).mkv", + Name = "Trailer 1 (2013).mkv", + IsDirectory = false + } + }).Verifiable(); + + var files = paths.Select(p => new FileSystemMetadata + { + FullName = p, + Name = Path.GetFileName(p), + IsDirectory = !Path.HasExtension(p) + }).ToList(); + + var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).ToList(); + + _fileSystemMock.Verify(); + var trailer = Assert.Single(extras); + Assert.Equal(ExtraType.Trailer, trailer.ExtraType); + Assert.Equal(typeof(Trailer), trailer.GetType()); + Assert.Equal(2013, trailer.ProductionYear); + } + + [Fact] public void FindExtras_SeriesWithTrailers_FindsCorrectExtras() { var owner = new Series { Name = "Dexter", Path = "/series/Dexter" }; |
