Optimize identity

This commit is contained in:
cxfksword 2023-03-05 15:53:56 +08:00
parent ebc701845a
commit 3f0ad0112d
5 changed files with 91 additions and 17 deletions

View File

@ -176,6 +176,20 @@ namespace Jellyfin.Plugin.MetaShark.Test
Assert.AreEqual(parseResult.ParentIndexNumber, 1); Assert.AreEqual(parseResult.ParentIndexNumber, 1);
Assert.AreEqual(parseResult.IndexNumber, 1); Assert.AreEqual(parseResult.IndexNumber, 1);
// 日文
fileName = "プロポーズ大作戦Ep05_x264.mp4";
parseResult = NameParser.Parse(fileName);
Assert.AreEqual(parseResult.Name, "プロポーズ大作戦Ep05");
Assert.AreEqual(parseResult.ParentIndexNumber, null);
Assert.AreEqual(parseResult.IndexNumber, 5);
fileName = "[01] [ANK-Raws] あっちこっち 01 (BDrip 1920x1080 HEVC-YUV420P10 FLAC)";
parseResult = NameParser.Parse(fileName);
Assert.AreEqual(parseResult.Name, "あっちこっち 01");
Assert.AreEqual(parseResult.ParentIndexNumber, null);
Assert.AreEqual(parseResult.IndexNumber, 1);
// 只中文 // 只中文
fileName = "齊天大聖 第02集"; fileName = "齊天大聖 第02集";
parseResult = NameParser.Parse(fileName); parseResult = NameParser.Parse(fileName);
@ -183,6 +197,13 @@ namespace Jellyfin.Plugin.MetaShark.Test
Assert.AreEqual(parseResult.ParentIndexNumber, null); Assert.AreEqual(parseResult.ParentIndexNumber, null);
Assert.AreEqual(parseResult.IndexNumber, 2); Assert.AreEqual(parseResult.IndexNumber, 2);
fileName = "齊天大聖 第 02 期";
parseResult = NameParser.Parse(fileName);
Assert.AreEqual(parseResult.Name, "齊天大聖");
Assert.AreEqual(parseResult.ParentIndexNumber, null);
Assert.AreEqual(parseResult.IndexNumber, 2);
// anime // anime
fileName = "[YYDM-11FANS][THERMAE_ROMAE][02][BDRIP][720P][X264-10bit_AAC][7FF2269F]"; fileName = "[YYDM-11FANS][THERMAE_ROMAE][02][BDRIP][720P][X264-10bit_AAC][7FF2269F]";
parseResult = NameParser.Parse(fileName); parseResult = NameParser.Parse(fileName);

View File

@ -97,7 +97,7 @@ namespace Jellyfin.Plugin.MetaShark.Test
Task.Run(async () => Task.Run(async () =>
{ {
var provider = new SeasonProvider(httpClientFactory, loggerFactory, libraryManagerStub.Object, httpContextAccessorStub.Object, doubanApi, tmdbApi, omdbApi); var provider = new SeasonProvider(httpClientFactory, loggerFactory, libraryManagerStub.Object, httpContextAccessorStub.Object, doubanApi, tmdbApi, omdbApi);
var result = await provider.GuestDoubanSeasonByYearAsync("机动战士高达0083 星尘的回忆", 1991, CancellationToken.None); var result = await provider.GuestDoubanSeasonByYearAsync("机动战士高达0083 星尘的回忆", 1991, null, CancellationToken.None);
Assert.AreEqual(result, "1766564"); Assert.AreEqual(result, "1766564");
}).GetAwaiter().GetResult(); }).GetAwaiter().GetResult();
} }

View File

@ -13,17 +13,22 @@ namespace Jellyfin.Plugin.MetaShark.Core
{ {
private static readonly Regex yearReg = new Regex(@"[12][890][0-9][0-9]", RegexOptions.Compiled); private static readonly Regex yearReg = new Regex(@"[12][890][0-9][0-9]", RegexOptions.Compiled);
private static readonly Regex seasonSuffixReg = new Regex(@"[ .]S\d{1,2}$", RegexOptions.Compiled); private static readonly Regex seasonSuffixReg = new Regex(@"[ .]S\d{1,2}$", RegexOptions.Compiled);
private static readonly Regex unusedReg = new Regex(@"\[.+?\]|\(.+?\)|【.+?】", RegexOptions.Compiled); private static readonly Regex unusedReg = new Regex(@"\[.+?\]|\(.+?\)|【.+?】", RegexOptions.Compiled);
private static readonly Regex fixSeasonNumberReg = new Regex(@"(\[|\.)S(\d{1,2})(\]|\.)", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex fixSeasonNumberReg = new Regex(@"(\[|\.)S(\d{1,2})(\]|\.)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static readonly Regex startWithHyphenCharReg = new Regex(@"^[-~]", RegexOptions.Compiled); private static readonly Regex startWithHyphenCharReg = new Regex(@"^[-~]", RegexOptions.Compiled);
private static readonly Regex chineseIndexNumberReg = new Regex(@"第([0-9零一二三四五六七八九]+?)(集|章|话|話)", RegexOptions.Compiled); private static readonly Regex chineseIndexNumberReg = new Regex(@"第\s*?([0-9零一二三四五六七八九]+?)\s*?(集|章|话|話|期)", RegexOptions.Compiled);
public static ParseNameResult Parse(string fileName, bool isTvSeries = false) private static readonly Regex normalizeNameReg = new Regex(@"第\s*?([0-9零一二三四五六七八九]+?)\s*?(集|章|话|話|期)", RegexOptions.Compiled);
private static readonly Regex specialIndexNumberReg = new Regex(@"ep(\d{1,2})", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static ParseNameResult Parse(string fileName, bool isEpisode = false)
{ {
fileName = NormalizeFileName(fileName);
var parseResult = new ParseNameResult(); var parseResult = new ParseNameResult();
var anitomyResult = AnitomySharp.AnitomySharp.Parse(fileName); var anitomyResult = AnitomySharp.AnitomySharp.Parse(fileName);
var isAnime = IsAnime(fileName); var isAnime = IsAnime(fileName);
@ -110,13 +115,13 @@ namespace Jellyfin.Plugin.MetaShark.Core
} }
} }
// 修复纯中文集数 // 修复纯中文集数/特殊标识集数
if (parseResult.IndexNumber is null) if (parseResult.IndexNumber is null)
{ {
parseResult.IndexNumber = ParseChineseIndexNumber(fileName); parseResult.IndexNumber = ParseChineseOrSpecialIndexNumber(fileName);
} }
// 解析不到title时使用默认名 // 解析不到title时或解析出多个title时使用默认名
if (string.IsNullOrEmpty(parseResult.Name)) if (string.IsNullOrEmpty(parseResult.Name))
{ {
parseResult.Name = fileName; parseResult.Name = fileName;
@ -167,14 +172,22 @@ namespace Jellyfin.Plugin.MetaShark.Core
return 0; return 0;
} }
private static int? ParseChineseIndexNumber(string fileName) private static string NormalizeFileName(string fileName)
{
// 去掉中文集数之间的空格要不然Anitomy解析不正确
fileName = normalizeNameReg.Replace(fileName, m => m.Value.Replace(" ", ""));
return fileName;
}
private static int? ParseChineseOrSpecialIndexNumber(string fileName)
{ {
var match = chineseIndexNumberReg.Match(fileName); var match = chineseIndexNumberReg.Match(fileName);
if (match.Success && match.Groups.Count > 1) if (match.Success && match.Groups.Count > 1)
{ {
if (int.TryParse(match.Groups[1].Value, out var seasonNumber)) if (int.TryParse(match.Groups[1].Value, out var indexNumber))
{ {
return seasonNumber; return indexNumber;
} }
var number = Utils.ChineseNumberToInt(match.Groups[1].Value); var number = Utils.ChineseNumberToInt(match.Groups[1].Value);
@ -183,6 +196,18 @@ namespace Jellyfin.Plugin.MetaShark.Core
return number; return number;
} }
} }
else
{
match = specialIndexNumberReg.Match(fileName);
if (match.Success && match.Groups.Count > 1)
{
if (int.TryParse(match.Groups[1].Value, out var indexNumber))
{
return indexNumber;
}
}
}
return null; return null;
} }
@ -196,7 +221,7 @@ namespace Jellyfin.Plugin.MetaShark.Core
} }
var folder = Path.GetFileName(Path.GetDirectoryName(path)) ?? string.Empty; var folder = Path.GetFileName(Path.GetDirectoryName(path)) ?? string.Empty;
return folder == "SPs" || folder.Contains("特典"); return folder == "SPs" || folder == "Specials" || folder.Contains("特典");
} }

View File

@ -171,20 +171,20 @@ namespace Jellyfin.Plugin.MetaShark.Providers
return null; return null;
} }
public async Task<string?> GuestDoubanSeasonByYearAsync(string name, int? year, CancellationToken cancellationToken) public async Task<string?> GuestDoubanSeasonByYearAsync(string seriesName, int? year, int? seasonNumber, CancellationToken cancellationToken)
{ {
if (year == null || year == 0) if (year == null || year == 0)
{ {
return null; return null;
} }
this.Log($"GuestDoubanSeasonByYear of [name]: {name} [year]: {year}"); this.Log($"GuestDoubanSeasonByYear of [name]: {seriesName} [year]: {year}");
// 先通过suggest接口查找减少搜索页访问次数避免封禁suggest没法区分电影或电视剧排序也比搜索页差些 // 先通过suggest接口查找减少搜索页访问次数避免封禁suggest没法区分电影或电视剧排序也比搜索页差些
if (config.EnableDoubanAvoidRiskControl) if (config.EnableDoubanAvoidRiskControl)
{ {
var suggestResult = await this._doubanApi.SearchBySuggestAsync(name, cancellationToken).ConfigureAwait(false); var suggestResult = await this._doubanApi.SearchBySuggestAsync(seriesName, cancellationToken).ConfigureAwait(false);
var suggestItem = suggestResult.Where(x => x.Year == year && x.Name == name).FirstOrDefault(); var suggestItem = suggestResult.Where(x => x.Year == year && x.Name == seriesName).FirstOrDefault();
if (suggestItem != null) if (suggestItem != null)
{ {
this.Log($"Found douban [id]: {suggestItem.Name}({suggestItem.Sid}) (suggest)"); this.Log($"Found douban [id]: {suggestItem.Name}({suggestItem.Sid}) (suggest)");
@ -200,10 +200,18 @@ namespace Jellyfin.Plugin.MetaShark.Providers
// 通过搜索页面查找 // 通过搜索页面查找
var result = await this._doubanApi.SearchAsync(name, cancellationToken).ConfigureAwait(false); var result = await this._doubanApi.SearchAsync(seriesName, cancellationToken).ConfigureAwait(false);
var item = result.Where(x => x.Category == "电视剧" && x.Year == year).FirstOrDefault(); var item = result.Where(x => x.Category == "电视剧" && x.Year == year).FirstOrDefault();
if (item != null && !string.IsNullOrEmpty(item.Sid)) if (item != null && !string.IsNullOrEmpty(item.Sid))
{ {
// 判断名称中是否有第X季有的话和seasonNumber比较用于修正多季都在同一年时每次都是错误取第一个的情况
var nameIndexNumber = ParseChineseSeasonNumberByName(item.Name);
if (nameIndexNumber.HasValue && seasonNumber.HasValue && nameIndexNumber != seasonNumber)
{
this.Log($"GuestDoubanSeasonByYear not found!");
return null;
}
this.Log($"Found douban [id]: {item.Name}({item.Sid})"); this.Log($"Found douban [id]: {item.Name}({item.Sid})");
return item.Sid; return item.Sid;
} }
@ -380,6 +388,26 @@ namespace Jellyfin.Plugin.MetaShark.Providers
} }
public int? ParseChineseSeasonNumberByName(string name)
{
var regSeason = new Regex(@"\s第([0-9零一二三四五六七八九]+?)(季|部)", RegexOptions.Compiled);
var match = regSeason.Match(name);
if (match.Success && match.Groups.Count > 1)
{
var seasonNumber = match.Groups[1].Value.ToInt();
if (seasonNumber <= 0)
{
seasonNumber = Utils.ChineseNumberToInt(match.Groups[1].Value) ?? 0;
}
if (seasonNumber > 0)
{
return seasonNumber;
}
}
return null;
}
/// <summary> /// <summary>
/// 浏览器来源请求返回代理地址no-referer对于background-image不生效其他客户端请求返回原始图片地址 /// 浏览器来源请求返回代理地址no-referer对于background-image不生效其他客户端请求返回原始图片地址
/// </summary> /// </summary>

View File

@ -165,7 +165,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
if (!string.IsNullOrEmpty(seriesName) && seasonYear > 0) if (!string.IsNullOrEmpty(seriesName) && seasonYear > 0)
{ {
var seasonSid = await this.GuestDoubanSeasonByYearAsync(seriesName, seasonYear, cancellationToken).ConfigureAwait(false); var seasonSid = await this.GuestDoubanSeasonByYearAsync(seriesName, seasonYear, seasonNumber, cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(seasonSid)) if (!string.IsNullOrEmpty(seasonSid))
{ {
return seasonSid; return seasonSid;