Skip to content

Commit

Permalink
[v2] Add movies module implementation (WIP)
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikfroehling committed Sep 24, 2024
1 parent 3371dbb commit 1baa2f8
Show file tree
Hide file tree
Showing 31 changed files with 2,627 additions and 6 deletions.
2 changes: 1 addition & 1 deletion src/libs/Trakt.NET/Internal/Extensions/StreamExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ internal static class StreamExtensions
}

internal static async Task<IReadOnlyList<TJsonObjectType>?> ReadAsJsonArrayAsync<TJsonObjectType>(this Stream stream,
CancellationToken cancellationToken = default) where TJsonObjectType : class
CancellationToken cancellationToken = default)
{
IReadOnlyList<TJsonObjectType>? values;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace TraktNET
{
[ExcludeFromCodeCoverage]
[JsonSerializable(typeof(uint))]
[JsonSerializable(typeof(IReadOnlyList<uint>))]
[JsonSerializable(typeof(TraktRateLimitInfo))]
public sealed partial class GeneralJsonSerializerContext : JsonSerializerContext
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,14 @@ internal static JsonSerializerContext GetContext<TJsonObjectType>()

private static readonly FrozenSet<Type> s_generalJsonTypes = FrozenSet.ToFrozenSet(new[]
{
typeof(uint),
typeof(TraktRateLimitInfo)
});

private static readonly FrozenSet<Type> s_movieJsonTypes = FrozenSet.ToFrozenSet(new[]
{
typeof(TraktBoxOfficeMovie),
typeof(TraktMostAnticipatedMovie),
typeof(TraktMostCollectedMovie),
typeof(TraktMostFavoritedMovie),
typeof(TraktMostPlayedMovie),
Expand All @@ -133,7 +136,8 @@ internal static JsonSerializerContext GetContext<TJsonObjectType>()
typeof(TraktMovie),
typeof(TraktMovieIds),
typeof(TraktMovieMinimal),
typeof(TraktTrendingMovie)
typeof(TraktTrendingMovie),
typeof(TraktUpdatedMovie)
});

private static readonly FrozenSet<Type> s_peopleJsonTypes = FrozenSet.ToFrozenSet(new[]
Expand Down Expand Up @@ -198,10 +202,13 @@ internal static JsonSerializerContext GetContext<TJsonObjectType>()
];

private static readonly HashSet<Type> s_generalJsonTypes = [
typeof(uint),
typeof(TraktRateLimitInfo)
];

private static readonly HashSet<Type> s_movieJsonTypes = [
typeof(TraktBoxOfficeMovie),
typeof(TraktMostAnticipatedMovie),
typeof(TraktMostCollectedMovie),
typeof(TraktMostFavoritedMovie),
typeof(TraktMostPlayedMovie),
Expand All @@ -210,7 +217,8 @@ internal static JsonSerializerContext GetContext<TJsonObjectType>()
typeof(TraktMovie),
typeof(TraktMovieIds),
typeof(TraktMovieMinimal),
typeof(TraktTrendingMovie)
typeof(TraktTrendingMovie),
typeof(TraktUpdatedMovie)
];

private static readonly HashSet<Type> s_peopleJsonTypes = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
namespace TraktNET
{
[ExcludeFromCodeCoverage]
[JsonSerializable(typeof(TraktBoxOfficeMovie))]
[JsonSerializable(typeof(IReadOnlyList<TraktBoxOfficeMovie>))]
[JsonSerializable(typeof(TraktMostAnticipatedMovie))]
[JsonSerializable(typeof(IReadOnlyList<TraktMostAnticipatedMovie>))]
[JsonSerializable(typeof(TraktMostCollectedMovie))]
[JsonSerializable(typeof(IReadOnlyList<TraktMostCollectedMovie>))]
[JsonSerializable(typeof(TraktMostFavoritedMovie))]
Expand All @@ -23,6 +27,8 @@ namespace TraktNET
[JsonSerializable(typeof(IReadOnlyList<TraktMovieMinimal>))]
[JsonSerializable(typeof(TraktTrendingMovie))]
[JsonSerializable(typeof(IReadOnlyList<TraktTrendingMovie>))]
[JsonSerializable(typeof(TraktUpdatedMovie))]
[JsonSerializable(typeof(IReadOnlyList<TraktUpdatedMovie>))]
public sealed partial class MoviesJsonSerializerContext : JsonSerializerContext
{
}
Expand Down
13 changes: 12 additions & 1 deletion src/libs/Trakt.NET/Internal/Requests/RequestHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,20 @@ internal static async Task<TraktResponse<TResponseContentType>> ExecuteSingleIte
response.TraktHeaders, response.ResponseMessage.Headers, response.ResponseMessage.Content.Headers);
}

internal static async Task<TraktListResponse<TResponseContentType>> ExecuteListRequestAsync<TResponseContentType>(
TraktContext context, RequestBase request, CancellationToken cancellationToken = default)
{
using RequestResponse response = await ExecuteRequestAsync(context, request, cancellationToken).ConfigureAwait(false);

IReadOnlyList<TResponseContentType>? responseContent =
await response.ResponseContentStream.ReadAsJsonArrayAsync<TResponseContentType>(cancellationToken).ConfigureAwait(false);

return TraktListResponse<TResponseContentType>.Create(response.ResponseMessage.StatusCode, responseContent,
response.TraktHeaders, response.ResponseMessage.Headers, response.ResponseMessage.Content.Headers);
}

internal static async Task<TraktPagedResponse<TResponseContentType>> ExecutePagedListRequestAsync<TResponseContentType>(
TraktContext context, RequestBase request, Func<uint?, uint?, RequestBase>? requestBuilder, CancellationToken cancellationToken = default)
where TResponseContentType : class
{
using RequestResponse response = await ExecuteRequestAsync(context, request, cancellationToken).ConfigureAwait(false);

Expand Down
9 changes: 9 additions & 0 deletions src/libs/Trakt.NET/Json/Movies/TraktBoxOfficeMovie.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TraktNET
{
/// <summary>A box office Trakt movie.</summary>
public record class TraktBoxOfficeMovie : TraktCollectionMovie
{
/// <summary>The revenue for the <see cref="Movie" />.</summary>

Check warning on line 6 in src/libs/Trakt.NET/Json/Movies/TraktBoxOfficeMovie.cs

View workflow job for this annotation

GitHub Actions / v2-alpha / build

XML comment has cref attribute 'Movie' that could not be resolved
public uint? Revenue { get; set; }
}
}
9 changes: 9 additions & 0 deletions src/libs/Trakt.NET/Json/Movies/TraktMostAnticipatedMovie.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TraktNET
{
/// <summary>A most anticipated Trakt movie.</summary>
public record class TraktMostAnticipatedMovie : TraktCollectionMovie
{
/// <summary>The list count for the <see cref="Movie" />.</summary>

Check warning on line 6 in src/libs/Trakt.NET/Json/Movies/TraktMostAnticipatedMovie.cs

View workflow job for this annotation

GitHub Actions / v2-alpha / build

XML comment has cref attribute 'Movie' that could not be resolved
public uint? ListCount { get; set; }
}
}
9 changes: 9 additions & 0 deletions src/libs/Trakt.NET/Json/Movies/TraktUpdatedMovie.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace TraktNET
{
/// <summary>An updated Trakt movie.</summary>
public record class TraktUpdatedMovie : TraktCollectionMovie
{
/// <summary>The UTC datetime, when the <see cref="Movie" /> was updated.</summary>

Check warning on line 6 in src/libs/Trakt.NET/Json/Movies/TraktUpdatedMovie.cs

View workflow job for this annotation

GitHub Actions / v2-alpha / build

XML comment has cref attribute 'Movie' that could not be resolved
public new DateTime? UpdatedAt { get; set; }
}
}
176 changes: 176 additions & 0 deletions src/libs/Trakt.NET/Modules/Movies/TraktMoviesModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -341,5 +341,181 @@ public Task<TraktPagedResponse<TraktMostCollectedMovie>> GetMostCollectedMoviesA
},
cancellationToken);
}

/// <summary>Gets the most anticipated movies.</summary>
/// <param name="extendedInfo">
/// Specifies how much data should be queried about the movies.
/// <para>See also <seealso cref="TraktExtendedInfo" />.</para>
/// </param>
/// <param name="filter">
/// Specifies optional filter for genres, languages, year, runtimes, ratings. etc.
/// <para>See also <seealso cref="TraktFilter" />.</para>
/// </param>
/// <param name="page">Specifies the page which should be queried. Defaults to the first page.</param>
/// <param name="limit">Specifies the number of items which should be queried per page. Defaults to 10.</param>
/// <param name="cancellationToken">
/// Propagates notification that the request should be canceled.<para/>
/// If provided, the exception <see cref="OperationCanceledException" /> should be catched.
/// </param>
/// <returns>
/// A paged response of type <see cref="TraktPagedResponse{TResponseContentType}" /> containing the queried most anticipated movies.
/// <para />
/// The response also contains information about the queried page number, the page's item count, maximum page count
/// and maximum item count.
/// <para />
/// See also <seealso cref="TraktPagedResponse{TResponseContentType}" /> and <seealso cref="TraktMostAnticipatedMovie" />.
/// </returns>
/// <remarks>
/// OAuth authorization is not required.
/// <para><see href="https://trakt.docs.apiary.io/#reference/movies/anticipated/get-the-most-anticipated-movies">
/// Trakt API Documentation: Movies: Anticipated - Get the most anticipated movies
/// </see></para>
/// </remarks>
/// <exception cref="TraktApiException">Thrown if the request fails.</exception>
public Task<TraktPagedResponse<TraktMostAnticipatedMovie>> GetMostAnticipatedMoviesAsync(TraktExtendedInfo? extendedInfo = null,
TraktFilter? filter = null, uint? page = null, uint? limit = null, CancellationToken cancellationToken = default)
{
var request = new MostAnticipatedMoviesGetRequest
{
ExtendedInfo = extendedInfo,
Page = page,
Limit = limit,
Filter = filter
};

return RequestHandler.ExecutePagedListRequestAsync<TraktMostAnticipatedMovie>(_context, request, (uint? page, uint? limit)
=> new MostAnticipatedMoviesGetRequest
{
ExtendedInfo = extendedInfo,
Page = page,
Limit = limit,
Filter = filter
},
cancellationToken);
}

/// <summary>Gets the weekend box office movies.</summary>
/// <param name="extendedInfo">
/// Specifies how much data should be queried about the movies.
/// <para>See also <seealso cref="TraktExtendedInfo" />.</para>
/// </param>
/// <param name="cancellationToken">
/// Propagates notification that the request should be canceled.<para/>
/// If provided, the exception <see cref="OperationCanceledException" /> should be catched.
/// </param>
/// <returns>
/// A list response of type <see cref="TraktListResponse{TResponseContentType}" /> containing the queried box office movies.
/// <para />
/// See also <seealso cref="TraktListResponse{TResponseContentType}" /> and <seealso cref="TraktBoxOfficeMovie" />.
/// </returns>
/// <remarks>
/// OAuth authorization is not required.
/// <para><see href="https://trakt.docs.apiary.io/#reference/movies/box-office/get-the-weekend-box-office">
/// Trakt API Documentation: Movies: Box Office - Get the weekend box office movies
/// </see></para>
/// </remarks>
/// <exception cref="TraktApiException">Thrown if the request fails.</exception>
public Task<TraktListResponse<TraktBoxOfficeMovie>> GetBoxOfficeMoviesAsync(TraktExtendedInfo? extendedInfo = null,
CancellationToken cancellationToken = default)
{
var request = new BoxOfficeMoviesGetRequest
{
ExtendedInfo = extendedInfo
};

return RequestHandler.ExecuteListRequestAsync<TraktBoxOfficeMovie>(_context, request, cancellationToken);
}

/// <summary>Gets recently updated movies.</summary>
/// <param name="extendedInfo">
/// Specifies how much data should be queried about the movies.
/// <para>See also <seealso cref="TraktExtendedInfo" />.</para>
/// </param>
/// <param name="startDate">Specifies an optional UTC start datetime after which the queried movies were updated.</param>
/// <param name="page">Specifies the page which should be queried. Defaults to the first page.</param>
/// <param name="limit">Specifies the number of items which should be queried per page. Defaults to 10.</param>
/// <param name="cancellationToken">
/// Propagates notification that the request should be canceled.<para/>
/// If provided, the exception <see cref="OperationCanceledException" /> should be catched.
/// </param>
/// <returns>
/// A paged response of type <see cref="TraktPagedResponse{TResponseContentType}" /> containing the queried updated movies.
/// <para />
/// The response also contains information about the queried page number, the page's item count, maximum page count
/// and maximum item count.
/// <para />
/// See also <seealso cref="TraktPagedResponse{TResponseContentType}" /> and <seealso cref="TraktUpdatedMovie" />.
/// </returns>
/// <remarks>
/// OAuth authorization is not required.
/// <para><see href="https://trakt.docs.apiary.io/#reference/movies/updates/get-recently-updated-movies">
/// Trakt API Documentation: Movies: Updates - Get recently updated movies
/// </see></para>
/// </remarks>
/// <exception cref="TraktApiException">Thrown if the request fails.</exception>
public Task<TraktPagedResponse<TraktUpdatedMovie>> GetRecentlyUpdatedMoviesAsync(TraktExtendedInfo? extendedInfo = null,
DateTime? startDate = null, uint? page = null, uint? limit = null, CancellationToken cancellationToken = default)
{
var request = new RecentlyUpdatedMoviesGetRequest
{
ExtendedInfo = extendedInfo,
Page = page,
Limit = limit,
StartDate = startDate
};

return RequestHandler.ExecutePagedListRequestAsync<TraktUpdatedMovie>(_context, request, (uint? page, uint? limit)
=> new RecentlyUpdatedMoviesGetRequest
{
ExtendedInfo = extendedInfo,
Page = page,
Limit = limit,
StartDate = startDate
},
cancellationToken);
}

/// <summary>Gets recently updated movie Trakt IDs.</summary>
/// <param name="startDate">Specifies an optional UTC start datetime after which the queried movie IDs were updated.</param>
/// <param name="page">Specifies the page which should be queried. Defaults to the first page.</param>
/// <param name="limit">Specifies the number of items which should be queried per page. Defaults to 10.</param>
/// <param name="cancellationToken">
/// Propagates notification that the request should be canceled.<para/>
/// If provided, the exception <see cref="OperationCanceledException" /> should be catched.
/// </param>
/// <returns>
/// A paged response of type <see cref="TraktPagedResponse{TResponseContentType}" /> containing the queried updated movie Trakt IDs.
/// <para />
/// The response also contains information about the queried page number, the page's item count, maximum page count
/// and maximum item count.
/// <para />
/// See also <seealso cref="TraktPagedResponse{TResponseContentType}" />.
/// </returns>
/// <remarks>
/// OAuth authorization is not required.
/// <para><see href="https://trakt.docs.apiary.io/#reference/movies/updated-ids/get-recently-updated-movie-trakt-ids">
/// Trakt API Documentation: Movies: Updated IDS - Get recently updated movie Trakt IDs
/// </see></para>
/// </remarks>
/// <exception cref="TraktApiException">Thrown if the request fails.</exception>
public Task<TraktPagedResponse<uint>> GetRecentlyUpdatedMovieTraktIDsAsync(DateTime? startDate = null, uint? page = null, uint? limit = null,
CancellationToken cancellationToken = default)
{
var request = new RecentlyUpdatedMovieIdsGetRequest
{
Page = page,
Limit = limit,
StartDate = startDate
};

return RequestHandler.ExecutePagedListRequestAsync<uint>(_context, request, (uint? page, uint? limit)
=> new RecentlyUpdatedMovieIdsGetRequest
{
Page = page,
Limit = limit,
StartDate = startDate
},
cancellationToken);
}
}
}
1 change: 0 additions & 1 deletion src/libs/Trakt.NET/Responses/TraktPagedResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ namespace TraktNET
/// <summary>A Trakt paged list response with items of content type <typeparamref name="TResponseContentType" />.</summary>
/// <typeparam name="TResponseContentType">The content type of the list items.</typeparam>
public partial class TraktPagedResponse<TResponseContentType> : TraktListResponse<TResponseContentType>, ITraktPagedResponseHeaders
where TResponseContentType : class
{

/// <summary>The Trakt "X-Pagination-Page-Count" header.</summary>
Expand Down
70 changes: 70 additions & 0 deletions src/tests/libs/JsonData/Movies/boxofficemovie.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
{
"revenue": 52000000,
"movie": {
"title": "Beetlejuice Beetlejuice",
"year": 2024,
"ids": {
"trakt": 734869,
"slug": "beetlejuice-beetlejuice-2024",
"imdb": "tt2049403",
"tmdb": 917496
},
"tagline": "The ghost with the most is back.",
"overview": "After a family tragedy, three generations of the Deetz family return home to Winter River.",
"released": "2024-09-06",
"runtime": 105,
"country": "us",
"status": "released",
"rating": 7.16738,
"votes": 1631,
"comment_count": 29,
"trailer": "https://youtube.com/watch?v=As-vKW4ZboU",
"homepage": "http://www.beetlejuicemovie.com",
"updated_at": "2024-09-21T17:39:23.000Z",
"language": "en",
"languages": [
"en",
"it",
"es"
],
"available_translations": [
"ar",
"az",
"bg",
"ca",
"cs",
"de",
"el",
"en",
"es",
"fa",
"fi",
"fr",
"he",
"hr",
"hu",
"it",
"ja",
"ka",
"ko",
"nl",
"pl",
"pt",
"ru",
"sk",
"sl",
"sv",
"th",
"tr",
"uk",
"vi",
"zh"
],
"genres": [
"comedy",
"fantasy",
"horror"
],
"certification": "PG-13"
}
}
Loading

0 comments on commit 1baa2f8

Please sign in to comment.