mirror of
https://github.com/Sarsoo/Spotify.NET.git
synced 2025-01-11 06:07:45 +00:00
Start refactoring for version 6
This commit is contained in:
parent
22d800d487
commit
2c4463529b
18
.vscode/csharp.code-snippets
vendored
Normal file
18
.vscode/csharp.code-snippets
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"model": {
|
||||
"scope": "csharp",
|
||||
"prefix": "model",
|
||||
"body": [
|
||||
"namespace SpotifyAPI.Web",
|
||||
"{",
|
||||
" public class $1",
|
||||
" {",
|
||||
" public ${2:string} ${3:Name} { get; set; }",
|
||||
"",
|
||||
" $4",
|
||||
" }",
|
||||
"}"
|
||||
],
|
||||
"description": "Creates a new model"
|
||||
}
|
||||
}
|
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@ -2,6 +2,4 @@
|
||||
"editor.detectIndentation": false,
|
||||
"editor.insertSpaces": true,
|
||||
"editor.tabSize": 2,
|
||||
"csharpfixformat.style.braces.onSameLine": false,
|
||||
"csharpfixformat.style.spaces.beforeParenthesis": false,
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
|
||||
<TargetFrameworks>netstandard2.1</TargetFrameworks>
|
||||
|
||||
<PackageId>SpotifyAPI.Web.Auth</PackageId>
|
||||
<Title>SpotifyAPI.Web.Auth</Title>
|
||||
<Authors>Jonas Dellinger</Authors>
|
||||
@ -27,7 +27,7 @@
|
||||
<DocumentationFile>bin\Release\netstandard2.0\SpotifyAPI.Web.Auth.xml</DocumentationFile>
|
||||
<NoWarn>1701;1702;1705;1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="EmbedIO" Version="2.9.2">
|
||||
<PrivateAssets>None</PrivateAssets>
|
||||
|
@ -1,79 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Moq;
|
||||
using Newtonsoft.Json;
|
||||
using NUnit.Framework;
|
||||
using SpotifyAPI.Web.Models;
|
||||
|
||||
namespace SpotifyAPI.Web.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class SpotifyWebAPITest
|
||||
{
|
||||
private static readonly string FixtureDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "../../../fixtures/");
|
||||
|
||||
private Mock<IClient> _mock;
|
||||
private SpotifyWebAPI _spotify;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_mock = new Mock<IClient>();
|
||||
_spotify = new SpotifyWebAPI
|
||||
{
|
||||
WebClient = _mock.Object,
|
||||
UseAuth = false
|
||||
};
|
||||
}
|
||||
|
||||
private static T GetFixture<T>(string file)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<T>(File.ReadAllText(Path.Combine(FixtureDir, file)));
|
||||
}
|
||||
|
||||
private static bool ContainsValues(string str, params string[] values)
|
||||
{
|
||||
return values.All(str.Contains);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldGetPrivateProfile_WithoutAuth()
|
||||
{
|
||||
_spotify.UseAuth = false;
|
||||
|
||||
Assert.Throws<InvalidOperationException>(() => _spotify.GetPrivateProfile());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldGetPrivateProfile_WithAuth()
|
||||
{
|
||||
PrivateProfile profile = GetFixture<PrivateProfile>("private-user.json");
|
||||
_mock.Setup(client => client.DownloadJson<PrivateProfile>(It.IsAny<string>(), It.IsAny<Dictionary<string, string>>()))
|
||||
.Returns(new Tuple<ResponseInfo, PrivateProfile>(ResponseInfo.Empty, profile));
|
||||
|
||||
_spotify.UseAuth = true;
|
||||
Assert.AreEqual(profile, _spotify.GetPrivateProfile());
|
||||
_mock.Verify(client => client.DownloadJson<PrivateProfile>(
|
||||
It.Is<string>(str => ContainsValues(str, "/me")),
|
||||
It.IsNotNull<Dictionary<string, string>>()), Times.Exactly(1));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShouldGetPublicProfile()
|
||||
{
|
||||
PublicProfile profile = GetFixture<PublicProfile>("public-user.json");
|
||||
_mock.Setup(client => client.DownloadJson<PublicProfile>(It.IsAny<string>(), It.IsAny<Dictionary<string, string>>()))
|
||||
.Returns(new Tuple<ResponseInfo, PublicProfile>(ResponseInfo.Empty, profile));
|
||||
|
||||
_spotify.UseAuth = false;
|
||||
Assert.AreEqual(profile, _spotify.GetPublicProfile("wizzler"));
|
||||
_mock.Verify(client => client.DownloadJson<PublicProfile>(
|
||||
It.Is<string>(str => ContainsValues(str, "/users/wizzler")),
|
||||
It.Is<Dictionary<string, string>>(headers => headers.Count == 0)), Times.Exactly(1));
|
||||
}
|
||||
|
||||
//Will add more tests once I decided if this is worth the effort (propably not?)
|
||||
}
|
||||
}
|
21
SpotifyAPI.Web.Tests/UtilTests/Test.cs
Normal file
21
SpotifyAPI.Web.Tests/UtilTests/Test.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace SpotifyAPI.Web.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class Test
|
||||
{
|
||||
[Test]
|
||||
public async Task Testing()
|
||||
{
|
||||
var token = "";
|
||||
|
||||
var spotify = new SpotifyClient(token);
|
||||
|
||||
var categories = await spotify.Browse.GetCategories();
|
||||
var playlists = await spotify.Browse.GetCategoryPlaylists(categories.Categories.Items[0].Id);
|
||||
}
|
||||
}
|
||||
}
|
51
SpotifyAPI.Web.Tests/UtilTests/URIExtensionTest.cs
Normal file
51
SpotifyAPI.Web.Tests/UtilTests/URIExtensionTest.cs
Normal file
@ -0,0 +1,51 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace SpotifyAPI.Web.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class URIExtensionTest
|
||||
{
|
||||
[Test]
|
||||
public void ApplyParameters_WithoutExistingParameters()
|
||||
{
|
||||
var expected = "http://google.com/?hello=world&nice=day";
|
||||
Uri uri = new Uri("http://google.com/");
|
||||
|
||||
var parameters = new Dictionary<string, string>
|
||||
{
|
||||
{ "hello", "world" },
|
||||
{ "nice", "day" }
|
||||
};
|
||||
Assert.AreEqual(expected, uri.ApplyParameters(parameters).ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ApplyParameters_WithExistingParameters()
|
||||
{
|
||||
var expected = "http://google.com/?existing=paramter&hello=world&nice=day";
|
||||
Uri uri = new Uri("http://google.com/?existing=paramter");
|
||||
|
||||
var parameters = new Dictionary<string, string>
|
||||
{
|
||||
{ "hello", "world" },
|
||||
{ "nice", "day" }
|
||||
};
|
||||
Assert.AreEqual(expected, uri.ApplyParameters(parameters).ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ApplyParameters_HandlesEscape()
|
||||
{
|
||||
var expected = "http://google.com/?existing=paramter&hello=%26world++";
|
||||
Uri uri = new Uri("http://google.com/?existing=paramter");
|
||||
|
||||
var parameters = new Dictionary<string, string>
|
||||
{
|
||||
{ "hello", "&world " },
|
||||
};
|
||||
Assert.AreEqual(expected, uri.ApplyParameters(parameters).ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace SpotifyAPI.Web.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class URIParameterFormatProviderTest
|
||||
{
|
||||
[Test]
|
||||
public void Format_NormalParameters()
|
||||
{
|
||||
var expected = "/users/wizzler";
|
||||
|
||||
var user = "wizzler";
|
||||
var formatter = new URIParameterFormatProvider();
|
||||
Func<FormattableString, string> func = (FormattableString str) => str.ToString(formatter);
|
||||
|
||||
Assert.AreEqual(expected, func($"/users/{user}"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Format_EscapedParameters()
|
||||
{
|
||||
var expected = "/users/++wizzler";
|
||||
|
||||
var user = " wizzler";
|
||||
var formatter = new URIParameterFormatProvider();
|
||||
Func<FormattableString, string> func = (FormattableString str) => str.ToString(formatter);
|
||||
|
||||
Assert.AreEqual(expected, func($"/users/{user}"));
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
{
|
||||
"birthdate": "1937-06-01",
|
||||
"country": "SE",
|
||||
"display_name": "JM Wizzler",
|
||||
"email": "email@example.com",
|
||||
"external_urls": {
|
||||
"spotify": "https://open.spotify.com/user/wizzler"
|
||||
},
|
||||
"followers" : {
|
||||
"href" : null,
|
||||
"total" : 3829
|
||||
},
|
||||
"href": "https://api.spotify.com/v1/users/wizzler",
|
||||
"id": "wizzler",
|
||||
"images": [
|
||||
{
|
||||
"height": 200,
|
||||
"url": "https://fbcdn-profile-a.akamaihd.net/hprofile-ak-frc3/t1.0-1/1970403_10152215092574354_1798272330_n.jpg",
|
||||
"width": 200
|
||||
}
|
||||
],
|
||||
"product": "premium",
|
||||
"type": "user",
|
||||
"uri": "spotify:user:wizzler"
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
{
|
||||
"external_urls": {
|
||||
"spotify": "https://open.spotify.com/user/wizzler"
|
||||
},
|
||||
"href": "https://api.spotify.com/v1/users/wizzler",
|
||||
"id": "wizzler",
|
||||
"type": "user",
|
||||
"uri": "spotify:user:wizzler"
|
||||
}
|
16
SpotifyAPI.Web/Clients/APIClient.cs
Normal file
16
SpotifyAPI.Web/Clients/APIClient.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using SpotifyAPI.Web.Http;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public abstract class APIClient
|
||||
{
|
||||
public APIClient(IAPIConnector apiConnector)
|
||||
{
|
||||
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
|
||||
|
||||
API = apiConnector;
|
||||
}
|
||||
|
||||
public IAPIConnector API { get; set; }
|
||||
}
|
||||
}
|
55
SpotifyAPI.Web/Clients/BrowseClient.cs
Normal file
55
SpotifyAPI.Web/Clients/BrowseClient.cs
Normal file
@ -0,0 +1,55 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using SpotifyAPI.Web.Http;
|
||||
using SpotifyAPI.Web.Models;
|
||||
using URLs = SpotifyAPI.Web.SpotifyUrls;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class BrowseClient : APIClient, IBrowseClient
|
||||
{
|
||||
public BrowseClient(IAPIConnector apiConnector) : base(apiConnector) { }
|
||||
|
||||
public Task<CategoriesResponse> GetCategories()
|
||||
{
|
||||
return API.Get<CategoriesResponse>(URLs.Categories());
|
||||
}
|
||||
|
||||
public Task<CategoriesResponse> GetCategories(CategoriesRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNull(request, nameof(request));
|
||||
|
||||
return API.Get<CategoriesResponse>(URLs.Categories(), request.BuildQueryParams());
|
||||
}
|
||||
|
||||
public Task<Category> GetCategory(string categoryId)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(categoryId, nameof(categoryId));
|
||||
|
||||
return API.Get<Category>(URLs.Category(categoryId));
|
||||
}
|
||||
|
||||
public Task<Category> GetCategory(string categoryId, CategoryRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(categoryId, nameof(categoryId));
|
||||
Ensure.ArgumentNotNull(request, nameof(request));
|
||||
|
||||
return API.Get<Category>(URLs.Category(categoryId), request.BuildQueryParams());
|
||||
}
|
||||
|
||||
public Task<CategoryPlaylistsResponse> GetCategoryPlaylists(string categoryId)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(categoryId, nameof(categoryId));
|
||||
|
||||
return API.Get<CategoryPlaylistsResponse>(URLs.CategoryPlaylists(categoryId));
|
||||
}
|
||||
|
||||
public Task<CategoryPlaylistsResponse> GetCategoryPlaylists(string categoryId, CategoriesPlaylistsRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(categoryId, nameof(categoryId));
|
||||
Ensure.ArgumentNotNull(request, nameof(request));
|
||||
|
||||
return API.Get<CategoryPlaylistsResponse>(URLs.CategoryPlaylists(categoryId), request.BuildQueryParams());
|
||||
}
|
||||
}
|
||||
}
|
16
SpotifyAPI.Web/Clients/Interfaces/IBrowseClient.cs
Normal file
16
SpotifyAPI.Web/Clients/Interfaces/IBrowseClient.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public interface IBrowseClient
|
||||
{
|
||||
Task<CategoriesResponse> GetCategories();
|
||||
Task<CategoriesResponse> GetCategories(CategoriesRequest request);
|
||||
|
||||
Task<Category> GetCategory(string categoryId);
|
||||
Task<Category> GetCategory(string categoryId, CategoryRequest request);
|
||||
|
||||
Task<CategoryPlaylistsResponse> GetCategoryPlaylists(string categoryId);
|
||||
Task<CategoryPlaylistsResponse> GetCategoryPlaylists(string categoryId, CategoriesPlaylistsRequest request);
|
||||
}
|
||||
}
|
9
SpotifyAPI.Web/Clients/Interfaces/ISpotifyClient.cs
Normal file
9
SpotifyAPI.Web/Clients/Interfaces/ISpotifyClient.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
interface ISpotifyClient
|
||||
{
|
||||
IUserProfileClient UserProfile { get; }
|
||||
|
||||
IBrowseClient Browse { get; }
|
||||
}
|
||||
}
|
24
SpotifyAPI.Web/Clients/Interfaces/IUserProfileClient.cs
Normal file
24
SpotifyAPI.Web/Clients/Interfaces/IUserProfileClient.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System.Threading.Tasks;
|
||||
using SpotifyAPI.Web.Models;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public interface IUserProfileClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Test
|
||||
/// </summary>
|
||||
/// <exception cref="APIUnauthorizedException">Thrown if the client is not authenticated.</exception>
|
||||
/// <returns>A <see cref="PrivateUser"/></returns>
|
||||
Task<PrivateUser> Current();
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="userId"></param>
|
||||
/// <exception cref="APIUnauthorizedException">Thrown if the client is not authenticated.</exception>
|
||||
/// <returns></returns>
|
||||
Task<PublicUser> Get(string userId);
|
||||
}
|
||||
}
|
30
SpotifyAPI.Web/Clients/SpotifyClient.cs
Normal file
30
SpotifyAPI.Web/Clients/SpotifyClient.cs
Normal file
@ -0,0 +1,30 @@
|
||||
using SpotifyAPI.Web.Http;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class SpotifyClient : ISpotifyClient
|
||||
{
|
||||
private IAPIConnector _apiConnector;
|
||||
|
||||
public SpotifyClient(string token, string tokenType = "Bearer") :
|
||||
this(new TokenHeaderAuthenticator(token, tokenType))
|
||||
{ }
|
||||
|
||||
public SpotifyClient(IAuthenticator authenticator) :
|
||||
this(new APIConnector(SpotifyUrls.API_V1, authenticator))
|
||||
{ }
|
||||
|
||||
public SpotifyClient(IAPIConnector apiConnector)
|
||||
{
|
||||
Ensure.ArgumentNotNull(apiConnector, nameof(apiConnector));
|
||||
|
||||
_apiConnector = apiConnector;
|
||||
UserProfile = new UserProfileClient(_apiConnector);
|
||||
Browse = new BrowseClient(_apiConnector);
|
||||
}
|
||||
|
||||
public IUserProfileClient UserProfile { get; }
|
||||
|
||||
public IBrowseClient Browse { get; }
|
||||
}
|
||||
}
|
24
SpotifyAPI.Web/Clients/UserProfileClient.cs
Normal file
24
SpotifyAPI.Web/Clients/UserProfileClient.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using SpotifyAPI.Web.Http;
|
||||
using SpotifyAPI.Web.Models;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class UserProfileClient : APIClient, IUserProfileClient
|
||||
{
|
||||
public UserProfileClient(IAPIConnector apiConnector) : base(apiConnector) { }
|
||||
|
||||
public Task<PrivateUser> Current()
|
||||
{
|
||||
return API.Get<PrivateUser>(SpotifyUrls.Me());
|
||||
}
|
||||
|
||||
public Task<PublicUser> Get(string userId)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(userId, nameof(userId));
|
||||
|
||||
return API.Get<PublicUser>(SpotifyUrls.User(userId));
|
||||
}
|
||||
}
|
||||
}
|
43
SpotifyAPI.Web/Exceptions/APIException.cs
Normal file
43
SpotifyAPI.Web/Exceptions/APIException.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SpotifyAPI.Web.Http;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
[System.Serializable]
|
||||
public class APIException : System.Exception
|
||||
{
|
||||
public APIException(IResponse response) : base(ParseAPIErrorMessage(response))
|
||||
{
|
||||
Ensure.ArgumentNotNull(response, nameof(response));
|
||||
|
||||
Response = response;
|
||||
}
|
||||
|
||||
private static string ParseAPIErrorMessage(IResponse response)
|
||||
{
|
||||
var body = response.Body as string;
|
||||
if (string.IsNullOrEmpty(body))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
try
|
||||
{
|
||||
JObject bodyObject = JObject.Parse(body);
|
||||
JObject error = bodyObject.Value<JObject>("error");
|
||||
if (error != null)
|
||||
{
|
||||
return error.Value<string>("message");
|
||||
}
|
||||
}
|
||||
catch (JsonReaderException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public IResponse Response { get; set; }
|
||||
}
|
||||
}
|
10
SpotifyAPI.Web/Exceptions/APIUnauthorizedException.cs
Normal file
10
SpotifyAPI.Web/Exceptions/APIUnauthorizedException.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using SpotifyAPI.Web.Http;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
[System.Serializable]
|
||||
public class APIUnauthorizedException : APIException
|
||||
{
|
||||
public APIUnauthorizedException(IResponse response) : base(response) { }
|
||||
}
|
||||
}
|
155
SpotifyAPI.Web/Http/APIConnector.cs
Normal file
155
SpotifyAPI.Web/Http/APIConnector.cs
Normal file
@ -0,0 +1,155 @@
|
||||
using System.Net.Http;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System.Net;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public class APIConnector : IAPIConnector
|
||||
{
|
||||
private Uri _baseAddress;
|
||||
private IAuthenticator _authenticator;
|
||||
private IJSONSerializer _jsonSerializer;
|
||||
private IHTTPClient _httpClient;
|
||||
|
||||
public APIConnector(Uri baseAddress, IAuthenticator authenticator) :
|
||||
this(baseAddress, authenticator, new NewtonsoftJSONSerializer(), new NetHttpClient())
|
||||
{ }
|
||||
public APIConnector(Uri baseAddress, IAuthenticator authenticator, IJSONSerializer jsonSerializer, IHTTPClient httpClient)
|
||||
{
|
||||
_baseAddress = baseAddress;
|
||||
_authenticator = authenticator;
|
||||
_jsonSerializer = jsonSerializer;
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
public Task<T> Delete<T>(Uri uri)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Delete);
|
||||
}
|
||||
|
||||
public Task<T> Delete<T>(Uri uri, IDictionary<string, string> parameters)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Delete, parameters);
|
||||
}
|
||||
|
||||
public Task<T> Delete<T>(Uri uri, IDictionary<string, string> parameters, object body)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Delete, parameters, body);
|
||||
}
|
||||
|
||||
public Task<T> Get<T>(Uri uri)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Get);
|
||||
}
|
||||
|
||||
public Task<T> Get<T>(Uri uri, IDictionary<string, string> parameters)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Get, parameters);
|
||||
}
|
||||
|
||||
public Task<T> Post<T>(Uri uri)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Post);
|
||||
}
|
||||
|
||||
public Task<T> Post<T>(Uri uri, IDictionary<string, string> parameters)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Post, parameters);
|
||||
}
|
||||
|
||||
public Task<T> Post<T>(Uri uri, IDictionary<string, string> parameters, object body)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Get, parameters, body);
|
||||
}
|
||||
|
||||
public Task<T> Put<T>(Uri uri)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Put);
|
||||
}
|
||||
|
||||
public Task<T> Put<T>(Uri uri, IDictionary<string, string> parameters)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Put, parameters);
|
||||
}
|
||||
|
||||
public Task<T> Put<T>(Uri uri, IDictionary<string, string> parameters, object body)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
|
||||
return SendAPIRequest<T>(uri, HttpMethod.Put, parameters, body);
|
||||
}
|
||||
|
||||
public void SetRequestTimeout(TimeSpan timeout)
|
||||
{
|
||||
_httpClient.SetRequestTimeout(timeout);
|
||||
}
|
||||
|
||||
private async Task<T> SendAPIRequest<T>(
|
||||
Uri uri,
|
||||
HttpMethod method,
|
||||
IDictionary<string, string> parameters = null,
|
||||
object body = null
|
||||
)
|
||||
{
|
||||
Ensure.ArgumentNotNull(uri, nameof(uri));
|
||||
Ensure.ArgumentNotNull(method, nameof(method));
|
||||
|
||||
var request = new Request
|
||||
{
|
||||
BaseAddress = _baseAddress,
|
||||
ContentType = "application/json",
|
||||
Parameters = parameters,
|
||||
Endpoint = uri,
|
||||
Method = method
|
||||
};
|
||||
|
||||
_jsonSerializer.SerializeRequest(request);
|
||||
await _authenticator.Apply(request).ConfigureAwait(false);
|
||||
IResponse response = await _httpClient.DoRequest(request).ConfigureAwait(false);
|
||||
ProcessErrors(response);
|
||||
|
||||
IAPIResponse<T> apiResponse = _jsonSerializer.DeserializeResponse<T>(response);
|
||||
return apiResponse.Body;
|
||||
}
|
||||
|
||||
private void ProcessErrors(IResponse response)
|
||||
{
|
||||
Ensure.ArgumentNotNull(response, nameof(response));
|
||||
|
||||
if ((int)response.StatusCode >= 200 && (int)response.StatusCode < 400)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (response.StatusCode)
|
||||
{
|
||||
case HttpStatusCode.Unauthorized:
|
||||
throw new APIUnauthorizedException(response);
|
||||
default:
|
||||
throw new APIException(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
17
SpotifyAPI.Web/Http/APIResponse.cs
Normal file
17
SpotifyAPI.Web/Http/APIResponse.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public class APIResponse<T> : IAPIResponse<T>
|
||||
{
|
||||
public APIResponse(IResponse response, T body = default(T))
|
||||
{
|
||||
Ensure.ArgumentNotNull(response, nameof(response));
|
||||
|
||||
Body = body;
|
||||
Response = response;
|
||||
}
|
||||
|
||||
public T Body { get; set; }
|
||||
|
||||
public IResponse Response { get; set; }
|
||||
}
|
||||
}
|
32
SpotifyAPI.Web/Http/Interfaces/IAPIConnector.cs
Normal file
32
SpotifyAPI.Web/Http/Interfaces/IAPIConnector.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public interface IAPIConnector
|
||||
{
|
||||
// IAuthenticator Authenticator { get; }
|
||||
|
||||
// IJSONSerializer JSONSerializer { get; }
|
||||
|
||||
// IHTTPClient HTTPClient { get; }
|
||||
|
||||
Task<T> Get<T>(Uri uri);
|
||||
Task<T> Get<T>(Uri uri, IDictionary<string, string> parameters);
|
||||
|
||||
Task<T> Post<T>(Uri uri);
|
||||
Task<T> Post<T>(Uri uri, IDictionary<string, string> parameters);
|
||||
Task<T> Post<T>(Uri uri, IDictionary<string, string> parameters, object body);
|
||||
|
||||
Task<T> Put<T>(Uri uri);
|
||||
Task<T> Put<T>(Uri uri, IDictionary<string, string> parameters);
|
||||
Task<T> Put<T>(Uri uri, IDictionary<string, string> parameters, object body);
|
||||
|
||||
Task<T> Delete<T>(Uri uri);
|
||||
Task<T> Delete<T>(Uri uri, IDictionary<string, string> parameters);
|
||||
Task<T> Delete<T>(Uri uri, IDictionary<string, string> parameters, object body);
|
||||
|
||||
void SetRequestTimeout(TimeSpan timeout);
|
||||
}
|
||||
}
|
9
SpotifyAPI.Web/Http/Interfaces/IAPIResponse.cs
Normal file
9
SpotifyAPI.Web/Http/Interfaces/IAPIResponse.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public interface IAPIResponse<out T>
|
||||
{
|
||||
T Body { get; }
|
||||
|
||||
IResponse Response { get; }
|
||||
}
|
||||
}
|
9
SpotifyAPI.Web/Http/Interfaces/IAuthenticator.cs
Normal file
9
SpotifyAPI.Web/Http/Interfaces/IAuthenticator.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public interface IAuthenticator
|
||||
{
|
||||
Task Apply(IRequest request);
|
||||
}
|
||||
}
|
12
SpotifyAPI.Web/Http/Interfaces/IHttpClient.cs
Normal file
12
SpotifyAPI.Web/Http/Interfaces/IHttpClient.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public interface IHTTPClient : IDisposable
|
||||
{
|
||||
Task<IResponse> DoRequest(IRequest request);
|
||||
|
||||
void SetRequestTimeout(TimeSpan timeout);
|
||||
}
|
||||
}
|
10
SpotifyAPI.Web/Http/Interfaces/IJSONSerializer.cs
Normal file
10
SpotifyAPI.Web/Http/Interfaces/IJSONSerializer.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public interface IJSONSerializer
|
||||
{
|
||||
void SerializeRequest(IRequest request);
|
||||
IAPIResponse<T> DeserializeResponse<T>(IResponse response);
|
||||
}
|
||||
}
|
23
SpotifyAPI.Web/Http/Interfaces/IRequest.cs
Normal file
23
SpotifyAPI.Web/Http/Interfaces/IRequest.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public interface IRequest
|
||||
{
|
||||
Uri BaseAddress { get; }
|
||||
|
||||
Uri Endpoint { get; }
|
||||
|
||||
IDictionary<string, string> Headers { get; }
|
||||
|
||||
IDictionary<string, string> Parameters { get; }
|
||||
|
||||
HttpMethod Method { get; }
|
||||
|
||||
string ContentType { get; }
|
||||
|
||||
object Body { get; set; }
|
||||
}
|
||||
}
|
16
SpotifyAPI.Web/Http/Interfaces/IResponse.cs
Normal file
16
SpotifyAPI.Web/Http/Interfaces/IResponse.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public interface IResponse
|
||||
{
|
||||
object Body { get; }
|
||||
|
||||
IReadOnlyDictionary<string, string> Headers { get; }
|
||||
|
||||
HttpStatusCode StatusCode { get; }
|
||||
|
||||
string ContentType { get; }
|
||||
}
|
||||
}
|
98
SpotifyAPI.Web/Http/NetHttpClient.cs
Normal file
98
SpotifyAPI.Web/Http/NetHttpClient.cs
Normal file
@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public class NetHttpClient : IHTTPClient
|
||||
{
|
||||
private HttpClient _httpClient;
|
||||
|
||||
public NetHttpClient()
|
||||
{
|
||||
_httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
public async Task<IResponse> DoRequest(IRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNull(request, nameof(request));
|
||||
|
||||
using (HttpRequestMessage requestMsg = BuildRequestMessage(request))
|
||||
{
|
||||
var responseMsg = await _httpClient
|
||||
.SendAsync(requestMsg, HttpCompletionOption.ResponseContentRead)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return await BuildResponse(responseMsg).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<IResponse> BuildResponse(HttpResponseMessage responseMsg)
|
||||
{
|
||||
Ensure.ArgumentNotNull(responseMsg, nameof(responseMsg));
|
||||
|
||||
// We only support text stuff for now
|
||||
using (var content = responseMsg.Content)
|
||||
{
|
||||
var headers = responseMsg.Headers.ToDictionary(header => header.Key, header => header.Value.First());
|
||||
var body = await responseMsg.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||
var contentType = content.Headers?.ContentType?.MediaType;
|
||||
|
||||
return new Response(headers)
|
||||
{
|
||||
ContentType = contentType,
|
||||
StatusCode = responseMsg.StatusCode,
|
||||
Body = body
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private HttpRequestMessage BuildRequestMessage(IRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNull(request, nameof(request));
|
||||
|
||||
var fullUri = new Uri(request.BaseAddress, request.Endpoint).ApplyParameters(request.Parameters);
|
||||
var requestMsg = new HttpRequestMessage(request.Method, fullUri);
|
||||
foreach (var header in request.Headers)
|
||||
{
|
||||
requestMsg.Headers.Add(header.Key, header.Value);
|
||||
}
|
||||
|
||||
switch (request.Body)
|
||||
{
|
||||
case HttpContent body:
|
||||
requestMsg.Content = body;
|
||||
break;
|
||||
case string body:
|
||||
requestMsg.Content = new StringContent(body);
|
||||
break;
|
||||
case Stream body:
|
||||
requestMsg.Content = new StreamContent(body);
|
||||
break;
|
||||
}
|
||||
|
||||
return requestMsg;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_httpClient?.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void SetRequestTimeout(TimeSpan timeout)
|
||||
{
|
||||
_httpClient.Timeout = timeout;
|
||||
}
|
||||
}
|
||||
}
|
50
SpotifyAPI.Web/Http/NewtonsoftJSONSerializer.cs
Normal file
50
SpotifyAPI.Web/Http/NewtonsoftJSONSerializer.cs
Normal file
@ -0,0 +1,50 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public class NewtonsoftJSONSerializer : IJSONSerializer
|
||||
{
|
||||
JsonSerializerSettings _serializerSettings;
|
||||
|
||||
public NewtonsoftJSONSerializer()
|
||||
{
|
||||
_serializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
NullValueHandling = NullValueHandling.Ignore,
|
||||
ContractResolver = new DefaultContractResolver
|
||||
{
|
||||
NamingStrategy = new SnakeCaseNamingStrategy()
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public IAPIResponse<T> DeserializeResponse<T>(IResponse response)
|
||||
{
|
||||
Ensure.ArgumentNotNull(response, nameof(response));
|
||||
|
||||
if (response.ContentType?.Equals("application/json", StringComparison.Ordinal) is true)
|
||||
{
|
||||
var body = JsonConvert.DeserializeObject<T>(response.Body as string, _serializerSettings);
|
||||
return new APIResponse<T>(response, body);
|
||||
}
|
||||
return new APIResponse<T>(response);
|
||||
}
|
||||
|
||||
public void SerializeRequest(IRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNull(request, nameof(request));
|
||||
|
||||
if (request.Body is string || request.Body is Stream || request.Body is HttpContent || request.Body is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
request.Body = JsonConvert.SerializeObject(request.Body, _serializerSettings);
|
||||
}
|
||||
}
|
||||
}
|
29
SpotifyAPI.Web/Http/Request.cs
Normal file
29
SpotifyAPI.Web/Http/Request.cs
Normal file
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
class Request : IRequest
|
||||
{
|
||||
public Request()
|
||||
{
|
||||
Headers = new Dictionary<string, string>();
|
||||
Parameters = new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
public Uri BaseAddress { get; set; }
|
||||
|
||||
public Uri Endpoint { get; set; }
|
||||
|
||||
public IDictionary<string, string> Headers { get; set; }
|
||||
|
||||
public IDictionary<string, string> Parameters { get; set; }
|
||||
|
||||
public HttpMethod Method { get; set; }
|
||||
|
||||
public string ContentType { get; set; }
|
||||
|
||||
public object Body { get; set; }
|
||||
}
|
||||
}
|
25
SpotifyAPI.Web/Http/Response.cs
Normal file
25
SpotifyAPI.Web/Http/Response.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Net;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
public class Response : IResponse
|
||||
{
|
||||
public Response(IDictionary<string, string> headers)
|
||||
{
|
||||
Ensure.ArgumentNotNull(headers, nameof(headers));
|
||||
|
||||
Headers = new ReadOnlyDictionary<string, string>(headers);
|
||||
}
|
||||
|
||||
public object Body { get; set; }
|
||||
|
||||
public IReadOnlyDictionary<string, string> Headers { get; set; }
|
||||
|
||||
public HttpStatusCode StatusCode { get; set; }
|
||||
|
||||
public string ContentType { get; set; }
|
||||
}
|
||||
}
|
23
SpotifyAPI.Web/Http/TokenHeaderAuthenticator.cs
Normal file
23
SpotifyAPI.Web/Http/TokenHeaderAuthenticator.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace SpotifyAPI.Web.Http
|
||||
{
|
||||
class TokenHeaderAuthenticator : IAuthenticator
|
||||
{
|
||||
public TokenHeaderAuthenticator(string token, string tokenType)
|
||||
{
|
||||
Token = token;
|
||||
TokenType = tokenType;
|
||||
}
|
||||
|
||||
public string Token { get; set; }
|
||||
|
||||
public string TokenType { get; set; }
|
||||
|
||||
public Task Apply(IRequest request)
|
||||
{
|
||||
request.Headers["Authorization"] = $"{TokenType} {Token}";
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,125 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using SpotifyAPI.Web.Models;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public interface IClient : IDisposable
|
||||
{
|
||||
JsonSerializerSettings JsonSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Downloads data from an URL and returns it
|
||||
/// </summary>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Tuple<ResponseInfo, string> Download(string url, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads data async from an URL and returns it
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Task<Tuple<ResponseInfo, string>> DownloadAsync(string url, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads data from an URL and returns it
|
||||
/// </summary>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Tuple<ResponseInfo, byte[]> DownloadRaw(string url, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads data async from an URL and returns it
|
||||
/// </summary>
|
||||
/// <param name="url"></param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Task<Tuple<ResponseInfo, byte[]>> DownloadRawAsync(string url, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads data from an URL and converts it to an object
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Type which the object gets converted to</typeparam>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Tuple<ResponseInfo, T> DownloadJson<T>(string url, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Downloads data async from an URL and converts it to an object
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Type which the object gets converted to</typeparam>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Task<Tuple<ResponseInfo, T>> DownloadJsonAsync<T>(string url, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Uploads data from an URL and returns the response
|
||||
/// </summary>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="body">The Body-Data (most likely a JSON String)</param>
|
||||
/// <param name="method">The Upload-method (POST,DELETE,PUT)</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Tuple<ResponseInfo, string> Upload(string url, string body, string method, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Uploads data async from an URL and returns the response
|
||||
/// </summary>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="body">The Body-Data (most likely a JSON String)</param>
|
||||
/// <param name="method">The Upload-method (POST,DELETE,PUT)</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Task<Tuple<ResponseInfo, string>> UploadAsync(string url, string body, string method, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Uploads data from an URL and returns the response
|
||||
/// </summary>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="body">The Body-Data (most likely a JSON String)</param>
|
||||
/// <param name="method">The Upload-method (POST,DELETE,PUT)</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Tuple<ResponseInfo, byte[]> UploadRaw(string url, string body, string method, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Uploads data async from an URL and returns the response
|
||||
/// </summary>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="body">The Body-Data (most likely a JSON String)</param>
|
||||
/// <param name="method">The Upload-method (POST,DELETE,PUT)</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Task<Tuple<ResponseInfo, byte[]>> UploadRawAsync(string url, string body, string method, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Uploads data from an URL and converts the response to an object
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Type which the object gets converted to</typeparam>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="body">The Body-Data (most likely a JSON String)</param>
|
||||
/// <param name="method">The Upload-method (POST,DELETE,PUT)</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Tuple<ResponseInfo, T> UploadJson<T>(string url, string body, string method, Dictionary<string, string> headers = null);
|
||||
|
||||
/// <summary>
|
||||
/// Uploads data async from an URL and converts the response to an object
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The Type which the object gets converted to</typeparam>
|
||||
/// <param name="url">An URL</param>
|
||||
/// <param name="body">The Body-Data (most likely a JSON String)</param>
|
||||
/// <param name="method">The Upload-method (POST,DELETE,PUT)</param>
|
||||
/// <param name="headers"></param>
|
||||
/// <returns></returns>
|
||||
Task<Tuple<ResponseInfo, T>> UploadJsonAsync<T>(string url, string body, string method, Dictionary<string, string> headers = null);
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AnalysisMeta
|
||||
{
|
||||
[JsonProperty("analyzer_platform")]
|
||||
public string AnalyzerVersion { get; set; }
|
||||
|
||||
[JsonProperty("platform")]
|
||||
public string Platform { get; set; }
|
||||
|
||||
[JsonProperty("status_code")]
|
||||
public int StatusCode { get; set; }
|
||||
|
||||
[JsonProperty("detailed_status")]
|
||||
public string DetailedStatus { get; set; }
|
||||
|
||||
[JsonProperty("timestamp")]
|
||||
public long Timestamp { get; set; }
|
||||
|
||||
[JsonProperty("analysis_time")]
|
||||
public double AnalysisTime { get; set; }
|
||||
|
||||
[JsonProperty("input_process")]
|
||||
public string InputProcess { get; set; }
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AnalysisSection
|
||||
{
|
||||
[JsonProperty("start")]
|
||||
public double Start { get; set; }
|
||||
|
||||
[JsonProperty("duration")]
|
||||
public double Duration { get; set; }
|
||||
|
||||
[JsonProperty("confidence")]
|
||||
public double Confidence { get; set; }
|
||||
|
||||
[JsonProperty("loudness")]
|
||||
public double Loudness { get; set; }
|
||||
|
||||
[JsonProperty("tempo")]
|
||||
public double Tempo { get; set; }
|
||||
|
||||
[JsonProperty("tempo_confidence")]
|
||||
public double TempoConfidence { get; set; }
|
||||
|
||||
[JsonProperty("key")]
|
||||
public int Key { get; set; }
|
||||
|
||||
[JsonProperty("key_confidence")]
|
||||
public double KeyConfidence { get; set; }
|
||||
|
||||
[JsonProperty("mode")]
|
||||
public int Mode { get; set; }
|
||||
|
||||
[JsonProperty("mode_confidence")]
|
||||
public double ModeConfidence { get; set; }
|
||||
|
||||
[JsonProperty("time_signature")]
|
||||
public int TimeSignature { get; set; }
|
||||
|
||||
[JsonProperty("time_signature_confidence")]
|
||||
public double TimeSignatureConfidence { get; set; }
|
||||
}
|
||||
}
|
@ -1,35 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AnalysisSegment
|
||||
{
|
||||
[JsonProperty("start")]
|
||||
public double Start { get; set; }
|
||||
|
||||
[JsonProperty("duration")]
|
||||
public double Duration { get; set; }
|
||||
|
||||
[JsonProperty("confidence")]
|
||||
public double Confidence { get; set; }
|
||||
|
||||
[JsonProperty("loudness_start")]
|
||||
public double LoudnessStart { get; set; }
|
||||
|
||||
[JsonProperty("loudness_max_time")]
|
||||
public double LoudnessMaxTime { get; set; }
|
||||
|
||||
[JsonProperty("loudness_max")]
|
||||
public double LoudnessMax { get; set; }
|
||||
|
||||
[JsonProperty("loudness_end")]
|
||||
public double LoudnessEnd { get; set; }
|
||||
|
||||
[JsonProperty("pitches")]
|
||||
public List<double> Pitches { get; set; }
|
||||
|
||||
[JsonProperty("timbre")]
|
||||
public List<double> Timbre { get; set; }
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AnalysisTimeSlice
|
||||
{
|
||||
[JsonProperty("start")]
|
||||
public double Start { get; set; }
|
||||
|
||||
[JsonProperty("duration")]
|
||||
public double Duration { get; set; }
|
||||
|
||||
[JsonProperty("confidence")]
|
||||
public double Confidence { get; set; }
|
||||
}
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AnalysisTrack
|
||||
{
|
||||
[JsonProperty("num_samples")]
|
||||
public int NumSamples { get; set; }
|
||||
|
||||
[JsonProperty("duration")]
|
||||
public double Duration { get; set; }
|
||||
|
||||
[JsonProperty("sample_md5")]
|
||||
public string SampleMD5 { get; set; }
|
||||
|
||||
[JsonProperty("offset_seconds")]
|
||||
public double OffsetSeconds { get; set; }
|
||||
|
||||
[JsonProperty("window_seconds")]
|
||||
public double WindowSeconds { get; set; }
|
||||
|
||||
[JsonProperty("analysis_sample_rate")]
|
||||
public int AnalysisSampleRate { get; set; }
|
||||
|
||||
[JsonProperty("analysis_channels")]
|
||||
public int AnalysisChannels { get; set; }
|
||||
|
||||
[JsonProperty("end_of_fade_in")]
|
||||
public double EndOfFadeIn { get; set; }
|
||||
|
||||
[JsonProperty("start_of_fade_out")]
|
||||
public double StartOfFadeOut { get; set; }
|
||||
|
||||
[JsonProperty("loudness")]
|
||||
public double Loudness { get; set; }
|
||||
|
||||
[JsonProperty("tempo")]
|
||||
public double Tempo { get; set; }
|
||||
|
||||
[JsonProperty("tempo_confidence")]
|
||||
public double TempoConfidence { get; set; }
|
||||
|
||||
[JsonProperty("time_signature")]
|
||||
public double TimeSignature { get; set; }
|
||||
|
||||
[JsonProperty("time_signature_confidence")]
|
||||
public double TimeSignatureConfidence { get; set; }
|
||||
|
||||
[JsonProperty("key")]
|
||||
public int Key { get; set; }
|
||||
|
||||
[JsonProperty("key_confidence")]
|
||||
public double KeyConfidence { get; set; }
|
||||
|
||||
[JsonProperty("mode")]
|
||||
public int Mode { get; set; }
|
||||
|
||||
[JsonProperty("mode_confidence")]
|
||||
public double ModeConfidence { get; set; }
|
||||
|
||||
[JsonProperty("codestring")]
|
||||
public string Codestring { get; set; }
|
||||
|
||||
[JsonProperty("code_version")]
|
||||
public double CodeVersion { get; set; }
|
||||
|
||||
[JsonProperty("echoprintstring")]
|
||||
public string Echoprintstring { get; set; }
|
||||
|
||||
[JsonProperty("echoprint_version")]
|
||||
public double EchoprintVersion { get; set; }
|
||||
|
||||
[JsonProperty("synchstring")]
|
||||
public string Synchstring { get; set; }
|
||||
|
||||
[JsonProperty("synch_version")]
|
||||
public double SynchVersion { get; set; }
|
||||
|
||||
[JsonProperty("rhythmstring")]
|
||||
public string Rhythmstring { get; set; }
|
||||
|
||||
[JsonProperty("rhythm_version")]
|
||||
public double RhythmVersion { get; set; }
|
||||
|
||||
}
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class ListResponse<T> : BasicModel
|
||||
{
|
||||
public List<T> List { get; set; }
|
||||
}
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AudioAnalysis : BasicModel
|
||||
{
|
||||
[JsonProperty("bars")]
|
||||
public List<AnalysisTimeSlice> Bars { get; set; }
|
||||
|
||||
[JsonProperty("beats")]
|
||||
public List<AnalysisTimeSlice> Beats { get; set; }
|
||||
|
||||
[JsonProperty("meta")]
|
||||
public AnalysisMeta Meta { get; set; }
|
||||
|
||||
[JsonProperty("sections")]
|
||||
public List<AnalysisSection> Sections { get; set; }
|
||||
|
||||
[JsonProperty("segments")]
|
||||
public List<AnalysisSegment> Segments { get; set; }
|
||||
|
||||
[JsonProperty("tatums")]
|
||||
public List<AnalysisTimeSlice> Tatums { get; set; }
|
||||
|
||||
[JsonProperty("track")]
|
||||
public AnalysisTrack Track { get; set; }
|
||||
}
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AudioFeatures : BasicModel
|
||||
{
|
||||
[JsonProperty("acousticness")]
|
||||
public float Acousticness { get; set; }
|
||||
|
||||
[JsonProperty("analysis_url")]
|
||||
public string AnalysisUrl { get; set; }
|
||||
|
||||
[JsonProperty("danceability")]
|
||||
public float Danceability { get; set; }
|
||||
|
||||
[JsonProperty("duration_ms")]
|
||||
public int DurationMs { get; set; }
|
||||
|
||||
[JsonProperty("energy")]
|
||||
public float Energy { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("instrumentalness")]
|
||||
public float Instrumentalness { get; set; }
|
||||
|
||||
[JsonProperty("key")]
|
||||
public int Key { get; set; }
|
||||
|
||||
[JsonProperty("liveness")]
|
||||
public float Liveness { get; set; }
|
||||
|
||||
[JsonProperty("loudness")]
|
||||
public float Loudness { get; set; }
|
||||
|
||||
[JsonProperty("mode")]
|
||||
public int Mode { get; set; }
|
||||
|
||||
[JsonProperty("speechiness")]
|
||||
public float Speechiness { get; set; }
|
||||
|
||||
[JsonProperty("tempo")]
|
||||
public float Tempo { get; set; }
|
||||
|
||||
[JsonProperty("time_signature")]
|
||||
public int TimeSignature { get; set; }
|
||||
|
||||
[JsonProperty("track_href")]
|
||||
public string TrackHref { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
|
||||
[JsonProperty("valence")]
|
||||
public float Valence { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class AvailabeDevices : BasicModel
|
||||
{
|
||||
[JsonProperty("devices")]
|
||||
public List<Device> Devices { get; set; }
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
using System.Net;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public abstract class BasicModel
|
||||
{
|
||||
[JsonProperty("error")]
|
||||
public Error Error { get; set; }
|
||||
|
||||
private ResponseInfo _info;
|
||||
|
||||
public bool HasError() => Error != null;
|
||||
|
||||
internal void AddResponseInfo(ResponseInfo info) => _info = info;
|
||||
|
||||
public string Header(string key) => _info.Headers?.Get(key);
|
||||
|
||||
public WebHeaderCollection Headers() => _info.Headers;
|
||||
|
||||
public HttpStatusCode StatusCode() => _info.StatusCode;
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class Category : BasicModel
|
||||
{
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("icons")]
|
||||
public List<Image> Icons { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class CategoryList : BasicModel
|
||||
{
|
||||
[JsonProperty("categories")]
|
||||
public Paging<Category> Categories { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class CategoryPlaylist : BasicModel
|
||||
{
|
||||
[JsonProperty("playlists")]
|
||||
public Paging<SimplePlaylist> Playlists { get; set; }
|
||||
}
|
||||
}
|
45
SpotifyAPI.Web/Models/Converters/PlaylistElementConverter.cs
Normal file
45
SpotifyAPI.Web/Models/Converters/PlaylistElementConverter.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class PlaylistElementConverter : JsonConverter
|
||||
{
|
||||
public override bool CanConvert(Type objectType) => true;
|
||||
|
||||
public override object ReadJson(JsonReader reader, Type objectType,
|
||||
object existingValue, JsonSerializer serializer)
|
||||
{
|
||||
var token = JToken.ReadFrom(reader);
|
||||
if (token.Type == JTokenType.Null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var type = token["type"].Value<string>();
|
||||
if (type == "track")
|
||||
{
|
||||
var obj = new FullTrack();
|
||||
serializer.Populate(token.CreateReader(), obj);
|
||||
return obj;
|
||||
}
|
||||
else if (type == "episode")
|
||||
{
|
||||
var obj = new FullEpisode();
|
||||
serializer.Populate(token.CreateReader(), obj);
|
||||
return obj;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new Exception($"Received unkown playlist element type: {type}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, object value,
|
||||
JsonSerializer serializer)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class CursorPaging<T> : BasicModel
|
||||
{
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("items")]
|
||||
public List<T> Items { get; set; }
|
||||
|
||||
[JsonProperty("limit")]
|
||||
public int Limit { get; set; }
|
||||
|
||||
[JsonProperty("next")]
|
||||
public string Next { get; set; }
|
||||
|
||||
[JsonProperty("cursors")]
|
||||
public Cursor Cursors { get; set; }
|
||||
|
||||
[JsonProperty("total")]
|
||||
public int Total { get; set; }
|
||||
|
||||
public bool HasNext()
|
||||
{
|
||||
return !string.IsNullOrEmpty(Next);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class Device
|
||||
{
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("is_active")]
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
[JsonProperty("is_restricted")]
|
||||
public bool IsRestricted { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("volume_percent")]
|
||||
public int VolumePercent { get; set; }
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class FeaturedPlaylists : BasicModel
|
||||
{
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
|
||||
[JsonProperty("playlists")]
|
||||
public Paging<SimplePlaylist> Playlists { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class FollowedArtists : BasicModel
|
||||
{
|
||||
[JsonProperty("artists")]
|
||||
public CursorPaging<FullArtist> Artists { get; set; }
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class FullAlbum : BasicModel
|
||||
{
|
||||
[JsonProperty("album_type")]
|
||||
public string AlbumType { get; set; }
|
||||
|
||||
[JsonProperty("artists")]
|
||||
public List<SimpleArtist> Artists { get; set; }
|
||||
|
||||
[JsonProperty("available_markets")]
|
||||
public List<string> AvailableMarkets { get; set; }
|
||||
|
||||
[JsonProperty("copyrights")]
|
||||
public List<Copyright> Copyrights { get; set; }
|
||||
|
||||
[JsonProperty("external_ids")]
|
||||
public Dictionary<string, string> ExternalIds { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("genres")]
|
||||
public List<string> Genres { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("images")]
|
||||
public List<Image> Images { get; set; }
|
||||
|
||||
[JsonProperty("label")]
|
||||
public string Label { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("popularity")]
|
||||
public int Popularity { get; set; }
|
||||
|
||||
[JsonProperty("release_date")]
|
||||
public string ReleaseDate { get; set; }
|
||||
|
||||
[JsonProperty("release_date_precision")]
|
||||
public string ReleaseDatePrecision { get; set; }
|
||||
|
||||
[JsonProperty("tracks")]
|
||||
public Paging<SimpleTrack> Tracks { get; set; }
|
||||
|
||||
[JsonProperty("restrictions")]
|
||||
public Dictionary<string, string> Restrictions { get; set; }
|
||||
|
||||
[JsonProperty("total_tracks")]
|
||||
public int TotalTracks { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class FullArtist : BasicModel
|
||||
{
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("followers")]
|
||||
public Followers Followers { get; set; }
|
||||
|
||||
[JsonProperty("genres")]
|
||||
public List<string> Genres { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("images")]
|
||||
public List<Image> Images { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("popularity")]
|
||||
public int Popularity { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class FullPlaylist : BasicModel
|
||||
{
|
||||
[JsonProperty("collaborative")]
|
||||
public bool Collaborative { get; set; }
|
||||
|
||||
[JsonProperty("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("followers")]
|
||||
public Followers Followers { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("images")]
|
||||
public List<Image> Images { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("owner")]
|
||||
public PublicProfile Owner { get; set; }
|
||||
|
||||
[JsonProperty("public")]
|
||||
public bool Public { get; set; }
|
||||
|
||||
[JsonProperty("snapshot_id")]
|
||||
public string SnapshotId { get; set; }
|
||||
|
||||
[JsonProperty("tracks")]
|
||||
public Paging<PlaylistTrack> Tracks { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class FullTrack : BasicModel
|
||||
{
|
||||
[JsonProperty("album")]
|
||||
public SimpleAlbum Album { get; set; }
|
||||
|
||||
[JsonProperty("artists")]
|
||||
public List<SimpleArtist> Artists { get; set; }
|
||||
|
||||
[JsonProperty("available_markets")]
|
||||
public List<string> AvailableMarkets { get; set; }
|
||||
|
||||
[JsonProperty("disc_number")]
|
||||
public int DiscNumber { get; set; }
|
||||
|
||||
[JsonProperty("duration_ms")]
|
||||
public int DurationMs { get; set; }
|
||||
|
||||
[JsonProperty("explicit")]
|
||||
public bool Explicit { get; set; }
|
||||
|
||||
[JsonProperty("external_ids")]
|
||||
public Dictionary<string, string> ExternalIds { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternUrls { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("popularity")]
|
||||
public int Popularity { get; set; }
|
||||
|
||||
[JsonProperty("preview_url")]
|
||||
public string PreviewUrl { get; set; }
|
||||
|
||||
[JsonProperty("track_number")]
|
||||
public int TrackNumber { get; set; }
|
||||
|
||||
[JsonProperty("restrictions")]
|
||||
public Dictionary<string, string> Restrictions { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Only filled when the "market"-parameter was supplied!
|
||||
/// </summary>
|
||||
[JsonProperty("is_playable")]
|
||||
public bool? IsPlayable { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Only filled when the "market"-parameter was supplied!
|
||||
/// </summary>
|
||||
[JsonProperty("linked_from")]
|
||||
public LinkedFrom LinkedFrom { get; set; }
|
||||
}
|
||||
}
|
@ -1,158 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class Image
|
||||
{
|
||||
[JsonProperty("url")]
|
||||
public string Url { get; set; }
|
||||
|
||||
[JsonProperty("width")]
|
||||
public int Width { get; set; }
|
||||
|
||||
[JsonProperty("height")]
|
||||
public int Height { get; set; }
|
||||
}
|
||||
|
||||
public class ErrorResponse : BasicModel
|
||||
{ }
|
||||
|
||||
public class Error
|
||||
{
|
||||
[JsonProperty("status")]
|
||||
public int Status { get; set; }
|
||||
|
||||
[JsonProperty("message")]
|
||||
public string Message { get; set; }
|
||||
}
|
||||
|
||||
public class PlaylistTrackCollection
|
||||
{
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("total")]
|
||||
public int Total { get; set; }
|
||||
}
|
||||
|
||||
public class Followers
|
||||
{
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("total")]
|
||||
public int Total { get; set; }
|
||||
}
|
||||
|
||||
public class PlaylistTrack
|
||||
{
|
||||
[JsonProperty("added_at")]
|
||||
public DateTime AddedAt { get; set; }
|
||||
|
||||
[JsonProperty("added_by")]
|
||||
public PublicProfile AddedBy { get; set; }
|
||||
|
||||
[JsonProperty("track")]
|
||||
public FullTrack Track { get; set; }
|
||||
|
||||
[JsonProperty("is_local")]
|
||||
public bool IsLocal { get; set; }
|
||||
}
|
||||
|
||||
public class DeleteTrackUri
|
||||
{
|
||||
/// <summary>
|
||||
/// Delete-Track Wrapper
|
||||
/// </summary>
|
||||
/// <param name="uri">An Spotify-URI</param>
|
||||
/// <param name="positions">Optional positions</param>
|
||||
public DeleteTrackUri(string uri, params int[] positions)
|
||||
{
|
||||
Positions = positions.ToList();
|
||||
Uri = uri;
|
||||
}
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
|
||||
[JsonProperty("positions")]
|
||||
public List<int> Positions { get; set; }
|
||||
|
||||
public bool ShouldSerializePositions()
|
||||
{
|
||||
return Positions.Count > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class Copyright
|
||||
{
|
||||
[JsonProperty("text")]
|
||||
public string Text { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
}
|
||||
|
||||
public class LinkedFrom
|
||||
{
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
|
||||
public class SavedTrack
|
||||
{
|
||||
[JsonProperty("added_at")]
|
||||
public DateTime AddedAt { get; set; }
|
||||
|
||||
[JsonProperty("track")]
|
||||
public FullTrack Track { get; set; }
|
||||
}
|
||||
|
||||
public class SavedAlbum
|
||||
{
|
||||
[JsonProperty("added_at")]
|
||||
public DateTime AddedAt { get; set; }
|
||||
|
||||
[JsonProperty("album")]
|
||||
public FullAlbum Album { get; set; }
|
||||
}
|
||||
|
||||
public class Cursor
|
||||
{
|
||||
[JsonProperty("after")]
|
||||
public string After { get; set; }
|
||||
|
||||
[JsonProperty("before")]
|
||||
public string Before { get; set; }
|
||||
}
|
||||
|
||||
public class Context
|
||||
{
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class NewAlbumReleases : BasicModel
|
||||
{
|
||||
[JsonProperty("albums")]
|
||||
public Paging<SimpleAlbum> Albums { get; set; }
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class Paging<T> : BasicModel
|
||||
{
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("items")]
|
||||
public List<T> Items { get; set; }
|
||||
|
||||
[JsonProperty("limit")]
|
||||
public int Limit { get; set; }
|
||||
|
||||
[JsonProperty("next")]
|
||||
public string Next { get; set; }
|
||||
|
||||
[JsonProperty("offset")]
|
||||
public int Offset { get; set; }
|
||||
|
||||
[JsonProperty("previous")]
|
||||
public string Previous { get; set; }
|
||||
|
||||
[JsonProperty("total")]
|
||||
public int Total { get; set; }
|
||||
|
||||
public bool HasNextPage()
|
||||
{
|
||||
return Next != null;
|
||||
}
|
||||
|
||||
public bool HasPreviousPage()
|
||||
{
|
||||
return Previous != null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class PlayHistory : BasicModel
|
||||
{
|
||||
[JsonProperty("track")]
|
||||
public SimpleTrack Track { get; set; }
|
||||
|
||||
[JsonProperty("played_at")]
|
||||
public DateTime PlayedAt { get; set; }
|
||||
|
||||
[JsonProperty("context")]
|
||||
public Context Context { get; set; }
|
||||
}
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using SpotifyAPI.Web.Enums;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class PlaybackContext : BasicModel
|
||||
{
|
||||
[JsonProperty("device")]
|
||||
public Device Device { get; set; }
|
||||
|
||||
[JsonProperty("repeat_state")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public RepeatState RepeatState { get; set; }
|
||||
|
||||
[JsonProperty("shuffle_state")]
|
||||
public bool ShuffleState { get; set; }
|
||||
|
||||
[JsonProperty("context")]
|
||||
public Context Context { get; set; }
|
||||
|
||||
[JsonProperty("timestamp")]
|
||||
public long Timestamp { get; set; }
|
||||
|
||||
[JsonProperty("progress_ms")]
|
||||
public int ProgressMs { get; set; }
|
||||
|
||||
[JsonProperty("is_playing")]
|
||||
public bool IsPlaying { get; set; }
|
||||
|
||||
[JsonProperty("item")]
|
||||
public FullTrack Item { get; set; }
|
||||
|
||||
[JsonProperty("currently_playing_type")]
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public TrackType CurrentlyPlayingType { get; set; }
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class PrivateProfile : BasicModel
|
||||
{
|
||||
[JsonProperty("birthdate")]
|
||||
public string Birthdate { get; set; }
|
||||
|
||||
[JsonProperty("country")]
|
||||
public string Country { get; set; }
|
||||
|
||||
[JsonProperty("display_name")]
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[JsonProperty("email")]
|
||||
public string Email { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("followers")]
|
||||
public Followers Followers { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("images")]
|
||||
public List<Image> Images { get; set; }
|
||||
|
||||
[JsonProperty("product")]
|
||||
public string Product { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class RecommendationSeed
|
||||
{
|
||||
[JsonProperty("afterFilteringSize")]
|
||||
public int AfterFilteringSize { get; set; }
|
||||
|
||||
[JsonProperty("afterRelinkingSize")]
|
||||
public int AfterRelinkingSize { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("initialPoolSize")]
|
||||
public int InitialPoolSize { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class RecommendationSeedGenres : BasicModel
|
||||
{
|
||||
[JsonProperty("genres")]
|
||||
public List<string> Genres { get; set; }
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class Recommendations : BasicModel
|
||||
{
|
||||
[JsonProperty("seeds")]
|
||||
public List<RecommendationSeed> Seeds { get; set; }
|
||||
|
||||
[JsonProperty("tracks")]
|
||||
public List<SimpleTrack> Tracks { get; set; }
|
||||
}
|
||||
}
|
17
SpotifyAPI.Web/Models/Request/CategoriesRequest.cs
Normal file
17
SpotifyAPI.Web/Models/Request/CategoriesRequest.cs
Normal file
@ -0,0 +1,17 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class CategoriesRequest : RequestParams
|
||||
{
|
||||
[QueryParam("country")]
|
||||
public string Country { get; set; }
|
||||
|
||||
[QueryParam("locale")]
|
||||
public string Locale { get; set; }
|
||||
|
||||
[QueryParam("limit")]
|
||||
public int? Limit { get; set; }
|
||||
|
||||
[QueryParam("offset")]
|
||||
public int? Offset { get; set; }
|
||||
}
|
||||
}
|
14
SpotifyAPI.Web/Models/Request/CategoryPlaylistsRequest.cs
Normal file
14
SpotifyAPI.Web/Models/Request/CategoryPlaylistsRequest.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class CategoriesPlaylistsRequest : RequestParams
|
||||
{
|
||||
[QueryParam("country")]
|
||||
public string Country { get; set; }
|
||||
|
||||
[QueryParam("limit")]
|
||||
public int? Limit { get; set; }
|
||||
|
||||
[QueryParam("offset")]
|
||||
public int? Offset { get; set; }
|
||||
}
|
||||
}
|
11
SpotifyAPI.Web/Models/Request/CategoryRequest.cs
Normal file
11
SpotifyAPI.Web/Models/Request/CategoryRequest.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class CategoryRequest : RequestParams
|
||||
{
|
||||
[QueryParam("country")]
|
||||
public string Country { get; set; }
|
||||
|
||||
[QueryParam("locale")]
|
||||
public string Locale { get; set; }
|
||||
}
|
||||
}
|
44
SpotifyAPI.Web/Models/Request/RequestParams.cs
Normal file
44
SpotifyAPI.Web/Models/Request/RequestParams.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public abstract class RequestParams
|
||||
{
|
||||
public Dictionary<string, string> BuildQueryParams()
|
||||
{
|
||||
var queryProps = this.GetType().GetProperties()
|
||||
.Where(prop => prop.GetCustomAttributes(typeof(QueryParamAttribute), true).Length > 0);
|
||||
|
||||
var queryParams = new Dictionary<string, string>();
|
||||
foreach (var prop in queryProps)
|
||||
{
|
||||
var attribute = prop.GetCustomAttribute(typeof(QueryParamAttribute)) as QueryParamAttribute;
|
||||
var value = prop.GetValue(this);
|
||||
if (value != null)
|
||||
{
|
||||
queryParams.Add(attribute.Key ?? prop.Name, value.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
return queryParams;
|
||||
}
|
||||
}
|
||||
|
||||
public class QueryParamAttribute : Attribute
|
||||
{
|
||||
public string Key { get; set; }
|
||||
|
||||
public QueryParamAttribute() { }
|
||||
public QueryParamAttribute(string key)
|
||||
{
|
||||
Key = key;
|
||||
}
|
||||
}
|
||||
|
||||
public class BodyParamAttribute : Attribute
|
||||
{
|
||||
public BodyParamAttribute() { }
|
||||
}
|
||||
}
|
7
SpotifyAPI.Web/Models/Response/CategoriesResponse.cs
Normal file
7
SpotifyAPI.Web/Models/Response/CategoriesResponse.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class CategoriesResponse
|
||||
{
|
||||
public Paging<Category> Categories { get; set; }
|
||||
}
|
||||
}
|
12
SpotifyAPI.Web/Models/Response/Category.cs
Normal file
12
SpotifyAPI.Web/Models/Response/Category.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class Category
|
||||
{
|
||||
public string Href { get; set; }
|
||||
public List<Image> Icons { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class CategoryPlaylistsResponse
|
||||
{
|
||||
public Paging<SimplePlaylist> Playlists { get; set; }
|
||||
}
|
||||
}
|
8
SpotifyAPI.Web/Models/Response/Copyright.cs
Normal file
8
SpotifyAPI.Web/Models/Response/Copyright.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class Copyright
|
||||
{
|
||||
public string Text { get; set; }
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
9
SpotifyAPI.Web/Models/Response/Followers.cs
Normal file
9
SpotifyAPI.Web/Models/Response/Followers.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class Followers
|
||||
{
|
||||
public string Href { get; set; }
|
||||
|
||||
public int Total { get; set; }
|
||||
}
|
||||
}
|
25
SpotifyAPI.Web/Models/Response/FullEpisode.cs
Normal file
25
SpotifyAPI.Web/Models/Response/FullEpisode.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class FullEpisode : IPlaylistElement
|
||||
{
|
||||
public string AudioPreviewUrl { get; set; }
|
||||
public string Description { get; set; }
|
||||
public int DurationMs { get; set; }
|
||||
public bool Explicit { get; set; }
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
public string Href { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<Image> Images { get; set; }
|
||||
public bool IsExternallyHosted { get; set; }
|
||||
public bool IsPlayable { get; set; }
|
||||
public List<string> Languages { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string ReleaseDate { get; set; }
|
||||
public string ReleaseDatePrecision { get; set; }
|
||||
public ResumePoint ResumePoint { get; set; }
|
||||
public SimpleShow Show { get; set; }
|
||||
public PlaylistElementType Type { get; set; }
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
28
SpotifyAPI.Web/Models/Response/FullTrack.cs
Normal file
28
SpotifyAPI.Web/Models/Response/FullTrack.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class FullTrack : IPlaylistElement
|
||||
{
|
||||
public SimpleAlbum Album { get; set; }
|
||||
public List<SimpleArtist> Artists { get; set; }
|
||||
public List<string> AvailableMarkets { get; set; }
|
||||
public int DiscNumber { get; set; }
|
||||
public int DurationMs { get; set; }
|
||||
public bool Explicit { get; set; }
|
||||
public Dictionary<string, string> ExternalIds { get; set; }
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
public string Href { get; set; }
|
||||
public string Id { get; set; }
|
||||
public bool IsPlayable { get; set; }
|
||||
public LinkedTrack LinkedFrom { get; set; }
|
||||
public Dictionary<string, string> Restrictions { get; set; }
|
||||
public string Name { get; set; }
|
||||
public int Popularity { get; set; }
|
||||
public string PreviewUrl { get; set; }
|
||||
public int TrackNumber { get; set; }
|
||||
public PlaylistElementType Type { get; set; }
|
||||
public string Uri { get; set; }
|
||||
public bool IsLocal { get; set; }
|
||||
}
|
||||
}
|
9
SpotifyAPI.Web/Models/Response/Image.cs
Normal file
9
SpotifyAPI.Web/Models/Response/Image.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class Image
|
||||
{
|
||||
public int Height { get; set; }
|
||||
public int Width { get; set; }
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public enum PlaylistElementType
|
||||
{
|
||||
Track,
|
||||
Episode
|
||||
}
|
||||
public interface IPlaylistElement
|
||||
{
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public PlaylistElementType Type { get; set; }
|
||||
}
|
||||
}
|
12
SpotifyAPI.Web/Models/Response/LinkedTrack.cs
Normal file
12
SpotifyAPI.Web/Models/Response/LinkedTrack.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Collections.Generic;
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class LinkedTrack
|
||||
{
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
public string Href { get; set; }
|
||||
public string Id { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string uri { get; set; }
|
||||
}
|
||||
}
|
15
SpotifyAPI.Web/Models/Response/Paging.cs
Normal file
15
SpotifyAPI.Web/Models/Response/Paging.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class Paging<T>
|
||||
{
|
||||
public string Href { get; set; }
|
||||
public List<T> Items { get; set; }
|
||||
public int Limit { get; set; }
|
||||
public string Next { get; set; }
|
||||
public int Offset { get; set; }
|
||||
public string Previous { get; set; }
|
||||
public int Total { get; set; }
|
||||
}
|
||||
}
|
11
SpotifyAPI.Web/Models/Response/PlaylistTrack.cs
Normal file
11
SpotifyAPI.Web/Models/Response/PlaylistTrack.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System;
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class PlaylistTrack
|
||||
{
|
||||
public DateTime? AddedAt { get; set; }
|
||||
public PublicUser AddedBy { get; set; }
|
||||
public bool IsLocal { get; set; }
|
||||
public IPlaylistElement Track { get; set; }
|
||||
}
|
||||
}
|
@ -3,30 +3,18 @@ using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class PublicProfile : BasicModel
|
||||
public class PrivateUser
|
||||
{
|
||||
[JsonProperty("display_name")]
|
||||
public string Country { get; set; }
|
||||
public string DisplayName { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public string Email { get; set; }
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("followers")]
|
||||
public Followers Followers { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("images")]
|
||||
public List<Image> Images { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Product { get; set; }
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
17
SpotifyAPI.Web/Models/Response/PublicUser.cs
Normal file
17
SpotifyAPI.Web/Models/Response/PublicUser.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class PublicUser
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
public Followers Followers { get; set; }
|
||||
public string Href { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<Image> Images { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
8
SpotifyAPI.Web/Models/Response/ResumePointObject.cs
Normal file
8
SpotifyAPI.Web/Models/Response/ResumePointObject.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class ResumePoint
|
||||
{
|
||||
public bool FullyPlayed { get; set; }
|
||||
public int ResumePositionMs { get; set; }
|
||||
}
|
||||
}
|
@ -1,53 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class SimpleAlbum : BasicModel
|
||||
public class SimpleAlbum
|
||||
{
|
||||
[JsonProperty("album_group")]
|
||||
public string AlbumGroup { get; set; }
|
||||
|
||||
[JsonProperty("album_type")]
|
||||
public string AlbumType { get; set; }
|
||||
|
||||
[JsonProperty("artists")]
|
||||
public List<SimpleArtist> Artists { get; set; }
|
||||
|
||||
[JsonProperty("available_markets")]
|
||||
public List<string> AvailableMarkets { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("images")]
|
||||
public List<Image> Images { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("release_date")]
|
||||
public string ReleaseDate { get; set; }
|
||||
|
||||
[JsonProperty("release_date_precision")]
|
||||
public string ReleaseDatePrecision { get; set; }
|
||||
|
||||
[JsonProperty("restrictions")]
|
||||
public Dictionary<string, string> Restrictions { get; set; }
|
||||
|
||||
[JsonProperty("total_tracks")]
|
||||
public int TotalTracks { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,26 +1,13 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class SimpleArtist : BasicModel
|
||||
public class SimpleArtist
|
||||
{
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
23
SpotifyAPI.Web/Models/Response/SimplePlaylist.cs
Normal file
23
SpotifyAPI.Web/Models/Response/SimplePlaylist.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.Collections.Generic;
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
/// <summary>
|
||||
/// <a href="https://developer.spotify.com/documentation/web-api/reference/object-model/#playlist-object-simplified">Docs</a>
|
||||
/// </summary>
|
||||
public class SimplePlaylist
|
||||
{
|
||||
public bool Collaborative { get; set; }
|
||||
public string Description { get; set; }
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
public string Href { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<Image> Images { get; set; }
|
||||
public string Name { get; set; }
|
||||
public PublicUser Owner { get; set; }
|
||||
public bool? Public { get; set; }
|
||||
public string SnapshotId { get; set; }
|
||||
public Paging<PlaylistTrack> Tracks { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
22
SpotifyAPI.Web/Models/Response/SimpleShow.cs
Normal file
22
SpotifyAPI.Web/Models/Response/SimpleShow.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public class SimpleShow
|
||||
{
|
||||
public List<string> AvailableMarkets { get; set; }
|
||||
public Copyright Copyright { get; set; }
|
||||
public string Description { get; set; }
|
||||
public bool Explicit { get; set; }
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
public string Href { get; set; }
|
||||
public string Id { get; set; }
|
||||
public List<Image> Images { get; set; }
|
||||
public bool IsExternallyHosted { get; set; }
|
||||
public List<string> Languages { get; set; }
|
||||
public string MediaType { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Publisher { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
using System.Net;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class ResponseInfo
|
||||
{
|
||||
public WebHeaderCollection Headers { get; set; }
|
||||
|
||||
public HttpStatusCode StatusCode { get; set; }
|
||||
|
||||
public static readonly ResponseInfo Empty = new ResponseInfo();
|
||||
}
|
||||
}
|
@ -1,19 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class SearchItem : BasicModel
|
||||
{
|
||||
[JsonProperty("artists")]
|
||||
public Paging<FullArtist> Artists { get; set; }
|
||||
|
||||
[JsonProperty("albums")]
|
||||
public Paging<SimpleAlbum> Albums { get; set; }
|
||||
|
||||
[JsonProperty("tracks")]
|
||||
public Paging<FullTrack> Tracks { get; set; }
|
||||
|
||||
[JsonProperty("playlists")]
|
||||
public Paging<SimplePlaylist> Playlists { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class SeveralAlbums : BasicModel
|
||||
{
|
||||
[JsonProperty("albums")]
|
||||
public List<FullAlbum> Albums { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class SeveralArtists : BasicModel
|
||||
{
|
||||
[JsonProperty("artists")]
|
||||
public List<FullArtist> Artists { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class SeveralAudioFeatures : BasicModel
|
||||
{
|
||||
[JsonProperty("audio_features")]
|
||||
public List<AudioFeatures> AudioFeatures { get; set; }
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class SeveralTracks : BasicModel
|
||||
{
|
||||
[JsonProperty("tracks")]
|
||||
public List<FullTrack> Tracks { get; set; }
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class SimplePlaylist : BasicModel
|
||||
{
|
||||
[JsonProperty("collaborative")]
|
||||
public bool Collaborative { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternalUrls { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("images")]
|
||||
public List<Image> Images { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("owner")]
|
||||
public PublicProfile Owner { get; set; }
|
||||
|
||||
[JsonProperty("public")]
|
||||
public bool Public { get; set; }
|
||||
|
||||
[JsonProperty("snapshot_id")]
|
||||
public string SnapshotId { get; set; }
|
||||
|
||||
[JsonProperty("tracks")]
|
||||
public PlaylistTrackCollection Tracks { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class SimpleTrack : BasicModel
|
||||
{
|
||||
[JsonProperty("artists")]
|
||||
public List<SimpleArtist> Artists { get; set; }
|
||||
|
||||
[JsonProperty("available_markets")]
|
||||
public List<string> AvailableMarkets { get; set; }
|
||||
|
||||
[JsonProperty("disc_number")]
|
||||
public int DiscNumber { get; set; }
|
||||
|
||||
[JsonProperty("duration_ms")]
|
||||
public int DurationMs { get; set; }
|
||||
|
||||
[JsonProperty("explicit")]
|
||||
public bool Explicit { get; set; }
|
||||
|
||||
[JsonProperty("external_urls")]
|
||||
public Dictionary<string, string> ExternUrls { get; set; }
|
||||
|
||||
[JsonProperty("href")]
|
||||
public string Href { get; set; }
|
||||
|
||||
[JsonProperty("id")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[JsonProperty("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[JsonProperty("preview_url")]
|
||||
public string PreviewUrl { get; set; }
|
||||
|
||||
[JsonProperty("track_number")]
|
||||
public int TrackNumber { get; set; }
|
||||
|
||||
[JsonProperty("restrictions")]
|
||||
public Dictionary<string, string> Restrictions { get; set; }
|
||||
|
||||
[JsonProperty("type")]
|
||||
public string Type { get; set; }
|
||||
|
||||
[JsonProperty("uri")]
|
||||
public string Uri { get; set; }
|
||||
}
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class Snapshot : BasicModel
|
||||
{
|
||||
[JsonProperty("snapshot_id")]
|
||||
public string SnapshotId { get; set; }
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class Token
|
||||
{
|
||||
public Token()
|
||||
{
|
||||
CreateDate = DateTime.Now;
|
||||
}
|
||||
|
||||
[JsonProperty("access_token")]
|
||||
public string AccessToken { get; set; }
|
||||
|
||||
[JsonProperty("token_type")]
|
||||
public string TokenType { get; set; }
|
||||
|
||||
[JsonProperty("expires_in")]
|
||||
public double ExpiresIn { get; set; }
|
||||
|
||||
[JsonProperty("refresh_token")]
|
||||
public string RefreshToken { get; set; }
|
||||
|
||||
[JsonProperty("error")]
|
||||
public string Error { get; set; }
|
||||
|
||||
[JsonProperty("error_description")]
|
||||
public string ErrorDescription { get; set; }
|
||||
|
||||
public DateTime CreateDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the token has expired
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool IsExpired()
|
||||
{
|
||||
return CreateDate.Add(TimeSpan.FromSeconds(ExpiresIn)) <= DateTime.Now;
|
||||
}
|
||||
|
||||
public bool HasError()
|
||||
{
|
||||
return Error != null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Reflection;
|
||||
|
||||
namespace SpotifyAPI.Web.Models
|
||||
{
|
||||
public class TuneableTrack
|
||||
{
|
||||
[String("acousticness")]
|
||||
public float? Acousticness { get; set; }
|
||||
|
||||
[String("danceability")]
|
||||
public float? Danceability { get; set; }
|
||||
|
||||
[String("duration_ms")]
|
||||
public int? DurationMs { get; set; }
|
||||
|
||||
[String("energy")]
|
||||
public float? Energy { get; set; }
|
||||
|
||||
[String("instrumentalness")]
|
||||
public float? Instrumentalness { get; set; }
|
||||
|
||||
[String("key")]
|
||||
public int? Key { get; set; }
|
||||
|
||||
[String("liveness")]
|
||||
public float? Liveness { get; set; }
|
||||
|
||||
[String("loudness")]
|
||||
public float? Loudness { get; set; }
|
||||
|
||||
[String("mode")]
|
||||
public int? Mode { get; set; }
|
||||
|
||||
[String("popularity")]
|
||||
public int? Popularity { get; set; }
|
||||
|
||||
[String("speechiness")]
|
||||
public float? Speechiness { get; set; }
|
||||
|
||||
[String("tempo")]
|
||||
public float? Tempo { get; set; }
|
||||
|
||||
[String("time_signature")]
|
||||
public int? TimeSignature { get; set; }
|
||||
|
||||
[String("valence")]
|
||||
public float? Valence { get; set; }
|
||||
|
||||
public string BuildUrlParams(string prefix)
|
||||
{
|
||||
List<string> urlParams = new List<string>();
|
||||
foreach (PropertyInfo info in GetType().GetProperties())
|
||||
{
|
||||
object value = info.GetValue(this);
|
||||
string name = info.GetCustomAttribute<StringAttribute>()?.Text;
|
||||
if (name == null || value == null)
|
||||
continue;
|
||||
urlParams.Add(value is float valueAsFloat ?
|
||||
$"{prefix}_{name}={valueAsFloat.ToString(CultureInfo.InvariantCulture)}" :
|
||||
$"{prefix}_{name}={value}");
|
||||
}
|
||||
if (urlParams.Count > 0)
|
||||
return "&" + string.Join("&", urlParams);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<TargetFrameworks>netstandard2.1</TargetFrameworks>
|
||||
<PackageId>SpotifyAPI.Web</PackageId>
|
||||
<Title>SpotifyAPI.Web</Title>
|
||||
<Authors>Jonas Dellinger</Authors>
|
||||
|
23
SpotifyAPI.Web/SpotifyUrls.cs
Normal file
23
SpotifyAPI.Web/SpotifyUrls.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
namespace SpotifyAPI.Web
|
||||
{
|
||||
public static class SpotifyUrls
|
||||
{
|
||||
static URIParameterFormatProvider _provider = new URIParameterFormatProvider();
|
||||
|
||||
public static Uri API_V1 = new Uri("https://api.spotify.com/v1/");
|
||||
|
||||
public static Uri Me() => _Uri("me");
|
||||
|
||||
public static Uri User(string userId) => _Uri($"users/{userId}");
|
||||
|
||||
public static Uri Categories() => _Uri("browse/categories");
|
||||
|
||||
public static Uri Category(string categoryId) => _Uri($"browse/categories/{categoryId}");
|
||||
|
||||
public static Uri CategoryPlaylists(string categoryId) => _Uri($"browse/categories/{categoryId}/playlists");
|
||||
|
||||
private static Uri _Uri(FormattableString path) => new Uri(path.ToString(_provider), UriKind.Relative);
|
||||
private static Uri _Uri(string path) => new Uri(path, UriKind.Relative);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user