Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Completed PlaylistsApi.RemoveItems. #48

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,4 @@ Huge thanks to **@aevansme**, **@brandongregoryscott** and **@akshays2112** for

Contributions welcomed. Read [CONTRIB.md](./CONTRIB.md)

[SpotifyApi.NetCore.Samples]:https://github.com/Ringobot/SpotifyApi.NetCore.Samples
[SpotifyApi.NetCore.Samples]:https://github.com/Ringobot/SpotifyApi.NetCore.Samples
39 changes: 39 additions & 0 deletions src/SpotifyApi.NetCore.Tests/PlaylistsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -252,5 +252,44 @@ public async Task GetPlaylistCoverImage_PlaylistId_AtLeastOnePlalistCoverImageRe
var playlistCoverImages = await api.GetPlaylistCoverImage<Image[]>("3cEYpjA9oz9GiPac4AsH4n", accessToken);
Assert.IsTrue(playlistCoverImages.Length > 0, "No playlist images were found.");
}

[TestMethod]
[TestCategory("Integration")]
public async Task RemoveItems_PlaylistId_SpotifyUris_SnapshotIdIsNotNull()
{
// act
Assert.IsNotNull(await api.RemoveItems("46sqDMykUCnssu2F3zWXEF", new string[] { "spotify:track:5ArQzSBevAdXTxRY6Ulhbq" },
accessToken: await TestsHelper.GetUserAccessToken()));
}

[TestMethod]
[TestCategory("Integration")]
public async Task RemoveItems_PlaylistId_SpotifyUris_SnapshotId_SnapshotIdIsNotNull()
{
// act
Assert.IsNotNull(await api.RemoveItems("46sqDMykUCnssu2F3zWXEF", new string[] { "spotify:track:5ArQzSBevAdXTxRY6Ulhbq" },
"MTQsMWNlNjE5NWJkYWFjOTNmNDM1M2NjZDM4NGNjMWViMTZlNzk0ZWEyYw==", accessToken: await TestsHelper.GetUserAccessToken()));
}

[TestMethod]
[TestCategory("Integration")]
public async Task RemoveItems_PlaylistId_SpotifyUriLocations_SnapshotIdIsNotNull()
{
// act
Assert.IsNotNull(await api.RemoveItems("46sqDMykUCnssu2F3zWXEF",
new (string uri, int[] positions)[] { ("spotify:track:1Eolhana7nKHYpcYpdVcT5", new int[] { 0 }) },
accessToken: await TestsHelper.GetUserAccessToken()));
}

[TestMethod]
[TestCategory("Integration")]
public async Task RemoveItems_PlaylistId_SpotifyUriLocations_SnapshotId_SnapshotIdIsNotNull()
{
// act
Assert.IsNotNull(await api.RemoveItems("46sqDMykUCnssu2F3zWXEF",
new (string uri, int[] positions)[] { ("spotify:track:7iL6o9tox1zgHpKUfh9vuC", new int[] { 0 }) },
"MTQsMWNlNjE5NWJkYWFjOTNmNDM1M2NjZDM4NGNjMWViMTZlNzk0ZWEyYw==", accessToken: await TestsHelper.GetUserAccessToken()));
}

}
}
6 changes: 3 additions & 3 deletions src/SpotifyApi.NetCore.Tests/TracksApiTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,8 @@ public async Task GetTrack_TrackIdNoMarket_MarketsArrayExists()
public async Task GetTrack_TrackIdMarket_AvailableMarketsIsNull()
{
// arrange
const string trackId = "5lA3pwMkBdd24StM90QrNR";
const string market = SpotifyCountryCodes.New_Zealand;
const string trackId = "11dFghVXANMlKmJXsNCbd8";
const string market = SpotifyCountryCodes.Spain;

var http = new HttpClient();
var accounts = new AccountsService(http, TestsHelper.GetLocalConfig());
Expand All @@ -64,7 +64,7 @@ public async Task GetTrack_TrackIdMarket_AvailableMarketsIsNull()
var response = await api.GetTrack(trackId, market);

// assert
Assert.IsNull(response.AvailableMarkets);
Assert.IsNull(response?.AvailableMarkets?.Length == 0 ? null : "Array not empty.");
}

[TestCategory("Integration")]
Expand Down
56 changes: 56 additions & 0 deletions src/SpotifyApi.NetCore/Models/PlaylistRemoveItemsPayloadData.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Newtonsoft.Json;
using System.Collections.Generic;

namespace SpotifyApi.NetCore.Models
{
public partial class PlaylistRemoveItemsPayloadDataUriItems
{

public PlaylistRemoveItemsPayloadDataUriItems(string[] uris, string snapshotId = null)
{
Uris = new PlaylistRemoveItemsPayloadDataUriItem[uris.Length];
for (int i = 0; i < Uris.Length; i++)
{
Uris[i] = new PlaylistRemoveItemsPayloadDataUriItem(uris[i]);
}
SnapshotId = snapshotId;
}

public PlaylistRemoveItemsPayloadDataUriItems((string uri, int[] positions)[] uriPositions, string snapshotId = null)
{
Uris = new PlaylistRemoveItemsPayloadDataUriItem[uriPositions.Length];
for (int i = 0; i < Uris.Length; i++)
{
Uris[i] = new PlaylistRemoveItemsPayloadDataUriItem(uriPositions[i]);
}
SnapshotId = snapshotId;
}

[JsonProperty("tracks", NullValueHandling = NullValueHandling.Ignore)]
public PlaylistRemoveItemsPayloadDataUriItem[] Uris { get; set; }

[JsonProperty("snapshot_id", NullValueHandling = NullValueHandling.Ignore)]
public string SnapshotId { get; set; }

}

public partial class PlaylistRemoveItemsPayloadDataUriItem
{

public PlaylistRemoveItemsPayloadDataUriItem(string uri) => this.Uri = uri;

public PlaylistRemoveItemsPayloadDataUriItem((string uri, int[] positions) uriPositions)
{
Uri = uriPositions.uri;
Positions = uriPositions.positions;
}

[JsonProperty("uri")]
public string Uri { get; set; }

[JsonProperty("positions", NullValueHandling = NullValueHandling.Ignore)]
public int[] Positions { get; set; }

}

}
29 changes: 25 additions & 4 deletions src/SpotifyApi.NetCore/PlaylistsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Text;
using SpotifyApi.NetCore.Models;

namespace SpotifyApi.NetCore
{
Expand Down Expand Up @@ -464,11 +465,21 @@ public async Task<T> GetPlaylistCoverImage<T>(
/// <remarks>
/// https://developer.spotify.com/documentation/web-api/reference/playlists/remove-tracks-playlist/
/// </remarks>
public Task<ModifyPlaylistResponse> RemoveItems(
public async Task<ModifyPlaylistResponse> RemoveItems(
string playlistId,
string[] spotifyUris,
string snapshotId = null,
string accessToken = null) => throw new NotImplementedException();
string accessToken = null)
{
if (string.IsNullOrWhiteSpace(playlistId)) throw new
ArgumentException("A valid Spotify playlist id must be specified.");

if (spotifyUris?.Length < 1 || spotifyUris?.Length > 100) throw new
ArgumentException("A minimum of 1 and a maximum of 100 Spotify uri must be specified.");

var builder = new UriBuilder($"{BaseUrl}/playlists/{playlistId}/tracks");
return (await Delete<ModifyPlaylistResponse>(builder.Uri, new PlaylistRemoveItemsPayloadDataUriItems(spotifyUris, snapshotId), accessToken)).Data;
}

/// <summary>
/// Remove one or more items from a user’s playlist.
Expand All @@ -485,11 +496,21 @@ public Task<ModifyPlaylistResponse> RemoveItems(
/// <remarks>
/// https://developer.spotify.com/documentation/web-api/reference/playlists/remove-tracks-playlist/
/// </remarks>
public Task<ModifyPlaylistResponse> RemoveItems(
public async Task<ModifyPlaylistResponse> RemoveItems(
string playlistId,
(string uri, int[] positions)[] spotifyUriPositions,
string snapshotId = null,
string accessToken = null) => throw new NotImplementedException();
string accessToken = null)
{
if (string.IsNullOrWhiteSpace(playlistId)) throw new
ArgumentException("A valid Spotify playlist id must be specified.");

if (spotifyUriPositions?.Length < 1 || spotifyUriPositions?.Length > 100) throw new
ArgumentException("A minimum of 1 and a maximum of 100 Spotify uri and positions must be specified.");

var builder = new UriBuilder($"{BaseUrl}/playlists/{playlistId}/tracks");
return (await Delete<ModifyPlaylistResponse>(builder.Uri, new PlaylistRemoveItemsPayloadDataUriItems(spotifyUriPositions, snapshotId), accessToken)).Data;
}

#endregion

Expand Down
2 changes: 1 addition & 1 deletion src/SpotifyApi.NetCore/SpotifyApi.NetCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="2.2.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="2.2.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
</ItemGroup>
</Project>
48 changes: 48 additions & 0 deletions src/SpotifyApi.NetCore/SpotifyWebApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,54 @@ protected internal virtual async Task<SpotifyResponse> Post(Uri uri, object data
protected internal virtual async Task<SpotifyResponse<T>> Post<T>(Uri uri, object data, string accessToken = null)
=> await PostOrPut<T>("POST", uri, data, accessToken);

/// <summary>
/// Helper to DELETE an object with content to put in request body.
/// </summary>
protected internal virtual async Task<SpotifyResponse<T>> Delete<T>(Uri uri, object data, string accessToken = null)
{
Logger.Debug($"DELETE {uri}. Token = {accessToken?.ToString()?.Substring(0, 4)}...", nameof(SpotifyWebApi));

_http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken ?? (await GetAccessToken()));

StringContent content = null;

if (data == null)
{
content = null;
}
else
{
content = new StringContent(JsonConvert.SerializeObject(data));
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}

HttpResponseMessage response = null;

HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Delete, uri);
request.Content = content;

response = await _http.SendAsync(request);

Logger.Information($"DELETE {uri} {response.StatusCode}", nameof(RestHttpClient));

await RestHttpClient.CheckForErrors(response);

var spotifyResponse = new SpotifyResponse<T>
{
StatusCode = response.StatusCode,
ReasonPhrase = response.ReasonPhrase
};

if (response.Content != null)
{
string json = await response.Content.ReadAsStringAsync();
if (!string.IsNullOrEmpty(json)) spotifyResponse.Data = JsonConvert.DeserializeObject<T>(json);
}

return spotifyResponse;
}

/// <summary>
/// Helper to DELETE an object
/// </summary>
Expand Down