fix: fix download douban image. close #35
This commit is contained in:
parent
cff4008c57
commit
2b07875250
|
@ -82,5 +82,26 @@ namespace Jellyfin.Plugin.MetaShark.Test
|
||||||
Console.WriteLine(result.ToJson());
|
Console.WriteLine(result.ToJson());
|
||||||
}).GetAwaiter().GetResult();
|
}).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void TestGetImageResponse()
|
||||||
|
{
|
||||||
|
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 httpContextAccessorStub = new Mock<IHttpContextAccessor>();
|
||||||
|
|
||||||
|
Task.Run(async () =>
|
||||||
|
{
|
||||||
|
var provider = new MovieImageProvider(httpClientFactory, loggerFactory, libraryManagerStub.Object, httpContextAccessorStub.Object, doubanApi, tmdbApi, omdbApi);
|
||||||
|
var result = await provider.GetImageResponse("https://img1.doubanio.com/view/photo/m/public/p2893270877.jpg", CancellationToken.None);
|
||||||
|
Assert.IsNotNull(result);
|
||||||
|
|
||||||
|
var str = result.ToJson();
|
||||||
|
Console.WriteLine(result.ToJson());
|
||||||
|
}).GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,35 +2,21 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Jellyfin.Extensions.Json;
|
using Jellyfin.Extensions.Json;
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Jellyfin.Plugin.MetaShark.Model;
|
using Jellyfin.Plugin.MetaShark.Model;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
|
||||||
using MediaBrowser.Common.Net;
|
|
||||||
using System.Net.Http.Json;
|
using System.Net.Http.Json;
|
||||||
using System.Security.Cryptography;
|
|
||||||
using Microsoft.AspNetCore.Mvc.ApiExplorer;
|
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Jellyfin.Plugin.MetaShark.Api.Http;
|
using Jellyfin.Plugin.MetaShark.Api.Http;
|
||||||
using System.Web;
|
using System.Web;
|
||||||
using static Microsoft.Extensions.Logging.EventSource.LoggingEventSource;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Jellyfin.Plugin.MetaShark.Providers;
|
|
||||||
using AngleSharp;
|
using AngleSharp;
|
||||||
using System.Net.WebSockets;
|
|
||||||
using Jellyfin.Data.Entities.Libraries;
|
|
||||||
using AngleSharp.Dom;
|
using AngleSharp.Dom;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Jellyfin.Plugin.MetaShark.Core;
|
using Jellyfin.Plugin.MetaShark.Core;
|
||||||
using System.Data;
|
|
||||||
using TMDbLib.Objects.Movies;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
using RateLimiter;
|
using RateLimiter;
|
||||||
using ComposableAsync;
|
using ComposableAsync;
|
||||||
|
|
||||||
|
@ -38,7 +24,8 @@ namespace Jellyfin.Plugin.MetaShark.Api
|
||||||
{
|
{
|
||||||
public class DoubanApi : IDisposable
|
public class DoubanApi : IDisposable
|
||||||
{
|
{
|
||||||
const string HTTP_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.44";
|
public const string HTTP_USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36 Edg/93.0.961.44";
|
||||||
|
public const string HTTP_REFERER = "https://www.douban.com/";
|
||||||
private readonly ILogger<DoubanApi> _logger;
|
private readonly ILogger<DoubanApi> _logger;
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
private CookieContainer _cookieContainer;
|
private CookieContainer _cookieContainer;
|
||||||
|
|
|
@ -1,24 +1,8 @@
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
using System.Net;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
namespace Jellyfin.Plugin.MetaShark.Configuration;
|
namespace Jellyfin.Plugin.MetaShark.Configuration;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The configuration options.
|
|
||||||
/// </summary>
|
|
||||||
public enum SomeOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Option one.
|
|
||||||
/// </summary>
|
|
||||||
OneOption,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Second option.
|
|
||||||
/// </summary>
|
|
||||||
AnotherOption
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Plugin configuration.
|
/// Plugin configuration.
|
||||||
|
@ -32,13 +16,17 @@ public class PluginConfiguration : BasePluginConfiguration
|
||||||
|
|
||||||
public string DoubanCookies { get; set; } = string.Empty;
|
public string DoubanCookies { get; set; } = string.Empty;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 开启防封禁
|
/// 豆瓣开启防封禁
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableDoubanAvoidRiskControl { get; set; } = false;
|
public bool EnableDoubanAvoidRiskControl { get; set; } = false;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 背景图使用原图
|
/// 豆瓣背景图使用原图
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool EnableDoubanBackdropRaw { get; set; } = false;
|
public bool EnableDoubanBackdropRaw { get; set; } = false;
|
||||||
|
/// <summary>
|
||||||
|
/// 豆瓣图片代理地址
|
||||||
|
/// </summary>
|
||||||
|
public string DoubanImageProxyBaseUrl { get; set; } = string.Empty;
|
||||||
|
|
||||||
public bool EnableTmdb { get; set; } = true;
|
public bool EnableTmdb { get; set; } = true;
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,13 @@
|
||||||
class="emby-input" placeholder="_vwo_uuid_v2=1; __utmv=2; ..."></textarea>
|
class="emby-input" placeholder="_vwo_uuid_v2=1; __utmv=2; ..."></textarea>
|
||||||
<div class="fieldDescription">可为空,填写可搜索到需登录访问的影片,使用(www.douban.com)分号“;”分隔格式cookie.</div>
|
<div class="fieldDescription">可为空,填写可搜索到需登录访问的影片,使用(www.douban.com)分号“;”分隔格式cookie.</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="inputContainer">
|
||||||
|
<label class="inputLabel inputLabelUnfocused" for="DoubanImageProxyBaseUrl">豆瓣图片代理地址</label>
|
||||||
|
<input id="DoubanImageProxyBaseUrl" name="DoubanImageProxyBaseUrl" type="text"
|
||||||
|
is="emby-input" placeholder="http://jellyfin.xxx.com" />
|
||||||
|
<div class="fieldDescription">可为空,填写jellyfin访问域名,只有使用了nginx代理或docker,且豆瓣图片没法显示时,才需要填写
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="checkboxContainer checkboxContainer-withDescription">
|
<div class="checkboxContainer checkboxContainer-withDescription">
|
||||||
<label class="emby-checkbox-label" for="EnableDoubanAvoidRiskControl">
|
<label class="emby-checkbox-label" for="EnableDoubanAvoidRiskControl">
|
||||||
<input id="EnableDoubanAvoidRiskControl" name="EnableDoubanAvoidRiskControl"
|
<input id="EnableDoubanAvoidRiskControl" name="EnableDoubanAvoidRiskControl"
|
||||||
|
@ -133,8 +140,10 @@
|
||||||
$('#current_version').text("v" + config.Version);
|
$('#current_version').text("v" + config.Version);
|
||||||
|
|
||||||
document.querySelector('#DoubanCookies').value = config.DoubanCookies;
|
document.querySelector('#DoubanCookies').value = config.DoubanCookies;
|
||||||
|
document.querySelector('#DoubanImageProxyBaseUrl').value = config.DoubanImageProxyBaseUrl;
|
||||||
document.querySelector('#EnableDoubanAvoidRiskControl').checked = config.EnableDoubanAvoidRiskControl;
|
document.querySelector('#EnableDoubanAvoidRiskControl').checked = config.EnableDoubanAvoidRiskControl;
|
||||||
document.querySelector('#EnableDoubanBackdropRaw').checked = config.EnableDoubanBackdropRaw;
|
document.querySelector('#EnableDoubanBackdropRaw').checked = config.EnableDoubanBackdropRaw;
|
||||||
|
|
||||||
document.querySelector('#EnableTmdb').checked = config.EnableTmdb;
|
document.querySelector('#EnableTmdb').checked = config.EnableTmdb;
|
||||||
document.querySelector('#EnableTmdbSearch').checked = config.EnableTmdbSearch;
|
document.querySelector('#EnableTmdbSearch').checked = config.EnableTmdbSearch;
|
||||||
document.querySelector('#EnableTmdbBackdrop').checked = config.EnableTmdbBackdrop;
|
document.querySelector('#EnableTmdbBackdrop').checked = config.EnableTmdbBackdrop;
|
||||||
|
@ -154,8 +163,10 @@
|
||||||
Dashboard.showLoadingMsg();
|
Dashboard.showLoadingMsg();
|
||||||
ApiClient.getPluginConfiguration(TemplateConfig.pluginUniqueId).then(function (config) {
|
ApiClient.getPluginConfiguration(TemplateConfig.pluginUniqueId).then(function (config) {
|
||||||
config.DoubanCookies = document.querySelector('#DoubanCookies').value;
|
config.DoubanCookies = document.querySelector('#DoubanCookies').value;
|
||||||
|
config.DoubanImageProxyBaseUrl = document.querySelector('#DoubanImageProxyBaseUrl').value;
|
||||||
config.EnableDoubanAvoidRiskControl = document.querySelector('#EnableDoubanAvoidRiskControl').checked;
|
config.EnableDoubanAvoidRiskControl = document.querySelector('#EnableDoubanAvoidRiskControl').checked;
|
||||||
config.EnableDoubanBackdropRaw = document.querySelector('#EnableDoubanBackdropRaw').checked;
|
config.EnableDoubanBackdropRaw = document.querySelector('#EnableDoubanBackdropRaw').checked;
|
||||||
|
|
||||||
config.EnableTmdb = document.querySelector('#EnableTmdb').checked;
|
config.EnableTmdb = document.querySelector('#EnableTmdb').checked;
|
||||||
config.EnableTmdbSearch = document.querySelector('#EnableTmdbSearch').checked;
|
config.EnableTmdbSearch = document.querySelector('#EnableTmdbSearch').checked;
|
||||||
config.EnableTmdbBackdrop = document.querySelector('#EnableTmdbBackdrop').checked;
|
config.EnableTmdbBackdrop = document.querySelector('#EnableTmdbBackdrop').checked;
|
||||||
|
|
|
@ -1,24 +1,11 @@
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using MediaBrowser.Common.Extensions;
|
using MediaBrowser.Common.Extensions;
|
||||||
using MediaBrowser.Controller.Library;
|
|
||||||
using MediaBrowser.Controller;
|
|
||||||
using MediaBrowser.Model.Entities;
|
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using MediaBrowser.Model.IO;
|
|
||||||
using MediaBrowser.Controller.Providers;
|
|
||||||
using Jellyfin.Plugin.MetaShark.Providers;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using MediaBrowser.Controller.Entities.TV;
|
|
||||||
using MediaBrowser.Controller.Entities.Movies;
|
|
||||||
using MediaBrowser.Common.Net;
|
using MediaBrowser.Common.Net;
|
||||||
using Jellyfin.Plugin.MetaShark.Api;
|
using Jellyfin.Plugin.MetaShark.Api;
|
||||||
using Jellyfin.Plugin.MetaShark.Model;
|
using Jellyfin.Plugin.MetaShark.Model;
|
||||||
|
@ -61,7 +48,8 @@ namespace Jellyfin.Plugin.MetaShark.Controllers
|
||||||
var httpClient = GetHttpClient();
|
var httpClient = GetHttpClient();
|
||||||
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url))
|
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url))
|
||||||
{
|
{
|
||||||
requestMessage.Headers.Add("Referer", "https://www.douban.com/");
|
requestMessage.Headers.Add("User-Agent", DoubanApi.HTTP_USER_AGENT);
|
||||||
|
requestMessage.Headers.Add("Referer", DoubanApi.HTTP_REFERER);
|
||||||
|
|
||||||
response = await httpClient.SendAsync(requestMessage);
|
response = await httpClient.SendAsync(requestMessage);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Globalization;
|
||||||
using Jellyfin.Plugin.MetaShark.Configuration;
|
using Jellyfin.Plugin.MetaShark.Configuration;
|
||||||
using MediaBrowser.Common.Configuration;
|
using MediaBrowser.Common.Configuration;
|
||||||
using MediaBrowser.Common.Plugins;
|
using MediaBrowser.Common.Plugins;
|
||||||
|
using MediaBrowser.Controller;
|
||||||
using MediaBrowser.Model.Plugins;
|
using MediaBrowser.Model.Plugins;
|
||||||
using MediaBrowser.Model.Serialization;
|
using MediaBrowser.Model.Serialization;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
@ -26,14 +27,17 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
||||||
public const string ProviderId = "MetaSharkID";
|
public const string ProviderId = "MetaSharkID";
|
||||||
|
|
||||||
|
|
||||||
|
private readonly IServerApplicationHost _appHost;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Plugin"/> class.
|
/// Initializes a new instance of the <see cref="Plugin"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="applicationPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
|
/// <param name="applicationPaths">Instance of the <see cref="IApplicationPaths"/> interface.</param>
|
||||||
/// <param name="xmlSerializer">Instance of the <see cref="IXmlSerializer"/> interface.</param>
|
/// <param name="xmlSerializer">Instance of the <see cref="IXmlSerializer"/> interface.</param>
|
||||||
public Plugin(IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
public Plugin(IServerApplicationHost appHost, IApplicationPaths applicationPaths, IXmlSerializer xmlSerializer)
|
||||||
: base(applicationPaths, xmlSerializer)
|
: base(applicationPaths, xmlSerializer)
|
||||||
{
|
{
|
||||||
|
this._appHost = appHost;
|
||||||
Plugin.Instance = this;
|
Plugin.Instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,8 +60,26 @@ public class Plugin : BasePlugin<PluginConfiguration>, IHasWebPages
|
||||||
new PluginPageInfo
|
new PluginPageInfo
|
||||||
{
|
{
|
||||||
Name = this.Name,
|
Name = this.Name,
|
||||||
EmbeddedResourcePath = string.Format(CultureInfo.InvariantCulture, "{0}.Configuration.configPage.html", GetType().Namespace)
|
EmbeddedResourcePath = string.Format(CultureInfo.InvariantCulture, "{0}.Configuration.configPage.html", GetType().Namespace),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetLocalApiBaseUrl(string hostname = "127.0.0.1")
|
||||||
|
{
|
||||||
|
return this._appHost.GetSmartApiUrl(hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetApiBaseUrl(HttpRequest request)
|
||||||
|
{
|
||||||
|
int? requestPort = request.Host.Port;
|
||||||
|
if (requestPort == null
|
||||||
|
|| (requestPort == 80 && string.Equals(request.Scheme, "http", StringComparison.OrdinalIgnoreCase))
|
||||||
|
|| (requestPort == 443 && string.Equals(request.Scheme, "https", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
{
|
||||||
|
requestPort = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._appHost.GetLocalApiUrl(request.Host.Host, request.Scheme, requestPort);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,18 +104,32 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
public async Task<HttpResponseMessage> GetImageResponse(string url, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
this.Log("GetImageResponse url: {0}", url);
|
|
||||||
if (url.Contains("doubanio.com"))
|
if (url.Contains("doubanio.com"))
|
||||||
{
|
{
|
||||||
|
// 相对链接补全
|
||||||
|
if (!url.StartsWith("http") && Plugin.Instance != null)
|
||||||
|
{
|
||||||
|
url = Plugin.Instance.GetLocalApiBaseUrl().TrimEnd('/') + url;
|
||||||
|
}
|
||||||
|
// 包含了代理地址的话,从url解析出原始豆瓣图片地址
|
||||||
|
if (url.Contains("/proxy/image"))
|
||||||
|
{
|
||||||
|
var uri = new UriBuilder(url);
|
||||||
|
url = HttpUtility.ParseQueryString(uri.Query).Get("url");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Log("GetImageResponse url: {0}", url);
|
||||||
// 豆瓣图,带referer下载
|
// 豆瓣图,带referer下载
|
||||||
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url))
|
using (var requestMessage = new HttpRequestMessage(HttpMethod.Get, url))
|
||||||
{
|
{
|
||||||
requestMessage.Headers.Add("Referer", "https://www.douban.com/");
|
requestMessage.Headers.Add("User-Agent", DoubanApi.HTTP_USER_AGENT);
|
||||||
|
requestMessage.Headers.Add("Referer", DoubanApi.HTTP_REFERER);
|
||||||
return await this._httpClientFactory.CreateClient().SendAsync(requestMessage, cancellationToken).ConfigureAwait(false);
|
return await this._httpClientFactory.CreateClient().SendAsync(requestMessage, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this.Log("GetImageResponse url: {0}", url);
|
||||||
return await this._httpClientFactory.CreateClient().GetAsync(new Uri(url), cancellationToken).ConfigureAwait(false);
|
return await this._httpClientFactory.CreateClient().GetAsync(new Uri(url), cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -478,35 +492,63 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 浏览器来源请求,返回代理地址(no-referer对于background-image不生效),其他客户端请求,返回原始图片地址
|
|
||||||
/// </summary>
|
|
||||||
protected string GetProxyImageUrl(string url)
|
protected string GetProxyImageUrl(string url)
|
||||||
{
|
{
|
||||||
var fromWeb = false;
|
var baseUrl = this.GetBaseUrl();
|
||||||
if (_httpContextAccessor.HttpContext != null)
|
var encodedUrl = HttpUtility.UrlEncode(url);
|
||||||
{
|
return $"{baseUrl}/plugin/metashark/proxy/image/?url={encodedUrl}";
|
||||||
var userAgent = _httpContextAccessor.HttpContext.Request.Headers.UserAgent.ToString();
|
|
||||||
fromWeb = userAgent.Contains("Chrome") || userAgent.Contains("Safari");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fromWeb)
|
|
||||||
{
|
|
||||||
var encodedUrl = HttpUtility.UrlEncode(url);
|
|
||||||
return $"/plugin/metashark/proxy/image/?url={encodedUrl}";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected string GetLocalProxyImageUrl(string url)
|
||||||
protected string GetAbsoluteProxyImageUrl(string url)
|
|
||||||
{
|
{
|
||||||
var encodedUrl = HttpUtility.UrlEncode(url);
|
var baseUrl = Plugin.Instance?.GetLocalApiBaseUrl("127.0.0.1");
|
||||||
return $"{this.RequestDomain}/plugin/metashark/proxy/image/?url={encodedUrl}";
|
if (!string.IsNullOrEmpty(config.DoubanImageProxyBaseUrl))
|
||||||
|
{
|
||||||
|
baseUrl = config.DoubanImageProxyBaseUrl.TrimEnd('/');
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(baseUrl))
|
||||||
|
{
|
||||||
|
var encodedUrl = HttpUtility.UrlEncode(url);
|
||||||
|
return $"{baseUrl}/plugin/metashark/proxy/image/?url={encodedUrl}";
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.GetProxyImageUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetBaseUrl()
|
||||||
|
{
|
||||||
|
// 配置优先
|
||||||
|
if (!string.IsNullOrEmpty(this.config.DoubanImageProxyBaseUrl))
|
||||||
|
{
|
||||||
|
return this.config.DoubanImageProxyBaseUrl.TrimEnd('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
// http请求时,获取请求的host (nginx代理/docker中部署时,没配置透传host时,本方式会有问题)
|
||||||
|
if (Plugin.Instance != null && this._httpContextAccessor.HttpContext != null)
|
||||||
|
{
|
||||||
|
// 特殊处理下搜索请求,直接使用相对链接,可以减少使用nginx代理但不透传host的问题
|
||||||
|
var userAgent = this._httpContextAccessor.HttpContext.Request.Headers.UserAgent.ToString();
|
||||||
|
var fromWeb = userAgent.Contains("Chrome") || userAgent.Contains("Safari");
|
||||||
|
var fromItemSearch = this._httpContextAccessor.HttpContext.Request.Path.ToString().Contains("/RemoteSearch");
|
||||||
|
if (fromWeb && fromItemSearch)
|
||||||
|
{
|
||||||
|
// 处理通过nginx反向代理后,url加了subpath访问的情况
|
||||||
|
var subpath = string.Empty;
|
||||||
|
var baseUrl = Plugin.Instance.GetApiBaseUrl(this._httpContextAccessor.HttpContext.Request);
|
||||||
|
var uri = new UriBuilder(baseUrl);
|
||||||
|
if (!string.IsNullOrEmpty(uri.Path) && uri.Path != "/")
|
||||||
|
{
|
||||||
|
subpath = "/" + uri.Path.Trim('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
return subpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plugin.Instance.GetApiBaseUrl(this._httpContextAccessor.HttpContext.Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 自动扫描刷新时,直接使用本地地址
|
||||||
|
return Plugin.Instance?.GetLocalApiBaseUrl("127.0.0.1") ?? string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void Log(string? message, params object?[] args)
|
protected void Log(string? message, params object?[] args)
|
||||||
|
|
|
@ -19,12 +19,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
{
|
{
|
||||||
public class EpisodeImageProvider : BaseProvider, IRemoteImageProvider
|
public class EpisodeImageProvider : BaseProvider, IRemoteImageProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="EpisodeImageProvider"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
|
||||||
/// <param name="logger">Instance of the <see cref="ILogger{OddbImageProvider}"/> interface.</param>
|
|
||||||
/// <param name="doubanApi">Instance of <see cref="DoubanApi"/>.</param>
|
|
||||||
public EpisodeImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
public EpisodeImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
||||||
: base(httpClientFactory, loggerFactory.CreateLogger<EpisodeImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
: base(httpClientFactory, loggerFactory.CreateLogger<EpisodeImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,12 +21,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
{
|
{
|
||||||
public class MovieImageProvider : BaseProvider, IRemoteImageProvider
|
public class MovieImageProvider : BaseProvider, IRemoteImageProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="MovieImageProvider"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
|
||||||
/// <param name="logger">Instance of the <see cref="ILogger{OddbImageProvider}"/> interface.</param>
|
|
||||||
/// <param name="doubanApi">Instance of <see cref="DoubanApi"/>.</param>
|
|
||||||
public MovieImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
public MovieImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
||||||
: base(httpClientFactory, loggerFactory.CreateLogger<MovieImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
: base(httpClientFactory, loggerFactory.CreateLogger<MovieImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
||||||
{
|
{
|
||||||
|
@ -64,9 +58,9 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
new RemoteImageInfo
|
new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = primary.Name,
|
ProviderName = primary.Name,
|
||||||
Url = primary.ImgMiddle,
|
Url = this.GetProxyImageUrl(primary.ImgMiddle),
|
||||||
Type = ImageType.Primary
|
Type = ImageType.Primary,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
res.AddRange(backdropImgs);
|
res.AddRange(backdropImgs);
|
||||||
return res;
|
return res;
|
||||||
|
@ -147,11 +141,10 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
{
|
{
|
||||||
if (config.EnableDoubanBackdropRaw)
|
if (config.EnableDoubanBackdropRaw)
|
||||||
{
|
{
|
||||||
var fromBackdropSearch = RequestPath.Contains("/RemoteImages");
|
|
||||||
return new RemoteImageInfo
|
return new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = Name,
|
ProviderName = Name,
|
||||||
Url = fromBackdropSearch ? GetAbsoluteProxyImageUrl(x.Raw) : x.Raw,
|
Url = this.GetProxyImageUrl(x.Raw),
|
||||||
Height = x.Height,
|
Height = x.Height,
|
||||||
Width = x.Width,
|
Width = x.Width,
|
||||||
Type = ImageType.Backdrop,
|
Type = ImageType.Backdrop,
|
||||||
|
@ -162,7 +155,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
return new RemoteImageInfo
|
return new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = Name,
|
ProviderName = Name,
|
||||||
Url = x.Large,
|
Url = this.GetProxyImageUrl(x.Large),
|
||||||
Type = ImageType.Backdrop,
|
Type = ImageType.Backdrop,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,7 +184,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
Name = c.Name,
|
Name = c.Name,
|
||||||
Type = c.RoleType,
|
Type = c.RoleType,
|
||||||
Role = c.Role,
|
Role = c.Role,
|
||||||
ImageUrl = c.Img,
|
ImageUrl = this.GetLocalProxyImageUrl(c.Img),
|
||||||
ProviderIds = new Dictionary<string, string> { { DoubanProviderId, c.Id } },
|
ProviderIds = new Dictionary<string, string> { { DoubanProviderId, c.Id } },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -197,6 +197,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
return await this.GetMetadataByTmdb(tmdbId, info, cancellationToken).ConfigureAwait(false);
|
return await this.GetMetadataByTmdb(tmdbId, info, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Log($"匹配失败!可检查下年份是否与豆瓣一致,是否需要登录访问. [name]: {info.Name} [year]: {info.Year}");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
{
|
{
|
||||||
public class PersonImageProvider : BaseProvider, IRemoteImageProvider
|
public class PersonImageProvider : BaseProvider, IRemoteImageProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="MovieImageProvider"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
|
||||||
/// <param name="logger">Instance of the <see cref="ILogger{OddbImageProvider}"/> interface.</param>
|
|
||||||
/// <param name="doubanApi">Instance of <see cref="DoubanApi"/>.</param>
|
|
||||||
public PersonImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
public PersonImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
||||||
: base(httpClientFactory, loggerFactory.CreateLogger<PersonImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
: base(httpClientFactory, loggerFactory.CreateLogger<PersonImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +48,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
new RemoteImageInfo
|
new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = celebrity.Name,
|
ProviderName = celebrity.Name,
|
||||||
Url = celebrity.Img,
|
Url = this.GetProxyImageUrl(celebrity.Img),
|
||||||
Type = ImageType.Primary
|
Type = ImageType.Primary
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -65,32 +59,5 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
return new List<RemoteImageInfo>();
|
return new List<RemoteImageInfo>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Query for a background photo
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sid">a subject/movie id</param>
|
|
||||||
/// <param name="cancellationToken">Instance of the <see cref="CancellationToken"/> interface.</param>
|
|
||||||
private async Task<IEnumerable<RemoteImageInfo>> GetBackdrop(string sid, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
this.Log("GetBackdrop of sid: {0}", sid);
|
|
||||||
var photo = await this._doubanApi.GetWallpaperBySidAsync(sid, cancellationToken);
|
|
||||||
var list = new List<RemoteImageInfo>();
|
|
||||||
|
|
||||||
if (photo == null)
|
|
||||||
{
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
return photo.Where(x => x.Width > x.Height * 1.3).Select(x =>
|
|
||||||
{
|
|
||||||
return new RemoteImageInfo
|
|
||||||
{
|
|
||||||
ProviderName = Name,
|
|
||||||
Url = x.Large,
|
|
||||||
Type = ImageType.Backdrop,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class PersonProvider : BaseProvider, IRemoteMetadataProvider<Person, PersonLookupInfo>
|
public class PersonProvider : BaseProvider, IRemoteMetadataProvider<Person, PersonLookupInfo>
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="MovieImageProvider"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
|
||||||
/// <param name="logger">Instance of the <see cref="ILogger{OddbImageProvider}"/> interface.</param>
|
|
||||||
/// <param name="doubanApi">Instance of <see cref="DoubanApi"/>.</param>
|
|
||||||
public PersonProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
public PersonProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
||||||
: base(httpClientFactory, loggerFactory.CreateLogger<PersonProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
: base(httpClientFactory, loggerFactory.CreateLogger<PersonProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,12 +21,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
{
|
{
|
||||||
public class SeasonImageProvider : BaseProvider, IRemoteImageProvider
|
public class SeasonImageProvider : BaseProvider, IRemoteImageProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SeasonImageProvider"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
|
||||||
/// <param name="logger">Instance of the <see cref="ILogger{OddbImageProvider}"/> interface.</param>
|
|
||||||
/// <param name="doubanApi">Instance of <see cref="DoubanApi"/>.</param>
|
|
||||||
public SeasonImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
public SeasonImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
||||||
: base(httpClientFactory, loggerFactory.CreateLogger<SeasonImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
: base(httpClientFactory, loggerFactory.CreateLogger<SeasonImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
||||||
{
|
{
|
||||||
|
@ -66,9 +60,9 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
new RemoteImageInfo
|
new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = primary.Name,
|
ProviderName = primary.Name,
|
||||||
Url = primary.ImgMiddle,
|
Url = this.GetProxyImageUrl(primary.ImgMiddle),
|
||||||
Type = ImageType.Primary
|
Type = ImageType.Primary,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
Name = c.Name,
|
Name = c.Name,
|
||||||
Type = c.RoleType,
|
Type = c.RoleType,
|
||||||
Role = c.Role,
|
Role = c.Role,
|
||||||
ImageUrl = c.Img,
|
ImageUrl = this.GetLocalProxyImageUrl(c.Img),
|
||||||
ProviderIds = new Dictionary<string, string> { { DoubanProviderId, c.Id } },
|
ProviderIds = new Dictionary<string, string> { { DoubanProviderId, c.Id } },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,6 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
{
|
{
|
||||||
public class SeriesImageProvider : BaseProvider, IRemoteImageProvider
|
public class SeriesImageProvider : BaseProvider, IRemoteImageProvider
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="SeriesImageProvider"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="httpClientFactory">Instance of the <see cref="IHttpClientFactory"/> interface.</param>
|
|
||||||
/// <param name="logger">Instance of the <see cref="ILogger{OddbImageProvider}"/> interface.</param>
|
|
||||||
/// <param name="doubanApi">Instance of <see cref="DoubanApi"/>.</param>
|
|
||||||
public SeriesImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
public SeriesImageProvider(IHttpClientFactory httpClientFactory, ILoggerFactory loggerFactory, ILibraryManager libraryManager, IHttpContextAccessor httpContextAccessor, DoubanApi doubanApi, TmdbApi tmdbApi, OmdbApi omdbApi)
|
||||||
: base(httpClientFactory, loggerFactory.CreateLogger<SeriesImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
: base(httpClientFactory, loggerFactory.CreateLogger<SeriesImageProvider>(), libraryManager, httpContextAccessor, doubanApi, tmdbApi, omdbApi)
|
||||||
{
|
{
|
||||||
|
@ -64,9 +58,9 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
new RemoteImageInfo
|
new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = primary.Name,
|
ProviderName = primary.Name,
|
||||||
Url = primary.ImgMiddle,
|
Url = this.GetProxyImageUrl(primary.ImgMiddle),
|
||||||
Type = ImageType.Primary
|
Type = ImageType.Primary,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
res.AddRange(dropback);
|
res.AddRange(dropback);
|
||||||
return res;
|
return res;
|
||||||
|
@ -147,11 +141,10 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
{
|
{
|
||||||
if (config.EnableDoubanBackdropRaw)
|
if (config.EnableDoubanBackdropRaw)
|
||||||
{
|
{
|
||||||
var fromBackdropSearch = RequestPath.Contains("/RemoteImages");
|
|
||||||
return new RemoteImageInfo
|
return new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = Name,
|
ProviderName = Name,
|
||||||
Url = fromBackdropSearch ? GetAbsoluteProxyImageUrl(x.Raw) : x.Raw,
|
Url = this.GetProxyImageUrl(x.Raw),
|
||||||
Height = x.Height,
|
Height = x.Height,
|
||||||
Width = x.Width,
|
Width = x.Width,
|
||||||
Type = ImageType.Backdrop,
|
Type = ImageType.Backdrop,
|
||||||
|
@ -162,7 +155,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
return new RemoteImageInfo
|
return new RemoteImageInfo
|
||||||
{
|
{
|
||||||
ProviderName = Name,
|
ProviderName = Name,
|
||||||
Url = x.Large,
|
Url = this.GetProxyImageUrl(x.Large),
|
||||||
Type = ImageType.Backdrop,
|
Type = ImageType.Backdrop,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -156,7 +156,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
Name = c.Name,
|
Name = c.Name,
|
||||||
Type = c.RoleType,
|
Type = c.RoleType,
|
||||||
Role = c.Role,
|
Role = c.Role,
|
||||||
ImageUrl = c.Img,
|
ImageUrl = this.GetLocalProxyImageUrl(c.Img),
|
||||||
ProviderIds = new Dictionary<string, string> { { DoubanProviderId, c.Id } },
|
ProviderIds = new Dictionary<string, string> { { DoubanProviderId, c.Id } },
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -168,6 +168,7 @@ namespace Jellyfin.Plugin.MetaShark.Providers
|
||||||
return await this.GetMetadataByTmdb(tmdbId, info, cancellationToken).ConfigureAwait(false);
|
return await this.GetMetadataByTmdb(tmdbId, info, cancellationToken).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.Log($"匹配失败!可检查下年份是否与豆瓣一致,是否需要登录访问. [name]: {info.Name} [year]: {info.Year}");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue