mirror of
https://github.com/Sonarr/Sonarr
synced 2026-05-09 05:40:53 +02:00
Standardize trakt settings (#1)
* enforce consistency between generators * separate additional parameters from manually added parameters. update years text between popular and user lists
This commit is contained in:
parent
4a0cce15db
commit
a410d0d57e
9 changed files with 93 additions and 121 deletions
|
|
@ -20,24 +20,31 @@ public virtual ImportListPageableRequestChain GetListItems()
|
|||
|
||||
private IEnumerable<ImportListRequest> GetSeriesRequest()
|
||||
{
|
||||
var link = Settings.BaseUrl.Trim();
|
||||
var requestBuilder = new HttpRequestBuilder(Settings.BaseUrl.Trim());
|
||||
|
||||
link += $"/users/{Settings.Username.Trim()}/lists/{Settings.Listname.ToUrlSlug()}/items/show,season,episode";
|
||||
requestBuilder
|
||||
.Resource("/users/{userName}/lists/{listName}/items/show,season,episode")
|
||||
.SetSegment("userName", Settings.Username.Trim())
|
||||
.SetSegment("listName", Settings.Listname.ToUrlSlug())
|
||||
.Accept(HttpAccept.Json);
|
||||
|
||||
var filterParams = TraktQueryHelper.BuildFilterParameters(Settings.Rating, Settings.Genres, Settings.Years, Settings.Limit, Settings.TraktAdditionalParameters);
|
||||
link += "?" + filterParams.ToQueryString();
|
||||
|
||||
var request = new ImportListRequest(link, HttpAccept.Json);
|
||||
foreach (var param in filterParams)
|
||||
{
|
||||
requestBuilder.AddQueryParam(param.Key, param.Value);
|
||||
}
|
||||
|
||||
request.HttpRequest.Headers.Add("trakt-api-version", "2");
|
||||
request.HttpRequest.Headers.Add("trakt-api-key", ClientId);
|
||||
requestBuilder
|
||||
.SetHeader("trakt-api-version", "2")
|
||||
.SetHeader("trakt-api-key", ClientId);
|
||||
|
||||
if (Settings.AccessToken.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
request.HttpRequest.Headers.Add("Authorization", "Bearer " + Settings.AccessToken);
|
||||
requestBuilder.SetHeader("Authorization", $"Bearer {Settings.AccessToken}");
|
||||
}
|
||||
|
||||
yield return request;
|
||||
yield return new ImportListRequest(requestBuilder.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,11 +13,6 @@ public TraktListSettingsValidator()
|
|||
RuleFor(c => c.Username).NotEmpty();
|
||||
RuleFor(c => c.Listname).NotEmpty();
|
||||
|
||||
RuleFor(c => c.Rating)
|
||||
.Matches(@"^\d+\-\d+$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.Rating.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Not a valid rating");
|
||||
|
||||
RuleFor(c => c.Years)
|
||||
.Matches(@"^\d+(\-\d+)?$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.Years.IsNotNullOrWhiteSpace())
|
||||
|
|
@ -35,18 +30,9 @@ public class TraktListSettings : TraktSettingsBase<TraktListSettings>
|
|||
[FieldDefinition(2, Label = "ImportListsTraktSettingsListName", HelpText = "ImportListsTraktSettingsListNameHelpText")]
|
||||
public string Listname { get; set; }
|
||||
|
||||
[FieldDefinition(3, Label = "ImportListsTraktSettingsRating", HelpText = "ImportListsTraktSettingsRatingSeriesHelpText")]
|
||||
public string Rating { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "ImportListsTraktSettingsGenres", HelpText = "ImportListsTraktSettingsGenresSeriesHelpText")]
|
||||
public string Genres { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "ImportListsTraktSettingsYears", HelpText = "ImportListsTraktSettingsYearsSeriesHelpText")]
|
||||
[FieldDefinition(3, Label = "ImportListsTraktSettingsYears", HelpText = "ImportListsTraktSettingsYearsSeriesHelpText")]
|
||||
public string Years { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "ImportListsTraktSettingsAdditionalParameters", HelpText = "ImportListsTraktSettingsAdditionalParametersHelpText", Advanced = true)]
|
||||
public string TraktAdditionalParameters { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
|
|
|||
|
|
@ -21,63 +21,72 @@ public virtual ImportListPageableRequestChain GetListItems()
|
|||
|
||||
private IEnumerable<ImportListRequest> GetSeriesRequest()
|
||||
{
|
||||
var link = Settings.BaseUrl.Trim();
|
||||
var requestBuilder = new HttpRequestBuilder(Settings.BaseUrl.Trim());
|
||||
|
||||
var resource = "/shows";
|
||||
|
||||
switch (Settings.TraktListType)
|
||||
{
|
||||
case (int)TraktPopularListType.Trending:
|
||||
link += "/shows/trending";
|
||||
resource += "/trending";
|
||||
break;
|
||||
case (int)TraktPopularListType.Popular:
|
||||
link += "/shows/popular";
|
||||
resource += "/popular";
|
||||
break;
|
||||
case (int)TraktPopularListType.Anticipated:
|
||||
link += "/shows/anticipated";
|
||||
resource += "/anticipated";
|
||||
break;
|
||||
case (int)TraktPopularListType.TopWatchedByWeek:
|
||||
link += "/shows/watched/weekly";
|
||||
resource += "/watched/weekly";
|
||||
break;
|
||||
case (int)TraktPopularListType.TopWatchedByMonth:
|
||||
link += "/shows/watched/monthly";
|
||||
resource += "/watched/monthly";
|
||||
break;
|
||||
#pragma warning disable CS0612
|
||||
case (int)TraktPopularListType.TopWatchedByYear:
|
||||
#pragma warning restore CS0612
|
||||
link += "/shows/watched/yearly";
|
||||
resource += "/watched/yearly";
|
||||
break;
|
||||
case (int)TraktPopularListType.TopWatchedByAllTime:
|
||||
link += "/shows/watched/all";
|
||||
resource += "/watched/all";
|
||||
break;
|
||||
case (int)TraktPopularListType.RecommendedByWeek:
|
||||
link += "/shows/recommended/weekly";
|
||||
resource += "/recommended/weekly";
|
||||
break;
|
||||
case (int)TraktPopularListType.RecommendedByMonth:
|
||||
link += "/shows/recommended/monthly";
|
||||
resource += "/recommended/monthly";
|
||||
break;
|
||||
#pragma warning disable CS0612
|
||||
case (int)TraktPopularListType.RecommendedByYear:
|
||||
#pragma warning restore CS0612
|
||||
link += "/shows/recommended/yearly";
|
||||
resource += "/recommended/yearly";
|
||||
break;
|
||||
case (int)TraktPopularListType.RecommendedByAllTime:
|
||||
link += "/shows/recommended/all";
|
||||
resource += "/recommended/all";
|
||||
break;
|
||||
}
|
||||
|
||||
requestBuilder
|
||||
.Resource(resource)
|
||||
.Accept(HttpAccept.Json);
|
||||
|
||||
var filterParams = TraktQueryHelper.BuildFilterParameters(Settings.Rating, Settings.Genres, Settings.Years, Settings.Limit, Settings.TraktAdditionalParameters);
|
||||
link += "?" + filterParams.ToQueryString();
|
||||
|
||||
var request = new ImportListRequest(link, HttpAccept.Json);
|
||||
foreach (var param in filterParams)
|
||||
{
|
||||
requestBuilder.AddQueryParam(param.Key, param.Value);
|
||||
}
|
||||
|
||||
request.HttpRequest.Headers.Add("trakt-api-version", "2");
|
||||
request.HttpRequest.Headers.Add("trakt-api-key", ClientId);
|
||||
requestBuilder
|
||||
.SetHeader("trakt-api-version", "2")
|
||||
.SetHeader("trakt-api-key", ClientId);
|
||||
|
||||
if (Settings.AccessToken.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
request.HttpRequest.Headers.Add("Authorization", "Bearer " + Settings.AccessToken);
|
||||
requestBuilder.SetHeader("Authorization", $"Bearer {Settings.AccessToken}");
|
||||
}
|
||||
|
||||
yield return request;
|
||||
yield return new ImportListRequest(requestBuilder.Build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,18 +45,9 @@ public TraktPopularSettings()
|
|||
[FieldDefinition(1, Label = "ImportListsTraktSettingsListType", Type = FieldType.Select, SelectOptions = typeof(TraktPopularListType), HelpText = "ImportListsTraktSettingsListTypeHelpText")]
|
||||
public int TraktListType { get; set; }
|
||||
|
||||
[FieldDefinition(2, Label = "ImportListsTraktSettingsRating", HelpText = "ImportListsTraktSettingsRatingSeriesHelpText")]
|
||||
public string Rating { get; set; }
|
||||
|
||||
[FieldDefinition(4, Label = "ImportListsTraktSettingsGenres", HelpText = "ImportListsTraktSettingsGenresSeriesHelpText")]
|
||||
public string Genres { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "ImportListsTraktSettingsYears", HelpText = "ImportListsTraktSettingsYearsSeriesHelpText")]
|
||||
[FieldDefinition(2, Label = "ImportListsTraktSettingsYears", HelpText = "ImportListsTraktSettingsYearsSeriesHelpTextPopular")]
|
||||
public string Years { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "ImportListsTraktSettingsAdditionalParameters", HelpText = "ImportListsTraktSettingsAdditionalParametersHelpText", Advanced = true)]
|
||||
public string TraktAdditionalParameters { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
|
|
|||
|
|
@ -7,16 +7,6 @@ namespace NzbDrone.Core.ImportLists.Trakt
|
|||
{
|
||||
public static class TraktQueryHelper
|
||||
{
|
||||
private static readonly HashSet<string> CommaSeparatedParams = new(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
"genres",
|
||||
"certifications",
|
||||
"networks",
|
||||
"languages",
|
||||
"countries",
|
||||
"status"
|
||||
};
|
||||
|
||||
public static Dictionary<string, string> BuildFilterParameters(string rating, string genres, string years, int limit, string additionalParameters)
|
||||
{
|
||||
var parameters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
|
@ -32,38 +22,27 @@ public static Dictionary<string, string> BuildFilterParameters(string rating, st
|
|||
|
||||
if (parts.Length == 2 && parts[0].IsNotNullOrWhiteSpace())
|
||||
{
|
||||
parameters[parts[0].Trim()] = parts[1].Trim();
|
||||
var key = parts[0].Trim();
|
||||
|
||||
// Skip explicitly handled parameters
|
||||
if (key.Equals("genres", StringComparison.OrdinalIgnoreCase) ||
|
||||
key.Equals("ratings", StringComparison.OrdinalIgnoreCase) ||
|
||||
key.Equals("years", StringComparison.OrdinalIgnoreCase) ||
|
||||
key.Equals("limit", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
parameters[key] = parts[1].Trim();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply explicit settings (higher priority)
|
||||
// For comma-separated params like genres, combine values from both sources
|
||||
if (genres.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
if (parameters.TryGetValue("genres", out var existingGenres) && existingGenres.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var allGenres = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
foreach (var g in genres.ToLower().Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
allGenres.Add(g.Trim());
|
||||
}
|
||||
|
||||
foreach (var g in existingGenres.ToLower().Split(',', StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
allGenres.Add(g.Trim());
|
||||
}
|
||||
|
||||
parameters["genres"] = string.Join(",", allGenres);
|
||||
}
|
||||
else
|
||||
{
|
||||
parameters["genres"] = genres.ToLower();
|
||||
}
|
||||
parameters["genres"] = genres.ToLower();
|
||||
}
|
||||
|
||||
// For ratings and years, explicit settings override additional parameters
|
||||
if (rating.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
parameters["ratings"] = rating;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Annotations;
|
||||
|
|
@ -31,6 +32,11 @@ public TraktSettingsBaseValidator()
|
|||
RuleFor(c => c.Limit)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("Must be integer greater than 0");
|
||||
|
||||
RuleFor(c => c.Rating)
|
||||
.Matches(@"^\d+\-\d+$", RegexOptions.IgnoreCase)
|
||||
.When(c => c.Rating.IsNotNullOrWhiteSpace())
|
||||
.WithMessage("Not a valid rating");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -59,6 +65,15 @@ public TraktSettingsBase()
|
|||
[FieldDefinition(0, Label = "ImportListsSettingsAuthUser", Type = FieldType.Textbox, Hidden = HiddenType.Hidden)]
|
||||
public string AuthUser { get; set; }
|
||||
|
||||
[FieldDefinition(95, Label = "ImportListsTraktSettingsRating", HelpText = "ImportListsTraktSettingsRatingSeriesHelpText")]
|
||||
public string Rating { get; set; }
|
||||
|
||||
[FieldDefinition(96, Label = "ImportListsTraktSettingsGenres", HelpText = "ImportListsTraktSettingsGenresSeriesHelpText")]
|
||||
public string Genres { get; set; }
|
||||
|
||||
[FieldDefinition(97, Label = "ImportListsTraktSettingsAdditionalParameters", HelpText = "ImportListsTraktSettingsAdditionalParametersHelpText", Advanced = true)]
|
||||
public string TraktAdditionalParameters { get; set; }
|
||||
|
||||
[FieldDefinition(98, Label = "ImportListsTraktSettingsLimit", HelpText = "ImportListsTraktSettingsLimitSeriesHelpText")]
|
||||
public int Limit { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,9 @@ public virtual ImportListPageableRequestChain GetListItems()
|
|||
|
||||
private IEnumerable<ImportListRequest> GetSeriesRequest()
|
||||
{
|
||||
var requestBuilder = new HttpRequestBuilder(_settings.BaseUrl.Trim());
|
||||
var link = _settings.BaseUrl.Trim();
|
||||
|
||||
var userName = _settings.Username.IsNotNullOrWhiteSpace() ? _settings.Username.Trim() : _settings.AuthUser.Trim();
|
||||
|
||||
switch (_settings.TraktListType)
|
||||
{
|
||||
|
|
@ -39,46 +41,37 @@ private IEnumerable<ImportListRequest> GetSeriesRequest()
|
|||
_ => "rank"
|
||||
};
|
||||
|
||||
requestBuilder
|
||||
.Resource("/users/{userName}/watchlist/shows/{sorting}")
|
||||
.SetSegment("sorting", watchSorting);
|
||||
link += $"/users/{userName}/watchlist/shows/{watchSorting}";
|
||||
break;
|
||||
case (int)TraktUserListType.UserWatchedList:
|
||||
requestBuilder
|
||||
.Resource("/users/{userName}/watched/shows")
|
||||
.AddQueryParam("extended", "full");
|
||||
link += $"/users/{userName}/watched/shows";
|
||||
break;
|
||||
case (int)TraktUserListType.UserCollectionList:
|
||||
requestBuilder.Resource("/users/{userName}/collection/shows");
|
||||
link += $"/users/{userName}/collection/shows";
|
||||
break;
|
||||
}
|
||||
|
||||
var userName = _settings.Username.IsNotNullOrWhiteSpace() ? _settings.Username.Trim() : _settings.AuthUser.Trim();
|
||||
|
||||
requestBuilder
|
||||
.SetSegment("userName", userName)
|
||||
.Accept(HttpAccept.Json)
|
||||
.WithRateLimit(4)
|
||||
.SetHeader("trakt-api-version", "2")
|
||||
.SetHeader("trakt-api-key", _clientId)
|
||||
.AddQueryParam("limit", _settings.Limit.ToString());
|
||||
|
||||
var filterParams = TraktQueryHelper.BuildFilterParameters(_settings.Rating, _settings.Genres, _settings.Years, _settings.Limit, _settings.TraktAdditionalParameters);
|
||||
|
||||
foreach (var param in filterParams)
|
||||
// Add extended parameter for watched list
|
||||
if (_settings.TraktListType == (int)TraktUserListType.UserWatchedList)
|
||||
{
|
||||
if (param.Key != "limit")
|
||||
{
|
||||
requestBuilder.AddQueryParam(param.Key, param.Value);
|
||||
}
|
||||
filterParams["extended"] = "full";
|
||||
}
|
||||
|
||||
link += "?" + filterParams.ToQueryString();
|
||||
|
||||
var request = new ImportListRequest(link, HttpAccept.Json);
|
||||
|
||||
request.HttpRequest.Headers.Add("trakt-api-version", "2");
|
||||
request.HttpRequest.Headers.Add("trakt-api-key", _clientId);
|
||||
|
||||
if (_settings.AccessToken.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
requestBuilder.SetHeader("Authorization", $"Bearer {_settings.AccessToken}");
|
||||
request.HttpRequest.Headers.Add("Authorization", $"Bearer {_settings.AccessToken}");
|
||||
}
|
||||
|
||||
yield return new ImportListRequest(requestBuilder.Build());
|
||||
yield return request;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,18 +49,9 @@ public TraktUserSettings()
|
|||
[FieldDefinition(4, Label = "Username", HelpText = "ImportListsTraktSettingsUserListUsernameHelpText")]
|
||||
public string Username { get; set; }
|
||||
|
||||
[FieldDefinition(5, Label = "ImportListsTraktSettingsRating", HelpText = "ImportListsTraktSettingsRatingSeriesHelpText")]
|
||||
public string Rating { get; set; }
|
||||
|
||||
[FieldDefinition(6, Label = "ImportListsTraktSettingsGenres", HelpText = "ImportListsTraktSettingsGenresSeriesHelpText")]
|
||||
public string Genres { get; set; }
|
||||
|
||||
[FieldDefinition(7, Label = "ImportListsTraktSettingsYears", HelpText = "ImportListsTraktSettingsYearsSeriesHelpText")]
|
||||
[FieldDefinition(5, Label = "ImportListsTraktSettingsYears", HelpText = "ImportListsTraktSettingsYearsSeriesHelpText")]
|
||||
public string Years { get; set; }
|
||||
|
||||
[FieldDefinition(8, Label = "ImportListsTraktSettingsAdditionalParameters", HelpText = "ImportListsTraktSettingsAdditionalParametersHelpText", Advanced = true)]
|
||||
public string TraktAdditionalParameters { get; set; }
|
||||
|
||||
public override NzbDroneValidationResult Validate()
|
||||
{
|
||||
return new NzbDroneValidationResult(Validator.Validate(this));
|
||||
|
|
|
|||
|
|
@ -943,7 +943,7 @@
|
|||
"ImportListsTraktSettingsAdditionalParametersHelpText": "Additional Trakt API parameters",
|
||||
"ImportListsTraktSettingsAuthenticateWithTrakt": "Authenticate with Trakt",
|
||||
"ImportListsTraktSettingsGenres": "Genres",
|
||||
"ImportListsTraktSettingsGenresSeriesHelpText": "Filter series by Trakt Genre (action,-romance,-anime)",
|
||||
"ImportListsTraktSettingsGenresSeriesHelpText": "Filter series by Trakt Genre slug (action,comedy)",
|
||||
"ImportListsTraktSettingsLimit": "Limit",
|
||||
"ImportListsTraktSettingsLimitSeriesHelpText": "Limit the number of series to get",
|
||||
"ImportListsTraktSettingsListName": "List Name",
|
||||
|
|
@ -979,6 +979,7 @@
|
|||
"ImportListsTraktSettingsWatchedListTypeInProgress": "In Progress",
|
||||
"ImportListsTraktSettingsYears": "Years",
|
||||
"ImportListsTraktSettingsYearsSeriesHelpText": "Filter series by minimum year or year range (1990-2000)",
|
||||
"ImportListsTraktSettingsYearsSeriesHelpTextPopular": "Filter series by a specific year or year range (1990-2000)",
|
||||
"ImportListsValidationInvalidApiKey": "API Key is invalid",
|
||||
"ImportListsValidationTestFailed": "Test was aborted due to an error: {exceptionMessage}",
|
||||
"ImportListsValidationUnableToConnectException": "Unable to connect to import list: {exceptionMessage}. Check the log surrounding this error for details.",
|
||||
|
|
|
|||
Loading…
Reference in a new issue