1
0
Fork 0
mirror of https://github.com/Radarr/Radarr synced 2024-12-21 23:42:23 +00:00

New: Filters for TMDb Person lists

This commit is contained in:
Bogdan 2024-09-17 00:21:29 +03:00
parent fabd40cbae
commit e54eda905b
11 changed files with 218 additions and 63 deletions

View file

@ -1,29 +1,29 @@
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.TMDb.Company
{
public class TMDbCompanyImport : TMDbImportListBase<TMDbCompanySettings>
{
public override string Name => "TMDb Company";
public override bool Enabled => true;
public override bool EnableAuto => false;
public TMDbCompanyImport(IRadarrCloudRequestBuilder requestBuilder,
IHttpClient httpClient,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie searchForNewMovie,
ICacheManager cacheManager,
Logger logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, searchForNewMovie, logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, cacheManager, logger)
{
}
public override string Name => "TMDb Company";
public override bool Enabled => true;
public override bool EnableAuto => false;
public override IParseImportListResponse GetParser()
{
return new TMDbCompanyParser();
@ -31,7 +31,7 @@ public override IParseImportListResponse GetParser()
public override IImportListRequestGenerator GetRequestGenerator()
{
return new TMDbCompanyRequestGenerator()
return new TMDbCompanyRequestGenerator
{
RequestBuilder = _requestBuilder,
Settings = Settings,

View file

@ -1,29 +1,29 @@
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.TMDb.Keyword
{
public class TMDbKeywordImport : TMDbImportListBase<TMDbKeywordSettings>
{
public override string Name => "TMDb Keyword";
public override bool Enabled => true;
public override bool EnableAuto => false;
public TMDbKeywordImport(IRadarrCloudRequestBuilder requestBuilder,
IHttpClient httpClient,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie searchForNewMovie,
ICacheManager cacheManager,
Logger logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, searchForNewMovie, logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, cacheManager, logger)
{
}
public override string Name => "TMDb Keyword";
public override bool Enabled => true;
public override bool EnableAuto => false;
public override IParseImportListResponse GetParser()
{
return new TMDbKeywordParser();
@ -31,7 +31,7 @@ public override IParseImportListResponse GetParser()
public override IImportListRequestGenerator GetRequestGenerator()
{
return new TMDbKeywordRequestGenerator()
return new TMDbKeywordRequestGenerator
{
RequestBuilder = _requestBuilder,
Settings = Settings,

View file

@ -1,8 +1,8 @@
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.TMDb.List
@ -19,9 +19,9 @@ public TMDbListImport(IRadarrCloudRequestBuilder requestBuilder,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie searchForNewMovie,
ICacheManager cacheManager,
Logger logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, searchForNewMovie, logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, cacheManager, logger)
{
}

View file

@ -1,29 +1,29 @@
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.TMDb.Person
{
public class TMDbPersonImport : TMDbImportListBase<TMDbPersonSettings>
{
public override string Name => "TMDb Person";
public override bool Enabled => true;
public override bool EnableAuto => false;
public TMDbPersonImport(IRadarrCloudRequestBuilder requestBuilder,
IHttpClient httpClient,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie searchForNewMovie,
ICacheManager cacheManager,
Logger logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, searchForNewMovie, logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, cacheManager, logger)
{
}
public override string Name => "TMDb Person";
public override bool Enabled => true;
public override bool EnableAuto => false;
public override IParseImportListResponse GetParser()
{
return new TMDbPersonParser(Settings);
@ -31,7 +31,7 @@ public override IParseImportListResponse GetParser()
public override IImportListRequestGenerator GetRequestGenerator()
{
return new TMDbPersonRequestGenerator()
return new TMDbPersonRequestGenerator
{
RequestBuilder = _requestBuilder,
Settings = Settings,

View file

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.ImportLists.ImportListMovies;
@ -35,7 +36,9 @@ public override IList<ImportListMovie> ParseResponse(ImportListResponse importRe
if (_settings.PersonCast)
{
foreach (var movie in jsonResponse.Cast)
var castMovies = FilterResults(jsonResponse.Cast);
foreach (var movie in castMovies)
{
// Movies with no Year Fix
if (string.IsNullOrWhiteSpace(movie.ReleaseDate))
@ -49,7 +52,9 @@ public override IList<ImportListMovie> ParseResponse(ImportListResponse importRe
if (crewTypes.Count > 0)
{
foreach (var movie in jsonResponse.Crew)
var crewMovies = FilterResults(jsonResponse.Crew);
foreach (var movie in crewMovies)
{
// Movies with no Year Fix
if (string.IsNullOrWhiteSpace(movie.ReleaseDate))
@ -67,9 +72,36 @@ public override IList<ImportListMovie> ParseResponse(ImportListResponse importRe
return movies;
}
private List<string> GetCrewDepartments()
private IEnumerable<CreditsResultResource> FilterResults(IReadOnlyCollection<CreditsResultResource> results)
{
var creditsDepartment = new List<string>();
var items = results.ToList();
if (_settings.MinVoteAverage.HasValue)
{
items = items.Where(r => _settings.MinVoteAverage.Value <= r.VoteAverage).ToList();
}
if (_settings.MinVotes.HasValue)
{
items = items.Where(r => _settings.MinVotes.Value <= r.VoteCount).ToList();
}
if (_settings.GenreIds.Any())
{
items = items.Where(r => r.GenreIds is { Count: > 0 } && _settings.GenreIds.Intersect(r.GenreIds).Any()).ToList();
}
if (_settings.LanguageCodes.Any())
{
items = items.Where(r => r.OriginalLanguage.IsNotNullOrWhiteSpace() && _settings.LanguageCodes.Contains(r.OriginalLanguage)).ToList();
}
return items;
}
private HashSet<string> GetCrewDepartments()
{
var creditsDepartment = new HashSet<string>();
if (_settings.PersonCastDirector)
{

View file

@ -24,13 +24,15 @@ private IEnumerable<ImportListRequest> GetMoviesRequest()
{
Logger.Info("Importing TMDb movies from person: {0}", Settings.PersonId);
var requestBuilder = RequestBuilder.Create()
var request = RequestBuilder.Create()
.SetSegment("api", "3")
.SetSegment("route", "person")
.SetSegment("id", Settings.PersonId)
.SetSegment("secondaryRoute", "/movie_credits");
.SetSegment("secondaryRoute", "/movie_credits")
.Accept(HttpAccept.Json)
.Build();
yield return new ImportListRequest(requestBuilder.Accept(HttpAccept.Json).Build());
yield return new ImportListRequest(request);
}
}
}

View file

@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using FluentValidation;
using NzbDrone.Core.Annotations;
@ -15,22 +17,36 @@ public TMDbPersonSettingsValidator()
.Equal(true)
.Unless(c => c.PersonCastDirector || c.PersonCastProducer || c.PersonCastSound || c.PersonCastWriting)
.WithMessage("Must Select One Credit Type Option");
RuleFor(c => c.PersonCastDirector)
.Equal(true)
.Unless(c => c.PersonCast || c.PersonCastProducer || c.PersonCastSound || c.PersonCastWriting)
.WithMessage("Must Select One Credit Type Option");
RuleFor(c => c.PersonCastProducer)
.Equal(true)
.Unless(c => c.PersonCastDirector || c.PersonCast || c.PersonCastSound || c.PersonCastWriting)
.WithMessage("Must Select One Credit Type Option");
RuleFor(c => c.PersonCastSound)
.Equal(true)
.Unless(c => c.PersonCastDirector || c.PersonCastProducer || c.PersonCast || c.PersonCastWriting)
.WithMessage("Must Select One Credit Type Option");
RuleFor(c => c.PersonCastWriting)
.Equal(true)
.Unless(c => c.PersonCastDirector || c.PersonCastProducer || c.PersonCastSound || c.PersonCast)
.WithMessage("Must Select One Credit Type Option");
RuleFor(c => c.MinVoteAverage)
.InclusiveBetween(0, 10)
.When(c => c.MinVoteAverage.HasValue)
.WithMessage("Minimum vote average must be between 0.0 and 10.0");
RuleFor(c => c.MinVotes)
.GreaterThan(0)
.When(c => c.MinVotes.HasValue)
.WithMessage("Minimum votes must be greater than 0");
}
}
@ -43,7 +59,7 @@ public TMDbPersonSettings()
PersonId = "";
}
[FieldDefinition(1, Label = "PersonId", Type = FieldType.Textbox, HelpText = "TMDb Id of Person to Follow")]
[FieldDefinition(1, Label = "Person Id", 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)]
@ -61,6 +77,18 @@ public TMDbPersonSettings()
[FieldDefinition(6, Label = "Person Writing Credits", HelpText = "Select if you want to include Writing credits", Type = FieldType.Checkbox)]
public bool PersonCastWriting { get; set; }
[FieldDefinition(7, Label = "Minimum Vote Average", HelpText = "Filter movies by votes (0.0-10.0)")]
public double? MinVoteAverage { get; set; }
[FieldDefinition(8, Label = "Minimum Number of Votes", HelpText = "Filter movies by number of votes")]
public int? MinVotes { get; set; }
[FieldDefinition(9, Label = "Genres", Type = FieldType.Select, SelectOptionsProviderAction = "getTmdbGenres", HelpText = "Filter movies by TMDb Genre Ids")]
public IEnumerable<int> GenreIds { get; set; } = Array.Empty<int>();
[FieldDefinition(10, Label = "Original Languages", Type = FieldType.Select, SelectOptionsProviderAction = "getTmdbLanguages", HelpText = "Filter by Languages")]
public IEnumerable<string> LanguageCodes { get; set; } = Array.Empty<string>();
public override NzbDroneValidationResult Validate()
{
return new NzbDroneValidationResult(Validator.Validate(this));

View file

@ -1,29 +1,29 @@
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.TMDb.Popular
{
public class TMDbPopularImport : TMDbImportListBase<TMDbPopularSettings>
{
public override string Name => "TMDb Popular";
public override bool Enabled => true;
public override bool EnableAuto => false;
public TMDbPopularImport(IRadarrCloudRequestBuilder requestBuilder,
IHttpClient httpClient,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie searchForNewMovie,
ICacheManager cacheManager,
Logger logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, searchForNewMovie, logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, cacheManager, logger)
{
}
public override string Name => "TMDb Popular";
public override bool Enabled => true;
public override bool EnableAuto => false;
public override IParseImportListResponse GetParser()
{
return new TMDbParser();
@ -31,7 +31,7 @@ public override IParseImportListResponse GetParser()
public override IImportListRequestGenerator GetRequestGenerator()
{
return new TMDbPopularRequestGenerator()
return new TMDbPopularRequestGenerator
{
RequestBuilder = _requestBuilder,
Settings = Settings,

View file

@ -1,3 +1,4 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace NzbDrone.Core.ImportLists.TMDb
@ -40,7 +41,7 @@ public class MovieResultResource
public string ReleaseDate { get; set; }
[JsonProperty("genre_ids")]
public int?[] GenreIds { get; set; }
public IReadOnlyCollection<int> GenreIds { get; set; }
public int Id { get; set; }
[JsonProperty("original_title")]
@ -118,9 +119,9 @@ public class CollectionResponseResource
public class PersonCreditsResource
{
public CreditsResultResource[] Cast { get; set; }
public CreditsResultResource[] Crew { get; set; }
public int Id { get; set; }
public IReadOnlyCollection<CreditsResultResource> Cast { get; set; }
public IReadOnlyCollection<CreditsResultResource> Crew { get; set; }
}
public class ListItemResource : MovieResultResource
@ -133,4 +134,24 @@ public class ListItemResource : MovieResultResource
[JsonProperty("original_name")]
public string OriginalName { get; set; }
}
public class LanguageResource
{
[JsonProperty("iso_639_1")]
public string Language { get; set; }
public string Name { get; set; }
[JsonProperty("english_name")]
public string EnglishName { get; set; }
}
public class GenresResponseResource
{
public IReadOnlyCollection<GenreResource> Genres { get; set; }
}
public class GenreResource
{
public int Id { get; set; }
public string Name { get; set; }
}
}

View file

@ -1,9 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.TMDb
@ -15,20 +18,89 @@ public abstract class TMDbImportListBase<TSettings> : HttpImportListBase<TSettin
public override TimeSpan MinRefreshInterval => TimeSpan.FromHours(12);
public override int PageSize => 20;
public readonly ISearchForNewMovie _skyhookProxy;
public readonly IHttpRequestBuilderFactory _requestBuilder;
private readonly ICached<object> _cacheOptions;
protected TMDbImportListBase(IRadarrCloudRequestBuilder requestBuilder,
IHttpClient httpClient,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie skyhookProxy,
Logger logger)
IHttpClient httpClient,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ICacheManager cacheManager,
Logger logger)
: base(httpClient, importListStatusService, configService, parsingService, logger)
{
_skyhookProxy = skyhookProxy;
_requestBuilder = requestBuilder.TMDB;
_cacheOptions = cacheManager.GetCache<object>(GetType());
}
public override object RequestAction(string action, IDictionary<string, string> query)
{
if (action == "getTmdbGenres")
{
var genres = _cacheOptions.Get("tmdb_genres", FetchTmdbGenres, TimeSpan.FromDays(1));
return new
{
options = genres
};
}
if (action == "getTmdbLanguages")
{
var languages = _cacheOptions.Get("tmdb_languages", FetchTmdbLanguages, TimeSpan.FromDays(1));
return new
{
options = languages
};
}
return new { };
}
private object FetchTmdbGenres()
{
var request = _requestBuilder.Create()
.SetSegment("api", "3")
.SetSegment("route", "genre")
.SetSegment("id", "")
.SetSegment("secondaryRoute", "movie/list")
.Build();
var genres = Json.Deserialize<GenresResponseResource>(_httpClient.Execute(request).Content);
return genres.Genres
.OrderBy(r => r.Name, StringComparer.InvariantCultureIgnoreCase)
.Select(r => new
{
Value = r.Id,
Name = r.Name,
Hint = $"{r.Id}"
});
}
private object FetchTmdbLanguages()
{
var request = _requestBuilder.Create()
.SetSegment("api", "3")
.SetSegment("route", "configuration")
.SetSegment("id", "")
.SetSegment("secondaryRoute", "languages")
.Build();
var languages = Json.Deserialize<List<LanguageResource>>(_httpClient.Execute(request).Content);
return languages
.OrderBy(r => r.Language, StringComparer.InvariantCultureIgnoreCase)
.Select(r => new
{
Value = r.Language,
Name = r.Language,
Hint = r.EnglishName
});
}
}
}

View file

@ -1,32 +1,32 @@
using System.Collections.Generic;
using System.Net.Http;
using NLog;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Cloud;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.Parser;
namespace NzbDrone.Core.ImportLists.TMDb.User
{
public class TMDbUserImport : TMDbImportListBase<TMDbUserSettings>
{
public override string Name => "TMDb User";
public override bool Enabled => true;
public override bool EnableAuto => false;
public TMDbUserImport(IRadarrCloudRequestBuilder requestBuilder,
IHttpClient httpClient,
IImportListStatusService importListStatusService,
IConfigService configService,
IParsingService parsingService,
ISearchForNewMovie searchForNewMovie,
ICacheManager cacheManager,
Logger logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, searchForNewMovie, logger)
: base(requestBuilder, httpClient, importListStatusService, configService, parsingService, cacheManager, logger)
{
}
public override string Name => "TMDb User";
public override bool Enabled => true;
public override bool EnableAuto => false;
public override IParseImportListResponse GetParser()
{
return new TMDbParser();
@ -34,7 +34,7 @@ public override IParseImportListResponse GetParser()
public override IImportListRequestGenerator GetRequestGenerator()
{
return new TMDbUserRequestGenerator()
return new TMDbUserRequestGenerator
{
RequestBuilder = _requestBuilder,
Settings = Settings,