Optimize identity

This commit is contained in:
cxfksword 2023-02-20 21:09:08 +08:00
parent ee19b16c7b
commit b46ab340f1
7 changed files with 84 additions and 65 deletions

View File

@ -107,10 +107,13 @@ namespace Jellyfin.Plugin.MetaShark.Api
httpClient.DefaultRequestHeaders.Add("Referer", "https://movie.douban.com/"); httpClient.DefaultRequestHeaders.Add("Referer", "https://movie.douban.com/");
this.LoadLoadDoubanCookie(); this.LoadLoadDoubanCookie();
Plugin.Instance!.ConfigurationChanged += (_, _) => if (Plugin.Instance != null)
{ {
this.LoadLoadDoubanCookie(); Plugin.Instance.ConfigurationChanged += (_, _) =>
}; {
this.LoadLoadDoubanCookie();
};
}
} }

View File

@ -16,7 +16,7 @@ namespace Jellyfin.Plugin.MetaShark.Core
private static readonly Regex unusedReg = new Regex(@"\[.+?\]|\(.+?\)|【.+?】", RegexOptions.Compiled); private static readonly Regex unusedReg = new Regex(@"\[.+?\]|\(.+?\)|【.+?】", RegexOptions.Compiled);
private static readonly Regex extrasReg = new Regex(@"\[(CM|Menu|NCED|NCOP|Drama)[0-9_]*?\]", RegexOptions.Compiled); private static readonly Regex extrasReg = new Regex(@"\[(OP|ED|PV|CM|Menu|NCED|NCOP|Drama|PreView)[0-9_]*?\]", RegexOptions.Compiled | RegexOptions.IgnoreCase);
public static ParseNameResult Parse(string fileName, bool isTvSeries = false) public static ParseNameResult Parse(string fileName, bool isTvSeries = false)
{ {

View File

@ -149,7 +149,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
item = result.Where(x => x.Category == cat && x.Year == info.Year).FirstOrDefault(); item = result.Where(x => x.Category == cat && x.Year == info.Year).FirstOrDefault();
if (item != null) if (item != null)
{ {
this.Log($"GuessByDouban found -> {item.Name}({item.Sid})"); this.Log($"Found douban [id]: {item.Name}({item.Sid})");
return item.Sid; return item.Sid;
} }
} }
@ -181,13 +181,13 @@ namespace Jellyfin.Plugin.MetaShark.Providers
var suggestItem = suggestResult.Where(x => x.Year == year && x.Name == name).FirstOrDefault(); var suggestItem = suggestResult.Where(x => x.Year == year && x.Name == name).FirstOrDefault();
if (suggestItem != null) if (suggestItem != null)
{ {
this.Log($"GuestDoubanSeasonByYear found -> {suggestItem.Name}({suggestItem.Sid}) (suggest)"); this.Log($"Found douban [id]: {suggestItem.Name}({suggestItem.Sid}) (suggest)");
return suggestItem.Sid; return suggestItem.Sid;
} }
suggestItem = suggestResult.Where(x => x.Year == year).FirstOrDefault(); suggestItem = suggestResult.Where(x => x.Year == year).FirstOrDefault();
if (suggestItem != null) if (suggestItem != null)
{ {
this.Log($"GuestDoubanSeasonByYear found -> {suggestItem.Name}({suggestItem.Sid}) (suggest)"); this.Log($"Found douban [id]: {suggestItem.Name}({suggestItem.Sid}) (suggest)");
return suggestItem.Sid; return suggestItem.Sid;
} }
} }
@ -198,7 +198,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
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))
{ {
this.Log($"GuestDoubanSeasonByYear found -> {item.Name}({item.Sid})"); this.Log($"Found douban [id]: {item.Name}({item.Sid})");
return item.Sid; return item.Sid;
} }
@ -207,36 +207,30 @@ namespace Jellyfin.Plugin.MetaShark.Providers
} }
protected async Task<string?> GuestByTmdbAsync(ItemLookupInfo info, CancellationToken cancellationToken) protected async Task<string?> GuestByTmdbAsync(string name, int? year, ItemLookupInfo info, CancellationToken cancellationToken)
{ {
// ParseName is required here.
// Caller provides the filename with extension stripped and NOT the parsed filename
var fileName = GetNotParsedName(info); var fileName = GetNotParsedName(info);
var parseResult = NameParser.Parse(fileName);
var searchName = !string.IsNullOrEmpty(parseResult.ChineseName) ? parseResult.ChineseName : parseResult.Name;
info.Year = parseResult.Year; // 默认parser对anime年份会解析出错以anitomy为准
this.Log($"GuestByTmdb of [name]: {name} [year]: {year}");
this.Log($"GuestByTmdb of [name]: {info.Name} [file_name]: {fileName} [year]: {info.Year} [search name]: {searchName}");
switch (info) switch (info)
{ {
case MovieInfo: case MovieInfo:
var movieResults = await this._tmdbApi.SearchMovieAsync(searchName, info.Year ?? 0, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); var movieResults = await this._tmdbApi.SearchMovieAsync(name, year ?? 0, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
var movieItem = movieResults.FirstOrDefault(); var movieItem = movieResults.FirstOrDefault();
if (movieItem != null) if (movieItem != null)
{ {
// bt种子都是英文名但电影是中日韩泰印法地区时都不适用相似匹配去掉限制 // bt种子都是英文名但电影是中日韩泰印法地区时都不适用相似匹配去掉限制
this.Log($"GuestByTmdb found -> {movieItem.Title}({movieItem.Id})"); this.Log($"Found tmdb [id]: {movieItem.Title}({movieItem.Id})");
return movieItem.Id.ToString(CultureInfo.InvariantCulture); return movieItem.Id.ToString(CultureInfo.InvariantCulture);
} }
break; break;
case SeriesInfo: case SeriesInfo:
var seriesResults = await this._tmdbApi.SearchSeriesAsync(searchName, info.MetadataLanguage, cancellationToken).ConfigureAwait(false); var seriesResults = await this._tmdbApi.SearchSeriesAsync(name, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
var seriesItem = seriesResults.FirstOrDefault(); var seriesItem = seriesResults.FirstOrDefault();
if (seriesItem != null) if (seriesItem != null)
{ {
// bt种子都是英文名但电影是中日韩泰印法地区时都不适用相似匹配去掉限制 // bt种子都是英文名但电影是中日韩泰印法地区时都不适用相似匹配去掉限制
this.Log($"GuestByTmdb found -> {seriesItem.Name}({seriesItem.Id})"); this.Log($"Found tmdb [id]: -> {seriesItem.Name}({seriesItem.Id})");
return seriesItem.Id.ToString(CultureInfo.InvariantCulture); return seriesItem.Id.ToString(CultureInfo.InvariantCulture);
} }
break; break;

View File

@ -1,5 +1,4 @@
using System.Reflection.Metadata; using Jellyfin.Plugin.MetaShark.Api;
using Jellyfin.Plugin.MetaShark.Api;
using Jellyfin.Plugin.MetaShark.Core; using Jellyfin.Plugin.MetaShark.Core;
using Jellyfin.Plugin.MetaShark.Model; using Jellyfin.Plugin.MetaShark.Model;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
@ -58,18 +57,19 @@ namespace Jellyfin.Plugin.MetaShark.Providers
/// <inheritdoc /> /// <inheritdoc />
public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken) public async Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo info, CancellationToken cancellationToken)
{ {
// 重新识别时info的IndexNumber和ParentIndexNumber是从文件路径解析出来的假如命名不规范就会导致解析出错误值 // 刷新元数据四种模式差别:
// 刷新元数据不覆盖时IndexNumber和ParentIndexNumber是从当前的元数据获取 // 自动扫描匹配info的Name、IndexNumber和ParentIndexNumber是从文件名解析出来的假如命名不规范就会导致解析出错误值
this.Log($"GetEpisodeMetadata of [name]: {info.Name} number: {info.IndexNumber} ParentIndexNumber: {info.ParentIndexNumber}"); // 识别info的Name、IndexNumber和ParentIndexNumber是从文件名解析出来的provinceIds有指定选择项的ProvinceId
// 搜索缺少的元数据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<Episode>(); var result = new MetadataResult<Episode>();
// 动画特典和extras处理 // 动画特典和extras处理
var specialEpisode = this.HandleAnimeSpecialAndExtras(info.Path); var specialResult = this.HandleAnimeSpecialAndExtras(info);
if (specialEpisode != null) if (specialResult != null)
{ {
result.HasMetadata = true; return specialResult;
result.Item = specialEpisode;
return result;
} }
// 剧集信息只有tmdb有 // 剧集信息只有tmdb有
@ -78,8 +78,9 @@ namespace Jellyfin.Plugin.MetaShark.Providers
var episodeNumber = info.IndexNumber; var episodeNumber = info.IndexNumber;
var indexNumberEnd = info.IndexNumberEnd; var indexNumberEnd = info.IndexNumberEnd;
// 修正anime命名格式导致的seasonNumber错误从season元数据读取) // 修正anime命名格式导致的seasonNumber错误从season元数据读取)
var parent = _libraryManager.FindByPath(Path.GetDirectoryName(info.Path), true); var episodeItem = _libraryManager.FindByPath(info.Path, false);
if (parent is Season season && seasonNumber != season.IndexNumber) var season = episodeItem != null ? ((Episode)episodeItem).Season : null;
if (season != null && seasonNumber != season.IndexNumber)
{ {
this.Log("FixSeasionNumber: old: {0} new: {1}", seasonNumber, season.IndexNumber); this.Log("FixSeasionNumber: old: {0} new: {1}", seasonNumber, season.IndexNumber);
seasonNumber = season.IndexNumber; seasonNumber = season.IndexNumber;
@ -130,17 +131,15 @@ namespace Jellyfin.Plugin.MetaShark.Providers
return result; return result;
} }
// 判断tmdb剧集信息数目和视频是否一致不一致不处理 // 自动搜索匹配时判断tmdb剧集信息数目和视频是否一致不一致不处理
var videoFilesCount = this.GetVideoFileCount(Path.GetDirectoryName(info.Path)); if (info.IsAutomated)
if (!info.IsAutomated && parent is Season)
{ {
// 刷新元数据时直接从season拿准确的视频数并排除特典等没有季号的视频 var videoFilesCount = this.GetVideoFileCount(Path.GetDirectoryName(info.Path));
videoFilesCount = ((Season)parent).GetEpisodes().Where(x => x.ParentIndexNumber == parent.IndexNumber).Count(); if (videoFilesCount > 0 && seasonResult.Episodes.Count != videoFilesCount)
} {
if (videoFilesCount > 0 && seasonResult.Episodes.Count != videoFilesCount) this.Log("Tmdb episode number not match. Name: {0} tmdb episode count: {1} video files count: {2}", info.Name, seasonResult.Episodes.Count, videoFilesCount);
{ return result;
this.Log("Tmdb episode number not match. Name: {0} tmdb episode count: {1} video files count: {2}", info.Name, seasonResult.Episodes.Count, videoFilesCount); }
return result;
} }
var episodeResult = seasonResult.Episodes[episodeNumber.Value - 1]; var episodeResult = seasonResult.Episodes[episodeNumber.Value - 1];
@ -224,32 +223,47 @@ namespace Jellyfin.Plugin.MetaShark.Providers
return guessInfo; return guessInfo;
} }
private Episode? HandleAnimeSpecialAndExtras(string filePath) private MetadataResult<Episode>? HandleAnimeSpecialAndExtras(EpisodeInfo info)
{ {
var fileName = Path.GetFileNameWithoutExtension(filePath) ?? string.Empty; var fileName = Path.GetFileNameWithoutExtension(info.Path) ?? string.Empty;
if (NameParser.IsExtra(fileName)) if (NameParser.IsExtra(fileName))
{ {
this.Log($"Found anime extra of [name]: {fileName}"); this.Log($"Found anime extra of [name]: {fileName}");
return new Episode var result = new MetadataResult<Episode>();
result.HasMetadata = true;
// 假如已有ParentIndexNumber设为特典覆盖掉
if (info.ParentIndexNumber.HasValue)
{
result.Item = new Episode
{
ParentIndexNumber = 0,
IndexNumber = null,
Name = fileName
};
return result;
}
// 没ParentIndexNumber时使用文件名
result.Item = new Episode
{ {
Name = fileName Name = fileName
}; };
return result;
} }
if (NameParser.IsSpecial(filePath)) if (NameParser.IsSpecial(info.Path))
{ {
this.Log($"Found anime sp of [name]: {fileName}"); this.Log($"Found anime sp of [name]: {fileName}");
var guessInfo = this.GuessEpisodeNumber(fileName); var result = new MetadataResult<Episode>();
var ep = new Episode result.HasMetadata = true;
result.Item = new Episode
{ {
ParentIndexNumber = 0, ParentIndexNumber = 0,
IndexNumber = guessInfo.episodeNumber, IndexNumber = null,
Name = fileName
}; };
if (!string.IsNullOrEmpty(guessInfo.Name))
{
ep.Name = guessInfo.Name;
}
return ep; return result;
} }
return null; return null;

View File

@ -146,6 +146,17 @@ namespace Jellyfin.Plugin.MetaShark.Providers
} }
} }
// 尝试通过搜索匹配获取tmdbId
if (string.IsNullOrEmpty(tmdbId) && subject.Year > 0)
{
var newTmdbId = await this.GuestByTmdbAsync(subject.Name, subject.Year, info, cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(newTmdbId))
{
tmdbId = newTmdbId;
movie.SetProviderId(MetadataProvider.Tmdb, tmdbId);
}
}
// 通过imdb获取电影系列信息 // 通过imdb获取电影系列信息
if (this.config.EnableTmdbCollection && !string.IsNullOrEmpty(tmdbId)) if (this.config.EnableTmdbCollection && !string.IsNullOrEmpty(tmdbId))
{ {

View File

@ -53,7 +53,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
info.SeriesProviderIds.TryGetValue(DoubanProviderId, out var sid); info.SeriesProviderIds.TryGetValue(DoubanProviderId, out var sid);
var seasonNumber = info.IndexNumber; // S00/Season 00特典目录会为0 var seasonNumber = info.IndexNumber; // S00/Season 00特典目录会为0
var seasonSid = info.GetProviderId(DoubanProviderId); var seasonSid = info.GetProviderId(DoubanProviderId);
this.Log($"GetSeasonMetaData of [name]: {info.Name} number: {info.IndexNumber} seriesTmdbId: {seriesTmdbId} sid: {sid} metaSource: {metaSource}"); this.Log($"GetSeasonMetaData of [name]: {info.Name} number: {info.IndexNumber} seriesTmdbId: {seriesTmdbId} sid: {sid} metaSource: {metaSource} IsAutomated: {info.IsAutomated}");
if (metaSource != MetaSource.Tmdb && !string.IsNullOrEmpty(sid)) if (metaSource != MetaSource.Tmdb && !string.IsNullOrEmpty(sid))
{ {
@ -63,7 +63,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
{ {
return result; return result;
} }
var seasonName = RemoveSeasonSubfix(series.Name); var seriesName = RemoveSeasonSubfix(series.Name);
// TODO:季文件夹名称不规范没法拿到seasonNumber尝试从文件名猜出 // TODO:季文件夹名称不规范没法拿到seasonNumber尝试从文件名猜出
@ -79,9 +79,9 @@ namespace Jellyfin.Plugin.MetaShark.Providers
seasonYear = season?.AirDate?.Year ?? 0; seasonYear = season?.AirDate?.Year ?? 0;
} }
if (!string.IsNullOrEmpty(seasonName) && seasonYear > 0) if (!string.IsNullOrEmpty(seriesName) && seasonYear > 0)
{ {
seasonSid = await this.GuestDoubanSeasonByYearAsync(seasonName, seasonYear, cancellationToken).ConfigureAwait(false); seasonSid = await this.GuestDoubanSeasonByYearAsync(seriesName, seasonYear, cancellationToken).ConfigureAwait(false);
} }
} }

View File

@ -81,7 +81,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
/// <inheritdoc /> /// <inheritdoc />
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken) public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
{ {
this.Log($"GetSeriesMetadata of [name]: {info.Name} [providerIds]: {info.ProviderIds.ToJson()}"); this.Log($"GetSeriesMetadata of [name]: {info.Name} [providerIds]: {info.ProviderIds.ToJson()} IsAutomated: {info.IsAutomated}");
var result = new MetadataResult<Series>(); var result = new MetadataResult<Series>();
// 使用刷新元数据时providerIds会保留旧有值只有识别/新增才会没值 // 使用刷新元数据时providerIds会保留旧有值只有识别/新增才会没值
@ -95,10 +95,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers
{ {
// 自动扫描搜索匹配元数据 // 自动扫描搜索匹配元数据
sid = await this.GuessByDoubanAsync(info, cancellationToken).ConfigureAwait(false); sid = await this.GuessByDoubanAsync(info, cancellationToken).ConfigureAwait(false);
// if (string.IsNullOrEmpty(sid))
// {
// tmdbId = await this.GuestByTmdbAsync(info, cancellationToken).ConfigureAwait(false);
// }
} }
if (metaSource != MetaSource.Tmdb && !string.IsNullOrEmpty(sid)) if (metaSource != MetaSource.Tmdb && !string.IsNullOrEmpty(sid))
@ -111,10 +107,11 @@ namespace Jellyfin.Plugin.MetaShark.Providers
} }
subject.Celebrities = await this._doubanApi.GetCelebritiesBySidAsync(sid, cancellationToken).ConfigureAwait(false); subject.Celebrities = await this._doubanApi.GetCelebritiesBySidAsync(sid, cancellationToken).ConfigureAwait(false);
var seriesName = RemoveSeasonSubfix(subject.Name);
var item = new Series var item = new Series
{ {
ProviderIds = new Dictionary<string, string> { { DoubanProviderId, subject.Sid }, { Plugin.ProviderId, MetaSource.Douban } }, ProviderIds = new Dictionary<string, string> { { DoubanProviderId, subject.Sid }, { Plugin.ProviderId, MetaSource.Douban } },
Name = RemoveSeasonSubfix(subject.Name), Name = seriesName,
OriginalTitle = subject.OriginalName, OriginalTitle = subject.OriginalName,
CommunityRating = subject.Rating, CommunityRating = subject.Rating,
Overview = subject.Intro, Overview = subject.Intro,
@ -142,7 +139,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
// 尝试通过搜索匹配获取tmdbId // 尝试通过搜索匹配获取tmdbId
if (string.IsNullOrEmpty(tmdbId)) if (string.IsNullOrEmpty(tmdbId))
{ {
var newTmdbId = await this.GuestByTmdbAsync(info, cancellationToken).ConfigureAwait(false); var newTmdbId = await this.GuestByTmdbAsync(seriesName, subject.Year, info, cancellationToken).ConfigureAwait(false);
if (!string.IsNullOrEmpty(newTmdbId)) if (!string.IsNullOrEmpty(newTmdbId))
{ {
tmdbId = newTmdbId; tmdbId = newTmdbId;