mirror of
https://github.com/Radarr/Radarr.git
synced 2024-09-19 07:52:33 +02:00
New: TMDb List Rework
This commit is contained in:
parent
bdc1adb2ed
commit
65287ec4f3
@ -16,17 +16,19 @@ public RadarrCloudRequestBuilder()
|
||||
Services = new HttpRequestBuilder("https://radarr.lidarr.audio/v1/")
|
||||
.CreateFactory();
|
||||
|
||||
TMDB = new HttpRequestBuilder("https://api.themoviedb.org/3/{route}/{id}{secondaryRoute}")
|
||||
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
|
||||
TMDB = new HttpRequestBuilder("https://api.themoviedb.org/{api}/{route}/{id}{secondaryRoute}")
|
||||
.SetHeader("Authorization", $"Bearer {AuthToken}")
|
||||
.CreateFactory();
|
||||
|
||||
TMDBSingle = new HttpRequestBuilder("https://api.themoviedb.org/3/{route}")
|
||||
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
|
||||
.SetHeader("Authorization", $"Bearer {AuthToken}")
|
||||
.CreateFactory();
|
||||
}
|
||||
|
||||
public IHttpRequestBuilderFactory Services { get; private set; }
|
||||
public IHttpRequestBuilderFactory TMDB { get; private set; }
|
||||
public IHttpRequestBuilderFactory TMDBSingle { get; private set; }
|
||||
|
||||
public string AuthToken => "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiIxYTczNzMzMDE5NjFkMDNmOTdmODUzYTg3NmRkMTIxMiIsInN1YiI6IjU4NjRmNTkyYzNhMzY4MGFiNjAxNzUzNCIsInNjb3BlcyI6WyJhcGlfcmVhZCJdLCJ2ZXJzaW9uIjoxfQ.gh1BwogCCKOda6xj9FRMgAAj_RYKMMPC3oNlcBtlmwk";
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,17 @@ public class MovieSearchRoot
|
||||
public int total_pages { get; set; }
|
||||
}
|
||||
|
||||
public class AuthRefreshTokenResponse
|
||||
{
|
||||
public string request_token { get; set; }
|
||||
}
|
||||
|
||||
public class AuthAccessTokenResponse
|
||||
{
|
||||
public string access_token { get; set; }
|
||||
public string account_id { get; set; }
|
||||
}
|
||||
|
||||
public class MovieResult
|
||||
{
|
||||
public string poster_path { get; set; }
|
||||
@ -37,6 +48,13 @@ public class MovieResult
|
||||
public string physical_release_note { get; set; }
|
||||
}
|
||||
|
||||
public class CreditsResult : MovieResult
|
||||
{
|
||||
public string department { get; set; }
|
||||
public string job { get; set; }
|
||||
public string credit_id { get; set; }
|
||||
}
|
||||
|
||||
public class MovieResourceRoot
|
||||
{
|
||||
public bool adult { get; set; }
|
||||
@ -181,17 +199,31 @@ public class Video
|
||||
|
||||
public class ListResponseRoot
|
||||
{
|
||||
public string created_by { get; set; }
|
||||
public string description { get; set; }
|
||||
public int favorite_count { get; set; }
|
||||
public string id { get; set; }
|
||||
public Item[] items { get; set; }
|
||||
public int item_count { get; set; }
|
||||
public Item[] results { get; set; }
|
||||
public int total_results { get; set; }
|
||||
public string iso_639_1 { get; set; }
|
||||
public string name { get; set; }
|
||||
public object poster_path { get; set; }
|
||||
}
|
||||
|
||||
public class CollectionResponseRoot
|
||||
{
|
||||
public int id { get; set; }
|
||||
public string name { get; set; }
|
||||
public string overview { get; set; }
|
||||
public string poster_path { get; set; }
|
||||
public string backdrop_path { get; set; }
|
||||
public MovieResult[] parts { get; set; }
|
||||
}
|
||||
|
||||
public class PersonCreditsRoot
|
||||
{
|
||||
public CreditsResult[] cast { get; set; }
|
||||
public CreditsResult[] crew { get; set; }
|
||||
public int id { get; set; }
|
||||
}
|
||||
|
||||
public class Item : MovieResult
|
||||
{
|
||||
public string media_type { get; set; }
|
||||
|
@ -63,6 +63,7 @@ public HashSet<int> GetChangedMovies(DateTime startTime)
|
||||
var startDate = startTime.ToString("o");
|
||||
|
||||
var request = _movieBuilder.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "movie")
|
||||
.SetSegment("id", "")
|
||||
.SetSegment("secondaryRoute", "changes")
|
||||
@ -82,6 +83,7 @@ public Tuple<Movie, List<Credit>> GetMovieInfo(int tmdbId, Profile profile, bool
|
||||
var langCode = profile != null ? IsoLanguages.Get(profile.Language)?.TwoLetterCode ?? "en" : "en";
|
||||
|
||||
var request = _movieBuilder.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "movie")
|
||||
.SetSegment("id", tmdbId.ToString())
|
||||
.SetSegment("secondaryRoute", "")
|
||||
@ -329,6 +331,7 @@ public Tuple<Movie, List<Credit>> GetMovieInfo(int tmdbId, Profile profile, bool
|
||||
public Movie GetMovieInfo(string imdbId)
|
||||
{
|
||||
var request = _movieBuilder.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "find")
|
||||
.SetSegment("id", imdbId)
|
||||
.SetSegment("secondaryRoute", "")
|
||||
@ -504,6 +507,7 @@ public List<Movie> SearchForNewMovie(string title)
|
||||
var firstChar = searchTerm.First();
|
||||
|
||||
var request = _movieBuilder.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "search")
|
||||
.SetSegment("id", "movie")
|
||||
.SetSegment("secondaryRoute", "")
|
||||
|
@ -51,7 +51,7 @@ public List<INetImport> Enabled()
|
||||
|
||||
public List<INetImport> Discoverable()
|
||||
{
|
||||
var enabledImporters = GetAvailableProviders().Where(n => (n.GetType() == typeof(Radarr.RadarrLists) || n.GetType() == typeof(TMDb.TMDbImport)));
|
||||
var enabledImporters = GetAvailableProviders().Where(n => (n.GetType() == typeof(Radarr.RadarrLists) || n.GetType() == typeof(TMDb.Popular.TMDbPopularImport)));
|
||||
var indexers = FilterBlockedIndexers(enabledImporters);
|
||||
return indexers.ToList();
|
||||
}
|
||||
|
@ -0,0 +1,42 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Collection
|
||||
{
|
||||
public class TMDbCollectionImport : TMDbNetImportBase<TMDbCollectionSettings>
|
||||
{
|
||||
public TMDbCollectionImport(IRadarrCloudRequestBuilder requestBuilder,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
ISearchForNewMovie searchForNewMovie,
|
||||
Logger logger)
|
||||
: base(requestBuilder, httpClient, configService, parsingService, searchForNewMovie, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "TMDb Collection";
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
public override IParseNetImportResponse GetParser()
|
||||
{
|
||||
return new TMDbCollectionParser(_skyhookProxy);
|
||||
}
|
||||
|
||||
public override INetImportRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new TMDbCollectionRequestGenerator()
|
||||
{
|
||||
RequestBuilder = _requestBuilder,
|
||||
Settings = Settings,
|
||||
Logger = _logger,
|
||||
HttpClient = _httpClient
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||
using NzbDrone.Core.Movies;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Collection
|
||||
{
|
||||
public class TMDbCollectionParser : TMDbParser
|
||||
{
|
||||
private readonly ISearchForNewMovie _skyhookProxy;
|
||||
|
||||
public TMDbCollectionParser(ISearchForNewMovie skyhookProxy)
|
||||
: base(skyhookProxy)
|
||||
{
|
||||
_skyhookProxy = skyhookProxy;
|
||||
}
|
||||
|
||||
public override IList<Movie> ParseResponse(NetImportResponse importResponse)
|
||||
{
|
||||
var movies = new List<Movie>();
|
||||
|
||||
if (!PreProcess(importResponse))
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
var jsonResponse = JsonConvert.DeserializeObject<CollectionResponseRoot>(importResponse.Content);
|
||||
|
||||
// no movies were return
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
foreach (var movie in jsonResponse.parts)
|
||||
{
|
||||
// Movies with no Year Fix
|
||||
if (string.IsNullOrWhiteSpace(movie.release_date))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
movies.AddIfNotNull(_skyhookProxy.MapMovie(movie));
|
||||
}
|
||||
|
||||
return movies;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Collection
|
||||
{
|
||||
public class TMDbCollectionRequestGenerator : INetImportRequestGenerator
|
||||
{
|
||||
public TMDbCollectionSettings Settings { get; set; }
|
||||
public IHttpClient HttpClient { get; set; }
|
||||
public IHttpRequestBuilderFactory RequestBuilder { get; set; }
|
||||
public Logger Logger { get; set; }
|
||||
|
||||
public TMDbCollectionRequestGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual NetImportPageableRequestChain GetMovies()
|
||||
{
|
||||
var pageableRequests = new NetImportPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetMoviesRequest());
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMoviesRequest()
|
||||
{
|
||||
Logger.Info($"Importing TMDb movies from collection: {Settings.CollectionId}");
|
||||
|
||||
yield return new NetImportRequest(RequestBuilder.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "collection")
|
||||
.SetSegment("id", Settings.CollectionId)
|
||||
.SetSegment("secondaryRoute", "")
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Collection
|
||||
{
|
||||
public class TMDbCollectionSettingsValidator : TMDbSettingsBaseValidator<TMDbCollectionSettings>
|
||||
{
|
||||
public TMDbCollectionSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.CollectionId).Matches(@"^[1-9][0-9]*$", RegexOptions.IgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public class TMDbCollectionSettings : TMDbSettingsBase<TMDbCollectionSettings>
|
||||
{
|
||||
protected override AbstractValidator<TMDbCollectionSettings> Validator => new TMDbCollectionSettingsValidator();
|
||||
|
||||
public TMDbCollectionSettings()
|
||||
{
|
||||
CollectionId = "";
|
||||
}
|
||||
|
||||
[FieldDefinition(1, Label = "Collection Id", Type = FieldType.Textbox, HelpText = "TMDb Id of Collection to Follow")]
|
||||
public string CollectionId { get; set; }
|
||||
}
|
||||
}
|
42
src/NzbDrone.Core/NetImport/TMDb/List/TMDbListImport.cs
Normal file
42
src/NzbDrone.Core/NetImport/TMDb/List/TMDbListImport.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.List
|
||||
{
|
||||
public class TMDbListImport : TMDbNetImportBase<TMDbListSettings>
|
||||
{
|
||||
public TMDbListImport(IRadarrCloudRequestBuilder requestBuilder,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
ISearchForNewMovie searchForNewMovie,
|
||||
Logger logger)
|
||||
: base(requestBuilder, httpClient, configService, parsingService, searchForNewMovie, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "TMDb List";
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
public override IParseNetImportResponse GetParser()
|
||||
{
|
||||
return new TMDbListParser(_skyhookProxy);
|
||||
}
|
||||
|
||||
public override INetImportRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new TMDbListRequestGenerator()
|
||||
{
|
||||
RequestBuilder = _requestBuilder,
|
||||
Settings = Settings,
|
||||
Logger = _logger,
|
||||
HttpClient = _httpClient
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
51
src/NzbDrone.Core/NetImport/TMDb/List/TMDbListParser.cs
Normal file
51
src/NzbDrone.Core/NetImport/TMDb/List/TMDbListParser.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||
using NzbDrone.Core.Movies;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.List
|
||||
{
|
||||
public class TMDbListParser : TMDbParser
|
||||
{
|
||||
private readonly ISearchForNewMovie _skyhookProxy;
|
||||
|
||||
public TMDbListParser(ISearchForNewMovie skyhookProxy)
|
||||
: base(skyhookProxy)
|
||||
{
|
||||
_skyhookProxy = skyhookProxy;
|
||||
}
|
||||
|
||||
public override IList<Movie> ParseResponse(NetImportResponse importResponse)
|
||||
{
|
||||
var movies = new List<Movie>();
|
||||
|
||||
if (!PreProcess(importResponse))
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
var jsonResponse = JsonConvert.DeserializeObject<ListResponseRoot>(importResponse.Content);
|
||||
|
||||
// no movies were return
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
foreach (var movie in jsonResponse.results)
|
||||
{
|
||||
// Movies with no Year Fix
|
||||
if (string.IsNullOrWhiteSpace(movie.release_date))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
movies.AddIfNotNull(_skyhookProxy.MapMovie(movie));
|
||||
}
|
||||
|
||||
return movies;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.List
|
||||
{
|
||||
public class TMDbListRequestGenerator : INetImportRequestGenerator
|
||||
{
|
||||
public TMDbListSettings Settings { get; set; }
|
||||
public IHttpClient HttpClient { get; set; }
|
||||
public IHttpRequestBuilderFactory RequestBuilder { get; set; }
|
||||
public Logger Logger { get; set; }
|
||||
|
||||
public TMDbListRequestGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual NetImportPageableRequestChain GetMovies()
|
||||
{
|
||||
var pageableRequests = new NetImportPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetMoviesRequest());
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMoviesRequest()
|
||||
{
|
||||
Logger.Info($"Importing TMDb movies from list: {Settings.ListId}");
|
||||
|
||||
var requestBuilder = RequestBuilder.Create()
|
||||
.SetSegment("api", "4")
|
||||
.SetSegment("route", "list")
|
||||
.SetSegment("id", Settings.ListId)
|
||||
.SetSegment("secondaryRoute", "");
|
||||
|
||||
yield return new NetImportRequest(requestBuilder.Accept(HttpAccept.Json)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
}
|
27
src/NzbDrone.Core/NetImport/TMDb/List/TMDbListSettings.cs
Normal file
27
src/NzbDrone.Core/NetImport/TMDb/List/TMDbListSettings.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.List
|
||||
{
|
||||
public class TMDbListSettingsValidator : TMDbSettingsBaseValidator<TMDbListSettings>
|
||||
{
|
||||
public TMDbListSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.ListId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class TMDbListSettings : TMDbSettingsBase<TMDbListSettings>
|
||||
{
|
||||
protected override AbstractValidator<TMDbListSettings> Validator => new TMDbListSettingsValidator();
|
||||
|
||||
public TMDbListSettings()
|
||||
{
|
||||
ListId = "";
|
||||
}
|
||||
|
||||
[FieldDefinition(1, Label = "ListId", Type = FieldType.Textbox, HelpText = "TMDb Id of List to Follow")]
|
||||
public string ListId { get; set; }
|
||||
}
|
||||
}
|
42
src/NzbDrone.Core/NetImport/TMDb/Person/TMDbPersonImport.cs
Normal file
42
src/NzbDrone.Core/NetImport/TMDb/Person/TMDbPersonImport.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Person
|
||||
{
|
||||
public class TMDbPersonImport : TMDbNetImportBase<TMDbPersonSettings>
|
||||
{
|
||||
public TMDbPersonImport(IRadarrCloudRequestBuilder requestBuilder,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
ISearchForNewMovie searchForNewMovie,
|
||||
Logger logger)
|
||||
: base(requestBuilder, httpClient, configService, parsingService, searchForNewMovie, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "TMDb Person";
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
public override IParseNetImportResponse GetParser()
|
||||
{
|
||||
return new TMDbPersonParser(Settings, _skyhookProxy);
|
||||
}
|
||||
|
||||
public override INetImportRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new TMDbPersonRequestGenerator()
|
||||
{
|
||||
RequestBuilder = _requestBuilder,
|
||||
Settings = Settings,
|
||||
Logger = _logger,
|
||||
HttpClient = _httpClient
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
102
src/NzbDrone.Core/NetImport/TMDb/Person/TMDbPersonParser.cs
Normal file
102
src/NzbDrone.Core/NetImport/TMDb/Person/TMDbPersonParser.cs
Normal file
@ -0,0 +1,102 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||
using NzbDrone.Core.Movies;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Person
|
||||
{
|
||||
public class TMDbPersonParser : TMDbParser
|
||||
{
|
||||
private readonly TMDbPersonSettings _settings;
|
||||
private readonly ISearchForNewMovie _skyhookProxy;
|
||||
|
||||
public TMDbPersonParser(TMDbPersonSettings settings, ISearchForNewMovie skyhookProxy)
|
||||
: base(skyhookProxy)
|
||||
{
|
||||
_settings = settings;
|
||||
_skyhookProxy = skyhookProxy;
|
||||
}
|
||||
|
||||
public override IList<Movie> ParseResponse(NetImportResponse importResponse)
|
||||
{
|
||||
var movies = new List<Movie>();
|
||||
|
||||
if (!PreProcess(importResponse))
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
var jsonResponse = JsonConvert.DeserializeObject<PersonCreditsRoot>(importResponse.Content);
|
||||
|
||||
// no movies were return
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
var crewTypes = GetCrewDepartments();
|
||||
|
||||
if (_settings.PersonCast)
|
||||
{
|
||||
foreach (var movie in jsonResponse.cast)
|
||||
{
|
||||
// Movies with no Year Fix
|
||||
if (string.IsNullOrWhiteSpace(movie.release_date))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
movies.AddIfNotNull(_skyhookProxy.MapMovie(movie));
|
||||
}
|
||||
}
|
||||
|
||||
if (crewTypes.Count > 0)
|
||||
{
|
||||
foreach (var movie in jsonResponse.crew)
|
||||
{
|
||||
// Movies with no Year Fix
|
||||
if (string.IsNullOrWhiteSpace(movie.release_date))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (crewTypes.Contains(movie.department))
|
||||
{
|
||||
movies.AddIfNotNull(_skyhookProxy.MapMovie(movie));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return movies;
|
||||
}
|
||||
|
||||
private List<string> GetCrewDepartments()
|
||||
{
|
||||
var creditsDepartment = new List<string>();
|
||||
|
||||
if (_settings.PersonCastDirector)
|
||||
{
|
||||
creditsDepartment.Add("Directing");
|
||||
}
|
||||
|
||||
if (_settings.PersonCastProducer)
|
||||
{
|
||||
creditsDepartment.Add("Production");
|
||||
}
|
||||
|
||||
if (_settings.PersonCastSound)
|
||||
{
|
||||
creditsDepartment.Add("Sound");
|
||||
}
|
||||
|
||||
if (_settings.PersonCastWriting)
|
||||
{
|
||||
creditsDepartment.Add("Writing");
|
||||
}
|
||||
|
||||
return creditsDepartment;
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Person
|
||||
{
|
||||
public class TMDbPersonRequestGenerator : INetImportRequestGenerator
|
||||
{
|
||||
public TMDbPersonSettings Settings { get; set; }
|
||||
public IHttpClient HttpClient { get; set; }
|
||||
public IHttpRequestBuilderFactory RequestBuilder { get; set; }
|
||||
public Logger Logger { get; set; }
|
||||
|
||||
public TMDbPersonRequestGenerator()
|
||||
{
|
||||
}
|
||||
|
||||
public virtual NetImportPageableRequestChain GetMovies()
|
||||
{
|
||||
var pageableRequests = new NetImportPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetMoviesRequest());
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMoviesRequest()
|
||||
{
|
||||
Logger.Info($"Importing TMDb movies from person: {Settings.PersonId}");
|
||||
|
||||
var requestBuilder = RequestBuilder.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "person")
|
||||
.SetSegment("id", Settings.PersonId)
|
||||
.SetSegment("secondaryRoute", "/movie_credits");
|
||||
|
||||
yield return new NetImportRequest(requestBuilder.Accept(HttpAccept.Json)
|
||||
.Build());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Person
|
||||
{
|
||||
public class TMDbPersonSettingsValidator : TMDbSettingsBaseValidator<TMDbPersonSettings>
|
||||
{
|
||||
public TMDbPersonSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.PersonId).Matches(@"^[1-9][0-9]*$", RegexOptions.IgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public class TMDbPersonSettings : TMDbSettingsBase<TMDbPersonSettings>
|
||||
{
|
||||
protected override AbstractValidator<TMDbPersonSettings> Validator => new TMDbPersonSettingsValidator();
|
||||
|
||||
public TMDbPersonSettings()
|
||||
{
|
||||
PersonId = "";
|
||||
}
|
||||
|
||||
[FieldDefinition(1, Label = "PersonId", Type = FieldType.Textbox, HelpText = "TMDb Id of Person to Follow")]
|
||||
public string PersonId { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "Person Cast", HelpText = "Select if you want to include Cast credits", Type = FieldType.Checkbox)]
|
||||
public bool PersonCast { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "Person Director Credits", HelpText = "Select if you want to include Director credits", Type = FieldType.Checkbox)]
|
||||
public bool PersonCastDirector { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Person Producer Credits", HelpText = "Select if you want to include Producer credits", Type = FieldType.Checkbox)]
|
||||
public bool PersonCastProducer { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Person Sound Credits", HelpText = "Select if you want to include Sound credits", Type = FieldType.Checkbox)]
|
||||
public bool PersonCastSound { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Person Writing Credits", HelpText = "Select if you want to include Writing credits", Type = FieldType.Checkbox)]
|
||||
public bool PersonCastWriting { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Popular
|
||||
{
|
||||
public class TMDbPopularImport : TMDbNetImportBase<TMDbPopularSettings>
|
||||
{
|
||||
public TMDbPopularImport(IRadarrCloudRequestBuilder requestBuilder,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
ISearchForNewMovie searchForNewMovie,
|
||||
Logger logger)
|
||||
: base(requestBuilder, httpClient, configService, parsingService, searchForNewMovie, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "TMDb Popular";
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
public override IParseNetImportResponse GetParser()
|
||||
{
|
||||
return new TMDbParser(_skyhookProxy);
|
||||
}
|
||||
|
||||
public override INetImportRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new TMDbPopularRequestGenerator()
|
||||
{
|
||||
RequestBuilder = _requestBuilder,
|
||||
Settings = Settings,
|
||||
Logger = _logger,
|
||||
HttpClient = _httpClient
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,9 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Popular
|
||||
{
|
||||
public enum TMDbListType
|
||||
public enum TMDbPopularListType
|
||||
{
|
||||
[EnumMember(Value = "List")]
|
||||
List = 0,
|
||||
[EnumMember(Value = "In Theaters")]
|
||||
Theaters = 1,
|
||||
[EnumMember(Value = "Popular")]
|
@ -0,0 +1,93 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Popular
|
||||
{
|
||||
public class TMDbPopularRequestGenerator : INetImportRequestGenerator
|
||||
{
|
||||
public TMDbPopularSettings Settings { get; set; }
|
||||
public IHttpClient HttpClient { get; set; }
|
||||
public IHttpRequestBuilderFactory RequestBuilder { get; set; }
|
||||
public Logger Logger { get; set; }
|
||||
|
||||
public int MaxPages { get; set; }
|
||||
|
||||
public TMDbPopularRequestGenerator()
|
||||
{
|
||||
MaxPages = 3;
|
||||
}
|
||||
|
||||
public virtual NetImportPageableRequestChain GetMovies()
|
||||
{
|
||||
var pageableRequests = new NetImportPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetMoviesRequests());
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMoviesRequests()
|
||||
{
|
||||
var minVoteCount = Settings.FilterCriteria.MinVotes;
|
||||
var minVoteAverage = Settings.FilterCriteria.MinVoteAverage;
|
||||
var ceritification = Settings.FilterCriteria.Ceritification;
|
||||
var includeGenreIds = Settings.FilterCriteria.IncludeGenreIds;
|
||||
var excludeGenreIds = Settings.FilterCriteria.ExcludeGenreIds;
|
||||
var languageCode = (TMDbLanguageCodes)Settings.FilterCriteria.LanguageCode;
|
||||
|
||||
var todaysDate = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
var threeMonthsAgo = DateTime.Parse(todaysDate).AddMonths(-3).ToString("yyyy-MM-dd");
|
||||
var threeMonthsFromNow = DateTime.Parse(todaysDate).AddMonths(3).ToString("yyyy-MM-dd");
|
||||
|
||||
var requestBuilder = RequestBuilder.Create()
|
||||
.SetSegment("api", "3")
|
||||
.SetSegment("route", "discover")
|
||||
.SetSegment("id", "")
|
||||
.SetSegment("secondaryRoute", "movie");
|
||||
|
||||
switch (Settings.ListType)
|
||||
{
|
||||
case (int)TMDbPopularListType.Theaters:
|
||||
requestBuilder.AddQueryParam("primary_release.gte", threeMonthsAgo)
|
||||
.AddQueryParam("primary_release_date.lte", todaysDate);
|
||||
break;
|
||||
case (int)TMDbPopularListType.Popular:
|
||||
requestBuilder.AddQueryParam("sort_by", "popularity.desc");
|
||||
break;
|
||||
case (int)TMDbPopularListType.Top:
|
||||
requestBuilder.AddQueryParam("sort_by", "vote_average.desc");
|
||||
break;
|
||||
case (int)TMDbPopularListType.Upcoming:
|
||||
requestBuilder.AddQueryParam("primary_release.gte", todaysDate)
|
||||
.AddQueryParam("primary_release_date.lte", threeMonthsFromNow);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ceritification.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.AddQueryParam("certification", ceritification)
|
||||
.AddQueryParam("certification_country", "US");
|
||||
}
|
||||
|
||||
requestBuilder
|
||||
.AddQueryParam("vote_count.gte", minVoteCount)
|
||||
.AddQueryParam("vote_average.gte", minVoteAverage)
|
||||
.AddQueryParam("with_genres", includeGenreIds)
|
||||
.AddQueryParam("without_genres", excludeGenreIds)
|
||||
.AddQueryParam("with_original_language", languageCode)
|
||||
.Accept(HttpAccept.Json);
|
||||
|
||||
for (var pageNumber = 1; pageNumber <= MaxPages; pageNumber++)
|
||||
{
|
||||
Logger.Info($"Importing TMDb movies from: {requestBuilder.BaseUrl}&page={pageNumber}");
|
||||
|
||||
requestBuilder.AddQueryParam("page", pageNumber, true);
|
||||
|
||||
yield return new NetImportRequest(requestBuilder.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.Popular
|
||||
{
|
||||
public class TMDbPopularSettingsValidator : TMDbSettingsBaseValidator<TMDbPopularSettings>
|
||||
{
|
||||
public TMDbPopularSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.ListType).NotEmpty();
|
||||
|
||||
RuleFor(c => c.FilterCriteria).SetValidator(_ => new TMDbFilterSettingsValidator());
|
||||
}
|
||||
}
|
||||
|
||||
public class TMDbPopularSettings : TMDbSettingsBase<TMDbPopularSettings>
|
||||
{
|
||||
protected override AbstractValidator<TMDbPopularSettings> Validator => new TMDbPopularSettingsValidator();
|
||||
|
||||
public TMDbPopularSettings()
|
||||
{
|
||||
ListType = (int)TMDbPopularListType.Popular;
|
||||
}
|
||||
|
||||
[FieldDefinition(1, Label = "List Type", Type = FieldType.Select, SelectOptions = typeof(TMDbPopularListType), HelpText = "Type of list your seeking to import from")]
|
||||
public int ListType { get; set; }
|
||||
|
||||
[FieldDefinition(2)]
|
||||
public TMDbFilterSettings FilterCriteria { get; } = new TMDbFilterSettings();
|
||||
}
|
||||
}
|
73
src/NzbDrone.Core/NetImport/TMDb/TMDbFilterSettings.cs
Normal file
73
src/NzbDrone.Core/NetImport/TMDb/TMDbFilterSettings.cs
Normal file
@ -0,0 +1,73 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb
|
||||
{
|
||||
public class TMDbFilterSettingsValidator : AbstractValidator<TMDbFilterSettings>
|
||||
{
|
||||
public TMDbFilterSettingsValidator()
|
||||
{
|
||||
// Range 0.0 - 10.0
|
||||
RuleFor(c => c.MinVoteAverage)
|
||||
.Matches(@"^(?!0\d)\d*(\.\d{1})?$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.MinVoteAverage.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Minimum vote average must be between 0 and 10");
|
||||
|
||||
// Greater than 0
|
||||
RuleFor(c => c.MinVotes)
|
||||
.Matches(@"^[1-9][0-9]*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.MinVotes.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Minimum votes must be greater than 0");
|
||||
|
||||
// Any valid certification
|
||||
RuleFor(c => c.Ceritification)
|
||||
.Matches(@"^\bNR\b|\bG\b|\bPG\b|\bPG\-13\b|\bR\b|\bNC\-17\b$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.Ceritification.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Not a valid certification");
|
||||
|
||||
// CSV of numbers
|
||||
RuleFor(c => c.IncludeGenreIds)
|
||||
.Matches(@"^\d+([,|]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.IncludeGenreIds.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Genre Ids must be comma (,) or pipe (|) separated number ids");
|
||||
|
||||
// CSV of numbers
|
||||
RuleFor(c => c.ExcludeGenreIds)
|
||||
.Matches(@"^\d+([,|]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.ExcludeGenreIds.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Genre Ids must be comma (,) or pipe (|) separated number ids");
|
||||
}
|
||||
}
|
||||
|
||||
public class TMDbFilterSettings
|
||||
{
|
||||
public TMDbFilterSettings()
|
||||
{
|
||||
MinVoteAverage = "5";
|
||||
MinVotes = "1";
|
||||
LanguageCode = (int)TMDbLanguageCodes.en;
|
||||
ExcludeGenreIds = "";
|
||||
IncludeGenreIds = "";
|
||||
}
|
||||
|
||||
[FieldDefinition(1, Label = "Minimum Vote Average", HelpText = "Filter movies by votes (0.0-10.0)")]
|
||||
public string MinVoteAverage { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "Minimum Number of Votes", HelpText = "Filter movies by number of votes")]
|
||||
public string MinVotes { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "Certification", HelpText = "Filter movies by a single ceritification (NR,G,PG,PG-13,R,NC-17)")]
|
||||
public string Ceritification { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Include Genre Ids", HelpText = "Filter movies by TMDb Genre Ids (Comma Separated)")]
|
||||
public string IncludeGenreIds { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Exclude Genre Ids", HelpText = "Filter movies by TMDb Genre Ids (Comma Separated)")]
|
||||
public string ExcludeGenreIds { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Original Language", Type = FieldType.Select, SelectOptions = typeof(TMDbLanguageCodes), HelpText = "Filter by Language")]
|
||||
public int LanguageCode { get; set; }
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb
|
||||
{
|
||||
public class TMDbImport : HttpNetImportBase<TMDbSettings>
|
||||
{
|
||||
public override string Name => "TMDb Lists";
|
||||
|
||||
public override NetImportType ListType => NetImportType.TMDB;
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
private readonly ISearchForNewMovie _skyhookProxy;
|
||||
|
||||
public TMDbImport(IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
ISearchForNewMovie skyhookProxy,
|
||||
Logger logger)
|
||||
: base(httpClient, configService, parsingService, logger)
|
||||
{
|
||||
_skyhookProxy = skyhookProxy;
|
||||
}
|
||||
|
||||
public override INetImportRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new TMDbRequestGenerator()
|
||||
{
|
||||
Settings = Settings,
|
||||
Logger = _logger,
|
||||
HttpClient = _httpClient
|
||||
};
|
||||
}
|
||||
|
||||
public override IParseNetImportResponse GetParser()
|
||||
{
|
||||
return new TMDbParser(Settings, _skyhookProxy);
|
||||
}
|
||||
}
|
||||
}
|
30
src/NzbDrone.Core/NetImport/TMDb/TMDbImportBase.cs
Normal file
30
src/NzbDrone.Core/NetImport/TMDb/TMDbImportBase.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb
|
||||
{
|
||||
public abstract class TMDbNetImportBase<TSettings> : HttpNetImportBase<TSettings>
|
||||
where TSettings : TMDbSettingsBase<TSettings>, new()
|
||||
{
|
||||
public override NetImportType ListType => NetImportType.TMDB;
|
||||
|
||||
public readonly ISearchForNewMovie _skyhookProxy;
|
||||
public readonly IHttpRequestBuilderFactory _requestBuilder;
|
||||
|
||||
protected TMDbNetImportBase(IRadarrCloudRequestBuilder requestBuilder,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
ISearchForNewMovie skyhookProxy,
|
||||
Logger logger)
|
||||
: base(httpClient, configService, parsingService, logger)
|
||||
{
|
||||
_skyhookProxy = skyhookProxy;
|
||||
_requestBuilder = requestBuilder.TMDB;
|
||||
}
|
||||
}
|
||||
}
|
@ -4,87 +4,56 @@
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||
using NzbDrone.Core.Movies;
|
||||
using NzbDrone.Core.NetImport.Exceptions;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb
|
||||
{
|
||||
public class TMDbParser : IParseNetImportResponse
|
||||
{
|
||||
private readonly TMDbSettings _settings;
|
||||
private readonly ISearchForNewMovie _skyhookProxy;
|
||||
private NetImportResponse _importResponse;
|
||||
|
||||
public TMDbParser(TMDbSettings settings, ISearchForNewMovie skyhookProxy)
|
||||
public TMDbParser(ISearchForNewMovie skyhookProxy)
|
||||
{
|
||||
_skyhookProxy = skyhookProxy;
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public IList<Movies.Movie> ParseResponse(NetImportResponse importResponse)
|
||||
public virtual IList<Movie> ParseResponse(NetImportResponse importResponse)
|
||||
{
|
||||
_importResponse = importResponse;
|
||||
var movies = new List<Movie>();
|
||||
|
||||
var movies = new List<Movies.Movie>();
|
||||
|
||||
if (!PreProcess(_importResponse))
|
||||
if (!PreProcess(importResponse))
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
if (_settings.ListType != (int)TMDbListType.List)
|
||||
var jsonResponse = JsonConvert.DeserializeObject<MovieSearchRoot>(importResponse.Content);
|
||||
|
||||
// no movies were return
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
var jsonResponse = JsonConvert.DeserializeObject<MovieSearchRoot>(_importResponse.Content);
|
||||
|
||||
// no movies were return
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
return jsonResponse.results.SelectList(_skyhookProxy.MapMovie);
|
||||
}
|
||||
else
|
||||
{
|
||||
var jsonResponse = JsonConvert.DeserializeObject<ListResponseRoot>(_importResponse.Content);
|
||||
|
||||
// no movies were return
|
||||
if (jsonResponse == null)
|
||||
{
|
||||
return movies;
|
||||
}
|
||||
|
||||
foreach (var movie in jsonResponse.items)
|
||||
{
|
||||
// Skip non-movie things
|
||||
if (movie.media_type != "movie")
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Movies with no Year Fix
|
||||
if (string.IsNullOrWhiteSpace(movie.release_date))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
movies.AddIfNotNull(_skyhookProxy.MapMovie(movie));
|
||||
}
|
||||
return movies;
|
||||
}
|
||||
|
||||
return movies;
|
||||
return jsonResponse.results.SelectList(_skyhookProxy.MapMovie);
|
||||
}
|
||||
|
||||
protected virtual bool PreProcess(NetImportResponse indexerResponse)
|
||||
protected virtual bool PreProcess(NetImportResponse listResponse)
|
||||
{
|
||||
if (indexerResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
if (listResponse.HttpResponse.StatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
throw new NetImportException(indexerResponse, "Indexer API call resulted in an unexpected StatusCode [{0}]", indexerResponse.HttpResponse.StatusCode);
|
||||
throw new NetImportException(listResponse,
|
||||
"TMDb API call resulted in an unexpected StatusCode [{0}]",
|
||||
listResponse.HttpResponse.StatusCode);
|
||||
}
|
||||
|
||||
if (indexerResponse.HttpResponse.Headers.ContentType != null && indexerResponse.HttpResponse.Headers.ContentType.Contains("text/json") &&
|
||||
indexerResponse.HttpRequest.Headers.Accept != null && !indexerResponse.HttpRequest.Headers.Accept.Contains("text/json"))
|
||||
if (listResponse.HttpResponse.Headers.ContentType != null &&
|
||||
listResponse.HttpResponse.Headers.ContentType.Contains("text/json") &&
|
||||
listResponse.HttpRequest.Headers.Accept != null &&
|
||||
!listResponse.HttpRequest.Headers.Accept.Contains("text/json"))
|
||||
{
|
||||
throw new NetImportException(indexerResponse, "Indexer responded with html content. Site is likely blocked or unavailable.");
|
||||
throw new NetImportException(listResponse,
|
||||
"TMDb responded with html content. Site is likely blocked or unavailable.");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1,118 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb
|
||||
{
|
||||
public class TMDbRequestGenerator : INetImportRequestGenerator
|
||||
{
|
||||
public TMDbSettings Settings { get; set; }
|
||||
public IHttpClient HttpClient { get; set; }
|
||||
public Logger Logger { get; set; }
|
||||
|
||||
public int MaxPages { get; set; }
|
||||
|
||||
public TMDbRequestGenerator()
|
||||
{
|
||||
MaxPages = 3;
|
||||
}
|
||||
|
||||
public virtual NetImportPageableRequestChain GetMovies()
|
||||
{
|
||||
var minVoteCount = Settings.MinVotes;
|
||||
var minVoteAverage = Settings.MinVoteAverage;
|
||||
var ceritification = Settings.Ceritification;
|
||||
var includeGenreIds = Settings.IncludeGenreIds;
|
||||
var excludeGenreIds = Settings.ExcludeGenreIds;
|
||||
var languageCode = (TMDbLanguageCodes)Settings.LanguageCode;
|
||||
|
||||
var todaysDate = DateTime.Now.ToString("yyyy-MM-dd");
|
||||
var threeMonthsAgo = DateTime.Parse(todaysDate).AddMonths(-3).ToString("yyyy-MM-dd");
|
||||
var threeMonthsFromNow = DateTime.Parse(todaysDate).AddMonths(3).ToString("yyyy-MM-dd");
|
||||
|
||||
if (ceritification.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
ceritification = $"&certification_country=US&certification={ceritification}";
|
||||
}
|
||||
|
||||
var tmdbParams = "";
|
||||
switch (Settings.ListType)
|
||||
{
|
||||
case (int)TMDbListType.List:
|
||||
tmdbParams = $"/3/list/{Settings.ListId}?api_key=1a7373301961d03f97f853a876dd1212";
|
||||
break;
|
||||
case (int)TMDbListType.Theaters:
|
||||
tmdbParams = $"/3/discover/movie?api_key=1a7373301961d03f97f853a876dd1212&primary_release_date.gte={threeMonthsAgo}&primary_release_date.lte={todaysDate}&vote_count.gte={minVoteCount}&vote_average.gte={minVoteAverage}{ceritification}&with_genres={includeGenreIds}&without_genres={excludeGenreIds}&with_original_language={languageCode}";
|
||||
break;
|
||||
case (int)TMDbListType.Popular:
|
||||
tmdbParams = $"/3/discover/movie?api_key=1a7373301961d03f97f853a876dd1212&sort_by=popularity.desc&vote_count.gte={minVoteCount}&vote_average.gte={minVoteAverage}{ceritification}&with_genres={includeGenreIds}&without_genres={excludeGenreIds}&with_original_language={languageCode}";
|
||||
break;
|
||||
case (int)TMDbListType.Top:
|
||||
tmdbParams = $"/3/discover/movie?api_key=1a7373301961d03f97f853a876dd1212&sort_by=vote_average.desc&vote_count.gte={minVoteCount}&vote_average.gte={minVoteAverage}{ceritification}&with_genres={includeGenreIds}&without_genres={excludeGenreIds}&with_original_language={languageCode}";
|
||||
break;
|
||||
case (int)TMDbListType.Upcoming:
|
||||
tmdbParams = $"/3/discover/movie?api_key=1a7373301961d03f97f853a876dd1212&primary_release_date.gte={todaysDate}&primary_release_date.lte={threeMonthsFromNow}&vote_count.gte={minVoteCount}&vote_average.gte={minVoteAverage}{ceritification}&with_genres={includeGenreIds}&without_genres={excludeGenreIds}&with_original_language={languageCode}";
|
||||
break;
|
||||
}
|
||||
|
||||
var pageableRequests = new NetImportPageableRequestChain();
|
||||
if (Settings.ListType != (int)TMDbListType.List)
|
||||
{
|
||||
// First query to get the total_Pages
|
||||
var requestBuilder = new HttpRequestBuilder($"{Settings.Link.TrimEnd("/")}")
|
||||
{
|
||||
LogResponseContent = true
|
||||
};
|
||||
|
||||
requestBuilder.Method = HttpMethod.GET;
|
||||
requestBuilder.Resource(tmdbParams);
|
||||
|
||||
var request = requestBuilder
|
||||
|
||||
// .AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
|
||||
.Accept(HttpAccept.Json)
|
||||
.Build();
|
||||
|
||||
var response = HttpClient.Execute(request);
|
||||
var result = Json.Deserialize<MovieSearchRoot>(response.Content);
|
||||
|
||||
// @TODO Prolly some error handling to do here
|
||||
pageableRequests.Add(GetMovies(tmdbParams, result.total_pages));
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
pageableRequests.Add(GetMovies(tmdbParams, 0));
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMovies(string tmdbParams, int totalPages)
|
||||
{
|
||||
var baseUrl = $"{Settings.Link.TrimEnd("/")}{tmdbParams}";
|
||||
if (Settings.ListType != (int)TMDbListType.List)
|
||||
{
|
||||
for (var pageNumber = 1; pageNumber <= totalPages; pageNumber++)
|
||||
{
|
||||
// Limit the amount of pages
|
||||
if (pageNumber >= MaxPages + 1)
|
||||
{
|
||||
Logger.Info(
|
||||
$"Found more than {MaxPages} pages, skipping the {totalPages - (MaxPages + 1)} remaining pages");
|
||||
break;
|
||||
}
|
||||
|
||||
Logger.Info($"Importing TMDb movies from: {baseUrl}&page={pageNumber}");
|
||||
yield return new NetImportRequest($"{baseUrl}&page={pageNumber}", HttpAccept.Json);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Info($"Importing TMDb movies from: {baseUrl}");
|
||||
yield return new NetImportRequest($"{baseUrl}", HttpAccept.Json);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,99 +1,28 @@
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.ThingiProvider;
|
||||
using NzbDrone.Core.Validation;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb
|
||||
{
|
||||
public class TMDbSettingsValidator : AbstractValidator<TMDbSettings>
|
||||
public class TMDbSettingsBaseValidator<TSettings> : AbstractValidator<TSettings>
|
||||
where TSettings : TMDbSettingsBase<TSettings>
|
||||
{
|
||||
public TMDbSettingsValidator()
|
||||
public TMDbSettingsBaseValidator()
|
||||
{
|
||||
RuleFor(c => c.Link).ValidRootUrl();
|
||||
|
||||
// Greater than 0
|
||||
RuleFor(c => c.ListId)
|
||||
.Matches(@"^[1-9][0-9]*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.ListType == (int)TMDbListType.List)
|
||||
.WithMessage("List Id is required when using TMDb Lists");
|
||||
|
||||
// Range 0.0 - 10.0
|
||||
RuleFor(c => c.MinVoteAverage)
|
||||
.Matches(@"^(?!0\d)\d*(\.\d{1})?$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.MinVoteAverage.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Minimum vote average must be between 0 and 10");
|
||||
|
||||
// Greater than 0
|
||||
RuleFor(c => c.MinVotes)
|
||||
.Matches(@"^[1-9][0-9]*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.MinVotes.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Minimum votes must be greater than 0");
|
||||
|
||||
// Any valid certification
|
||||
RuleFor(c => c.Ceritification)
|
||||
.Matches(@"^\bNR\b|\bG\b|\bPG\b|\bPG\-13\b|\bR\b|\bNC\-17\b$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.Ceritification.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Not a valid certification");
|
||||
|
||||
// CSV of numbers
|
||||
RuleFor(c => c.IncludeGenreIds)
|
||||
.Matches(@"^\d+([,|]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.IncludeGenreIds.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Genre Ids must be comma (,) or pipe (|) separated number ids");
|
||||
|
||||
// CSV of numbers
|
||||
RuleFor(c => c.ExcludeGenreIds)
|
||||
.Matches(@"^\d+([,|]\d+)*$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.ExcludeGenreIds.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Genre Ids must be comma (,) or pipe (|) separated number ids");
|
||||
}
|
||||
}
|
||||
|
||||
public class TMDbSettings : IProviderConfig
|
||||
public class TMDbSettingsBase<TSettings> : IProviderConfig
|
||||
where TSettings : TMDbSettingsBase<TSettings>
|
||||
{
|
||||
private static readonly TMDbSettingsValidator Validator = new TMDbSettingsValidator();
|
||||
|
||||
public TMDbSettings()
|
||||
protected virtual AbstractValidator<TSettings> Validator => new TMDbSettingsBaseValidator<TSettings>();
|
||||
public TMDbSettingsBase()
|
||||
{
|
||||
Link = "https://api.themoviedb.org";
|
||||
ListType = (int)TMDbListType.Popular;
|
||||
MinVoteAverage = "5";
|
||||
MinVotes = "1";
|
||||
LanguageCode = (int)TMDbLanguageCodes.en;
|
||||
}
|
||||
|
||||
[FieldDefinition(0, Label = "TMDb API URL", HelpText = "Link to to TMDb API URL, do not change unless you know what you are doing.")]
|
||||
public string Link { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "List Type", Type = FieldType.Select, SelectOptions = typeof(TMDbListType), HelpText = "Type of list your seeking to import from")]
|
||||
public int ListType { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "Public List ID", HelpText = "Required for List (Ignores Filtering Options)")]
|
||||
public string ListId { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "Minimum Vote Average", HelpText = "Filter movies by votes (0.0-10.0)")]
|
||||
public string MinVoteAverage { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "Minimum Number of Votes", HelpText = "Filter movies by number of votes")]
|
||||
public string MinVotes { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "Certification", HelpText = "Filter movies by a single ceritification (NR,G,PG,PG-13,R,NC-17)")]
|
||||
public string Ceritification { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "Include Genre Ids", HelpText = "Filter movies by TMDb Genre Ids (Comma Separated)")]
|
||||
public string IncludeGenreIds { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "Exclude Genre Ids", HelpText = "Filter movies by TMDb Genre Ids (Comma Separated)")]
|
||||
public string ExcludeGenreIds { get; set; }
|
||||
|
||||
[FieldDefinition(8, Label = "Original Language", Type = FieldType.Select, SelectOptions = typeof(TMDbLanguageCodes), HelpText = "Filter by Language")]
|
||||
public int LanguageCode { get; set; }
|
||||
|
||||
public NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
return new NzbDroneValidationResult(Validator.Validate((TSettings)this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
97
src/NzbDrone.Core/NetImport/TMDb/User/TMDbUserImport.cs
Normal file
97
src/NzbDrone.Core/NetImport/TMDb/User/TMDbUserImport.cs
Normal file
@ -0,0 +1,97 @@
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cloud;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Common.Serializer;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.MetadataSource.SkyHook.Resource;
|
||||
using NzbDrone.Core.Parser;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.User
|
||||
{
|
||||
public class TMDbUserImport : TMDbNetImportBase<TMDbUserSettings>
|
||||
{
|
||||
public TMDbUserImport(IRadarrCloudRequestBuilder requestBuilder,
|
||||
IHttpClient httpClient,
|
||||
IConfigService configService,
|
||||
IParsingService parsingService,
|
||||
ISearchForNewMovie searchForNewMovie,
|
||||
Logger logger)
|
||||
: base(requestBuilder, httpClient, configService, parsingService, searchForNewMovie, logger)
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => "TMDb User";
|
||||
public override bool Enabled => true;
|
||||
public override bool EnableAuto => false;
|
||||
|
||||
public override IParseNetImportResponse GetParser()
|
||||
{
|
||||
return new TMDbParser(_skyhookProxy);
|
||||
}
|
||||
|
||||
public override INetImportRequestGenerator GetRequestGenerator()
|
||||
{
|
||||
return new TMDbUserRequestGenerator()
|
||||
{
|
||||
RequestBuilder = _requestBuilder,
|
||||
Settings = Settings,
|
||||
Logger = _logger,
|
||||
HttpClient = _httpClient
|
||||
};
|
||||
}
|
||||
|
||||
public override object RequestAction(string action, IDictionary<string, string> query)
|
||||
{
|
||||
if (action == "startOAuth")
|
||||
{
|
||||
var requestBuilder = _requestBuilder.Create()
|
||||
.SetSegment("api", "4")
|
||||
.SetSegment("route", "auth")
|
||||
.SetSegment("id", "")
|
||||
.SetSegment("secondaryRoute", "request_token")
|
||||
.AddQueryParam("redirect_to", query["callbackUrl"]);
|
||||
|
||||
requestBuilder.Method = HttpMethod.POST;
|
||||
|
||||
var request = requestBuilder.Build();
|
||||
|
||||
var response = Json.Deserialize<AuthRefreshTokenResponse>(_httpClient.Execute(request).Content);
|
||||
|
||||
var oAuthRequest = new HttpRequestBuilder(Settings.OAuthUrl)
|
||||
.AddQueryParam("request_token", response.request_token)
|
||||
.Build();
|
||||
|
||||
return new
|
||||
{
|
||||
OauthUrl = oAuthRequest.Url.ToString(),
|
||||
RequestToken = response.request_token
|
||||
};
|
||||
}
|
||||
else if (action == "getOAuthToken")
|
||||
{
|
||||
var requestBuilder = _requestBuilder.Create()
|
||||
.SetSegment("api", "4")
|
||||
.SetSegment("route", "auth")
|
||||
.SetSegment("id", "")
|
||||
.SetSegment("secondaryRoute", "access_token")
|
||||
.AddQueryParam("request_token", query["requestToken"]);
|
||||
|
||||
requestBuilder.Method = HttpMethod.POST;
|
||||
|
||||
var request = requestBuilder.Build();
|
||||
|
||||
var response = Json.Deserialize<AuthAccessTokenResponse>(_httpClient.Execute(request).Content);
|
||||
|
||||
return new
|
||||
{
|
||||
accountId = response.account_id,
|
||||
accessToken = response.access_token,
|
||||
};
|
||||
}
|
||||
|
||||
return new { };
|
||||
}
|
||||
}
|
||||
}
|
16
src/NzbDrone.Core/NetImport/TMDb/User/TMDbUserListType.cs
Normal file
16
src/NzbDrone.Core/NetImport/TMDb/User/TMDbUserListType.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.User
|
||||
{
|
||||
public enum TMDbUserListType
|
||||
{
|
||||
[EnumMember(Value = "Watchlist")]
|
||||
Watchlist = 1,
|
||||
[EnumMember(Value = "Recommendations")]
|
||||
Recommendations = 2,
|
||||
[EnumMember(Value = "Rated")]
|
||||
Rated = 3,
|
||||
[EnumMember(Value = "Favorite")]
|
||||
Favorite = 4
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Http;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.User
|
||||
{
|
||||
public class TMDbUserRequestGenerator : INetImportRequestGenerator
|
||||
{
|
||||
public TMDbUserSettings Settings { get; set; }
|
||||
public IHttpClient HttpClient { get; set; }
|
||||
public IHttpRequestBuilderFactory RequestBuilder { get; set; }
|
||||
public Logger Logger { get; set; }
|
||||
|
||||
public int MaxPages { get; set; }
|
||||
|
||||
public TMDbUserRequestGenerator()
|
||||
{
|
||||
MaxPages = 3;
|
||||
}
|
||||
|
||||
public virtual NetImportPageableRequestChain GetMovies()
|
||||
{
|
||||
var pageableRequests = new NetImportPageableRequestChain();
|
||||
|
||||
pageableRequests.Add(GetMoviesRequests());
|
||||
|
||||
return pageableRequests;
|
||||
}
|
||||
|
||||
private IEnumerable<NetImportRequest> GetMoviesRequests()
|
||||
{
|
||||
var requestBuilder = RequestBuilder.Create()
|
||||
.SetHeader("Authorization", $"Bearer {Settings.AccessToken}")
|
||||
.SetSegment("api", "4")
|
||||
.SetSegment("route", "account")
|
||||
.SetSegment("id", Settings.AccountId);
|
||||
|
||||
switch (Settings.ListType)
|
||||
{
|
||||
case (int)TMDbUserListType.Watchlist:
|
||||
requestBuilder.SetSegment("secondaryRoute", "/movie/watchlist");
|
||||
break;
|
||||
case (int)TMDbUserListType.Recommendations:
|
||||
requestBuilder.SetSegment("secondaryRoute", "/movie/recommendations");
|
||||
break;
|
||||
case (int)TMDbUserListType.Rated:
|
||||
requestBuilder.SetSegment("secondaryRoute", "/movie/rated");
|
||||
break;
|
||||
case (int)TMDbUserListType.Favorite:
|
||||
requestBuilder.SetSegment("secondaryRoute", "/movie/favorites");
|
||||
break;
|
||||
}
|
||||
|
||||
requestBuilder.Accept(HttpAccept.Json);
|
||||
|
||||
requestBuilder.Method = HttpMethod.GET;
|
||||
|
||||
yield return new NetImportRequest(requestBuilder.Build());
|
||||
}
|
||||
}
|
||||
}
|
40
src/NzbDrone.Core/NetImport/TMDb/User/TMDbUserSettings.cs
Normal file
40
src/NzbDrone.Core/NetImport/TMDb/User/TMDbUserSettings.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using FluentValidation;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
||||
namespace NzbDrone.Core.NetImport.TMDb.User
|
||||
{
|
||||
public class TMDbUserSettingsValidator : TMDbSettingsBaseValidator<TMDbUserSettings>
|
||||
{
|
||||
public TMDbUserSettingsValidator()
|
||||
: base()
|
||||
{
|
||||
RuleFor(c => c.ListType).NotEmpty();
|
||||
RuleFor(c => c.AccessToken).NotEmpty();
|
||||
RuleFor(c => c.AccountId).NotEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
public class TMDbUserSettings : TMDbSettingsBase<TMDbUserSettings>
|
||||
{
|
||||
protected override AbstractValidator<TMDbUserSettings> Validator => new TMDbUserSettingsValidator();
|
||||
|
||||
public TMDbUserSettings()
|
||||
{
|
||||
ListType = (int)TMDbUserListType.Watchlist;
|
||||
}
|
||||
|
||||
public string OAuthUrl => "https://www.themoviedb.org/auth/access";
|
||||
|
||||
[FieldDefinition(0, Label = "Account Id", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||
public string AccountId { get; set; }
|
||||
|
||||
[FieldDefinition(0, Label = "Access Token", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
[FieldDefinition(1, Label = "List Type", Type = FieldType.Select, SelectOptions = typeof(TMDbUserListType), HelpText = "Type of list your seeking to import from")]
|
||||
public int ListType { get; set; }
|
||||
|
||||
[FieldDefinition(99, Label = "Authenticate with TMDB", Type = FieldType.OAuth)]
|
||||
public string SignIn { get; set; }
|
||||
}
|
||||
}
|
@ -28,17 +28,17 @@
|
||||
<Reference Include="System.Web.Extensions" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<RuntimeFiles Include="..\Runtimes\$(RuntimeIdentifier)\*"/>
|
||||
<RuntimeFiles Include="..\Runtimes\$(RuntimeIdentifier)\*" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="..\..\Logo\64.png">
|
||||
<Link>Resources\Logo\64.png</Link>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
<Target Name="CopyRuntimeFilesOnBuild" AfterTargets="AfterBuild" >
|
||||
<Target Name="CopyRuntimeFilesOnBuild" AfterTargets="AfterBuild">
|
||||
<Copy SourceFiles="@(RuntimeFiles)" DestinationFolder="$(OutDir)" />
|
||||
</Target>
|
||||
<Target Name="CopyRuntimeFilesOnPublish" AfterTargets="Publish" >
|
||||
<Target Name="CopyRuntimeFilesOnPublish" AfterTargets="Publish">
|
||||
<Copy SourceFiles="@(RuntimeFiles)" DestinationFolder="$(PublishDir)" />
|
||||
</Target>
|
||||
</Project>
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using NzbDrone.Core.Movies;
|
||||
@ -30,7 +31,12 @@ private object Search()
|
||||
|
||||
foreach (var movie in results)
|
||||
{
|
||||
var mapped = _movieSearch.MapMovieToTmdbMovie(movie);
|
||||
var mapped = movie;
|
||||
|
||||
if (movie.TmdbId == 0 || !movie.Images.Any() || movie.Overview.IsNullOrWhiteSpace())
|
||||
{
|
||||
mapped = _movieSearch.MapMovieToTmdbMovie(movie);
|
||||
}
|
||||
|
||||
if (mapped != null)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user