From d8dd385d84c5ca69ec1939fe67deef85b1503a08 Mon Sep 17 00:00:00 2001 From: werwolf2303 Date: Fri, 7 Nov 2025 18:01:12 +0100 Subject: [PATCH] Fix #1102 --- .../gianlu/librespot/dealer/ApiClient.java | 82 ++++++++++++------- 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/lib/src/main/java/xyz/gianlu/librespot/dealer/ApiClient.java b/lib/src/main/java/xyz/gianlu/librespot/dealer/ApiClient.java index 430bd8f8..0c27584b 100644 --- a/lib/src/main/java/xyz/gianlu/librespot/dealer/ApiClient.java +++ b/lib/src/main/java/xyz/gianlu/librespot/dealer/ApiClient.java @@ -23,6 +23,7 @@ import com.spotify.clienttoken.http.v0.ClientToken; import com.spotify.connectstate.Connect; import com.spotify.extendedmetadata.ExtendedMetadata; +import com.spotify.extendedmetadata.ExtensionKindOuterClass; import com.spotify.metadata.Metadata; import com.spotify.playlist4.Playlist4ApiProto; import okhttp3.*; @@ -98,7 +99,7 @@ public void sendAsync(@NotNull String method, @NotNull String suffix, @Nullable * Sends a request to the Spotify API. * * @param method The request method - * @param suffix The suffix to be appended to {@link #baseUrl} also know as path + * @param suffix The suffix to be appended to {@link #baseUrl} also known as path * @param headers Additional headers * @param body The request body * @param tries How many times the request should be reattempted (0 = none) @@ -143,57 +144,47 @@ else if (resp.code() != 200) @NotNull public Metadata.Track getMetadata4Track(@NotNull TrackId track) throws IOException, TokenProvider.TokenException { - try (Response resp = send("GET", "/metadata/4/track/" + track.hexId(), null, null)) { - StatusCodeException.checkStatus(resp); + ExtendedMetadata.BatchedExtensionResponse response = getExtendedMetadata(ExtensionKindOuterClass.ExtensionKind.TRACK_V4, track); - ResponseBody body; - if ((body = resp.body()) == null) throw new IOException(); - return Metadata.Track.parseFrom(body.byteStream()); - } + checkExtendedMetadataResponse(response); + + return Metadata.Track.parseFrom(response.getExtendedMetadata(0).getExtensionData(0).getExtensionData().getValue()); } @NotNull public Metadata.Episode getMetadata4Episode(@NotNull EpisodeId episode) throws IOException, TokenProvider.TokenException { - try (Response resp = send("GET", "/metadata/4/episode/" + episode.hexId(), null, null)) { - StatusCodeException.checkStatus(resp); + ExtendedMetadata.BatchedExtensionResponse response = getExtendedMetadata(ExtensionKindOuterClass.ExtensionKind.EPISODE_V4, episode); - ResponseBody body; - if ((body = resp.body()) == null) throw new IOException(); - return Metadata.Episode.parseFrom(body.byteStream()); - } + checkExtendedMetadataResponse(response); + + return Metadata.Episode.parseFrom(response.getExtendedMetadata(0).getExtensionData(0).getExtensionData().getValue()); } @NotNull public Metadata.Album getMetadata4Album(@NotNull AlbumId album) throws IOException, TokenProvider.TokenException { - try (Response resp = send("GET", "/metadata/4/album/" + album.hexId(), null, null)) { - StatusCodeException.checkStatus(resp); + ExtendedMetadata.BatchedExtensionResponse response = getExtendedMetadata(ExtensionKindOuterClass.ExtensionKind.ALBUM_V4, album); - ResponseBody body; - if ((body = resp.body()) == null) throw new IOException(); - return Metadata.Album.parseFrom(body.byteStream()); - } + checkExtendedMetadataResponse(response); + + return Metadata.Album.parseFrom(response.getExtendedMetadata(0).getExtensionData(0).getExtensionData().getValue()); } @NotNull public Metadata.Artist getMetadata4Artist(@NotNull ArtistId artist) throws IOException, TokenProvider.TokenException { - try (Response resp = send("GET", "/metadata/4/artist/" + artist.hexId(), null, null)) { - StatusCodeException.checkStatus(resp); + ExtendedMetadata.BatchedExtensionResponse response = getExtendedMetadata(ExtensionKindOuterClass.ExtensionKind.ARTIST_V4, artist); - ResponseBody body; - if ((body = resp.body()) == null) throw new IOException(); - return Metadata.Artist.parseFrom(body.byteStream()); - } + checkExtendedMetadataResponse(response); + + return Metadata.Artist.parseFrom(response.getExtendedMetadata(0).getExtensionData(0).getExtensionData().getValue()); } @NotNull public Metadata.Show getMetadata4Show(@NotNull ShowId show) throws IOException, TokenProvider.TokenException { - try (Response resp = send("GET", "/metadata/4/show/" + show.hexId(), null, null)) { - StatusCodeException.checkStatus(resp); + ExtendedMetadata.BatchedExtensionResponse response = getExtendedMetadata(ExtensionKindOuterClass.ExtensionKind.SHOW_V4, show); - ResponseBody body; - if ((body = resp.body()) == null) throw new IOException(); - return Metadata.Show.parseFrom(body.byteStream()); - } + checkExtendedMetadataResponse(response); + + return Metadata.Show.parseFrom(response.getExtendedMetadata(0).getExtensionData(0).getExtensionData().getValue()); } @NotNull @@ -207,6 +198,17 @@ public EntityCanvazResponse getCanvases(@NotNull EntityCanvazRequest req) throws } } + public void checkExtendedMetadataResponse(ExtendedMetadata.BatchedExtensionResponse response) throws IOException { + if (response.getExtendedMetadataCount() == 0) + throw new IOException("No metadata in BatchedExtensionResponse"); + + if (response.getExtendedMetadata(0).getExtensionDataCount() == 0) + throw new IOException("No metadata in ExtendedMetadata in BatchedExtensionResponse"); + + if (response.getExtendedMetadata(0).getExtensionData(0).getHeader().getStatusCode() != 200) + throw new IOException("Bad status code for metadata: " + response.getExtendedMetadata(0).getExtensionData(0).getHeader().getStatusCode()); + } + @NotNull public ExtendedMetadata.BatchedExtensionResponse getExtendedMetadata(@NotNull ExtendedMetadata.BatchedEntityRequest req) throws IOException, TokenProvider.TokenException { try (Response resp = send("POST", "/extended-metadata/v0/extended-metadata", null, protoBody(req))) { @@ -218,6 +220,24 @@ public ExtendedMetadata.BatchedExtensionResponse getExtendedMetadata(@NotNull Ex } } + @NotNull + public ExtendedMetadata.BatchedExtensionResponse getExtendedMetadata(@NotNull ExtensionKindOuterClass.ExtensionKind extensionKind, @NotNull SpotifyId spotifyId) throws IOException, TokenProvider.TokenException { + try (Response resp = send("POST", "/extended-metadata/v0/extended-metadata", null, protoBody(ExtendedMetadata.BatchedEntityRequest.newBuilder() + .addEntityRequest(ExtendedMetadata.EntityRequest.newBuilder() + .setEntityUri(spotifyId.toSpotifyUri()) + .addQuery(ExtendedMetadata.ExtensionQuery.newBuilder() + .setExtensionKind(extensionKind) + .build()) + .build()) + .build()))) { + StatusCodeException.checkStatus(resp); + + ResponseBody body; + if ((body = resp.body()) == null) throw new IOException(); + return ExtendedMetadata.BatchedExtensionResponse.parseFrom(body.byteStream()); + } + } + @NotNull public Playlist4ApiProto.SelectedListContent getPlaylist(@NotNull PlaylistId id) throws IOException, TokenProvider.TokenException { try (Response resp = send("GET", "/playlist/v2/playlist/" + id.id(), null, null)) {