diff --git a/src/libs/Trakt.NET/Enums/TraktSmartListItemType.cs b/src/libs/Trakt.NET/Enums/TraktSmartListItemType.cs
new file mode 100644
index 000000000..e7ef37e9d
--- /dev/null
+++ b/src/libs/Trakt.NET/Enums/TraktSmartListItemType.cs
@@ -0,0 +1,20 @@
+namespace TraktNET
+{
+ /// Determines the item type to narrow a smart list holding both media types.
+ [TraktEnum(HasPathSupport = true)]
+ public enum TraktSmartListItemType
+ {
+ /// An invalid smart list item type.
+ Unspecified,
+
+ /// All items (movies and shows).
+ All,
+
+ /// Movies only.
+ Movies,
+
+ /// Shows only.
+ Shows
+ }
+}
+
diff --git a/src/libs/Trakt.NET/Internal/Modules/TraktSmartListsModule.cs b/src/libs/Trakt.NET/Internal/Modules/TraktSmartListsModule.cs
index 6c7ea3930..f53e81518 100644
--- a/src/libs/Trakt.NET/Internal/Modules/TraktSmartListsModule.cs
+++ b/src/libs/Trakt.NET/Internal/Modules/TraktSmartListsModule.cs
@@ -19,14 +19,19 @@ private Task> GetSmartListImplAsync(string listIdO
}
private Task> GetSmartListItemsImplAsync(
- string listIdOrSlug, TraktFilter? filter = null, string? watchnow = null,
+ string listIdOrSlug, TraktSmartListItemType? type = null, TraktSortBy? sortBy = null, TraktSortHow? sortHow = null,
+ TraktFilter? filter = null, string? watchnow = null, string? watchnowCountry = null,
TraktExtendedInfo? extendedInfo = null, uint? page = null, uint? limit = null, CancellationToken cancellationToken = default)
{
var request = new SmartListItemsGetRequest
{
ListId = listIdOrSlug,
+ Type = type,
+ SortBy = sortBy,
+ SortHow = sortHow,
Filter = filter,
Watchnow = watchnow,
+ WatchnowCountry = watchnowCountry,
ExtendedInfo = extendedInfo,
Page = page,
Limit = limit
@@ -36,8 +41,12 @@ private Task> GetSmartListItemsImplAsync(
=> new SmartListItemsGetRequest
{
ListId = listIdOrSlug,
+ Type = type,
+ SortBy = sortBy,
+ SortHow = sortHow,
Filter = filter,
Watchnow = watchnow,
+ WatchnowCountry = watchnowCountry,
ExtendedInfo = extendedInfo,
Page = page,
Limit = limit
diff --git a/src/libs/Trakt.NET/Internal/Parameters/TraktFilter.cs b/src/libs/Trakt.NET/Internal/Parameters/TraktFilter.cs
index bfd071cd7..f27a80386 100644
--- a/src/libs/Trakt.NET/Internal/Parameters/TraktFilter.cs
+++ b/src/libs/Trakt.NET/Internal/Parameters/TraktFilter.cs
@@ -31,6 +31,12 @@ public sealed partial class TraktFilter
private const string IgnoreWatchlistedName = "ignore_watchlisted";
private const string StartDateName = "start_date";
private const string EndDateName = "end_date";
+ private const string ParentalNudityName = "parental_nudity";
+ private const string ParentalViolenceName = "parental_violence";
+ private const string ParentalProfanityName = "parental_profanity";
+ private const string ParentalAlcoholName = "parental_alcohol";
+ private const string ParentalFrighteningName = "parental_frightening";
+ private const string ParentalIncludeUnratedName = "parental_include_unrated";
public override string ToString()
{
@@ -162,9 +168,38 @@ public override string ToString()
values.Add($"{EndDateName}={EndDate.Value.ToTraktSortDateTimeString()}");
}
+ AddParentalRange(values, ParentalNudity, ParentalNudityName);
+ AddParentalRange(values, ParentalViolence, ParentalViolenceName);
+ AddParentalRange(values, ParentalProfanity, ParentalProfanityName);
+ AddParentalRange(values, ParentalAlcohol, ParentalAlcoholName);
+ AddParentalRange(values, ParentalFrightening, ParentalFrighteningName);
+
+ if (ParentalIncludeUnrated.HasValue)
+ {
+ values.Add($"{ParentalIncludeUnratedName}={ParentalIncludeUnrated.Value.ToString().ToLower(CultureInfo.CurrentCulture)}");
+ }
+
return string.Join("&", values);
}
+ private static void AddParentalRange(List values, Range? range, string name)
+ {
+ if (range.HasValue)
+ {
+ uint firstValue = range.Value.From;
+ uint secondValue = range.Value.To;
+
+ if (firstValue <= secondValue)
+ {
+ values.Add($"{name}={firstValue}-{secondValue}");
+ }
+ else
+ {
+ values.Add($"{name}={secondValue}-{firstValue}");
+ }
+ }
+ }
+
private static void AddRange(List values, Range? range, string name)
{
if (range.HasValue && range.Value.From > 0 && range.Value.To > 0)
diff --git a/src/libs/Trakt.NET/Internal/Requests/SmartListRequests.cs b/src/libs/Trakt.NET/Internal/Requests/SmartListRequests.cs
index 87623dc32..a323144af 100644
--- a/src/libs/Trakt.NET/Internal/Requests/SmartListRequests.cs
+++ b/src/libs/Trakt.NET/Internal/Requests/SmartListRequests.cs
@@ -14,12 +14,24 @@ internal sealed partial class SmartListGetRequest
SupportsExtendedInfo = true, SupportsPagination = true, OAuthRequirement = TraktOAuthRequirement.OptionalButMightBeRequired)]
internal sealed partial class SmartListItemsGetRequest
{
+ [TraktRequestParameter]
+ internal TraktSmartListItemType? Type { get; set; }
+
+ [TraktRequestParameter]
+ internal TraktSortBy? SortBy { get; set; }
+
+ [TraktRequestParameter]
+ internal TraktSortHow? SortHow { get; set; }
+
[TraktRequestQuery("filter")]
internal TraktFilter? Filter { get; set; }
[TraktRequestQuery("watchnow")]
internal string? Watchnow { get; set; }
+ [TraktRequestQuery("watchnow_country")]
+ internal string? WatchnowCountry { get; set; }
+
internal override TraktRequestObjectType RequestObjectType => TraktRequestObjectType.List;
}
}
diff --git a/src/libs/Trakt.NET/Json/SmartLists/TraktSmartListFilters.cs b/src/libs/Trakt.NET/Json/SmartLists/TraktSmartListFilters.cs
index 67aa41c3c..f92c0beb8 100644
--- a/src/libs/Trakt.NET/Json/SmartLists/TraktSmartListFilters.cs
+++ b/src/libs/Trakt.NET/Json/SmartLists/TraktSmartListFilters.cs
@@ -42,6 +42,9 @@ public record class TraktSmartListFilters
/// Collection of watchnow streaming service options.
public string[]? Watchnow { get; set; }
+ /// 2-character country code for watchnow.
+ public string? WatchnowCountry { get; set; }
+
/// Year range [min, max]. Max 2 items.
public uint[]? Years { get; set; }
@@ -66,6 +69,24 @@ public record class TraktSmartListFilters
/// MyAnimeList ratings range [min, max]. Max 2 items.
public float[]? MalRatings { get; set; }
+ /// Parental guide nudity severity range [min, max] from 0 (none) to 3 (severe). Max 2 items.
+ public uint[]? ParentalNudity { get; set; }
+
+ /// Parental guide violence severity range [min, max] from 0 (none) to 3 (severe). Max 2 items.
+ public uint[]? ParentalViolence { get; set; }
+
+ /// Parental guide profanity severity range [min, max] from 0 (none) to 3 (severe). Max 2 items.
+ public uint[]? ParentalProfanity { get; set; }
+
+ /// Parental guide alcohol severity range [min, max] from 0 (none) to 3 (severe). Max 2 items.
+ public uint[]? ParentalAlcohol { get; set; }
+
+ /// Parental guide frightening severity range [min, max] from 0 (none) to 3 (severe). Max 2 items.
+ public uint[]? ParentalFrightening { get; set; }
+
+ /// Gets or sets whether to keep titles without a parental guide when a parental range is set.
+ public bool? ParentalIncludeUnrated { get; set; }
+
/// Gets or sets whether watched items should be ignored.
public bool? IgnoreWatched { get; set; }
diff --git a/src/libs/Trakt.NET/Modules/TraktSmartListsModule.cs b/src/libs/Trakt.NET/Modules/TraktSmartListsModule.cs
index f4af8e26d..e46713b4c 100644
--- a/src/libs/Trakt.NET/Modules/TraktSmartListsModule.cs
+++ b/src/libs/Trakt.NET/Modules/TraktSmartListsModule.cs
@@ -119,8 +119,12 @@ public Task> GetSmartListAsync(TraktSmartList list
/// Gets items of a smart list.
/// The id or slug of the smart list, for which items should be retrieved.
+ /// Determines, which type of smart list items should be queried. See also .
+ /// Determines, how to sort the smart list items. See also .
+ /// Determines, the sort direction for the smart list items. See also .
/// Optional filters. See also .
/// Optional watchnow streaming service options.
+ /// Optional 2-letter country code for watchnow streaming services.
/// The extended information options. See also .
/// The page number of items to retrieve.
/// The page limit of items to retrieve.
@@ -141,14 +145,19 @@ public Task> GetSmartListAsync(TraktSmartList list
/// Thrown, if the request fails.
/// Thrown, if validation of request data fails.
public Task> GetSmartListItemsAsync(
- string listIdOrSlug, TraktFilter? filter = null, string? watchnow = null,
+ string listIdOrSlug, TraktSmartListItemType? type = null, TraktSortBy? sortBy = null, TraktSortHow? sortHow = null,
+ TraktFilter? filter = null, string? watchnow = null, string? watchnowCountry = null,
TraktExtendedInfo? extendedInfo = null, uint? page = null, uint? limit = null, CancellationToken cancellationToken = default)
- => GetSmartListItemsImplAsync(listIdOrSlug, filter, watchnow, extendedInfo, page, limit, cancellationToken);
+ => GetSmartListItemsImplAsync(listIdOrSlug, type, sortBy, sortHow, filter, watchnow, watchnowCountry, extendedInfo, page, limit, cancellationToken);
/// Gets items of a smart list.
/// The Trakt-ID of the smart list, for which items should be retrieved.
+ /// Determines, which type of smart list items should be queried. See also .
+ /// Determines, how to sort the smart list items. See also .
+ /// Determines, the sort direction for the smart list items. See also .
/// Optional filters. See also .
/// Optional watchnow streaming service options.
+ /// Optional 2-letter country code for watchnow streaming services.
/// The extended information options. See also .
/// The page number of items to retrieve.
/// The page limit of items to retrieve.
@@ -170,19 +179,24 @@ public Task> GetSmartListItemsAsync(
/// Thrown, if validation of request data fails.
/// Thrown, if the given is 0.
public Task> GetSmartListItemsAsync(
- uint traktListId, TraktFilter? filter = null, string? watchnow = null,
+ uint traktListId, TraktSmartListItemType? type = null, TraktSortBy? sortBy = null, TraktSortHow? sortHow = null,
+ TraktFilter? filter = null, string? watchnow = null, string? watchnowCountry = null,
TraktExtendedInfo? extendedInfo = null, uint? page = null, uint? limit = null, CancellationToken cancellationToken = default)
{
if (traktListId == 0)
throw new ArgumentException("list id must not be 0", nameof(traktListId));
- return GetSmartListItemsAsync(traktListId.ToInvariantCultureString(), filter, watchnow, extendedInfo, page, limit, cancellationToken);
+ return GetSmartListItemsAsync(traktListId.ToInvariantCultureString(), type, sortBy, sortHow, filter, watchnow, watchnowCountry, extendedInfo, page, limit, cancellationToken);
}
/// Gets items of a smart list.
/// The ids of the smart list, for which items should be retrieved.
+ /// Determines, which type of smart list items should be queried. See also .
+ /// Determines, how to sort the smart list items. See also .
+ /// Determines, the sort direction for the smart list items. See also .
/// Optional filters. See also .
/// Optional watchnow streaming service options.
+ /// Optional 2-letter country code for watchnow streaming services.
/// The extended information options. See also .
/// The page number of items to retrieve.
/// The page limit of items to retrieve.
@@ -205,7 +219,8 @@ public Task> GetSmartListItemsAsync(
/// Thrown, if the given is null.
/// Thrown, if the given has not any ids set.
public Task> GetSmartListItemsAsync(
- TraktListIDs listIds, TraktFilter? filter = null, string? watchnow = null,
+ TraktListIDs listIds, TraktSmartListItemType? type = null, TraktSortBy? sortBy = null, TraktSortHow? sortHow = null,
+ TraktFilter? filter = null, string? watchnow = null, string? watchnowCountry = null,
TraktExtendedInfo? extendedInfo = null, uint? page = null, uint? limit = null, CancellationToken cancellationToken = default)
{
ArgumentValidator.ThrowIfNull(listIds);
@@ -213,13 +228,17 @@ public Task> GetSmartListItemsAsync(
if (!listIds.HasAnyID)
throw new ArgumentException($"{nameof(listIds)} has not any ids set", nameof(listIds));
- return GetSmartListItemsAsync(listIds.BestID, filter, watchnow, extendedInfo, page, limit, cancellationToken);
+ return GetSmartListItemsAsync(listIds.BestID, type, sortBy, sortHow, filter, watchnow, watchnowCountry, extendedInfo, page, limit, cancellationToken);
}
/// Gets items of a smart list.
/// The smart list, for which items should be retrieved.
+ /// Determines, which type of smart list items should be queried. See also .
+ /// Determines, how to sort the smart list items. See also .
+ /// Determines, the sort direction for the smart list items. See also .
/// Optional filters. See also .
/// Optional watchnow streaming service options.
+ /// Optional 2-letter country code for watchnow streaming services.
/// The extended information options. See also .
/// The page number of items to retrieve.
/// The page limit of items to retrieve.
@@ -241,11 +260,12 @@ public Task> GetSmartListItemsAsync(
/// Thrown, if validation of request data fails.
/// Thrown, if the given is null.
public Task> GetSmartListItemsAsync(
- TraktSmartList list, TraktFilter? filter = null, string? watchnow = null,
+ TraktSmartList list, TraktSmartListItemType? type = null, TraktSortBy? sortBy = null, TraktSortHow? sortHow = null,
+ TraktFilter? filter = null, string? watchnow = null, string? watchnowCountry = null,
TraktExtendedInfo? extendedInfo = null, uint? page = null, uint? limit = null, CancellationToken cancellationToken = default)
{
ArgumentValidator.ThrowIfNull(list);
- return GetSmartListItemsAsync(list.IDs!, filter, watchnow, extendedInfo, page, limit, cancellationToken);
+ return GetSmartListItemsAsync(list.IDs!, type, sortBy, sortHow, filter, watchnow, watchnowCountry, extendedInfo, page, limit, cancellationToken);
}
}
}
diff --git a/src/libs/Trakt.NET/Parameters/TraktFilter.cs b/src/libs/Trakt.NET/Parameters/TraktFilter.cs
index 9140fa9cf..39927e3cb 100644
--- a/src/libs/Trakt.NET/Parameters/TraktFilter.cs
+++ b/src/libs/Trakt.NET/Parameters/TraktFilter.cs
@@ -86,5 +86,23 @@ public sealed partial class TraktFilter
/// Gets or sets the end date constraint.
public DateTime? EndDate { get; set; }
+
+ /// Parental guide nudity severity range between 0 (none) and 3 (severe).
+ public Range? ParentalNudity { get; set; }
+
+ /// Parental guide violence severity range between 0 (none) and 3 (severe).
+ public Range? ParentalViolence { get; set; }
+
+ /// Parental guide profanity severity range between 0 (none) and 3 (severe).
+ public Range? ParentalProfanity { get; set; }
+
+ /// Parental guide alcohol severity range between 0 (none) and 3 (severe).
+ public Range? ParentalAlcohol { get; set; }
+
+ /// Parental guide frightening severity range between 0 (none) and 3 (severe).
+ public Range? ParentalFrightening { get; set; }
+
+ /// Gets or sets whether to keep titles without a parental guide when a parental range is set.
+ public bool? ParentalIncludeUnrated { get; set; }
}
}
diff --git a/src/tests/libs/JsonData/SmartLists/smartlist.json b/src/tests/libs/JsonData/SmartLists/smartlist.json
index c8004b644..eb3e8e90d 100644
--- a/src/tests/libs/JsonData/SmartLists/smartlist.json
+++ b/src/tests/libs/JsonData/SmartLists/smartlist.json
@@ -45,6 +45,7 @@
"watchnow": [
"netflix"
],
+ "watchnow_country": "us",
"years": [
2010,
2020
@@ -77,6 +78,27 @@
7.0,
9.5
],
+ "parental_nudity": [
+ 0,
+ 1
+ ],
+ "parental_violence": [
+ 0,
+ 2
+ ],
+ "parental_profanity": [
+ 1,
+ 3
+ ],
+ "parental_alcohol": [
+ 0,
+ 0
+ ],
+ "parental_frightening": [
+ 2,
+ 3
+ ],
+ "parental_include_unrated": true,
"ignore_watched": true,
"ignore_watchlisted": false,
"ignore_watching": true,
diff --git a/src/tests/libs/Trakt.NET.Core.Tests/Enums/TraktSmartListItemTypeTests.cs b/src/tests/libs/Trakt.NET.Core.Tests/Enums/TraktSmartListItemTypeTests.cs
new file mode 100644
index 000000000..ca9690bf3
--- /dev/null
+++ b/src/tests/libs/Trakt.NET.Core.Tests/Enums/TraktSmartListItemTypeTests.cs
@@ -0,0 +1,79 @@
+using System.Text.Json;
+
+namespace TraktNET.Enums
+{
+ public sealed class TraktSmartListItemTypeTests
+ {
+ [Fact]
+ public void TestTraktSmartListItemTypeToJson()
+ {
+ TraktSmartListItemType.Unspecified.ToJson().ShouldBeNull();
+ TraktSmartListItemType.All.ToJson().ShouldBe("all");
+ TraktSmartListItemType.Movies.ToJson().ShouldBe("movies");
+ TraktSmartListItemType.Shows.ToJson().ShouldBe("shows");
+ ((TraktSmartListItemType)99).ToJson().ShouldBeNull();
+ }
+
+ [Fact]
+ public void TestTraktSmartListItemTypeFromJson()
+ {
+ "unspecified".ToTraktSmartListItemType().ShouldBe(TraktSmartListItemType.Unspecified);
+ "all".ToTraktSmartListItemType().ShouldBe(TraktSmartListItemType.All);
+ "movies".ToTraktSmartListItemType().ShouldBe(TraktSmartListItemType.Movies);
+ "shows".ToTraktSmartListItemType().ShouldBe(TraktSmartListItemType.Shows);
+
+ string? nullValue = null;
+ nullValue.ToTraktSmartListItemType().ShouldBe(TraktSmartListItemType.Unspecified);
+ "invalid".ToTraktSmartListItemType().ShouldBe(TraktSmartListItemType.Unspecified);
+ "".ToTraktSmartListItemType().ShouldBe(TraktSmartListItemType.Unspecified);
+ }
+
+ [Fact]
+ public void TestTraktSmartListItemTypeToURI()
+ {
+ TraktSmartListItemType.Unspecified.ToURI().ShouldBe(string.Empty);
+ TraktSmartListItemType.All.ToURI().ShouldBe("all");
+ TraktSmartListItemType.Movies.ToURI().ShouldBe("movies");
+ TraktSmartListItemType.Shows.ToURI().ShouldBe("shows");
+ ((TraktSmartListItemType)99).ToURI().ShouldBe(string.Empty);
+ }
+
+ [Fact]
+ public void TestTraktSmartListItemTypeAsPathParameter()
+ {
+ TraktSmartListItemType.Unspecified.AsPathParameter().ShouldBe(string.Empty);
+ TraktSmartListItemType.All.AsPathParameter().ShouldBe("all");
+ TraktSmartListItemType.Movies.AsPathParameter().ShouldBe("movies");
+ TraktSmartListItemType.Shows.AsPathParameter().ShouldBe("shows");
+ ((TraktSmartListItemType)99).AsPathParameter().ShouldBe(string.Empty);
+ }
+
+ [Fact]
+ public void TestTraktSmartListItemTypeDisplayName()
+ {
+ TraktSmartListItemType.Unspecified.DisplayName().ShouldBe("Unspecified");
+ TraktSmartListItemType.All.DisplayName().ShouldBe("All");
+ TraktSmartListItemType.Movies.DisplayName().ShouldBe("Movies");
+ TraktSmartListItemType.Shows.DisplayName().ShouldBe("Shows");
+ ((TraktSmartListItemType)99).DisplayName().ShouldBe("99");
+ }
+
+ [Fact]
+ public void TestTraktSmartListItemTypeJsonConverter()
+ {
+ var converter = new TraktSmartListItemTypeJsonConverter();
+ converter.CanConvert(typeof(TraktSmartListItemType)).ShouldBeTrue();
+ converter.CanConvert(typeof(int)).ShouldBeFalse();
+
+ var options = new JsonSerializerOptions
+ {
+ Converters = { converter }
+ };
+
+ JsonSerializer.Serialize(TraktSmartListItemType.Movies, options).ShouldBe("\"movies\"");
+ JsonSerializer.Deserialize("\"movies\"", options).ShouldBe(TraktSmartListItemType.Movies);
+ JsonSerializer.Deserialize("\"\"", options).ShouldBe(TraktSmartListItemType.Unspecified);
+ }
+ }
+}
+
diff --git a/src/tests/libs/Trakt.NET.Core.Tests/Parameters/TraktFilterTests.cs b/src/tests/libs/Trakt.NET.Core.Tests/Parameters/TraktFilterTests.cs
index 239f93e3c..230f2b0f5 100644
--- a/src/tests/libs/Trakt.NET.Core.Tests/Parameters/TraktFilterTests.cs
+++ b/src/tests/libs/Trakt.NET.Core.Tests/Parameters/TraktFilterTests.cs
@@ -34,6 +34,12 @@ public void TestTraktFilterConstructor()
filter.IgnoreWatchlisted.ShouldBeNull();
filter.StartDate.ShouldBeNull();
filter.EndDate.ShouldBeNull();
+ filter.ParentalNudity.ShouldBeNull();
+ filter.ParentalViolence.ShouldBeNull();
+ filter.ParentalProfanity.ShouldBeNull();
+ filter.ParentalAlcohol.ShouldBeNull();
+ filter.ParentalFrightening.ShouldBeNull();
+ filter.ParentalIncludeUnrated.ShouldBeNull();
}
[Fact]
@@ -506,6 +512,114 @@ public void TestTraktFilterToStringDates()
filter.ToString().ShouldBe("start_date=2024-01-01&end_date=2024-12-31");
}
+ [Fact]
+ public void TestTraktFilterToStringParentalNudity()
+ {
+ var filter = new TraktFilter
+ {
+ ParentalNudity = new Range(0, 1)
+ };
+
+ filter.ToString().ShouldBe("parental_nudity=0-1");
+
+ filter = new TraktFilter
+ {
+ ParentalNudity = new Range(1, 0)
+ };
+
+ filter.ToString().ShouldBe("parental_nudity=0-1");
+ }
+
+ [Fact]
+ public void TestTraktFilterToStringParentalViolence()
+ {
+ var filter = new TraktFilter
+ {
+ ParentalViolence = new Range(1, 2)
+ };
+
+ filter.ToString().ShouldBe("parental_violence=1-2");
+
+ filter = new TraktFilter
+ {
+ ParentalViolence = new Range(2, 1)
+ };
+
+ filter.ToString().ShouldBe("parental_violence=1-2");
+ }
+
+ [Fact]
+ public void TestTraktFilterToStringParentalProfanity()
+ {
+ var filter = new TraktFilter
+ {
+ ParentalProfanity = new Range(0, 3)
+ };
+
+ filter.ToString().ShouldBe("parental_profanity=0-3");
+
+ filter = new TraktFilter
+ {
+ ParentalProfanity = new Range(3, 0)
+ };
+
+ filter.ToString().ShouldBe("parental_profanity=0-3");
+ }
+
+ [Fact]
+ public void TestTraktFilterToStringParentalAlcohol()
+ {
+ var filter = new TraktFilter
+ {
+ ParentalAlcohol = new Range(2, 3)
+ };
+
+ filter.ToString().ShouldBe("parental_alcohol=2-3");
+
+ filter = new TraktFilter
+ {
+ ParentalAlcohol = new Range(3, 2)
+ };
+
+ filter.ToString().ShouldBe("parental_alcohol=2-3");
+ }
+
+ [Fact]
+ public void TestTraktFilterToStringParentalFrightening()
+ {
+ var filter = new TraktFilter
+ {
+ ParentalFrightening = new Range(1, 3)
+ };
+
+ filter.ToString().ShouldBe("parental_frightening=1-3");
+
+ filter = new TraktFilter
+ {
+ ParentalFrightening = new Range(3, 1)
+ };
+
+ filter.ToString().ShouldBe("parental_frightening=1-3");
+ }
+
+ [Fact]
+ public void TestTraktFilterToStringParentalIncludeUnrated()
+ {
+ var filter = new TraktFilter
+ {
+ ParentalIncludeUnrated = true
+ };
+
+ filter.ToString().ShouldBe("parental_include_unrated=true");
+
+ filter = new TraktFilter
+ {
+ ParentalIncludeUnrated = false
+ };
+
+ filter.ToString().ShouldBe("parental_include_unrated=false");
+ }
+
[Fact]
public void TestTraktFilterToStringAllValues()
{
@@ -536,7 +650,13 @@ public void TestTraktFilterToStringAllValues()
IgnoreCollected = true,
IgnoreWatchlisted = true,
StartDate = new DateTime(2024, 01, 01, 0, 0, 0, DateTimeKind.Utc),
- EndDate = new DateTime(2024, 12, 31, 0, 0, 0, DateTimeKind.Utc)
+ EndDate = new DateTime(2024, 12, 31, 0, 0, 0, DateTimeKind.Utc),
+ ParentalNudity = new Range(0, 1),
+ ParentalViolence = new Range(1, 2),
+ ParentalProfanity = new Range(0, 3),
+ ParentalAlcohol = new Range(2, 3),
+ ParentalFrightening = new Range(1, 3),
+ ParentalIncludeUnrated = true
};
filter.ToString().ShouldBe("query=testquery&years=2020-2024&genres=action,drama&languages=en,de"
@@ -544,7 +664,9 @@ public void TestTraktFilterToStringAllValues()
+ "&tmdb_votes=2000-5000&imdb_ratings=5.5-10&imdb_votes=2000-5000&rt_meters=70-90&rt_user_meters=70-90"
+ "&metascores=5.5-10&certifications=R,tv-pg&network_ids=7,8,9&status=ended,planned"
+ "&episode_types=series_premiere,season_premiere&hide=unwatched&ignore_watched=true&ignore_collected=true"
- + "&ignore_watchlisted=true&start_date=2024-01-01&end_date=2024-12-31");
+ + "&ignore_watchlisted=true&start_date=2024-01-01&end_date=2024-12-31"
+ + "&parental_nudity=0-1&parental_violence=1-2&parental_profanity=0-3&parental_alcohol=2-3&parental_frightening=1-3"
+ + "&parental_include_unrated=true");
}
}
}
diff --git a/src/tests/libs/Trakt.NET.Json.Tests/SmartLists/TraktSmartListTests.cs b/src/tests/libs/Trakt.NET.Json.Tests/SmartLists/TraktSmartListTests.cs
index 13550f3e8..c3fb41cf7 100644
--- a/src/tests/libs/Trakt.NET.Json.Tests/SmartLists/TraktSmartListTests.cs
+++ b/src/tests/libs/Trakt.NET.Json.Tests/SmartLists/TraktSmartListTests.cs
@@ -84,6 +84,8 @@ public async Task TestTraktSmartListFromJson()
smartList.Filters.Watchnow.Length.ShouldBe(1);
smartList.Filters.Watchnow[0].ShouldBe("netflix");
+ smartList.Filters.WatchnowCountry.ShouldBe("us");
+
smartList.Filters.Years.ShouldNotBeNull();
smartList.Filters.Years.Length.ShouldBe(2);
smartList.Filters.Years[0].ShouldBe(2010U);
@@ -124,6 +126,33 @@ public async Task TestTraktSmartListFromJson()
smartList.Filters.MalRatings[0].ShouldBe(7.0f);
smartList.Filters.MalRatings[1].ShouldBe(9.5f);
+ smartList.Filters.ParentalNudity.ShouldNotBeNull();
+ smartList.Filters.ParentalNudity.Length.ShouldBe(2);
+ smartList.Filters.ParentalNudity[0].ShouldBe(0U);
+ smartList.Filters.ParentalNudity[1].ShouldBe(1U);
+
+ smartList.Filters.ParentalViolence.ShouldNotBeNull();
+ smartList.Filters.ParentalViolence.Length.ShouldBe(2);
+ smartList.Filters.ParentalViolence[0].ShouldBe(0U);
+ smartList.Filters.ParentalViolence[1].ShouldBe(2U);
+
+ smartList.Filters.ParentalProfanity.ShouldNotBeNull();
+ smartList.Filters.ParentalProfanity.Length.ShouldBe(2);
+ smartList.Filters.ParentalProfanity[0].ShouldBe(1U);
+ smartList.Filters.ParentalProfanity[1].ShouldBe(3U);
+
+ smartList.Filters.ParentalAlcohol.ShouldNotBeNull();
+ smartList.Filters.ParentalAlcohol.Length.ShouldBe(2);
+ smartList.Filters.ParentalAlcohol[0].ShouldBe(0U);
+ smartList.Filters.ParentalAlcohol[1].ShouldBe(0U);
+
+ smartList.Filters.ParentalFrightening.ShouldNotBeNull();
+ smartList.Filters.ParentalFrightening.Length.ShouldBe(2);
+ smartList.Filters.ParentalFrightening[0].ShouldBe(2U);
+ smartList.Filters.ParentalFrightening[1].ShouldBe(3U);
+
+ smartList.Filters.ParentalIncludeUnrated.ShouldBe(true);
+
smartList.Filters.IgnoreWatched.ShouldBe(true);
smartList.Filters.IgnoreWatchlisted.ShouldBe(false);
smartList.Filters.IgnoreWatching.ShouldBe(true);
diff --git a/src/tests/libs/Trakt.NET.Modules.Tests/SmartListsModule/GetSmartListItemsTests.cs b/src/tests/libs/Trakt.NET.Modules.Tests/SmartListsModule/GetSmartListItemsTests.cs
index 563973233..3802190e0 100644
--- a/src/tests/libs/Trakt.NET.Modules.Tests/SmartListsModule/GetSmartListItemsTests.cs
+++ b/src/tests/libs/Trakt.NET.Modules.Tests/SmartListsModule/GetSmartListItemsTests.cs
@@ -45,7 +45,7 @@ public async Task TestGetSmartListItemsWithFilterAndQuery()
TraktClient client = ModuleTestUtility.GetClient(expectedUri, responseContent);
TraktPagedResponse response = await client.SmartLists.GetSmartListItemsAsync(
- ListSlug, filter, watchnow: "netflix", cancellationToken: TestContext.Current.CancellationToken);
+ ListSlug, filter: filter, watchnow: "netflix", cancellationToken: TestContext.Current.CancellationToken);
response.ShouldNotBeNull();
response.IsSuccess.ShouldBeTrue();
@@ -239,6 +239,67 @@ public async Task TestGetSmartListItemsWithExtendedInfoPageAndLimit()
response.PageCount.ShouldBe(1U);
}
+ [Fact]
+ public async Task TestGetSmartListItemsWithTypeSortByAndSortHow()
+ {
+ string responseContent = await TestUtility.GetJsonFileContentAsync("Lists\\listitems.json");
+
+ string expectedUri = $"smart-lists/{ListSlug}/items/movies/rank/desc";
+
+ TraktClient client = ModuleTestUtility.GetClient(expectedUri, responseContent);
+
+ TraktPagedResponse response = await client.SmartLists.GetSmartListItemsAsync(
+ ListSlug, TraktSmartListItemType.Movies, TraktSortBy.Rank, TraktSortHow.Descending,
+ cancellationToken: TestContext.Current.CancellationToken);
+
+ response.ShouldNotBeNull();
+ response.IsSuccess.ShouldBeTrue();
+ response.HasValue.ShouldBeTrue();
+ response.Content.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task TestGetSmartListItemsWithWatchnowCountry()
+ {
+ string responseContent = await TestUtility.GetJsonFileContentAsync("Lists\\listitems.json");
+
+ string expectedUri = $"{GetSmartListItemsUri}?watchnow=netflix&watchnow_country=us";
+
+ TraktClient client = ModuleTestUtility.GetClient(expectedUri, responseContent);
+
+ TraktPagedResponse response = await client.SmartLists.GetSmartListItemsAsync(
+ ListSlug, watchnow: "netflix", watchnowCountry: "us", cancellationToken: TestContext.Current.CancellationToken);
+
+ response.ShouldNotBeNull();
+ response.IsSuccess.ShouldBeTrue();
+ response.HasValue.ShouldBeTrue();
+ response.Content.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public async Task TestGetSmartListItemsWithParentalFilter()
+ {
+ string responseContent = await TestUtility.GetJsonFileContentAsync("Lists\\listitems.json");
+
+ var filter = new TraktFilter
+ {
+ ParentalNudity = new Range(0, 1),
+ ParentalIncludeUnrated = true
+ };
+
+ string expectedUri = $"{GetSmartListItemsUri}?parental_nudity=0-1&parental_include_unrated=true";
+
+ TraktClient client = ModuleTestUtility.GetClient(expectedUri, responseContent);
+
+ TraktPagedResponse response = await client.SmartLists.GetSmartListItemsAsync(
+ ListSlug, filter: filter, cancellationToken: TestContext.Current.CancellationToken);
+
+ response.ShouldNotBeNull();
+ response.IsSuccess.ShouldBeTrue();
+ response.HasValue.ShouldBeTrue();
+ response.Content.ShouldNotBeNull();
+ }
+
[Fact]
public async Task TestGetSmartListItemsComplete()
{
@@ -247,15 +308,17 @@ public async Task TestGetSmartListItemsComplete()
var filter = new TraktFilter
{
Genres = ["science-fiction"],
- IgnoreWatched = true
+ IgnoreWatched = true,
+ ParentalViolence = new Range(1, 2)
};
- string expectedUri = $"{GetSmartListItemsUri}?genres=science-fiction&ignore_watched=true&watchnow=netflix&extended={ExtendedInfo.ToURI()}&page={Page}&limit={Limit}";
+ string expectedUri = $"smart-lists/{ListSlug}/items/movies/rank/desc?genres=science-fiction&ignore_watched=true&parental_violence=1-2&watchnow=netflix&watchnow_country=us&extended={ExtendedInfo.ToURI()}&page={Page}&limit={Limit}";
TraktClient client = ModuleTestUtility.GetClient(expectedUri, responseContent, Page, 1, Limit, ListItemCount);
TraktPagedResponse response = await client.SmartLists.GetSmartListItemsAsync(
- ListSlug, filter, watchnow: "netflix", extendedInfo: ExtendedInfo, page: Page, limit: Limit, cancellationToken: TestContext.Current.CancellationToken);
+ ListSlug, TraktSmartListItemType.Movies, TraktSortBy.Rank, TraktSortHow.Descending,
+ filter, "netflix", "us", ExtendedInfo, Page, Limit, cancellationToken: TestContext.Current.CancellationToken);
response.ShouldNotBeNull();
response.IsSuccess.ShouldBeTrue();
diff --git a/src/tests/libs/Trakt.NET.Requests.Tests/Get/SmartLists/SmartListItemsGetRequestTests.cs b/src/tests/libs/Trakt.NET.Requests.Tests/Get/SmartLists/SmartListItemsGetRequestTests.cs
index 4ae0dab60..ed4ecabbf 100644
--- a/src/tests/libs/Trakt.NET.Requests.Tests/Get/SmartLists/SmartListItemsGetRequestTests.cs
+++ b/src/tests/libs/Trakt.NET.Requests.Tests/Get/SmartLists/SmartListItemsGetRequestTests.cs
@@ -9,21 +9,39 @@ public sealed class SmartListItemsGetRequestTests
private const string URIPath = "smart-lists/123/items";
[Theory]
- [InlineData(null, null, null, null, $"{URIPath}")]
- [InlineData("us", null, null, null, $"{URIPath}?watchnow=us")]
- [InlineData(null, TraktExtendedInfo.None, null, null, $"{URIPath}")]
- [InlineData(null, TraktExtendedInfo.Full, null, null, $"{URIPath}?extended=full")]
- [InlineData(null, null, 10, null, $"{URIPath}?page=10")]
- [InlineData(null, null, null, 20, $"{URIPath}?limit=20")]
- [InlineData(null, null, 10, 20, $"{URIPath}?page=10&limit=20")]
- [InlineData("us", TraktExtendedInfo.Full, 10, 20, $"{URIPath}?watchnow=us&extended=full&page=10&limit=20")]
- public void TestSmartListItemsGetRequestHasValidURIPath(string? watchnow,
+ [InlineData(null, null, null, null, null, null, null, null, URIPath)]
+ [InlineData(null, null, null, "us", null, null, null, null, $"{URIPath}?watchnow=us")]
+ [InlineData(null, null, null, null, "us", null, null, null, $"{URIPath}?watchnow_country=us")]
+ [InlineData(null, null, null, "us", "us", null, null, null, $"{URIPath}?watchnow=us&watchnow_country=us")]
+ [InlineData(null, null, null, null, null, TraktExtendedInfo.None, null, null, URIPath)]
+ [InlineData(null, null, null, null, null, TraktExtendedInfo.Full, null, null, $"{URIPath}?extended=full")]
+ [InlineData(null, null, null, null, null, null, 10, null, $"{URIPath}?page=10")]
+ [InlineData(null, null, null, null, null, null, null, 20, $"{URIPath}?limit=20")]
+ [InlineData(null, null, null, null, null, null, 10, 20, $"{URIPath}?page=10&limit=20")]
+ [InlineData(null, null, null, "us", "us", TraktExtendedInfo.Full, 10, 20, $"{URIPath}?watchnow=us&watchnow_country=us&extended=full&page=10&limit=20")]
+ [InlineData(null, null, TraktSortHow.Ascending, null, null, null, null, null, $"{URIPath}/asc")]
+ [InlineData(null, null, TraktSortHow.Descending, null, null, null, null, null, $"{URIPath}/desc")]
+ [InlineData(null, TraktSortBy.Rank, null, null, null, null, null, null, $"{URIPath}/rank")]
+ [InlineData(null, TraktSortBy.Rank, TraktSortHow.Ascending, null, null, null, null, null, $"{URIPath}/rank/asc")]
+ [InlineData(null, TraktSortBy.Rank, TraktSortHow.Descending, null, null, null, null, null, $"{URIPath}/rank/desc")]
+ [InlineData(TraktSmartListItemType.All, null, null, null, null, null, null, null, $"{URIPath}/all")]
+ [InlineData(TraktSmartListItemType.Movies, null, null, null, null, null, null, null, $"{URIPath}/movies")]
+ [InlineData(TraktSmartListItemType.Shows, null, null, null, null, null, null, null, $"{URIPath}/shows")]
+ [InlineData(TraktSmartListItemType.Movies, TraktSortBy.Rank, null, null, null, null, null, null, $"{URIPath}/movies/rank")]
+ [InlineData(TraktSmartListItemType.Movies, TraktSortBy.Rank, TraktSortHow.Descending, null, null, null, null, null, $"{URIPath}/movies/rank/desc")]
+ [InlineData(TraktSmartListItemType.Movies, TraktSortBy.Rank, TraktSortHow.Descending, "us", "us", TraktExtendedInfo.Full, 10, 20, $"{URIPath}/movies/rank/desc?watchnow=us&watchnow_country=us&extended=full&page=10&limit=20")]
+ public void TestSmartListItemsGetRequestHasValidURIPath(TraktSmartListItemType? type, TraktSortBy? sortBy,
+ TraktSortHow? sortHow, string? watchnow, string? watchnowCountry,
TraktExtendedInfo? extendedInfo, int? page, int? limit, string expectedURIPath)
{
var request = new SmartListItemsGetRequest
{
ListId = "123",
+ Type = type,
+ SortBy = sortBy,
+ SortHow = sortHow,
Watchnow = watchnow,
+ WatchnowCountry = watchnowCountry,
ExtendedInfo = extendedInfo,
Page = (uint?)page,
Limit = (uint?)limit
@@ -47,6 +65,24 @@ public void TestSmartListItemsGetRequestHasValidURIPathWithFilter()
request.RequestUri.ShouldBe(new Uri($"{URIPath}?query=game of thrones", UriKind.Relative));
}
+ [Fact]
+ public void TestSmartListItemsGetRequestHasValidURIPathWithParentalFilter()
+ {
+ var filter = new TraktFilter
+ {
+ ParentalNudity = new Range(0, 1),
+ ParentalIncludeUnrated = true
+ };
+ var request = new SmartListItemsGetRequest
+ {
+ ListId = "123",
+ Filter = filter
+ };
+
+ request.BuildUri();
+ request.RequestUri.ShouldBe(new Uri($"{URIPath}?parental_nudity=0-1&parental_include_unrated=true", UriKind.Relative));
+ }
+
[Fact]
public void TestSmartListItemsGetRequestHasValidOAuthRequirement()
{