Parse anime special
This commit is contained in:
parent
49b1a2f498
commit
6b56ba4ea0
|
@ -10,6 +10,8 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Model.Serialization;
|
||||
|
||||
namespace Jellyfin.Plugin.MetaShark.Test
|
||||
{
|
||||
|
@ -30,21 +32,26 @@ namespace Jellyfin.Plugin.MetaShark.Test
|
|||
[TestMethod]
|
||||
public void TestGuessEpisodeNumber()
|
||||
{
|
||||
var doubanApi = new DoubanApi(loggerFactory);
|
||||
var tmdbApi = new TmdbApi(loggerFactory);
|
||||
var omdbApi = new OmdbApi(loggerFactory);
|
||||
var httpClientFactory = new DefaultHttpClientFactory();
|
||||
var libraryManagerStub = new Mock<ILibraryManager>();
|
||||
|
||||
var doubanApi = new DoubanApi(loggerFactory);
|
||||
var tmdbApi = new TmdbApi(loggerFactory);
|
||||
var omdbApi = new OmdbApi(loggerFactory);
|
||||
|
||||
var provider = new EpisodeProvider(httpClientFactory, loggerFactory, libraryManagerStub.Object, doubanApi, tmdbApi, omdbApi);
|
||||
var indexNumber = provider.GuessEpisodeNumber("[POPGO][Stand_Alone_Complex][05][1080P][BluRay][x264_FLACx2_AC3x1][chs_jpn][D87C36B6].mkv");
|
||||
Assert.AreEqual(indexNumber, 5);
|
||||
var guessInfo = provider.GuessEpisodeNumber("[POPGO][Stand_Alone_Complex][05][1080P][BluRay][x264_FLACx2_AC3x1][chs_jpn][D87C36B6].mkv");
|
||||
Assert.AreEqual(guessInfo.episodeNumber, 5);
|
||||
|
||||
indexNumber = provider.GuessEpisodeNumber("Fullmetal Alchemist Brotherhood.E05.1920X1080");
|
||||
Assert.AreEqual(indexNumber, 5);
|
||||
guessInfo = provider.GuessEpisodeNumber("Fullmetal Alchemist Brotherhood.E05.1920X1080");
|
||||
Assert.AreEqual(guessInfo.episodeNumber, 5);
|
||||
|
||||
indexNumber = provider.GuessEpisodeNumber("[SAIO-Raws] Neon Genesis Evangelion 05 [BD 1440x1080 HEVC-10bit OPUSx2 ASSx2].mkv");
|
||||
Assert.AreEqual(indexNumber, 5);
|
||||
guessInfo = provider.GuessEpisodeNumber("[SAIO-Raws] Neon Genesis Evangelion 05 [BD 1440x1080 HEVC-10bit OPUSx2 ASSx2].mkv");
|
||||
Assert.AreEqual(guessInfo.episodeNumber, 5);
|
||||
|
||||
guessInfo = provider.GuessEpisodeNumber("[Moozzi2] Samurai Champloo [SP03] Battlecry (Opening) PV (BD 1920x1080 x.264 AC3).mkv");
|
||||
Assert.AreEqual(guessInfo.episodeNumber, 3);
|
||||
Assert.AreEqual(guessInfo.seasonNumber, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace Jellyfin.Plugin.MetaShark.Api
|
|||
|
||||
private void SetDoubanCookie(CookieContainer cookieContainer)
|
||||
{
|
||||
var configCookie = Plugin.Instance!.Configuration.DoubanCookies.Trim();
|
||||
var configCookie = Plugin.Instance?.Configuration.DoubanCookies.Trim() ?? string.Empty;
|
||||
if (string.IsNullOrEmpty(configCookie))
|
||||
{
|
||||
return;
|
||||
|
|
|
@ -35,7 +35,8 @@ namespace Jellyfin.Plugin.MetaShark.Api
|
|||
{
|
||||
_logger = loggerFactory.CreateLogger<TmdbApi>();
|
||||
_memoryCache = new MemoryCache(new MemoryCacheOptions());
|
||||
var apiKey = string.IsNullOrEmpty(Plugin.Instance!.Configuration.TmdbApiKey) ? DEFAULT_API_KEY : Plugin.Instance!.Configuration.TmdbApiKey;
|
||||
var config = Plugin.Instance?.Configuration;
|
||||
var apiKey = config == null || string.IsNullOrEmpty(config.TmdbApiKey) ? DEFAULT_API_KEY : config.TmdbApiKey;
|
||||
_tmDbClient = new TMDbClient(apiKey);
|
||||
_tmDbClient.RequestTimeout = TimeSpan.FromSeconds(10);
|
||||
// Not really interested in NotFoundException
|
||||
|
@ -675,7 +676,7 @@ namespace Jellyfin.Plugin.MetaShark.Api
|
|||
|
||||
private bool IsEnable()
|
||||
{
|
||||
return Plugin.Instance!.Configuration.EnableTmdb;
|
||||
return Plugin.Instance?.Configuration.EnableTmdb ?? false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Jellyfin.Plugin.MetaShark.Model
|
||||
{
|
||||
public class GuessInfo
|
||||
{
|
||||
public int? episodeNumber { get; set; }
|
||||
|
||||
public int? seasonNumber { get; set; }
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ using System.Threading;
|
|||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using TMDbLib.Objects.General;
|
||||
using Jellyfin.Plugin.MetaShark.Configuration;
|
||||
|
||||
namespace Jellyfin.Plugin.MetaShark.Providers
|
||||
{
|
||||
|
@ -51,7 +52,15 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
{
|
||||
get
|
||||
{
|
||||
return Plugin.Instance!.Configuration.Pattern;
|
||||
return this.config.Pattern;
|
||||
}
|
||||
}
|
||||
|
||||
protected PluginConfiguration config
|
||||
{
|
||||
get
|
||||
{
|
||||
return Plugin.Instance?.Configuration ?? new PluginConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
};
|
||||
|
||||
public EpisodeProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
||||
: base(httpClientFactory, loggerFactory.CreateLogger<SeriesProvider>(), libraryManager, doubanApi, tmdbApi, omdbApi)
|
||||
: base(httpClientFactory, loggerFactory.CreateLogger<EpisodeProvider>(), libraryManager, doubanApi, tmdbApi, omdbApi)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -70,18 +70,22 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
this.Log("FixSeasionNumber: old: {0} new: {1}", seasonNumber, season.IndexNumber);
|
||||
seasonNumber = season.IndexNumber;
|
||||
}
|
||||
// 没有season级目录时,会为null
|
||||
// 没有season级目录或目录不命名不规范时,会为null
|
||||
if (seasonNumber is null or 0)
|
||||
{
|
||||
seasonNumber = 1;
|
||||
}
|
||||
// 修正anime命名格式导致的episodeNumber错误
|
||||
var fileName = Path.GetFileName(info.Path) ?? string.Empty;
|
||||
var newEpisodeNumber = this.GuessEpisodeNumber(fileName);
|
||||
this.Log("GuessEpisodeNumber: fileName: {0} episodeNumber: {1}", fileName, newEpisodeNumber);
|
||||
if (newEpisodeNumber.HasValue && newEpisodeNumber != episodeNumber)
|
||||
var guessInfo = this.GuessEpisodeNumber(fileName);
|
||||
this.Log("GuessEpisodeNumber: fileName: {0} seasonNumber: {1} episodeNumber: {2}", fileName, guessInfo.seasonNumber, guessInfo.episodeNumber);
|
||||
if (guessInfo.seasonNumber.HasValue && guessInfo.seasonNumber != seasonNumber)
|
||||
{
|
||||
episodeNumber = newEpisodeNumber;
|
||||
seasonNumber = guessInfo.seasonNumber.Value;
|
||||
}
|
||||
if (guessInfo.episodeNumber.HasValue && guessInfo.episodeNumber != episodeNumber)
|
||||
{
|
||||
episodeNumber = guessInfo.episodeNumber;
|
||||
|
||||
result.HasMetadata = true;
|
||||
result.Item = new Episode
|
||||
|
@ -146,17 +150,23 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
return _httpClientFactory.CreateClient().GetAsync(new Uri(url), cancellationToken);
|
||||
}
|
||||
|
||||
public int? GuessEpisodeNumber(string fileName, double max = double.PositiveInfinity)
|
||||
public GuessInfo GuessEpisodeNumber(string fileName, double max = double.PositiveInfinity)
|
||||
{
|
||||
int? episodeIndex = null;
|
||||
var guessInfo = new GuessInfo();
|
||||
|
||||
var result = AnitomySharp.AnitomySharp.Parse(fileName).FirstOrDefault(x => x.Category == AnitomySharp.Element.ElementCategory.ElementEpisodeNumber);
|
||||
if (result != null)
|
||||
var parseResult = AnitomySharp.AnitomySharp.Parse(fileName);
|
||||
var animeSpecialType = parseResult.FirstOrDefault(x => x.Category == AnitomySharp.Element.ElementCategory.ElementAnimeType && x.Value == "SP");
|
||||
if (animeSpecialType != null)
|
||||
{
|
||||
episodeIndex = result.Value.ToInt();
|
||||
guessInfo.seasonNumber = 0;
|
||||
}
|
||||
var animeEpisode = parseResult.FirstOrDefault(x => x.Category == AnitomySharp.Element.ElementCategory.ElementEpisodeNumber);
|
||||
if (animeEpisode != null)
|
||||
{
|
||||
guessInfo.episodeNumber = animeEpisode.Value.ToInt();
|
||||
}
|
||||
|
||||
if (!episodeIndex.HasValue)
|
||||
if (!guessInfo.episodeNumber.HasValue)
|
||||
{
|
||||
foreach (var regex in EpisodeFileNameRegex)
|
||||
{
|
||||
|
@ -164,18 +174,18 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
continue;
|
||||
if (!int.TryParse(regex.Match(fileName).Groups[1].Value.Trim('.'), out var index))
|
||||
continue;
|
||||
episodeIndex = index;
|
||||
guessInfo.episodeNumber = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (episodeIndex > 1000)
|
||||
if (guessInfo.episodeNumber > 1000)
|
||||
{
|
||||
// 可能解析了分辨率,忽略返回
|
||||
episodeIndex = null;
|
||||
guessInfo.episodeNumber = null;
|
||||
}
|
||||
|
||||
return episodeIndex;
|
||||
return guessInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
|
||||
// 从douban搜索
|
||||
var res = await this._doubanApi.SearchAsync(info.Name, cancellationToken).ConfigureAwait(false);
|
||||
result.AddRange(res.Take(Plugin.Instance!.Configuration.MaxSearchResult).Select(x =>
|
||||
result.AddRange(res.Take(this.config.MaxSearchResult).Select(x =>
|
||||
{
|
||||
return new RemoteSearchResult
|
||||
{
|
||||
|
@ -68,7 +68,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
if (Plugin.Instance?.Configuration.EnableTmdbSearch ?? false)
|
||||
{
|
||||
var tmdbList = await _tmdbApi.SearchMovieAsync(info.Name, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||
result.AddRange(tmdbList.Take(Plugin.Instance!.Configuration.MaxSearchResult).Select(x =>
|
||||
result.AddRange(tmdbList.Take(this.config.MaxSearchResult).Select(x =>
|
||||
{
|
||||
return new RemoteSearchResult
|
||||
{
|
||||
|
@ -143,7 +143,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
result.Item = movie;
|
||||
result.QueriedById = true;
|
||||
result.HasMetadata = true;
|
||||
subject.LimitDirectorCelebrities.Take(Plugin.Instance!.Configuration.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
subject.LimitDirectorCelebrities.Take(this.config.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = c.Name,
|
||||
Type = c.RoleType,
|
||||
|
@ -220,7 +220,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
// 演员
|
||||
if (item.Credits?.Cast != null)
|
||||
{
|
||||
foreach (var actor in item.Credits.Cast.OrderBy(a => a.Order).Take(Plugin.Instance!.Configuration.MaxCastMembers))
|
||||
foreach (var actor in item.Credits.Cast.OrderBy(a => a.Order).Take(this.config.MaxCastMembers))
|
||||
{
|
||||
var personInfo = new PersonInfo
|
||||
{
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
|
||||
result.Item = movie;
|
||||
result.HasMetadata = true;
|
||||
subject.LimitDirectorCelebrities.Take(Plugin.Instance!.Configuration.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
subject.LimitDirectorCelebrities.Take(this.config.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = c.Name,
|
||||
Type = c.RoleType,
|
||||
|
@ -200,7 +200,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
|
||||
// result.Item = movie;
|
||||
// result.HasMetadata = true;
|
||||
// subject.Celebrities.Take(Plugin.Instance!.Configuration.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
// subject.Celebrities.Take(this.config.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
// {
|
||||
// Name = c.Name,
|
||||
// Type = c.RoleType,
|
||||
|
@ -222,7 +222,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
// 演员
|
||||
if (item.Credits?.Cast != null)
|
||||
{
|
||||
foreach (var actor in item.Credits.Cast.OrderBy(a => a.Order).Take(Plugin.Instance!.Configuration.MaxCastMembers))
|
||||
foreach (var actor in item.Credits.Cast.OrderBy(a => a.Order).Take(this.config.MaxCastMembers))
|
||||
{
|
||||
var personInfo = new PersonInfo
|
||||
{
|
||||
|
|
|
@ -44,7 +44,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
|
||||
// 从douban搜索
|
||||
var res = await this._doubanApi.SearchAsync(info.Name, cancellationToken).ConfigureAwait(false);
|
||||
result.AddRange(res.Take(Plugin.Instance!.Configuration.MaxSearchResult).Select(x =>
|
||||
result.AddRange(res.Take(this.config.MaxSearchResult).Select(x =>
|
||||
{
|
||||
return new RemoteSearchResult
|
||||
{
|
||||
|
@ -60,7 +60,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
if (Plugin.Instance?.Configuration.EnableTmdbSearch ?? false)
|
||||
{
|
||||
var tmdbList = await this._tmdbApi.SearchSeriesAsync(info.Name, info.MetadataLanguage, cancellationToken).ConfigureAwait(false);
|
||||
result.AddRange(tmdbList.Take(Plugin.Instance!.Configuration.MaxSearchResult).Select(x =>
|
||||
result.AddRange(tmdbList.Take(this.config.MaxSearchResult).Select(x =>
|
||||
{
|
||||
return new RemoteSearchResult
|
||||
{
|
||||
|
@ -142,7 +142,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
result.Item = item;
|
||||
result.QueriedById = true;
|
||||
result.HasMetadata = true;
|
||||
subject.LimitDirectorCelebrities.Take(Plugin.Instance!.Configuration.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
subject.LimitDirectorCelebrities.Take(this.config.MaxCastMembers).ToList().ForEach(c => result.AddPerson(new PersonInfo
|
||||
{
|
||||
Name = c.Name,
|
||||
Type = c.RoleType,
|
||||
|
@ -279,7 +279,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
|||
// 演员
|
||||
if (seriesResult.Credits?.Cast != null)
|
||||
{
|
||||
foreach (var actor in seriesResult.Credits.Cast.OrderBy(a => a.Order).Take(Plugin.Instance!.Configuration.MaxCastMembers))
|
||||
foreach (var actor in seriesResult.Credits.Cast.OrderBy(a => a.Order).Take(this.config.MaxCastMembers))
|
||||
{
|
||||
var personInfo = new PersonInfo
|
||||
{
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
[](https://github.com/cxfksword/jellyfin-plugin-metashark/releases)
|
||||
[](https://github.com/cxfksword/jellyfin-plugin-metashark/main/LICENSE)
|
||||
|
||||
jellyfin电影元数据插件,影片信息只要从豆瓣获取,并由TheMovieDb补充缺失的季数据和剧集数据。
|
||||
jellyfin电影元数据插件,影片信息只要从豆瓣获取,并由TheMovieDb补充缺失的剧集数据。
|
||||
|
||||
功能:
|
||||
* 支持从豆瓣和TMDB获取元数据
|
||||
|
|
Loading…
Reference in New Issue