mirror of
https://github.com/Sarsoo/Spotify.NET.git
synced 2024-12-23 14:46:26 +00:00
Pagination implementation adapted - Less methods,more defaults #451
This commit is contained in:
parent
7445d3ca0e
commit
5ae126699c
@ -59,7 +59,7 @@ namespace Example.CLI.PersistentConfig
|
||||
var me = await spotify.UserProfile.Current();
|
||||
Console.WriteLine($"Welcome {me.DisplayName} ({me.Id}), your authenticated!");
|
||||
|
||||
var playlists = await spotify.PaginateAll(() => spotify.Playlists.CurrentUsers());
|
||||
var playlists = await spotify.PaginateAll(spotify.Playlists.CurrentUsers());
|
||||
Console.WriteLine($"Total Playlists in your Account: {playlists.Count}");
|
||||
|
||||
_server.Dispose();
|
||||
|
@ -4,14 +4,60 @@ namespace SpotifyAPI.Web
|
||||
{
|
||||
public interface IShowsClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Get Spotify catalog information for a single show identified by its unique Spotify ID.
|
||||
/// </summary>
|
||||
/// <param name="showId">The Spotify ID for the show.</param>
|
||||
/// <remarks>
|
||||
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-a-show
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")]
|
||||
Task<FullShow> Get(string showId);
|
||||
|
||||
/// <summary>
|
||||
/// Get Spotify catalog information for a single show identified by its unique Spotify ID.
|
||||
/// </summary>
|
||||
/// <param name="showId">The Spotify ID for the show.</param>
|
||||
/// <param name="request">The request-model which contains required and optional parameters.</param>
|
||||
/// <remarks>
|
||||
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-a-show
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")]
|
||||
Task<FullShow> Get(string showId, ShowRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Get Spotify catalog information for several shows based on their Spotify IDs.
|
||||
/// </summary>
|
||||
/// <param name="request">The request-model which contains required and optional parameters.</param>
|
||||
/// <remarks>
|
||||
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-multiple-shows
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
Task<ShowsResponse> GetSeveral(ShowsRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Get Spotify catalog information about an show’s episodes.
|
||||
/// Optional parameters can be used to limit the number of episodes returned.
|
||||
/// </summary>
|
||||
/// <param name="showId">The Spotify ID for the show.</param>
|
||||
/// <remarks>
|
||||
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-a-shows-episodes
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
Task<Paging<SimpleEpisode>> GetEpisodes(string showId);
|
||||
|
||||
/// <summary>
|
||||
/// Get Spotify catalog information about an show’s episodes.
|
||||
/// Optional parameters can be used to limit the number of episodes returned.
|
||||
/// </summary>
|
||||
/// <param name="showId">The Spotify ID for the show.</param>
|
||||
/// <param name="request">The request-model which contains required and optional parameters.</param>
|
||||
/// <remarks>
|
||||
/// https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-a-shows-episodes
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
Task<Paging<SimpleEpisode>> GetEpisodes(string showId, ShowEpisodesRequest request);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using System.Threading;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
@ -7,56 +8,296 @@ namespace SpotifyAPI.Web
|
||||
{
|
||||
public interface ISpotifyClient
|
||||
{
|
||||
/// <summary>
|
||||
/// The default paginator used by the Paginator methods
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IPaginator DefaultPaginator { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify User Profiles
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IUserProfileClient UserProfile { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Browse Endpoints
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IBrowseClient Browse { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Shows
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IShowsClient Shows { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Playlists
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IPlaylistsClient Playlists { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Search
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
ISearchClient Search { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Follows
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IFollowClient Follow { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Tracks
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
ITracksClient Tracks { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Player Endpoints
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IPlayerClient Player { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Albums
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IAlbumsClient Albums { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Artists
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IArtistsClient Artists { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Personalization Endpoints
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IPersonalizationClient Personalization { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify Podcast Episodes
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IEpisodesClient Episodes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Operations related to Spotify User Library
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
ILibraryClient Library { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns the last response received by an API call.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
IResponse? LastResponse { get; }
|
||||
|
||||
Task<IList<T>> PaginateAll<T>(Paging<T> firstPage);
|
||||
Task<IList<T>> PaginateAll<T>(Paging<T> firstPage, IPaginator paginator);
|
||||
Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage);
|
||||
Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator);
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">The first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
Task<IList<T>> PaginateAll<T>(Paging<T> firstPage, IPaginator? paginator = default!);
|
||||
|
||||
Task<IList<T>> PaginateAll<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper);
|
||||
Task<IList<T>> PaginateAll<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper, IPaginator paginator);
|
||||
Task<IList<T>> PaginateAll<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper);
|
||||
Task<IList<T>> PaginateAll<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper, IPaginator paginator);
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator? paginator = default!);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
Task<IList<T>> PaginateAll<T>(Task<Paging<T>> firstPageTask, IPaginator? paginator = default!);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">A first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Paging<T, TNext> firstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = default!
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Func<Task<Paging<T, TNext>>> getFirstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = default!
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A Task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Task<Paging<T, TNext>> firstPageTask,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = default!
|
||||
);
|
||||
|
||||
#if NETSTANDARD2_1
|
||||
IAsyncEnumerable<T> Paginate<T>(Paging<T> firstPage);
|
||||
IAsyncEnumerable<T> Paginate<T>(Paging<T> firstPage, IPaginator paginator);
|
||||
IAsyncEnumerable<T> Paginate<T>(Func<Task<Paging<T>>> getFirstPage);
|
||||
IAsyncEnumerable<T> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator);
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">A first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>An iterable IAsyncEnumerable</returns>
|
||||
IAsyncEnumerable<T> Paginate<T>(
|
||||
Paging<T> firstPage,
|
||||
IPaginator? paginator = default!,
|
||||
CancellationToken cancellationToken = default!
|
||||
);
|
||||
|
||||
IAsyncEnumerable<T> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper);
|
||||
IAsyncEnumerable<T> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper, IPaginator paginator);
|
||||
IAsyncEnumerable<T> Paginate<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper);
|
||||
IAsyncEnumerable<T> Paginate<T, TNext>(Func<Task<Paging<T, TNext>>> getFirstPage, Func<TNext, Paging<T, TNext>> mapper, IPaginator paginator);
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A Function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>An iterable IAsyncEnumerable</returns>
|
||||
IAsyncEnumerable<T> Paginate<T>(
|
||||
Func<Task<Paging<T>>> getFirstPage,
|
||||
IPaginator? paginator = default!,
|
||||
CancellationToken cancellationToken = default!
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A Task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>An iterable IAsyncEnumerable</returns>
|
||||
IAsyncEnumerable<T> Paginate<T>(
|
||||
Task<Paging<T>> firstPageTask,
|
||||
IPaginator? paginator = default!,
|
||||
CancellationToken cancellationToken = default!
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">A first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<T> Paginate<T, TNext>(
|
||||
Paging<T, TNext> firstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = default!,
|
||||
CancellationToken cancellationToken = default!
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A Function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<T> Paginate<T, TNext>(
|
||||
Func<Task<Paging<T, TNext>>> getFirstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = default!,
|
||||
CancellationToken cancellationToken = default!
|
||||
);
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A Task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
IAsyncEnumerable<T> Paginate<T, TNext>(
|
||||
Task<Paging<T, TNext>> firstPageTask,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = default!,
|
||||
CancellationToken cancellationToken = default!
|
||||
);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using SpotifyAPI.Web.Http;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
@ -80,157 +82,287 @@ namespace SpotifyAPI.Web
|
||||
|
||||
public IResponse? LastResponse { get; private set; }
|
||||
|
||||
public Task<IList<T>> PaginateAll<T>(Paging<T> firstPage)
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">The first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
public Task<IList<T>> PaginateAll<T>(Paging<T> firstPage, IPaginator? paginator = null)
|
||||
{
|
||||
return DefaultPaginator.PaginateAll(firstPage, _apiConnector);
|
||||
return (paginator ?? DefaultPaginator).PaginateAll(firstPage, _apiConnector);
|
||||
}
|
||||
|
||||
public Task<IList<T>> PaginateAll<T>(Paging<T> firstPage, IPaginator paginator)
|
||||
{
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
|
||||
return paginator.PaginateAll(firstPage, _apiConnector);
|
||||
}
|
||||
|
||||
public async Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage)
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
public async Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator? paginator = null)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
|
||||
return await DefaultPaginator.PaginateAll(
|
||||
await getFirstPage().ConfigureAwait(false), _apiConnector
|
||||
).ConfigureAwait(false);
|
||||
var firstPage = await getFirstPage().ConfigureAwait(false);
|
||||
return await (paginator ?? DefaultPaginator).PaginateAll(firstPage, _apiConnector).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public async Task<IList<T>> PaginateAll<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator)
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
public async Task<IList<T>> PaginateAll<T>(Task<Paging<T>> firstPageTask, IPaginator? paginator = null)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
Ensure.ArgumentNotNull(firstPageTask, nameof(firstPageTask));
|
||||
|
||||
return await paginator.PaginateAll(
|
||||
await getFirstPage().ConfigureAwait(false), _apiConnector
|
||||
).ConfigureAwait(false);
|
||||
var firstPage = await firstPageTask.ConfigureAwait(false);
|
||||
return await (paginator ?? DefaultPaginator).PaginateAll(firstPage, _apiConnector).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Paging<T, TNext> firstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper
|
||||
)
|
||||
{
|
||||
return DefaultPaginator.PaginateAll(firstPage, mapper, _apiConnector);
|
||||
}
|
||||
|
||||
public async Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Func<Task<Paging<T, TNext>>> getFirstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper
|
||||
)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
|
||||
return await DefaultPaginator.PaginateAll(await getFirstPage().ConfigureAwait(false), mapper, _apiConnector).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">A first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>A list containing all fetched pages</returns>
|
||||
public Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Paging<T, TNext> firstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator paginator)
|
||||
IPaginator? paginator = null
|
||||
)
|
||||
{
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
|
||||
return paginator.PaginateAll(firstPage, mapper, _apiConnector);
|
||||
return (paginator ?? DefaultPaginator).PaginateAll(firstPage, mapper, _apiConnector);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
public async Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Func<Task<Paging<T, TNext>>> getFirstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator paginator
|
||||
IPaginator? paginator = null
|
||||
)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
|
||||
return await paginator.PaginateAll(
|
||||
await getFirstPage().ConfigureAwait(false), mapper, _apiConnector
|
||||
).ConfigureAwait(false);
|
||||
var firstPage = await getFirstPage().ConfigureAwait(false);
|
||||
return await (paginator ?? DefaultPaginator).PaginateAll(firstPage, mapper, _apiConnector).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches all pages and returns them grouped in a list.
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A Task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
public async Task<IList<T>> PaginateAll<T, TNext>(
|
||||
Task<Paging<T, TNext>> firstPageTask,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = null
|
||||
)
|
||||
{
|
||||
Ensure.ArgumentNotNull(firstPageTask, nameof(firstPageTask));
|
||||
|
||||
var firstPage = await firstPageTask.ConfigureAwait(false);
|
||||
return await (paginator ?? DefaultPaginator).PaginateAll(firstPage, mapper, _apiConnector).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
#if NETSTANDARD2_1
|
||||
public IAsyncEnumerable<T> Paginate<T>(Paging<T> firstPage)
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">A first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>An iterable IAsyncEnumerable</returns>
|
||||
public IAsyncEnumerable<T> Paginate<T>(
|
||||
Paging<T> firstPage,
|
||||
IPaginator? paginator = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
return DefaultPaginator.Paginate(firstPage, _apiConnector);
|
||||
return (paginator ?? DefaultPaginator).Paginate(firstPage, _apiConnector, cancellationToken);
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<T> Paginate<T>(Paging<T> firstPage, IPaginator paginator)
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A Function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>An iterable IAsyncEnumerable</returns>
|
||||
public async IAsyncEnumerable<T> Paginate<T>(
|
||||
Func<Task<Paging<T>>> getFirstPage,
|
||||
IPaginator? paginator = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
|
||||
return paginator.Paginate(firstPage, _apiConnector);
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<T> Paginate<T>(Func<Task<Paging<T>>> getFirstPage)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
|
||||
var firstPage = await getFirstPage().ConfigureAwait(false);
|
||||
await foreach (var item in DefaultPaginator.Paginate(firstPage, _apiConnector))
|
||||
await foreach (var item in (paginator ?? DefaultPaginator)
|
||||
.Paginate(firstPage, _apiConnector)
|
||||
.WithCancellation(cancellationToken)
|
||||
)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
public async IAsyncEnumerable<T> Paginate<T>(Func<Task<Paging<T>>> getFirstPage, IPaginator paginator)
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A Task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <returns>An iterable IAsyncEnumerable</returns>
|
||||
public async IAsyncEnumerable<T> Paginate<T>(
|
||||
Task<Paging<T>> firstPageTask,
|
||||
IPaginator? paginator = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
Ensure.ArgumentNotNull(firstPageTask, nameof(firstPageTask));
|
||||
|
||||
var firstPage = await getFirstPage().ConfigureAwait(false);
|
||||
await foreach (var item in DefaultPaginator.Paginate(firstPage, _apiConnector))
|
||||
var firstPage = await firstPageTask.ConfigureAwait(false);
|
||||
await foreach (var item in (paginator ?? DefaultPaginator)
|
||||
.Paginate(firstPage, _apiConnector)
|
||||
.WithCancellation(cancellationToken)
|
||||
)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
public IAsyncEnumerable<T> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper)
|
||||
{
|
||||
return DefaultPaginator.Paginate(firstPage, mapper, _apiConnector);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPage">A first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
public IAsyncEnumerable<T> Paginate<T, TNext>(
|
||||
Paging<T, TNext> firstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator paginator
|
||||
IPaginator? paginator = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
|
||||
return paginator.Paginate(firstPage, mapper, _apiConnector);
|
||||
return (paginator ?? DefaultPaginator).Paginate(firstPage, mapper, _apiConnector, cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="getFirstPage">A Function to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
public async IAsyncEnumerable<T> Paginate<T, TNext>(
|
||||
Func<Task<Paging<T, TNext>>> getFirstPage,
|
||||
Func<TNext, Paging<T, TNext>> mapper
|
||||
)
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator? paginator = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
|
||||
var firstPage = await getFirstPage().ConfigureAwait(false);
|
||||
await foreach (var item in DefaultPaginator.Paginate(firstPage, mapper, _apiConnector))
|
||||
await foreach (var item in (paginator ?? DefaultPaginator)
|
||||
.Paginate(firstPage, mapper, _apiConnector)
|
||||
.WithCancellation(cancellationToken)
|
||||
)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Paginate through pages by using IAsyncEnumerable, introduced in C# 8
|
||||
/// Some responses (e.g search response) have the pagination nested in a JSON Property.
|
||||
/// To workaround this limitation, the mapper is required and needs to point to the correct next pagination.
|
||||
/// The default paginator will fetch all available resources without a delay between requests.
|
||||
/// This can drain your request limit quite fast, so consider using a custom paginator with delays.
|
||||
/// </summary>
|
||||
/// <param name="firstPageTask">A Task to retrive the first page, will be included in the output list!</param>
|
||||
/// <param name="mapper">A function which maps response objects to the next paging object</param>
|
||||
/// <param name="paginator">Optional. If not supplied, DefaultPaginator will be used</param>
|
||||
/// <param name="cancellationToken">An optional Cancellation Token</param>
|
||||
/// <typeparam name="T">The Paging-Type</typeparam>
|
||||
/// <typeparam name="TNext">The Response-Type</typeparam>
|
||||
/// <returns></returns>
|
||||
public async IAsyncEnumerable<T> Paginate<T, TNext>(
|
||||
Func<Task<Paging<T, TNext>>> getFirstPage,
|
||||
Task<Paging<T, TNext>> firstPageTask,
|
||||
Func<TNext, Paging<T, TNext>> mapper,
|
||||
IPaginator paginator
|
||||
)
|
||||
IPaginator? paginator = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
Ensure.ArgumentNotNull(getFirstPage, nameof(getFirstPage));
|
||||
Ensure.ArgumentNotNull(paginator, nameof(paginator));
|
||||
Ensure.ArgumentNotNull(firstPageTask, nameof(firstPageTask));
|
||||
|
||||
var firstPage = await getFirstPage().ConfigureAwait(false);
|
||||
await foreach (var item in paginator.Paginate(firstPage, mapper, _apiConnector))
|
||||
var firstPage = await firstPageTask.ConfigureAwait(false);
|
||||
await foreach (var item in (paginator ?? DefaultPaginator)
|
||||
.Paginate(firstPage, mapper, _apiConnector)
|
||||
.WithCancellation(cancellationToken)
|
||||
)
|
||||
{
|
||||
yield return item;
|
||||
}
|
||||
|
@ -2,12 +2,30 @@ namespace SpotifyAPI.Web
|
||||
{
|
||||
public class ShowEpisodesRequest : RequestParams
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum number of episodes to return. Default: 20. Minimum: 1. Maximum: 50.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[QueryParam("limit")]
|
||||
public int? Limit { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The index of the first episode to return.
|
||||
/// Default: 0 (the first object). Use with limit to get the next set of episodes.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[QueryParam("offset")]
|
||||
public int? Offset { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// An ISO 3166-1 alpha-2 country code. If a country code is specified, only shows and episodes
|
||||
/// that are available in that market will be returned.
|
||||
/// If a valid user access token is specified in the request header,
|
||||
/// the country associated with the user account will take priority over this parameter.
|
||||
/// Note: If neither market or user country are provided, the content is considered unavailable for the client.
|
||||
/// Users can view the country that is associated with their account in the account settings.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[QueryParam("market")]
|
||||
public string? Market { get; set; }
|
||||
}
|
||||
|
@ -2,6 +2,16 @@ namespace SpotifyAPI.Web
|
||||
{
|
||||
public class ShowRequest : RequestParams
|
||||
{
|
||||
/// <summary>
|
||||
/// An ISO 3166-1 alpha-2 country code. If a country code is specified,
|
||||
/// only shows and episodes that are available in that market will be returned.
|
||||
/// If a valid user access token is specified in the request header,
|
||||
/// the country associated with the user account will take priority over this parameter.
|
||||
/// Note: If neither market or user country are provided, the content
|
||||
/// is considered unavailable for the client.
|
||||
/// Users can view the country that is associated with their account in the account settings.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[QueryParam("market")]
|
||||
public string? Market { get; set; }
|
||||
}
|
||||
|
@ -4,6 +4,12 @@ namespace SpotifyAPI.Web
|
||||
{
|
||||
public class ShowsRequest : RequestParams
|
||||
{
|
||||
/// <summary>
|
||||
/// Get Spotify catalog information for several shows based on their Spotify IDs.
|
||||
/// </summary>
|
||||
/// <param name="ids">
|
||||
/// A comma-separated list of the Spotify IDs for the shows. Maximum: 50 IDs.
|
||||
/// </param>
|
||||
public ShowsRequest(IList<string> ids)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyList(ids, nameof(ids));
|
||||
@ -11,9 +17,23 @@ namespace SpotifyAPI.Web
|
||||
Ids = ids;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A comma-separated list of the Spotify IDs for the shows. Maximum: 50 IDs.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[QueryParam("ids")]
|
||||
public IList<string> Ids { get; }
|
||||
|
||||
/// <summary>
|
||||
/// An ISO 3166-1 alpha-2 country code. If a country code is specified, only shows and episodes
|
||||
/// that are available in that market will be returned.
|
||||
/// If a valid user access token is specified in the request header,
|
||||
/// the country associated with the user account will take priority over this parameter.
|
||||
/// Note: If neither market or user country are provided,
|
||||
/// the content is considered unavailable for the client.
|
||||
/// Users can view the country that is associated with their account in the account settings.
|
||||
/// </summary>
|
||||
/// <value></value>
|
||||
[QueryParam("market")]
|
||||
public string? Market { get; set; }
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ namespace SpotifyAPI.Web
|
||||
{
|
||||
public class CategoriesResponse
|
||||
{
|
||||
public Paging<Category> Categories { get; set; } = default!;
|
||||
public Paging<Category, CategoriesResponse> Categories { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ namespace SpotifyAPI.Web
|
||||
{
|
||||
public class CategoryPlaylistsResponse
|
||||
{
|
||||
public Paging<SimplePlaylist> Playlists { get; set; } = default!;
|
||||
public Paging<SimplePlaylist, CategoryPlaylistsResponse> Playlists { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ namespace SpotifyAPI.Web
|
||||
public class FeaturedPlaylistsResponse
|
||||
{
|
||||
public string Message { get; set; } = default!;
|
||||
public Paging<SimplePlaylist> Playlists { get; set; } = default!;
|
||||
public Paging<SimplePlaylist, FeaturedPlaylistsResponse> Playlists { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ namespace SpotifyAPI.Web
|
||||
public class NewReleasesResponse
|
||||
{
|
||||
public string Message { get; set; } = default!;
|
||||
public Paging<SimpleAlbum> Albums { get; set; } = default!;
|
||||
public Paging<SimpleAlbum, NewReleasesResponse> Albums { get; set; } = default!;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user