mirror of https://github.com/jellyfin/jellyfin.git
Parse episode extras - only suffix style is supported
This commit is contained in:
parent
2146ddd20c
commit
0569017b79
|
@ -47,6 +47,8 @@ using MediaBrowser.Model.Querying;
|
|||
using MediaBrowser.Model.Tasks;
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Season = MediaBrowser.Controller.Entities.TV.Season;
|
||||
using Series = MediaBrowser.Controller.Entities.TV.Series;
|
||||
using Episode = MediaBrowser.Controller.Entities.TV.Episode;
|
||||
using EpisodeInfo = Emby.Naming.TV.EpisodeInfo;
|
||||
using Genre = MediaBrowser.Controller.Entities.Genre;
|
||||
|
@ -2614,11 +2616,12 @@ namespace Emby.Server.Implementations.Library
|
|||
yield break;
|
||||
}
|
||||
|
||||
var resolver = new EpisodeResolver(_namingOptions);
|
||||
var count = fileSystemChildren.Count;
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
var current = fileSystemChildren[i];
|
||||
if (current.IsDirectory && _namingOptions.AllExtrasTypesFolderNames.ContainsKey(current.Name))
|
||||
if (!owner.IsInMixedFolder && current.IsDirectory && _namingOptions.AllExtrasTypesFolderNames.ContainsKey(current.Name))
|
||||
{
|
||||
var filesInSubFolder = _fileSystem.GetFiles(current.FullName, null, false, false);
|
||||
foreach (var file in filesInSubFolder)
|
||||
|
@ -2637,11 +2640,46 @@ namespace Emby.Server.Implementations.Library
|
|||
}
|
||||
else if (!current.IsDirectory && _extraResolver.TryGetExtraTypeForOwner(current.FullName, ownerVideoInfo, out var extraType))
|
||||
{
|
||||
var extra = GetExtra(current, extraType.Value);
|
||||
if (extra is not null)
|
||||
// if owner is dir, don't own episode extras
|
||||
// test if extra filename is formatted like an episode
|
||||
int? dashIndex = current.Name?.LastIndexOf('-');
|
||||
String prefix = null;
|
||||
if (dashIndex is int dashIndexValue)
|
||||
{
|
||||
yield return extra;
|
||||
if (dashIndexValue >= 0)
|
||||
{
|
||||
prefix = current.Name.Substring(0, dashIndexValue); // possible episode name
|
||||
String path = current.FullName;
|
||||
path = string.Concat(path.AsSpan(0, path.LastIndexOf('-')), current.Extension);
|
||||
var episodeInfo = resolver.Resolve(path, false);
|
||||
|
||||
String SeriesName = null;
|
||||
if (owner is Series series)
|
||||
{
|
||||
SeriesName = series.Name;
|
||||
}
|
||||
if (owner is Season season)
|
||||
{
|
||||
SeriesName = season.SeriesName;
|
||||
}
|
||||
if (SeriesName is not null && SeriesName.Equals(episodeInfo?.SeriesName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// don't attach episode extras to series or season
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if owner is Episode, only suffix type matches will be allowed, episode name must match exactly
|
||||
if (owner is not Episode || (prefix is not null && prefix.Equals(ownerVideoInfo.Name, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var extra = GetExtra(current, extraType.Value);
|
||||
if (extra is not null)
|
||||
{
|
||||
yield return extra;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ using MediaBrowser.Controller.Channels;
|
|||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
|
@ -1344,7 +1345,7 @@ namespace MediaBrowser.Controller.Entities
|
|||
/// <returns><c>true</c> if any items have changed, else <c>false</c>.</returns>
|
||||
protected virtual async Task<bool> RefreshedOwnedItems(MetadataRefreshOptions options, IReadOnlyList<FileSystemMetadata> fileSystemChildren, CancellationToken cancellationToken)
|
||||
{
|
||||
if (!IsFileProtocol || !SupportsOwnedItems || IsInMixedFolder || this is ICollectionFolder or UserRootFolder or AggregateFolder || this.GetType() == typeof(Folder))
|
||||
if (!IsFileProtocol || !SupportsOwnedItems || (IsInMixedFolder && this is not Episode) || this is ICollectionFolder or UserRootFolder or AggregateFolder || this.GetType() == typeof(Folder))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
public int? IndexNumberEnd { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
protected override bool SupportsOwnedItems => IsStacked || MediaSourceCount > 1;
|
||||
protected override bool SupportsOwnedItems => true;
|
||||
|
||||
[JsonIgnore]
|
||||
public override bool SupportsInheritedParentImages => true;
|
||||
|
|
|
@ -302,4 +302,146 @@ public class FindExtrasTests
|
|||
Assert.Equal("/series/Dexter/trailer.mkv", extras[0].Path);
|
||||
Assert.Equal("/series/Dexter/trailers/trailer2.mkv", extras[1].Path);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_SeriesWithExtras_FindsCorrectExtras()
|
||||
{
|
||||
var owner = new Series { Name = "Dexter", Path = "/series/Dexter" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/series/Dexter/Season 1/Dexter - S01E01.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E01-deleted.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-interview.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-scene.mkv",
|
||||
"/series/Dexter/Season 1/It's a begining-behindthescenes.mkv",
|
||||
"/series/Dexter/Season 1/interviews/The Cast.mkv",
|
||||
"/series/Dexter/Funny-behindthescenes.mkv",
|
||||
"/series/Dexter/interviews/The Director.mkv",
|
||||
"/series/Dexter/Dexter - S02E05.mkv",
|
||||
"/series/Dexter/Dexter - S02E05-clip.mkv",
|
||||
"/series/Dexter/Dexter - S03E05/Dexter - S03E05 - Fifth.mkv",
|
||||
"/series/Dexter/Dexter - S03E05/Dexter - S03E05 - Fifth-featurette.mkv",
|
||||
};
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
Name = Path.GetFileName(p),
|
||||
Extension = Path.GetExtension(p),
|
||||
IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p))
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||
|
||||
Assert.Equal(2, extras.Count);
|
||||
Assert.Equal(ExtraType.BehindTheScenes, extras[0].ExtraType);
|
||||
Assert.Equal(typeof(Video), extras[0].GetType());
|
||||
Assert.Equal("Funny-behindthescenes", extras[0].FileNameWithoutExtension);
|
||||
Assert.Equal("/series/Dexter/Funny-behindthescenes.mkv", extras[0].Path);
|
||||
Assert.Equal("/series/Dexter/interviews/The Director.mkv", extras[1].Path);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_SeasonWithExtras_FindsCorrectExtras()
|
||||
{
|
||||
var owner = new Season { Name = "Season 1", SeriesName = "Dexter", Path = "/series/Dexter/Season 1" };
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/series/Dexter/Season 1/Dexter - S01E01.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E01-deleted.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-interview.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-scene.mkv",
|
||||
"/series/Dexter/Season 1/It's a begining-behindthescenes.mkv",
|
||||
"/series/Dexter/Season 1/interviews/The Cast.mkv",
|
||||
"/series/Dexter/Funny-behindthescenes.mkv",
|
||||
"/series/Dexter/interviews/The Director.mkv",
|
||||
"/series/Dexter/Dexter - S02E05.mkv",
|
||||
"/series/Dexter/Dexter - S02E05-clip.mkv",
|
||||
"/series/Dexter/Dexter - S03E05/Dexter - S03E05 - Fifth.mkv",
|
||||
"/series/Dexter/Dexter - S03E05/Dexter - S03E05 - Fifth-featurette.mkv",
|
||||
};
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
Name = Path.GetFileName(p),
|
||||
Extension = Path.GetExtension(p),
|
||||
IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p))
|
||||
}).ToList();
|
||||
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||
|
||||
Assert.Equal(2, extras.Count);
|
||||
Assert.Equal(ExtraType.BehindTheScenes, extras[0].ExtraType);
|
||||
Assert.Equal(typeof(Video), extras[0].GetType());
|
||||
Assert.Equal("It's a begining-behindthescenes", extras[0].FileNameWithoutExtension);
|
||||
Assert.Equal("/series/Dexter/Season 1/It's a begining-behindthescenes.mkv", extras[0].Path);
|
||||
Assert.Equal("/series/Dexter/Season 1/interviews/The Cast.mkv", extras[1].Path);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindExtras_EpisodeWithExtras_FindsCorrectExtras()
|
||||
{
|
||||
var paths = new List<string>
|
||||
{
|
||||
"/series/Dexter/Season 1/Dexter - S01E01.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E01-deleted.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-interview.mkv",
|
||||
"/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-scene.mkv",
|
||||
"/series/Dexter/Season 1/It's a begining-behindthescenes.mkv",
|
||||
"/series/Dexter/Season 1/interviews/The Cast.mkv",
|
||||
"/series/Dexter/Funny-behindthescenes.mkv",
|
||||
"/series/Dexter/interviews/The Director.mkv",
|
||||
"/series/Dexter/Dexter - S02E05.mkv",
|
||||
"/series/Dexter/Dexter - S02E05-clip.mkv",
|
||||
"/series/Dexter/Dexter - S03E05/Dexter - S03E05 - Fifth.mkv",
|
||||
"/series/Dexter/Dexter - S03E05/Dexter - S03E05 - Fifth-featurette.mkv",
|
||||
};
|
||||
|
||||
var files = paths.Select(p => new FileSystemMetadata
|
||||
{
|
||||
FullName = p,
|
||||
Name = Path.GetFileName(p),
|
||||
Extension = Path.GetExtension(p),
|
||||
IsDirectory = string.IsNullOrEmpty(Path.GetExtension(p))
|
||||
}).ToList();
|
||||
|
||||
var owner = new Episode { Name = "Dexter - S01E01", Path = "/series/Dexter/Season 1/Dexter - S01E01.mkv", IsInMixedFolder = true };
|
||||
var extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||
|
||||
Assert.Single(extras);
|
||||
Assert.Equal(ExtraType.DeletedScene, extras[0].ExtraType);
|
||||
Assert.Equal(typeof(Video), extras[0].GetType());
|
||||
Assert.Equal("/series/Dexter/Season 1/Dexter - S01E01-deleted.mkv", extras[0].Path);
|
||||
|
||||
owner = new Episode { Name = "Dexter - S01E02 - Second Epi", Path = "/series/Dexter/Season 1/Dexter - S01E02 - Second Epi.mkv", IsInMixedFolder = true };
|
||||
extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||
|
||||
Assert.Equal(2, extras.Count);
|
||||
Assert.Equal(ExtraType.Interview, extras[0].ExtraType);
|
||||
Assert.Equal(ExtraType.Scene, extras[1].ExtraType);
|
||||
Assert.Equal(typeof(Video), extras[0].GetType());
|
||||
Assert.Equal("/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-interview.mkv", extras[0].Path);
|
||||
Assert.Equal("/series/Dexter/Season 1/Dexter - S01E02 - Second Epi-scene.mkv", extras[1].Path);
|
||||
|
||||
owner = new Episode { Name = "Dexter - S02E05", Path = "/series/Dexter/Dexter - S02E05.mkv", IsInMixedFolder = true };
|
||||
extras = _libraryManager.FindExtras(owner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||
|
||||
Assert.Single(extras);
|
||||
Assert.Equal(ExtraType.Clip, extras[0].ExtraType);
|
||||
Assert.Equal(typeof(Video), extras[0].GetType());
|
||||
Assert.Equal("/series/Dexter/Dexter - S02E05-clip.mkv", extras[0].Path);
|
||||
|
||||
// episode folder with special feature subfolders are not supported yet, but it should be considered as not mixed, but current is marked as mixed
|
||||
Folder folderOwner = new Folder { Name = "Dexter - S03E05", Path = "/series/Dexter/Dexter - S03E05", IsInMixedFolder = true };
|
||||
extras = _libraryManager.FindExtras(folderOwner, files, new DirectoryService(_fileSystemMock.Object)).OrderBy(e => e.ExtraType).ToList();
|
||||
|
||||
Assert.Single(extras);
|
||||
Assert.Equal(ExtraType.Clip, extras[0].ExtraType);
|
||||
Assert.Equal(typeof(Video), extras[0].GetType());
|
||||
Assert.Equal("/series/Dexter/Dexter - S03E05/Dexter - S03E05 - Fifth-featurette.mkv", extras[0].Path);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue