Merge pull request #17399 from Shadowghost/fix-extra-year
Fix incorrect year on local trailers
This commit is contained in:
@@ -3199,11 +3199,11 @@ namespace Emby.Server.Implementations.Library
|
||||
}
|
||||
}
|
||||
|
||||
if (!episode.ProductionYear.HasValue)
|
||||
if (episode.ProductionYear is null)
|
||||
{
|
||||
episode.ProductionYear = episodeInfo.Year;
|
||||
|
||||
if (episode.ProductionYear.HasValue)
|
||||
if (episode.ProductionYear is not null)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace Emby.Server.Implementations.Sorting
|
||||
return x.PremiereDate.Value;
|
||||
}
|
||||
|
||||
if (x.ProductionYear.HasValue)
|
||||
if (x.ProductionYear is not null)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Emby.Server.Implementations.Sorting
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (x.ProductionYear.HasValue)
|
||||
if (x.ProductionYear is not null)
|
||||
{
|
||||
return x.ProductionYear.Value;
|
||||
}
|
||||
|
||||
@@ -1546,15 +1546,27 @@ namespace MediaBrowser.Controller.Entities
|
||||
var extras = LibraryManager.FindExtras(item, fileSystemChildren, options.DirectoryService).ToArray();
|
||||
var newExtraIds = Array.ConvertAll(extras, x => x.Id);
|
||||
|
||||
var currentExtraIds = LibraryManager.GetItemList(new InternalItemsQuery()
|
||||
var currentExtras = LibraryManager.GetItemList(new InternalItemsQuery()
|
||||
{
|
||||
OwnerIds = [item.Id]
|
||||
}).Select(e => e.Id).ToArray();
|
||||
});
|
||||
|
||||
var currentExtraIds = currentExtras.Select(e => e.Id).ToArray();
|
||||
|
||||
var extrasChanged = !currentExtraIds.OrderBy(x => x).SequenceEqual(newExtraIds.OrderBy(x => x));
|
||||
|
||||
if (!extrasChanged && !options.ReplaceAllMetadata && options.MetadataRefreshMode != MetadataRefreshMode.FullRefresh)
|
||||
{
|
||||
// The owner's dates may only have become known after its extras were created, so keep
|
||||
// them in sync even when there is nothing to refresh.
|
||||
foreach (var extra in currentExtras)
|
||||
{
|
||||
if (extra.ExtraType is not null && InheritDatesFromOwner(item, extra))
|
||||
{
|
||||
await extra.UpdateToRepositoryAsync(ItemUpdateType.MetadataEdit, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1570,6 +1582,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
|
||||
i.OwnerId = ownerId;
|
||||
i.ParentId = Guid.Empty;
|
||||
|
||||
return RefreshMetadataForOwnedItem(i, true, subOptions, cancellationToken);
|
||||
});
|
||||
|
||||
@@ -2652,6 +2665,32 @@ namespace MediaBrowser.Controller.Entities
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the owner's premiere date and production year to an owned item, returning whether anything changed.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner.</param>
|
||||
/// <param name="ownedItem">The owned item.</param>
|
||||
/// <returns><c>true</c> if the owned item was changed, else <c>false</c>.</returns>
|
||||
internal static bool InheritDatesFromOwner(BaseItem owner, BaseItem ownedItem)
|
||||
{
|
||||
// Extras have no release date of their own, so the owner's is authoritative.
|
||||
var changed = false;
|
||||
|
||||
if (owner.ProductionYear is not null && ownedItem.ProductionYear != owner.ProductionYear)
|
||||
{
|
||||
ownedItem.ProductionYear = owner.ProductionYear;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
if (owner.PremiereDate is not null && ownedItem.PremiereDate != owner.PremiereDate)
|
||||
{
|
||||
ownedItem.PremiereDate = owner.PremiereDate;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
|
||||
protected async Task RefreshMetadataForOwnedItem(BaseItem ownedItem, bool copyTitleMetadata, MetadataRefreshOptions options, CancellationToken cancellationToken)
|
||||
{
|
||||
var newOptions = new MetadataRefreshOptions(options)
|
||||
@@ -2711,6 +2750,11 @@ namespace MediaBrowser.Controller.Entities
|
||||
ownedItem.CustomRating = item.CustomRating;
|
||||
newOptions.ForceSave = true;
|
||||
}
|
||||
|
||||
if (InheritDatesFromOwner(item, ownedItem))
|
||||
{
|
||||
newOptions.ForceSave = true;
|
||||
}
|
||||
}
|
||||
|
||||
await ownedItem.RefreshMetadata(newOptions, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -90,7 +90,7 @@ namespace MediaBrowser.Controller.Entities.Movies
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
|
||||
|
||||
if (!ProductionYear.HasValue)
|
||||
if (ProductionYear is null)
|
||||
{
|
||||
var info = LibraryManager.ParseName(Name);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
|
||||
|
||||
if (!ProductionYear.HasValue)
|
||||
if (ProductionYear is null)
|
||||
{
|
||||
var info = LibraryManager.ParseName(Name);
|
||||
|
||||
|
||||
@@ -507,7 +507,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
|
||||
|
||||
if (!ProductionYear.HasValue)
|
||||
if (ProductionYear is null)
|
||||
{
|
||||
var info = LibraryManager.ParseName(Name);
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
{
|
||||
var hasChanges = base.BeforeMetadataRefresh(replaceAllMetadata);
|
||||
|
||||
if (!ProductionYear.HasValue)
|
||||
if (ProductionYear is null)
|
||||
{
|
||||
var info = LibraryManager.ParseName(Name);
|
||||
|
||||
|
||||
@@ -730,7 +730,7 @@ namespace MediaBrowser.Controller.Entities
|
||||
// Apply year filter
|
||||
if (query.Years.Length > 0)
|
||||
{
|
||||
if (!(item.ProductionYear.HasValue && query.Years.Contains(item.ProductionYear.Value)))
|
||||
if (item.ProductionYear is null || !query.Years.Contains(item.ProductionYear.Value))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace MediaBrowser.LocalMetadata.Savers
|
||||
await writer.WriteElementStringAsync(null, "Rating", null, item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
if (item.ProductionYear.HasValue && item is not Person)
|
||||
if (item.ProductionYear is not null && item is not Person)
|
||||
{
|
||||
await writer.WriteElementStringAsync(null, "ProductionYear", null, item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace MediaBrowser.MediaEncoding.Probing
|
||||
}
|
||||
|
||||
// Guess ProductionYear from PremiereDate if missing
|
||||
if (!info.ProductionYear.HasValue && info.PremiereDate.HasValue)
|
||||
if (info.ProductionYear is null && info.PremiereDate is not null)
|
||||
{
|
||||
info.ProductionYear = info.PremiereDate.Value.Year;
|
||||
}
|
||||
|
||||
@@ -1114,7 +1114,7 @@ namespace MediaBrowser.Providers.Manager
|
||||
target.PremiereDate = source.PremiereDate;
|
||||
}
|
||||
|
||||
if (replaceData || !target.ProductionYear.HasValue)
|
||||
if (replaceData || target.ProductionYear is null)
|
||||
{
|
||||
target.ProductionYear = source.ProductionYear;
|
||||
}
|
||||
|
||||
@@ -386,7 +386,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions refreshOptions, LibraryOptions libraryOptions)
|
||||
internal void FetchEmbeddedInfo(Video video, Model.MediaInfo.MediaInfo data, MetadataRefreshOptions refreshOptions, LibraryOptions libraryOptions)
|
||||
{
|
||||
var replaceData = refreshOptions.ReplaceAllMetadata;
|
||||
|
||||
@@ -432,17 +432,19 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
}
|
||||
}
|
||||
|
||||
if (data.ProductionYear.HasValue)
|
||||
// Extras have no release date of their own, they inherit it from the item they belong to.
|
||||
var useContainerDates = video.ExtraType is null;
|
||||
if (useContainerDates && data.ProductionYear is not null)
|
||||
{
|
||||
if (!video.ProductionYear.HasValue || replaceData)
|
||||
if (video.ProductionYear is null || replaceData)
|
||||
{
|
||||
video.ProductionYear = data.ProductionYear;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.PremiereDate.HasValue)
|
||||
if (useContainerDates && data.PremiereDate is not null)
|
||||
{
|
||||
if (!video.PremiereDate.HasValue || replaceData)
|
||||
if (video.PremiereDate is null || replaceData)
|
||||
{
|
||||
video.PremiereDate = data.PremiereDate;
|
||||
}
|
||||
@@ -482,7 +484,7 @@ namespace MediaBrowser.Providers.MediaInfo
|
||||
}
|
||||
|
||||
// If we don't have a ProductionYear try and get it from PremiereDate
|
||||
if (video.PremiereDate.HasValue && !video.ProductionYear.HasValue)
|
||||
if (useContainerDates && video.PremiereDate is not null && video.ProductionYear is null)
|
||||
{
|
||||
video.ProductionYear = video.PremiereDate.Value.ToLocalTime().Year;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
writer.WriteElementString("title", album.Name);
|
||||
}
|
||||
|
||||
if (album.ProductionYear.HasValue)
|
||||
if (album.ProductionYear is not null)
|
||||
{
|
||||
writer.WriteElementString("year", album.ProductionYear.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
@@ -544,7 +544,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
||||
writer.WriteElementString("rating", item.CommunityRating.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
if (item.ProductionYear.HasValue)
|
||||
if (item.ProductionYear is not null)
|
||||
{
|
||||
writer.WriteElementString("year", item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture));
|
||||
}
|
||||
|
||||
@@ -497,7 +497,7 @@ public sealed class RecordingsManager : IRecordingsManager, IDisposable
|
||||
// trim trailing period from the folder name
|
||||
var folderName = _fileSystem.GetValidFilename(timer.Name).Trim().TrimEnd('.').Trim();
|
||||
|
||||
if (metadata is not null && metadata.ProductionYear.HasValue)
|
||||
if (metadata is not null && metadata.ProductionYear is not null)
|
||||
{
|
||||
folderName += " (" + metadata.ProductionYear.Value.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
@@ -532,7 +532,7 @@ public sealed class RecordingsManager : IRecordingsManager, IDisposable
|
||||
}
|
||||
|
||||
var folderName = _fileSystem.GetValidFilename(timer.Name).Trim();
|
||||
if (timer.ProductionYear.HasValue)
|
||||
if (timer.ProductionYear is not null)
|
||||
{
|
||||
folderName += " (" + timer.ProductionYear.Value.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
@@ -550,7 +550,7 @@ public sealed class RecordingsManager : IRecordingsManager, IDisposable
|
||||
}
|
||||
|
||||
var folderName = _fileSystem.GetValidFilename(timer.Name).Trim();
|
||||
if (timer.ProductionYear.HasValue)
|
||||
if (timer.ProductionYear is not null)
|
||||
{
|
||||
folderName += " (" + timer.ProductionYear.Value.ToString(CultureInfo.InvariantCulture) + ")";
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ public class RecordingsMetadataManager
|
||||
null,
|
||||
DateTime.UtcNow.ToString(DateAddedFormat, CultureInfo.InvariantCulture)).ConfigureAwait(false);
|
||||
|
||||
if (item.ProductionYear.HasValue)
|
||||
if (item.ProductionYear is not null)
|
||||
{
|
||||
await writer.WriteElementStringAsync(null, "year", null, item.ProductionYear.Value.ToString(CultureInfo.InvariantCulture)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Threading;
|
||||
using Jellyfin.Database.Implementations.Entities;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Movies;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.MediaSegments;
|
||||
@@ -366,4 +367,80 @@ public class BaseItemTests
|
||||
Assert.Contains(alt2.Id, ids);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritDatesFromOwner_OwnerHasDates_OverwritesOwnedItemDates()
|
||||
{
|
||||
var owner = new Movie
|
||||
{
|
||||
ProductionYear = 1982,
|
||||
PremiereDate = new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc)
|
||||
};
|
||||
|
||||
// 2016 is what the container creation date of a re-encoded trailer would have yielded.
|
||||
var trailer = new Trailer
|
||||
{
|
||||
ExtraType = ExtraType.Trailer,
|
||||
ProductionYear = 2016,
|
||||
PremiereDate = new DateTime(2016, 5, 4, 0, 0, 0, DateTimeKind.Utc)
|
||||
};
|
||||
|
||||
Assert.True(BaseItem.InheritDatesFromOwner(owner, trailer));
|
||||
Assert.Equal(owner.ProductionYear, trailer.ProductionYear);
|
||||
Assert.Equal(owner.PremiereDate, trailer.PremiereDate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritDatesFromOwner_OwnerHasNoDates_KeepsOwnedItemDates()
|
||||
{
|
||||
var owner = new Movie();
|
||||
var trailer = new Trailer
|
||||
{
|
||||
ExtraType = ExtraType.Trailer,
|
||||
ProductionYear = 1982,
|
||||
PremiereDate = new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc)
|
||||
};
|
||||
|
||||
Assert.False(BaseItem.InheritDatesFromOwner(owner, trailer));
|
||||
Assert.Equal(1982, trailer.ProductionYear);
|
||||
Assert.Equal(new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc), trailer.PremiereDate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritDatesFromOwner_DatesAlreadyMatch_ReportsNoChange()
|
||||
{
|
||||
var owner = new Movie
|
||||
{
|
||||
ProductionYear = 1982,
|
||||
PremiereDate = new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc)
|
||||
};
|
||||
|
||||
var trailer = new Trailer
|
||||
{
|
||||
ExtraType = ExtraType.Trailer,
|
||||
ProductionYear = owner.ProductionYear,
|
||||
PremiereDate = owner.PremiereDate
|
||||
};
|
||||
|
||||
Assert.False(BaseItem.InheritDatesFromOwner(owner, trailer));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InheritDatesFromOwner_OwnedItemHasNoDates_TakesOwnerDates()
|
||||
{
|
||||
var owner = new Movie
|
||||
{
|
||||
ProductionYear = 1982,
|
||||
PremiereDate = new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc)
|
||||
};
|
||||
|
||||
var trailer = new Trailer
|
||||
{
|
||||
ExtraType = ExtraType.Trailer
|
||||
};
|
||||
|
||||
Assert.True(BaseItem.InheritDatesFromOwner(owner, trailer));
|
||||
Assert.Equal(1982, trailer.ProductionYear);
|
||||
Assert.Equal(new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc), trailer.PremiereDate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ using AutoFixture;
|
||||
using AutoFixture.AutoMoq;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Providers.MediaInfo;
|
||||
using Moq;
|
||||
using Xunit;
|
||||
@@ -75,4 +77,62 @@ public class FFProbeVideoInfoTests
|
||||
|
||||
Assert.All(chapters, chapter => Assert.True(chapter.StartPositionTicks < runtime));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void FetchEmbeddedInfo_NoExtra_AppliesContainerDates(bool replaceAllMetadata)
|
||||
{
|
||||
var video = new Video();
|
||||
|
||||
_fFProbeVideoInfo.FetchEmbeddedInfo(video, CreateMediaInfoWithDates(), CreateRefreshOptions(replaceAllMetadata), new LibraryOptions());
|
||||
|
||||
Assert.Equal(2016, video.ProductionYear);
|
||||
Assert.Equal(new DateTime(2016, 5, 4, 0, 0, 0, DateTimeKind.Utc), video.PremiereDate);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false)]
|
||||
[InlineData(true)]
|
||||
public void FetchEmbeddedInfo_Extra_IgnoresContainerDates(bool replaceAllMetadata)
|
||||
{
|
||||
var video = new Video
|
||||
{
|
||||
ExtraType = ExtraType.Trailer,
|
||||
ProductionYear = 1982,
|
||||
PremiereDate = new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc)
|
||||
};
|
||||
|
||||
_fFProbeVideoInfo.FetchEmbeddedInfo(video, CreateMediaInfoWithDates(), CreateRefreshOptions(replaceAllMetadata), new LibraryOptions());
|
||||
|
||||
Assert.Equal(1982, video.ProductionYear);
|
||||
Assert.Equal(new DateTime(1982, 6, 25, 0, 0, 0, DateTimeKind.Utc), video.PremiereDate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FetchEmbeddedInfo_ExtraWithoutDates_StaysWithoutDates()
|
||||
{
|
||||
var video = new Video
|
||||
{
|
||||
ExtraType = ExtraType.Trailer
|
||||
};
|
||||
|
||||
_fFProbeVideoInfo.FetchEmbeddedInfo(video, CreateMediaInfoWithDates(), CreateRefreshOptions(false), new LibraryOptions());
|
||||
|
||||
Assert.Null(video.ProductionYear);
|
||||
Assert.Null(video.PremiereDate);
|
||||
}
|
||||
|
||||
private static MediaBrowser.Model.MediaInfo.MediaInfo CreateMediaInfoWithDates()
|
||||
=> new()
|
||||
{
|
||||
ProductionYear = 2016,
|
||||
PremiereDate = new DateTime(2016, 5, 4, 0, 0, 0, DateTimeKind.Utc)
|
||||
};
|
||||
|
||||
private static MetadataRefreshOptions CreateRefreshOptions(bool replaceAllMetadata)
|
||||
=> new(Mock.Of<IDirectoryService>())
|
||||
{
|
||||
ReplaceAllMetadata = replaceAllMetadata
|
||||
};
|
||||
}
|
||||
|
||||
@@ -305,6 +305,47 @@ public class FindExtrasTests
|
||||
Assert.Empty(extras);
|
||||
}
|
||||
|
||||
[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()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user