diff --git a/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs b/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs index 4c5fc8f..c8bd63a 100644 --- a/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs +++ b/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs @@ -174,19 +174,20 @@ namespace Jellyfin.Plugin.MetaShark.Test Assert.AreEqual(parseResult.Name, "New World"); Assert.AreEqual(parseResult.Year, 2013); - // 只英文S01E01 + // 只英文 S01E01 fileName = "She-Hulk.Attorney.At.Law.S01E01.1080p.WEBRip.x265-RARBG"; parseResult = NameParser.Parse(fileName); Assert.AreEqual(parseResult.Name, "She-Hulk Attorney At Law"); Assert.AreEqual(parseResult.ParentIndexNumber, 1); Assert.AreEqual(parseResult.IndexNumber, 1); - // 只英文S01EP01 - fileName = "Detective.Dee.S01EP18.2004.1080p.WEB-DL.x264.AAC-HQCS"; + // 测试 SXXEPXX 格式 + fileName = "神探狄仁杰2 Detective.Dee.Ⅱ.S02EP02.2006.2160p.WEB-DL.x264.AAC-HQC"; parseResult = NameParser.Parse(fileName); - Assert.AreEqual(parseResult.Name, "Detective Dee"); - Assert.AreEqual(parseResult.ParentIndexNumber, 1); - Assert.AreEqual(parseResult.IndexNumber, 18); + Assert.AreEqual(parseResult.ChineseName, "神探狄仁杰2"); + Assert.AreEqual(parseResult.Name, "Detective Dee Ⅱ"); + Assert.AreEqual(parseResult.ParentIndexNumber, 2); + Assert.AreEqual(parseResult.IndexNumber, 2); // 日文 diff --git a/Jellyfin.Plugin.MetaShark/Core/NameParser.cs b/Jellyfin.Plugin.MetaShark/Core/NameParser.cs index c7690c1..e8bf797 100644 --- a/Jellyfin.Plugin.MetaShark/Core/NameParser.cs +++ b/Jellyfin.Plugin.MetaShark/Core/NameParser.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Emby.Naming.TV; using Jellyfin.Plugin.MetaShark.Model; namespace Jellyfin.Plugin.MetaShark.Core @@ -110,7 +111,7 @@ namespace Jellyfin.Plugin.MetaShark.Core // 假如Anitomy解析不到year,尝试使用jellyfin默认parser,看能不能解析成功 if (parseResult.Year == null && !isAnime) { - var nativeParseResult = ParseMovie(fileName); + var nativeParseResult = ParseMovieByDefault(fileName); if (nativeParseResult.Year != null) { parseResult = nativeParseResult; @@ -143,8 +144,10 @@ namespace Jellyfin.Plugin.MetaShark.Core return name.Replace(".", " ").Trim(); } - // emby原始电影解析 - public static ParseNameResult ParseMovie(string fileName) + /// + /// emby原始电影解析 + /// + public static ParseNameResult ParseMovieByDefault(string fileName) { // 默认解析器会错误把分辨率当年份,先删除 fileName = resolutionReg.Replace(fileName, ""); @@ -165,6 +168,16 @@ namespace Jellyfin.Plugin.MetaShark.Core return parseResult; } + /// + /// emby原始剧集解析 + /// + public static EpisodePathParserResult ParseEpisodeByDefault(string fileName) + { + var nameOptions = new Emby.Naming.Common.NamingOptions(); + return new EpisodePathParser(nameOptions) + .Parse(fileName, false); + } + private static int ParseYear(string val) { diff --git a/Jellyfin.Plugin.MetaShark/Providers/EpisodeProvider.cs b/Jellyfin.Plugin.MetaShark/Providers/EpisodeProvider.cs index 0bbb34d..04f688d 100644 --- a/Jellyfin.Plugin.MetaShark/Providers/EpisodeProvider.cs +++ b/Jellyfin.Plugin.MetaShark/Providers/EpisodeProvider.cs @@ -44,8 +44,8 @@ namespace Jellyfin.Plugin.MetaShark.Providers // 刷新元数据四种模式差别: // 自动扫描匹配:info的Name、IndexNumber和ParentIndexNumber是从文件名解析出来的,假如命名不规范,就会导致解析出错误值 // 识别:info的Name、IndexNumber和ParentIndexNumber是从文件名解析出来的,provinceIds有指定选择项的ProvinceId + // 覆盖所有元数据:info的Name、IndexNumber和ParentIndexNumber是从文件名解析出来的,provinceIds保留所有旧值 // 搜索缺少的元数据:info的Name、IndexNumber和ParentIndexNumber是从当前的元数据获取,provinceIds保留所有旧值 - // 覆盖所有元数据:info的Name、IndexNumber和ParentIndexNumber是从当前的元数据获取,provinceIds保留所有旧值 this.Log($"GetEpisodeMetadata of [name]: {info.Name} number: {info.IndexNumber} ParentIndexNumber: {info.ParentIndexNumber} IsAutomated: {info.IsAutomated}"); var result = new MetadataResult(); @@ -139,6 +139,14 @@ namespace Jellyfin.Plugin.MetaShark.Providers info.Year = parseResult.Year; info.Name = parseResult.ChineseName ?? parseResult.Name; + // 修正文件名有特殊命名SXXEPXX时,默认解析到错误季数的问题,如神探狄仁杰 Detective.Dee.S01EP01.2006.2160p.WEB-DL.x264.AAC-HQC + // TODO: 会导致覆盖用户手动修改元数据的季数 + if (info.ParentIndexNumber.HasValue && parseResult.ParentIndexNumber.HasValue && parseResult.ParentIndexNumber > 0 && info.ParentIndexNumber != parseResult.ParentIndexNumber) + { + this.Log("FixSeasonNumber by anitomy. old: {0} new: {1}", info.ParentIndexNumber, parseResult.ParentIndexNumber); + info.ParentIndexNumber = parseResult.ParentIndexNumber; + } + // 没有season级目录(即虚拟季)ParentIndexNumber默认是1,季文件夹命名不规范时,ParentIndexNumber默认是null if (info.ParentIndexNumber is null) { @@ -152,11 +160,10 @@ namespace Jellyfin.Plugin.MetaShark.Providers var season = episodeItem != null ? ((Episode)episodeItem).Season : null; if (season != null && season.IndexNumber.HasValue && info.ParentIndexNumber != season.IndexNumber) { - this.Log("FixSeasonNumber: old: {0} new: {1}", info.ParentIndexNumber, season.IndexNumber); + this.Log("FixSeasonNumber by season. old: {0} new: {1}", info.ParentIndexNumber, season.IndexNumber); info.ParentIndexNumber = season.IndexNumber; } - // // 当没有season级目录时,默认为1,即当成只有一季(不需要处理,虚拟季jellyfin默认传的ParentIndexNumber=1) // if (info.ParentIndexNumber is null && season != null && season.LocationType == LocationType.Virtual) // { @@ -172,7 +179,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers info.ParentIndexNumber = this.GuessSeasonNumberByDirectoryName(seasonFolderPath); } - // 识别特典 if (info.ParentIndexNumber is null && NameParser.IsAnime(fileName) && (parseResult.IsSpecial || NameParser.IsSpecialDirectory(info.Path))) { @@ -186,17 +192,16 @@ namespace Jellyfin.Plugin.MetaShark.Providers // info.ParentIndexNumber = 1; // } - // 特典优先使用文件名(特典除了前面特别设置,还有SXX/Season XX等默认的) if (info.ParentIndexNumber.HasValue && info.ParentIndexNumber == 0) { info.Name = parseResult.SpecialName == info.Name ? fileName : parseResult.SpecialName; } - // 大于1000,可能错误解析了分辨率 - if (parseResult.IndexNumber.HasValue && parseResult.IndexNumber < 1000) + if (parseResult.IndexNumber.HasValue && parseResult.IndexNumber < 1000 && info.IndexNumber != parseResult.IndexNumber) { + this.Log("FixEpisodeNumber by anitomy. old: {0} new: {1}", info.IndexNumber, parseResult.IndexNumber); info.IndexNumber = parseResult.IndexNumber; }