From 8cb221a2045e8c7f1426c182a513c155c69c964d Mon Sep 17 00:00:00 2001 From: cxfksword <718792+cxfksword@users.noreply.github.com> Date: Tue, 17 Jan 2023 15:06:04 +0800 Subject: [PATCH] feat: add tmdb backdrop --- .../Jellyfin.Plugin.MetaShark.Test.csproj | 11 +--- .../MovieImageProviderTest.cs | 60 +++++++++++++++++++ .../ParseNameTest.cs | 14 ++++- Jellyfin.Plugin.MetaShark/Api/DoubanApi.cs | 4 +- .../Configuration/PluginConfiguration.cs | 2 + .../Configuration/configPage.html | 10 ++++ Jellyfin.Plugin.MetaShark/Core/NameParser.cs | 11 ++-- .../Providers/MovieImageProvider.cs | 56 +++++++++++++---- 8 files changed, 137 insertions(+), 31 deletions(-) create mode 100644 Jellyfin.Plugin.MetaShark.Test/MovieImageProviderTest.cs diff --git a/Jellyfin.Plugin.MetaShark.Test/Jellyfin.Plugin.MetaShark.Test.csproj b/Jellyfin.Plugin.MetaShark.Test/Jellyfin.Plugin.MetaShark.Test.csproj index 022da1b..110ee80 100644 --- a/Jellyfin.Plugin.MetaShark.Test/Jellyfin.Plugin.MetaShark.Test.csproj +++ b/Jellyfin.Plugin.MetaShark.Test/Jellyfin.Plugin.MetaShark.Test.csproj @@ -1,13 +1,10 @@ - net6.0 enable enable - false - @@ -15,11 +12,9 @@ - - - + + - - + \ No newline at end of file diff --git a/Jellyfin.Plugin.MetaShark.Test/MovieImageProviderTest.cs b/Jellyfin.Plugin.MetaShark.Test/MovieImageProviderTest.cs new file mode 100644 index 0000000..f2dd110 --- /dev/null +++ b/Jellyfin.Plugin.MetaShark.Test/MovieImageProviderTest.cs @@ -0,0 +1,60 @@ +using Jellyfin.Plugin.MetaShark.Api; +using Jellyfin.Plugin.MetaShark.Core; +using Jellyfin.Plugin.MetaShark.Providers; +using MediaBrowser.Controller.Library; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Entities; +using Microsoft.AspNetCore.Http; +using Microsoft.Extensions.Logging; +using Moq; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Jellyfin.Plugin.MetaShark.Test +{ + [TestClass] + public class MovieImageProviderTest + { + + ILoggerFactory loggerFactory = LoggerFactory.Create(builder => + builder.AddSimpleConsole(options => + { + options.IncludeScopes = true; + options.SingleLine = true; + options.TimestampFormat = "hh:mm:ss "; + })); + + + + [TestMethod] + public void TestGetMovieImage() + { + var info = new MediaBrowser.Controller.Entities.Movies.Movie() + { + Name = "机动战士高达 逆袭的夏亚", + PreferredMetadataLanguage = "zh", + ProviderIds = new Dictionary { { BaseProvider.DoubanProviderId, "1401536" }, { MetadataProvider.Tmdb.ToString(), "16157" } } + }; + var doubanApi = new DoubanApi(loggerFactory); + var tmdbApi = new TmdbApi(loggerFactory); + var omdbApi = new OmdbApi(loggerFactory); + var httpClientFactory = new DefaultHttpClientFactory(); + var libraryManagerStub = new Mock(); + var httpContextAccessorStub = new Mock(); + + Task.Run(async () => + { + var provider = new MovieImageProvider(httpClientFactory, loggerFactory, libraryManagerStub.Object, httpContextAccessorStub.Object, doubanApi, tmdbApi, omdbApi); + var result = await provider.GetImages(info, CancellationToken.None); + Assert.IsNotNull(result); + + var str = result.ToJson(); + Console.WriteLine(result.ToJson()); + }).GetAwaiter().GetResult(); + } + + } +} diff --git a/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs b/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs index ba12dc9..feeba9a 100644 --- a/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs +++ b/Jellyfin.Plugin.MetaShark.Test/ParseNameTest.cs @@ -54,6 +54,14 @@ namespace Jellyfin.Plugin.MetaShark.Test parseResult = NameParser.Parse(fileName); Console.WriteLine(parseResult.ToJson()); + // 只中文 + fileName = "机动战士高达 逆袭的夏亚"; + parseResult = NameParser.Parse(fileName); + Console.WriteLine(parseResult.ToJson()); + + fileName = "秒速5厘米"; + parseResult = NameParser.Parse(fileName); + Console.WriteLine(parseResult.ToJson()); // 标题加年份 @@ -98,6 +106,9 @@ namespace Jellyfin.Plugin.MetaShark.Test // anime混合中日文 fileName = "[异域-11番小队][罗马浴场 THERMAE_ROMAE][1-6+SP][BDRIP][720P][X264-10bit_AAC]"; + var anitomyResult = AnitomySharp.AnitomySharp.Parse(fileName); + Console.WriteLine(anitomyResult.ToJson()); + parseResult = NameParser.Parse(fileName); Console.WriteLine(parseResult.ToJson()); @@ -121,9 +132,6 @@ namespace Jellyfin.Plugin.MetaShark.Test // 只英文 fileName = "She-Hulk.Attorney.At.Law.S01E01.1080p.WEBRip.x265-RARBG"; - var anitomyResult = AnitomySharp.AnitomySharp.Parse(fileName); - Console.WriteLine(anitomyResult.ToJson()); - parseResult = NameParser.Parse(fileName); Console.WriteLine(parseResult.ToJson()); diff --git a/Jellyfin.Plugin.MetaShark/Api/DoubanApi.cs b/Jellyfin.Plugin.MetaShark/Api/DoubanApi.cs index 1a7e2fa..233526b 100644 --- a/Jellyfin.Plugin.MetaShark/Api/DoubanApi.cs +++ b/Jellyfin.Plugin.MetaShark/Api/DoubanApi.cs @@ -79,8 +79,8 @@ namespace Jellyfin.Plugin.MetaShark.Api Regex regFamily = new Regex(@"家庭成员: \n(.+?)\n", RegexOptions.Compiled); Regex regCelebrityImdb = new Regex(@"imdb编号:\s+?(nm\d+)", RegexOptions.Compiled); - // 默认1秒请求1次 - private TimeLimiter _defaultTimeConstraint = TimeLimiter.GetFromMaxCountByInterval(1, TimeSpan.FromMilliseconds(1000)); + // 默认500毫秒请求1次 + private TimeLimiter _defaultTimeConstraint = TimeLimiter.GetFromMaxCountByInterval(1, TimeSpan.FromMilliseconds(500)); // 未登录最多1分钟10次请求,不然5分钟后会被封ip private TimeLimiter _guestTimeConstraint = TimeLimiter.Compose(new CountByIntervalAwaitableConstraint(10, TimeSpan.FromMinutes(1)), new CountByIntervalAwaitableConstraint(1, TimeSpan.FromMilliseconds(5000))); // 登录后最多1分钟20次请求,不然会触发机器人检验 diff --git a/Jellyfin.Plugin.MetaShark/Configuration/PluginConfiguration.cs b/Jellyfin.Plugin.MetaShark/Configuration/PluginConfiguration.cs index 983a65c..06e9650 100644 --- a/Jellyfin.Plugin.MetaShark/Configuration/PluginConfiguration.cs +++ b/Jellyfin.Plugin.MetaShark/Configuration/PluginConfiguration.cs @@ -35,6 +35,8 @@ public class PluginConfiguration : BasePluginConfiguration public bool EnableTmdbSearch { get; set; } = false; + public bool EnableTmdbBackdrop { get; set; } = false; + public string TmdbApiKey { get; set; } = string.Empty; public string TmdbHost { get; set; } = string.Empty; diff --git a/Jellyfin.Plugin.MetaShark/Configuration/configPage.html b/Jellyfin.Plugin.MetaShark/Configuration/configPage.html index 064e6c8..a3214ea 100644 --- a/Jellyfin.Plugin.MetaShark/Configuration/configPage.html +++ b/Jellyfin.Plugin.MetaShark/Configuration/configPage.html @@ -69,6 +69,14 @@
勾选后,识别时会同时返回TheMovieDb搜索结果
+
+ +
勾选后,当影片在豆瓣找不到背景图时,改使用TheMovieDb的补全
+
@@ -104,6 +112,7 @@ document.querySelector('#EnableDoubanAvoidRiskControl').checked = config.EnableDoubanAvoidRiskControl; document.querySelector('#EnableTmdb').checked = config.EnableTmdb; document.querySelector('#EnableTmdbSearch').checked = config.EnableTmdbSearch; + document.querySelector('#EnableTmdbBackdrop').checked = config.EnableTmdbBackdrop; document.querySelector('#TmdbApiKey').value = config.TmdbApiKey; document.querySelector('#TmdbHost').value = config.TmdbHost; @@ -121,6 +130,7 @@ config.EnableDoubanAvoidRiskControl = document.querySelector('#EnableDoubanAvoidRiskControl').checked; config.EnableTmdb = document.querySelector('#EnableTmdb').checked; config.EnableTmdbSearch = document.querySelector('#EnableTmdbSearch').checked; + config.EnableTmdbBackdrop = document.querySelector('#EnableTmdbBackdrop').checked; config.TmdbApiKey = document.querySelector('#TmdbApiKey').value; config.TmdbHost = document.querySelector('#TmdbHost').value; ApiClient.updatePluginConfiguration(TemplateConfig.pluginUniqueId, config).then(function (result) { diff --git a/Jellyfin.Plugin.MetaShark/Core/NameParser.cs b/Jellyfin.Plugin.MetaShark/Core/NameParser.cs index c818e26..aa7a96b 100644 --- a/Jellyfin.Plugin.MetaShark/Core/NameParser.cs +++ b/Jellyfin.Plugin.MetaShark/Core/NameParser.cs @@ -13,7 +13,7 @@ namespace Jellyfin.Plugin.MetaShark.Core 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 unusedReg = new Regex(@"\[.+?\]|\(.+?\)", RegexOptions.Compiled); + private static readonly Regex unusedReg = new Regex(@"\[.+?\]|\(.+?\)|【.+?】", RegexOptions.Compiled); public static ParseNameResult Parse(string fileName, bool isTvSeries = false) { @@ -25,15 +25,16 @@ namespace Jellyfin.Plugin.MetaShark.Core { case AnitomySharp.Element.ElementCategory.ElementAnimeTitle: // 处理混合中英文的标题,中文一般在最前面,如V字仇杀队.V.for.Vendetta - char[] seperatorChars = { ' ', '.' }; - var firstSpaceIndex = item.Value.IndexOfAny(seperatorChars); + char[] delimiters = { ' ', '.' }; + var firstSpaceIndex = item.Value.IndexOfAny(delimiters); if (firstSpaceIndex > 0) { var firstString = item.Value.Substring(0, firstSpaceIndex); - if (firstString.HasChinese()) + var lastString = item.Value.Substring(firstSpaceIndex + 1); + if (firstString.HasChinese() && !lastString.HasChinese()) { parseResult.ChineseName = CleanName(firstString); - parseResult.Name = CleanName(item.Value.Substring(firstSpaceIndex + 1)); + parseResult.Name = CleanName(lastString); } else { diff --git a/Jellyfin.Plugin.MetaShark/Providers/MovieImageProvider.cs b/Jellyfin.Plugin.MetaShark/Providers/MovieImageProvider.cs index 4508d4c..1d1f858 100644 --- a/Jellyfin.Plugin.MetaShark/Providers/MovieImageProvider.cs +++ b/Jellyfin.Plugin.MetaShark/Providers/MovieImageProvider.cs @@ -62,7 +62,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers { return Enumerable.Empty(); } - var backdropImgs = await GetBackdrop(sid, cancellationToken); + var backdropImgs = await GetBackdrop(item, cancellationToken); var res = new List { new RemoteImageInfo @@ -139,28 +139,58 @@ namespace Jellyfin.Plugin.MetaShark.Providers /// /// Query for a background photo /// - /// a subject/movie id /// Instance of the interface. - private async Task> GetBackdrop(string sid, CancellationToken cancellationToken) + private async Task> GetBackdrop(BaseItem item, CancellationToken cancellationToken) { - this.Log("GetBackdrop of sid: {0}", sid); - var photo = await this._doubanApi.GetWallpaperBySidAsync(sid, cancellationToken); + var sid = item.GetProviderId(DoubanProviderId); + var tmdbId = item.GetProviderId(MetadataProvider.Tmdb); var list = new List(); - if (photo == null) + // 从豆瓣获取背景图 + if (!string.IsNullOrEmpty(sid)) + { + var photo = await this._doubanApi.GetWallpaperBySidAsync(sid, cancellationToken); + if (photo != null && photo.Count > 0) + { + this.Log("GetBackdrop from douban sid: {0}", sid); + list = photo.Where(x => x.Width > x.Height * 1.3).Select(x => + { + return new RemoteImageInfo + { + ProviderName = Name, + Url = x.Large, + Type = ImageType.Backdrop, + }; + }).ToList(); + + } + } + if (list.Count > 0) { return list; } - return photo.Where(x => x.Width > x.Height * 1.3).Select(x => + // 从TheMovieDb获取背景图 + if (config.EnableTmdbBackdrop && !string.IsNullOrEmpty(tmdbId)) { - return new RemoteImageInfo + var language = item.GetPreferredMetadataLanguage(); + var movie = await _tmdbApi + .GetMovieAsync(tmdbId.ToInt(), language, language, cancellationToken) + .ConfigureAwait(false); + + if (movie != null && !string.IsNullOrEmpty(movie.BackdropPath)) { - ProviderName = Name, - Url = x.Large, - Type = ImageType.Backdrop, - }; - }); + this.Log("GetBackdrop from tmdb id: {0}", tmdbId); + list.Add(new RemoteImageInfo + { + ProviderName = Name, + Url = _tmdbApi.GetBackdropUrl(movie.BackdropPath), + Type = ImageType.Backdrop, + }); + } + } + + return list; } }