New: Watch list sorting and rate limit for Trakt Import Lists

This commit is contained in:
Bogdan 2025-02-22 15:20:39 +02:00
parent 553645a07c
commit 554e15d438
6 changed files with 69 additions and 28 deletions

View file

@ -25,10 +25,7 @@ namespace NzbDrone.Core.ImportLists.Trakt.User
public override IImportListRequestGenerator GetRequestGenerator()
{
return new TraktUserRequestGenerator(_traktProxy)
{
Settings = Settings
};
return new TraktUserRequestGenerator(_traktProxy, Settings);
}
}
}

View file

@ -1,14 +1,14 @@
using System.Runtime.Serialization;
using NzbDrone.Core.Annotations;
namespace NzbDrone.Core.ImportLists.Trakt.User
{
public enum TraktUserListType
{
[EnumMember(Value = "User Watch List")]
[FieldOption(Label = "ImportListsTraktSettingsUserListTypeWatch")]
UserWatchList = 0,
[EnumMember(Value = "User Watched List")]
[FieldOption(Label = "ImportListsTraktSettingsUserListTypeWatched")]
UserWatchedList = 1,
[EnumMember(Value = "User Collection List")]
[FieldOption(Label = "ImportListsTraktSettingsUserListTypeCollection")]
UserCollectionList = 2
}
}

View file

@ -1,6 +1,6 @@
using System.Collections.Generic;
using System.Net.Http;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Core.Notifications.Trakt;
namespace NzbDrone.Core.ImportLists.Trakt.User
@ -8,11 +8,12 @@ namespace NzbDrone.Core.ImportLists.Trakt.User
public class TraktUserRequestGenerator : IImportListRequestGenerator
{
private readonly ITraktProxy _traktProxy;
public TraktUserSettings Settings { get; set; }
private readonly TraktUserSettings _settings;
public TraktUserRequestGenerator(ITraktProxy traktProxy)
public TraktUserRequestGenerator(ITraktProxy traktProxy, TraktUserSettings settings)
{
_traktProxy = traktProxy;
_settings = settings;
}
public virtual ImportListPageableRequestChain GetMovies()
@ -26,25 +27,39 @@ namespace NzbDrone.Core.ImportLists.Trakt.User
private IEnumerable<ImportListRequest> GetMoviesRequest()
{
var link = string.Empty;
var userName = Settings.Username.IsNotNullOrWhiteSpace() ? Settings.Username.Trim() : Settings.AuthUser.Trim();
var requestBuilder = new HttpRequestBuilder(_settings.Link.Trim());
switch (Settings.TraktListType)
switch (_settings.TraktListType)
{
case (int)TraktUserListType.UserWatchList:
link += $"users/{userName}/watchlist/movies?limit={Settings.Limit}";
var watchSorting = _settings.TraktWatchSorting switch
{
(int)TraktUserWatchSorting.Added => "added",
(int)TraktUserWatchSorting.Title => "title",
(int)TraktUserWatchSorting.Released => "released",
_ => "rank"
};
requestBuilder
.Resource("/users/{userName}/watchlist/movies/{sorting}")
.SetSegment("sorting", watchSorting);
break;
case (int)TraktUserListType.UserWatchedList:
link += $"users/{userName}/watched/movies?limit={Settings.Limit}";
requestBuilder.Resource("/users/{userName}/watched/movies");
break;
case (int)TraktUserListType.UserCollectionList:
link += $"users/{userName}/collection/movies?limit={Settings.Limit}";
requestBuilder.Resource("/users/{userName}/collection/movies");
break;
}
var request = new ImportListRequest(_traktProxy.BuildRequest(link, HttpMethod.Get, Settings.AccessToken));
var userName = _settings.Username.IsNotNullOrWhiteSpace() ? _settings.Username.Trim() : _settings.AuthUser.Trim();
yield return request;
requestBuilder
.SetSegment("userName", userName)
.WithRateLimit(4)
.AddQueryParam("limit", _settings.Limit.ToString());
yield return new ImportListRequest(_traktProxy.BuildRequest(requestBuilder.Build(), _settings.AccessToken));
}
}
}

View file

@ -20,12 +20,16 @@ namespace NzbDrone.Core.ImportLists.Trakt.User
public TraktUserSettings()
{
TraktListType = (int)TraktUserListType.UserWatchList;
TraktWatchSorting = (int)TraktUserWatchSorting.Rank;
}
[FieldDefinition(1, Label = "List Type", Type = FieldType.Select, SelectOptions = typeof(TraktUserListType), HelpText = "Type of list you're seeking to import from")]
[FieldDefinition(1, Label = "List Type", Type = FieldType.Select, SelectOptions = typeof(TraktUserListType), HelpText = "ImportListsTraktSettingsListTypeHelpText")]
public int TraktListType { get; set; }
[FieldDefinition(2, Label = "Username", HelpText = "Username for the List to import from (empty to use Auth User)")]
[FieldDefinition(2, Label = "ImportListsTraktSettingsWatchListSorting", Type = FieldType.Select, SelectOptions = typeof(TraktUserWatchSorting), HelpText = "ImportListsTraktSettingsWatchListSortingHelpText")]
public int TraktWatchSorting { get; set; }
[FieldDefinition(3, Label = "Username", HelpText = "ImportListsTraktSettingsUserListUsernameHelpText")]
public string Username { get; set; }
public override NzbDroneValidationResult Validate()
@ -33,4 +37,12 @@ namespace NzbDrone.Core.ImportLists.Trakt.User
return new NzbDroneValidationResult(Validator.Validate(this));
}
}
public enum TraktUserWatchSorting
{
Rank = 0,
Added = 1,
Title = 2,
Released = 3
}
}

View file

@ -792,6 +792,12 @@
"ImportListsTraktSettingsPopularListTypeTrendingMovies": "Trending Movies",
"ImportListsTraktSettingsRating": "Rating",
"ImportListsTraktSettingsRatingMovieHelpText": "Filter movies by rating range (0-100)",
"ImportListsTraktSettingsUserListTypeCollection": "User Collection List",
"ImportListsTraktSettingsUserListTypeWatch": "User Watch List",
"ImportListsTraktSettingsUserListTypeWatched": "User Watched List",
"ImportListsTraktSettingsUserListUsernameHelpText": "Username for the List to import from (leave empty to use Auth User)",
"ImportListsTraktSettingsWatchListSorting": "Watch List Sorting",
"ImportListsTraktSettingsWatchListSortingHelpText": "If List Type is Watch, select the order to sort the list",
"ImportListsTraktSettingsYears": "Years",
"ImportListsTraktSettingsYearsMovieHelpText": "Filter movies by year or year range",
"ImportMechanismHealthCheckMessage": "Enable Completed Download Handling",

View file

@ -1,6 +1,5 @@
using System;
using System.Net.Http;
using NLog;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
@ -16,6 +15,7 @@ namespace NzbDrone.Core.Notifications.Trakt
void AddToCollection(TraktCollectMoviesResource payload, string accessToken);
void RemoveFromCollection(TraktCollectMoviesResource payload, string accessToken);
HttpRequest BuildRequest(string resource, HttpMethod method, string accessToken);
HttpRequest BuildRequest(HttpRequest request, string accessToken);
}
public class TraktProxy : ITraktProxy
@ -27,12 +27,12 @@ namespace NzbDrone.Core.Notifications.Trakt
private const string ClientId = "64508a8bf370cee550dde4806469922fd7cd70afb2d5690e3ee7f75ae784b70e";
private readonly IHttpClient _httpClient;
private readonly Logger _logger;
public TraktProxy(IHttpClient httpClient, Logger logger)
private static TimeSpan DefaultRateLimit => TimeSpan.FromSeconds(2);
public TraktProxy(IHttpClient httpClient)
{
_httpClient = httpClient;
_logger = logger;
}
public void AddToCollection(TraktCollectMoviesResource payload, string accessToken)
@ -87,16 +87,27 @@ namespace NzbDrone.Core.Notifications.Trakt
{
var request = new HttpRequestBuilder(URL).Resource(resource).Build();
request.RateLimit = TimeSpan.FromSeconds(2);
request.Headers.Accept = HttpAccept.Json.Value;
request.RateLimit = DefaultRateLimit;
request.Method = method;
return BuildRequest(request, accessToken);
}
public HttpRequest BuildRequest(HttpRequest request, string accessToken)
{
if (request.RateLimit < DefaultRateLimit)
{
request.RateLimit = DefaultRateLimit;
}
request.Headers.Accept = HttpAccept.Json.Value;
request.Headers.Add("trakt-api-version", "2");
request.Headers.Add("trakt-api-key", ClientId);
if (accessToken.IsNotNullOrWhiteSpace())
{
request.Headers.Add("Authorization", "Bearer " + accessToken);
request.Headers.Add("Authorization", $"Bearer {accessToken}");
}
return request;