mirror of
https://github.com/Jackett/Jackett.git
synced 2025-09-17 17:34:09 +02:00
Feature/omdb api integration (#1509)
* Line endings... * Refactoring how MetaIndexers handle fallbacks Originally this modification was part of a much larger refactoring, however for the sake of reviewability I split it into smaller chunks. Sadly it is still quite large. I wanted to split it even more, however after a certain point there was really no value in creating smaller chunks. The biggest part of this modification would be still huge. So all in all, there're 3 aspects of this modification - It modifies BaseIndexer so that it now implements IIndexer (will be very useful later on) - Resolving most of the warnings currently in Jackett (the only ones remaining are related to Autofac, however if I could I would just burn Autofac altogether rather than fix the warnings. Will open discussion on this.) - Biggest part: refactoring how MetaIndexers handle fallbacks and how they provide the final result set MetaIndexers now accept any kind of fallback and filtering mechanism that implements the necessary interface, so that in the future IMDB fallback and filtering won't be the only one. I know there are not a lot of unit tests around Jackett at the moment, however this renders the class much more unittestable as well. * Integrate OMDB API for the fallback option * Safeguarding when no API key is specified * Autofac started complaining... I don't understand... * How did that not make the previous commit?
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -140,6 +140,10 @@
|
|||||||
<span class="input-header">Enhanced logging: </span>
|
<span class="input-header">Enhanced logging: </span>
|
||||||
<input id="jackett-logging" class="form-control input-right" type="checkbox" />
|
<input id="jackett-logging" class="form-control input-right" type="checkbox" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="input-area">
|
||||||
|
<span class="input-header">OMDB API key: </span>
|
||||||
|
<input id="jackett-omdbkey" class="form-control input-right" type="text" value="" placeholder="">
|
||||||
|
</div>
|
||||||
<hr />
|
<hr />
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
Jackett Version <span id="app-version"></span>
|
Jackett Version <span id="app-version"></span>
|
||||||
|
@@ -332,7 +332,7 @@ namespace Jackett.Controllers
|
|||||||
cfg["password"] = string.IsNullOrEmpty(serverService.Config.AdminPassword) ? string.Empty : serverService.Config.AdminPassword.Substring(0, 10);
|
cfg["password"] = string.IsNullOrEmpty(serverService.Config.AdminPassword) ? string.Empty : serverService.Config.AdminPassword.Substring(0, 10);
|
||||||
cfg["logging"] = Startup.TracingEnabled;
|
cfg["logging"] = Startup.TracingEnabled;
|
||||||
cfg["basepathoverride"] = serverService.Config.BasePathOverride;
|
cfg["basepathoverride"] = serverService.Config.BasePathOverride;
|
||||||
|
cfg["omdbkey"] = serverService.Config.OmdbApiKey;
|
||||||
|
|
||||||
jsonReply["config"] = cfg;
|
jsonReply["config"] = cfg;
|
||||||
jsonReply["app_version"] = config.GetVersion();
|
jsonReply["app_version"] = config.GetVersion();
|
||||||
@@ -364,10 +364,12 @@ namespace Jackett.Controllers
|
|||||||
bool preRelease = (bool)postData["prerelease"];
|
bool preRelease = (bool)postData["prerelease"];
|
||||||
bool logging = (bool)postData["logging"];
|
bool logging = (bool)postData["logging"];
|
||||||
string basePathOverride = (string)postData["basepathoverride"];
|
string basePathOverride = (string)postData["basepathoverride"];
|
||||||
|
string omdbApiKey = (string)postData["omdbkey"];
|
||||||
|
|
||||||
Engine.Server.Config.UpdateDisabled = updateDisabled;
|
Engine.Server.Config.UpdateDisabled = updateDisabled;
|
||||||
Engine.Server.Config.UpdatePrerelease = preRelease;
|
Engine.Server.Config.UpdatePrerelease = preRelease;
|
||||||
Engine.Server.Config.BasePathOverride = basePathOverride;
|
Engine.Server.Config.BasePathOverride = basePathOverride;
|
||||||
|
Engine.Server.Config.OmdbApiKey = omdbApiKey;
|
||||||
Startup.BasePath = Engine.Server.BasePath();
|
Startup.BasePath = Engine.Server.BasePath();
|
||||||
Engine.Server.SaveConfig();
|
Engine.Server.SaveConfig();
|
||||||
|
|
||||||
|
@@ -18,76 +18,67 @@ namespace Jackett
|
|||||||
{
|
{
|
||||||
public class JackettModule : Autofac.Module
|
public class JackettModule : Autofac.Module
|
||||||
{
|
{
|
||||||
protected override void Load(ContainerBuilder builder)
|
protected override void Load (ContainerBuilder builder)
|
||||||
{
|
{
|
||||||
// Just register everything!
|
// Just register everything!
|
||||||
var thisAssembly = typeof(JackettModule).Assembly;
|
var thisAssembly = typeof (JackettModule).Assembly;
|
||||||
builder.RegisterAssemblyTypes(thisAssembly)
|
builder.RegisterAssemblyTypes (thisAssembly)
|
||||||
.Except<IIndexer>()
|
.Except<IIndexer> ()
|
||||||
.Except<IImdbResolver>()
|
.Except<IImdbResolver> ()
|
||||||
.Except<IFallbackStrategyProvider>()
|
.Except<OmdbResolver> ()
|
||||||
.Except<ImdbFallbackStrategyProvider>()
|
.Except<IFallbackStrategyProvider> ()
|
||||||
.Except<IFallbackStrategy>()
|
.Except<ImdbFallbackStrategyProvider> ()
|
||||||
.Except<ImdbFallbackStrategy>()
|
.Except<IFallbackStrategy> ()
|
||||||
.Except<IResultFilterProvider>()
|
.Except<ImdbFallbackStrategy> ()
|
||||||
.Except<ImdbTitleResultFilterProvider>()
|
.Except<IResultFilterProvider> ()
|
||||||
.Except<IResultFilter>()
|
.Except<ImdbTitleResultFilterProvider> ()
|
||||||
.Except<ImdbTitleResultFilterProvider>()
|
.Except<IResultFilter> ()
|
||||||
.Except<BaseMetaIndexer>()
|
.Except<ImdbTitleResultFilterProvider> ()
|
||||||
.Except<AggregateIndexer>()
|
.Except<BaseMetaIndexer> ()
|
||||||
.AsImplementedInterfaces().SingleInstance();
|
.Except<AggregateIndexer> ()
|
||||||
builder.RegisterApiControllers(thisAssembly).InstancePerRequest();
|
.AsImplementedInterfaces ().SingleInstance ();
|
||||||
builder.RegisterType<HttpWebClient>();
|
builder.RegisterApiControllers (thisAssembly).InstancePerRequest ();
|
||||||
|
builder.RegisterType<HttpWebClient> ();
|
||||||
|
|
||||||
// Register the best web client for the platform or the override
|
// Register the best web client for the platform or the override
|
||||||
switch (Startup.ClientOverride)
|
switch (Startup.ClientOverride) {
|
||||||
{
|
case "httpclient":
|
||||||
case "httpclient":
|
builder.RegisterType<HttpWebClient> ().As<IWebClient> ();
|
||||||
builder.RegisterType<HttpWebClient>().As<IWebClient>();
|
break;
|
||||||
break;
|
case "httpclient2":
|
||||||
case "httpclient2":
|
builder.RegisterType<HttpWebClient2> ().As<IWebClient> ();
|
||||||
builder.RegisterType<HttpWebClient2>().As<IWebClient>();
|
break;
|
||||||
break;
|
case "safecurl":
|
||||||
case "safecurl":
|
builder.RegisterType<UnixSafeCurlWebClient> ().As<IWebClient> ();
|
||||||
builder.RegisterType<UnixSafeCurlWebClient>().As<IWebClient>();
|
break;
|
||||||
break;
|
case "libcurl":
|
||||||
case "libcurl":
|
builder.RegisterType<UnixLibCurlWebClient> ().As<IWebClient> ();
|
||||||
builder.RegisterType<UnixLibCurlWebClient>().As<IWebClient>();
|
break;
|
||||||
break;
|
case "automatic":
|
||||||
case "automatic":
|
default:
|
||||||
default:
|
if (System.Environment.OSVersion.Platform == PlatformID.Unix) {
|
||||||
if (System.Environment.OSVersion.Platform == PlatformID.Unix)
|
var usehttpclient = false;
|
||||||
{
|
try {
|
||||||
var usehttpclient = false;
|
Type monotype = Type.GetType ("Mono.Runtime");
|
||||||
try {
|
if (monotype != null) {
|
||||||
Type monotype = Type.GetType("Mono.Runtime");
|
MethodInfo displayName = monotype.GetMethod ("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
||||||
if (monotype != null)
|
if (displayName != null) {
|
||||||
{
|
var monoVersion = displayName.Invoke (null, null).ToString ();
|
||||||
MethodInfo displayName = monotype.GetMethod("GetDisplayName", BindingFlags.NonPublic | BindingFlags.Static);
|
var monoVersionO = new Version (monoVersion.Split (' ') [0]);
|
||||||
if (displayName != null)
|
if ((monoVersionO.Major >= 4 && monoVersionO.Minor >= 8) || monoVersionO.Major >= 5) {
|
||||||
{
|
// check if btls is supported
|
||||||
var monoVersion = displayName.Invoke(null, null).ToString();
|
var monoSecurity = Assembly.Load ("Mono.Security");
|
||||||
var monoVersionO = new Version(monoVersion.Split(' ')[0]);
|
Type monoTlsProviderFactory = monoSecurity.GetType ("Mono.Security.Interface.MonoTlsProviderFactory");
|
||||||
if ((monoVersionO.Major >= 4 && monoVersionO.Minor >= 8) || monoVersionO.Major >= 5)
|
if (monoTlsProviderFactory != null) {
|
||||||
{
|
MethodInfo isProviderSupported = monoTlsProviderFactory.GetMethod ("IsProviderSupported");
|
||||||
// check if btls is supported
|
if (isProviderSupported != null) {
|
||||||
var monoSecurity = Assembly.Load("Mono.Security");
|
var btlsSupported = (bool)isProviderSupported.Invoke (null, new string [] { "btls" });
|
||||||
Type monoTlsProviderFactory = monoSecurity.GetType("Mono.Security.Interface.MonoTlsProviderFactory");
|
if (btlsSupported) {
|
||||||
if (monoTlsProviderFactory != null)
|
// initialize btls
|
||||||
{
|
MethodInfo initialize = monoTlsProviderFactory.GetMethod ("Initialize", new [] { typeof (string) });
|
||||||
MethodInfo isProviderSupported = monoTlsProviderFactory.GetMethod("IsProviderSupported");
|
if (initialize != null) {
|
||||||
if(isProviderSupported != null)
|
initialize.Invoke (null, new string [] { "btls" });
|
||||||
{
|
usehttpclient = true;
|
||||||
var btlsSupported = (bool)isProviderSupported.Invoke(null, new string[] { "btls" });
|
|
||||||
if (btlsSupported)
|
|
||||||
{
|
|
||||||
// initialize btls
|
|
||||||
MethodInfo initialize = monoTlsProviderFactory.GetMethod("Initialize", new[] { typeof(string) });
|
|
||||||
if (initialize != null)
|
|
||||||
{
|
|
||||||
initialize.Invoke(null, new string[] { "btls" });
|
|
||||||
usehttpclient = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,56 +86,45 @@ namespace Jackett
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
} catch (Exception e) {
|
||||||
{
|
Console.Out.WriteLine ("Error while deciding which HttpWebClient to use: " + e);
|
||||||
Console.Out.WriteLine("Error while deciding which HttpWebClient to use: " + e);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (usehttpclient)
|
if (usehttpclient)
|
||||||
builder.RegisterType<HttpWebClient>().As<IWebClient>();
|
builder.RegisterType<HttpWebClient> ().As<IWebClient> ();
|
||||||
else
|
|
||||||
builder.RegisterType<UnixLibCurlWebClient>().As<IWebClient>();
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
builder.RegisterType<UnixLibCurlWebClient> ().As<IWebClient> ();
|
||||||
builder.RegisterType<HttpWebClient>().As<IWebClient>();
|
} else {
|
||||||
}
|
builder.RegisterType<HttpWebClient> ().As<IWebClient> ();
|
||||||
break;
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register indexers
|
// Register indexers
|
||||||
var indexerTypes = thisAssembly.GetTypes().Where(p => typeof (IIndexer).IsAssignableFrom (p) && !p.IsInterface && !p.IsInNamespace("Jackett.Indexers.Meta"));
|
var indexerTypes = thisAssembly.GetTypes ().Where (p => typeof (IIndexer).IsAssignableFrom (p) && !p.IsInterface && !p.IsInNamespace ("Jackett.Indexers.Meta"));
|
||||||
foreach (var indexer in indexerTypes)
|
foreach (var indexer in indexerTypes) {
|
||||||
{
|
builder.RegisterType (indexer).Named<IIndexer> (BaseIndexer.GetIndexerID (indexer));
|
||||||
builder.RegisterType(indexer).Named<IIndexer>(BaseIndexer.GetIndexerID(indexer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mapper.CreateMap<WebClientByteResult, WebClientStringResult>().ForMember(x => x.Content, opt => opt.Ignore()).AfterMap((be, str) =>
|
Mapper.CreateMap<WebClientByteResult, WebClientStringResult> ().ForMember (x => x.Content, opt => opt.Ignore ()).AfterMap ((be, str) => {
|
||||||
{
|
str.Content = Encoding.UTF8.GetString (be.Content);
|
||||||
str.Content = Encoding.UTF8.GetString(be.Content);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Mapper.CreateMap<WebClientStringResult, WebClientByteResult>().ForMember(x => x.Content, opt => opt.Ignore()).AfterMap((str, be) =>
|
Mapper.CreateMap<WebClientStringResult, WebClientByteResult> ().ForMember (x => x.Content, opt => opt.Ignore ()).AfterMap ((str, be) => {
|
||||||
{
|
if (!string.IsNullOrEmpty (str.Content)) {
|
||||||
if (!string.IsNullOrEmpty(str.Content))
|
be.Content = Encoding.UTF8.GetBytes (str.Content);
|
||||||
{
|
|
||||||
be.Content = Encoding.UTF8.GetBytes(str.Content);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Mapper.CreateMap<WebClientStringResult, WebClientStringResult>();
|
Mapper.CreateMap<WebClientStringResult, WebClientStringResult> ();
|
||||||
Mapper.CreateMap<WebClientByteResult, WebClientByteResult>();
|
Mapper.CreateMap<WebClientByteResult, WebClientByteResult> ();
|
||||||
Mapper.CreateMap<ReleaseInfo, ReleaseInfo>();
|
Mapper.CreateMap<ReleaseInfo, ReleaseInfo> ();
|
||||||
|
|
||||||
Mapper.CreateMap<ReleaseInfo, TrackerCacheResult>().AfterMap((r, t) =>
|
Mapper.CreateMap<ReleaseInfo, TrackerCacheResult> ().AfterMap ((r, t) => {
|
||||||
{
|
if (r.Category != null) {
|
||||||
if (r.Category != null)
|
var CategoryDesc = string.Join (", ", r.Category.Select (x => TorznabCatType.GetCatDesc (x)).Where (x => !string.IsNullOrEmpty (x)));
|
||||||
{
|
|
||||||
var CategoryDesc = string.Join(", ", r.Category.Select(x => TorznabCatType.GetCatDesc(x)).Where(x => !string.IsNullOrEmpty(x)));
|
|
||||||
t.CategoryDesc = CategoryDesc;
|
t.CategoryDesc = CategoryDesc;
|
||||||
}
|
} else {
|
||||||
else
|
|
||||||
{
|
|
||||||
t.CategoryDesc = "";
|
t.CategoryDesc = "";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -24,6 +24,7 @@ namespace Jackett.Models.Config
|
|||||||
public bool UpdateDisabled { get; set; }
|
public bool UpdateDisabled { get; set; }
|
||||||
public bool UpdatePrerelease { get; set; }
|
public bool UpdatePrerelease { get; set; }
|
||||||
public string BasePathOverride { get; set; }
|
public string BasePathOverride { get; set; }
|
||||||
|
public string OmdbApiKey { get; set; }
|
||||||
|
|
||||||
public string[] GetListenAddresses(bool? external = null)
|
public string[] GetListenAddresses(bool? external = null)
|
||||||
{
|
{
|
||||||
|
@@ -4,6 +4,8 @@ using System.Threading.Tasks;
|
|||||||
using System.Web;
|
using System.Web;
|
||||||
using CsQuery;
|
using CsQuery;
|
||||||
using Jackett.Utils.Clients;
|
using Jackett.Utils.Clients;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace Jackett.Services
|
namespace Jackett.Services
|
||||||
{
|
{
|
||||||
@@ -12,36 +14,34 @@ namespace Jackett.Services
|
|||||||
Task<IEnumerable<string>> GetAllTitles(string imdbId);
|
Task<IEnumerable<string>> GetAllTitles(string imdbId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ImdbResolver : IImdbResolver
|
public struct Movie
|
||||||
{
|
{
|
||||||
public ImdbResolver(IWebClient webClient)
|
public string Title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OmdbResolver : IImdbResolver
|
||||||
|
{
|
||||||
|
public OmdbResolver(IWebClient webClient, string omdbApiKey)
|
||||||
{
|
{
|
||||||
WebClient = webClient;
|
WebClient = webClient;
|
||||||
|
apiKey = omdbApiKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IEnumerable<string>> GetAllTitles(string imdbId)
|
public async Task<IEnumerable<string>> GetAllTitles(string imdbId)
|
||||||
{
|
{
|
||||||
|
if (apiKey == null)
|
||||||
|
return new string[] { };
|
||||||
|
|
||||||
if (!imdbId.StartsWith("tt", StringComparison.Ordinal))
|
if (!imdbId.StartsWith("tt", StringComparison.Ordinal))
|
||||||
imdbId = "tt" + imdbId;
|
imdbId = "tt" + imdbId;
|
||||||
var request = new WebRequest("http://www.imdb.com/title/" + imdbId + "/releaseinfo");
|
var request = new WebRequest("http://omdbapi.com/?apikey=" + apiKey + "&i=" + imdbId);
|
||||||
var result = await WebClient.GetString(request);
|
var result = await WebClient.GetString(request);
|
||||||
|
var movie = JsonConvert.DeserializeObject<Movie>(result.Content);
|
||||||
|
|
||||||
CQ dom = result.Content;
|
return new string[] { movie.Title };
|
||||||
|
|
||||||
var mainTitle = dom["h3[itemprop=name]"].Find("a")[0].InnerHTML.Replace("\"", "");
|
|
||||||
|
|
||||||
var akas = dom["table#akas"].Find("tbody").Find("tr");
|
|
||||||
var titleList = new List<string>();
|
|
||||||
titleList.Add(mainTitle);
|
|
||||||
foreach (var row in akas) {
|
|
||||||
string title = row.FirstElementChild.InnerHTML;
|
|
||||||
if (title == "(original title)" || title == "")
|
|
||||||
titleList.Add(HttpUtility.HtmlDecode(row.FirstElementChild.NextElementSibling.InnerHTML));
|
|
||||||
}
|
|
||||||
|
|
||||||
return titleList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private IWebClient WebClient;
|
private IWebClient WebClient;
|
||||||
|
private string apiKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -131,7 +131,7 @@ namespace Jackett.Services
|
|||||||
|
|
||||||
public void InitAggregateIndexer()
|
public void InitAggregateIndexer()
|
||||||
{
|
{
|
||||||
var imdbResolver = new ImdbResolver(container.Resolve<IWebClient>());
|
var imdbResolver = new OmdbResolver(container.Resolve<IWebClient>(), container.Resolve<IServerService>().Config.OmdbApiKey);
|
||||||
var imdbFallbackStrategyProvider = new ImdbFallbackStrategyProvider(imdbResolver);
|
var imdbFallbackStrategyProvider = new ImdbFallbackStrategyProvider(imdbResolver);
|
||||||
var imdbTitleResultFilterProvider = new ImdbTitleResultFilterProvider(imdbResolver);
|
var imdbTitleResultFilterProvider = new ImdbTitleResultFilterProvider(imdbResolver);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user