Added Episodes Client and restructured config #451

This commit is contained in:
Jonas Dellinger 2020-05-11 18:43:52 +02:00
parent 0cd3027c28
commit cc42c3971f
9 changed files with 153 additions and 47 deletions

View File

@ -0,0 +1,33 @@
using System.Threading.Tasks;
using SpotifyAPI.Web.Http;
using URLs = SpotifyAPI.Web.SpotifyUrls;
namespace SpotifyAPI.Web
{
public class EpisodesClient : APIClient, IEpisodesClient
{
public EpisodesClient(IAPIConnector apiConnector) : base(apiConnector) { }
public Task<FullEpisode> Get(string episodeId)
{
Ensure.ArgumentNotNullOrEmptyString(episodeId, nameof(episodeId));
return API.Get<FullEpisode>(URLs.Episode(episodeId));
}
public Task<FullEpisode> Get(string episodeId, EpisodeRequest request)
{
Ensure.ArgumentNotNullOrEmptyString(episodeId, nameof(episodeId));
Ensure.ArgumentNotNull(request, nameof(request));
return API.Get<FullEpisode>(URLs.Episode(episodeId), request.BuildQueryParams());
}
public Task<EpisodesResponse> GetSeveral(EpisodesRequest request)
{
Ensure.ArgumentNotNull(request, nameof(request));
return API.Get<EpisodesResponse>(URLs.Episodes(), request.BuildQueryParams());
}
}
}

View File

@ -0,0 +1,15 @@
using System.Threading.Tasks;
namespace SpotifyAPI.Web
{
public interface IEpisodesClient
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")]
Task<FullEpisode> Get(string episodeId);
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1716")]
Task<FullEpisode> Get(string episodeId, EpisodeRequest request);
Task<EpisodesResponse> GetSeveral(EpisodesRequest request);
}
}

View File

@ -30,6 +30,8 @@ namespace SpotifyAPI.Web
IPersonalizationClient Personalization { get; } IPersonalizationClient Personalization { get; }
IEpisodesClient Episodes { get; }
Task<List<T>> Paginate<T>(Paging<T> firstPage); Task<List<T>> Paginate<T>(Paging<T> firstPage);
Task<List<T>> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper); Task<List<T>> Paginate<T, TNext>(Paging<T, TNext> firstPage, Func<TNext, Paging<T, TNext>> mapper);
Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage); Task<List<T>> Paginate<T>(Func<Task<Paging<T>>> getFirstPage);

View File

@ -18,7 +18,7 @@ namespace SpotifyAPI.Web
Ensure.ArgumentNotNull(config, nameof(config)); Ensure.ArgumentNotNull(config, nameof(config));
_apiConnector = config.CreateAPIConnector(); _apiConnector = config.CreateAPIConnector();
DefaultPaginator = config.Paginator; DefaultPaginator = config.DefaultPaginator;
UserProfile = new UserProfileClient(_apiConnector); UserProfile = new UserProfileClient(_apiConnector);
Browse = new BrowseClient(_apiConnector); Browse = new BrowseClient(_apiConnector);
Shows = new ShowsClient(_apiConnector); Shows = new ShowsClient(_apiConnector);
@ -30,6 +30,7 @@ namespace SpotifyAPI.Web
Albums = new AlbumsClient(_apiConnector); Albums = new AlbumsClient(_apiConnector);
Artists = new ArtistsClient(_apiConnector); Artists = new ArtistsClient(_apiConnector);
Personalization = new PersonalizationClient(_apiConnector); Personalization = new PersonalizationClient(_apiConnector);
Episodes = new EpisodesClient(_apiConnector);
} }
public IPaginator DefaultPaginator { get; } public IPaginator DefaultPaginator { get; }
@ -56,6 +57,8 @@ namespace SpotifyAPI.Web
public IPersonalizationClient Personalization { get; } public IPersonalizationClient Personalization { get; }
public IEpisodesClient Episodes { get; }
public Task<List<T>> Paginate<T>(Paging<T> firstPage) public Task<List<T>> Paginate<T>(Paging<T> firstPage)
{ {
return DefaultPaginator.Paginate(firstPage, _apiConnector); return DefaultPaginator.Paginate(firstPage, _apiConnector);

View File

@ -5,19 +5,16 @@ namespace SpotifyAPI.Web
{ {
public class SpotifyClientConfig public class SpotifyClientConfig
{ {
public Uri BaseAddress { get; } public Uri BaseAddress { get; private set; }
public IAuthenticator Authenticator { get; } public IAuthenticator Authenticator { get; private set; }
public IJSONSerializer JSONSerializer { get; } public IJSONSerializer JSONSerializer { get; private set; }
public IHTTPClient HTTPClient { get; } public IHTTPClient HTTPClient { get; private set; }
public IHTTPLogger HTTPLogger { get; } public IHTTPLogger HTTPLogger { get; private set; }
public IPaginator Paginator { get; set; } public IRetryHandler RetryHandler { get; private set; }
public IPaginator DefaultPaginator { get; private set; }
public IRetryHandler RetryHandler { get; }
/// <summary> /// <summary>
/// This config spefies the internal parts of the SpotifyClient. /// This config spefies the internal parts of the SpotifyClient.
/// In apps where multiple different access tokens are used, one should create a default config and then use
/// <see cref="WithToken" /> or <see cref="WithAuthenticator" /> to specify the auth details.
/// </summary> /// </summary>
/// <param name="baseAddress"></param> /// <param name="baseAddress"></param>
/// <param name="authenticator"></param> /// <param name="authenticator"></param>
@ -42,77 +39,92 @@ namespace SpotifyAPI.Web
HTTPClient = httpClient; HTTPClient = httpClient;
RetryHandler = retryHandler; RetryHandler = retryHandler;
HTTPLogger = httpLogger; HTTPLogger = httpLogger;
Paginator = paginator; DefaultPaginator = paginator;
} }
internal IAPIConnector CreateAPIConnector() internal IAPIConnector CreateAPIConnector()
{ {
Ensure.ArgumentNotNull(BaseAddress, nameof(BaseAddress)); return new APIConnector(
Ensure.ArgumentNotNull(Authenticator, nameof(Authenticator)); BaseAddress,
Ensure.ArgumentNotNull(JSONSerializer, nameof(JSONSerializer)); Authenticator,
Ensure.ArgumentNotNull(HTTPClient, nameof(HTTPClient)); JSONSerializer,
HTTPClient,
return new APIConnector(BaseAddress, Authenticator, JSONSerializer, HTTPClient, RetryHandler, HTTPLogger); RetryHandler,
HTTPLogger
);
} }
public SpotifyClientConfig WithToken(string token, string tokenType = "Bearer") public void AddToken(string token, string tokenType = "Bearer")
{ {
Ensure.ArgumentNotNull(token, nameof(token)); Ensure.ArgumentNotNull(token, nameof(token));
Authenticator = new TokenHeaderAuthenticator(token, tokenType);
return WithAuthenticator(new TokenHeaderAuthenticator(token, tokenType));
} }
public SpotifyClientConfig WithRetryHandler(IRetryHandler retryHandler) public void AddRetryHandler(IRetryHandler retryHandler)
{ {
return new SpotifyClientConfig( RetryHandler = retryHandler;
BaseAddress, Authenticator, JSONSerializer, HTTPClient, retryHandler, HTTPLogger, Paginator);
} }
public SpotifyClientConfig WithAuthenticator(IAuthenticator authenticator) public void AddAuthenticator(IAuthenticator authenticator)
{ {
return new SpotifyClientConfig( Ensure.ArgumentNotNull(authenticator, nameof(authenticator));
BaseAddress, authenticator, JSONSerializer, HTTPClient, RetryHandler, HTTPLogger, Paginator);
Authenticator = authenticator;
} }
public SpotifyClientConfig WithHTTPLogger(IHTTPLogger httpLogger) public void AddHTTPLogger(IHTTPLogger httpLogger)
{ {
return new SpotifyClientConfig( HTTPLogger = httpLogger;
BaseAddress, Authenticator, JSONSerializer, HTTPClient, RetryHandler, httpLogger, Paginator);
} }
public SpotifyClientConfig WithPaginator(IPaginator paginator) public void AddHTTPClient(IHTTPClient httpClient)
{ {
return new SpotifyClientConfig( Ensure.ArgumentNotNull(httpClient, nameof(httpClient));
BaseAddress, Authenticator, JSONSerializer, HTTPClient, RetryHandler, HTTPLogger, paginator);
HTTPClient = httpClient;
}
public void AddJSONSerializer(IJSONSerializer jsonSerializer)
{
Ensure.ArgumentNotNull(jsonSerializer, nameof(jsonSerializer));
JSONSerializer = jsonSerializer;
}
public void AddDefaultPaginator(IPaginator paginator)
{
DefaultPaginator = paginator;
} }
public static SpotifyClientConfig CreateDefault(string token, string tokenType = "Bearer") public static SpotifyClientConfig CreateDefault(string token, string tokenType = "Bearer")
{ {
Ensure.ArgumentNotNull(token, nameof(token)); return CreateDefault(options =>
{
return CreateDefault(new TokenHeaderAuthenticator(token, tokenType)); options.AddToken(token, tokenType);
});
} }
/// <summary> public static SpotifyClientConfig CreateDefault(Action<SpotifyClientConfig> optionsCallback)
/// Creates a default configuration, which is not useable without calling <see cref="WithToken" /> or
/// <see cref="WithAuthenticator" />
/// </summary>
public static SpotifyClientConfig CreateDefault()
{ {
return CreateDefault(null); Ensure.ArgumentNotNull(optionsCallback, nameof(optionsCallback));
}
public static SpotifyClientConfig CreateDefault(IAuthenticator authenticator) var config = new SpotifyClientConfig(
{
return new SpotifyClientConfig(
SpotifyUrls.APIV1, SpotifyUrls.APIV1,
authenticator, null,
new NewtonsoftJSONSerializer(), new NewtonsoftJSONSerializer(),
new NetHttpClient(), new NetHttpClient(),
null, null,
null, null,
new SimplePaginator() new SimplePaginator()
); );
optionsCallback(config);
if (config.Authenticator == null)
{
throw new NullReferenceException("The authenticator was not set after the options callback was run. Please specify a token with AddToken or AddAuthenticator");
}
return config;
} }
} }
} }

View File

@ -0,0 +1,8 @@
namespace SpotifyAPI.Web
{
public class EpisodeRequest : RequestParams
{
[QueryParam("market")]
public string Market { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System.Collections.Generic;
namespace SpotifyAPI.Web
{
public class EpisodesRequest : RequestParams
{
public EpisodesRequest(IList<string> ids)
{
Ensure.ArgumentNotNullOrEmptyList(ids, nameof(ids));
Ids = ids;
}
[QueryParam("ids")]
public IList<string> Ids { get; set; }
[QueryParam("market")]
public string Market { get; set; }
}
}

View File

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace SpotifyAPI.Web
{
public class EpisodesResponse
{
public List<FullEpisode> Episodes { get; set; }
}
}

View File

@ -105,6 +105,10 @@ namespace SpotifyAPI.Web
public static Uri PersonalizationTop(string type) => EUri($"me/top/{type}"); public static Uri PersonalizationTop(string type) => EUri($"me/top/{type}");
public static Uri Episode(string episodeId) => EUri($"episodes/{episodeId}");
public static Uri Episodes() => EUri($"episodes");
private static Uri EUri(FormattableString path) => new Uri(path.ToString(_provider), UriKind.Relative); private static Uri EUri(FormattableString path) => new Uri(path.ToString(_provider), UriKind.Relative);
} }
} }