Skip to content
Merged
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
16 changes: 16 additions & 0 deletions spotify-web-api-core/src/main/resources/spotify-web-api.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3752,6 +3752,14 @@ categories:
\ their account in the [account settings](https://www.spotify.com/se/account/overview/)."
type: String
required: false
- location: BODY
name: ids
description: "A JSON array of the [Spotify IDs](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids).\
\ \nA maximum of 50 items can be specified in one request. *Note: if\
\ the `ids` parameter is present in the query string, any IDs listed here\
\ in the body will be ignored.*"
type: "Array[String]"
required: false
responseDescription: "On success, the HTTP status code in the response header\
\ is `200` OK.\nOn error, the header status code is an [error code](https://developer.spotify.com/documentation/web-api/#response-status-codes)\
\ and the response body contains an [error object](https://developer.spotify.com/documentation/web-api/#error-details).\
Expand Down Expand Up @@ -3931,6 +3939,14 @@ categories:
\ Maximum: 50 IDs."
type: String
required: true
- location: BODY
name: ids
description: "A JSON array of the [Spotify IDs](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids).\
\ \nA maximum of 50 items can be specified in one request. *Note: if\
\ the `ids` parameter is present in the query string, any IDs listed here\
\ in the body will be ignored.*"
type: "Array[String]"
required: false
responseDescription: "On success, the HTTP status code in the response header\
\ is `200` OK. On error, the header status code is an [error code](https://developer.spotify.com/documentation/web-api/#response-status-codes)\
\ and the response body contains an [error object](https://developer.spotify.com/documentation/web-api/#error-details).\
Expand Down
30 changes: 30 additions & 0 deletions spotify-web-api-generator-open-api/spotify-web-api-openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2695,6 +2695,21 @@ paths:
required: true
schema:
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
ids:
type: array
description: "A JSON array of the [Spotify IDs](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids).\
\ \nA maximum of 50 items can be specified in one request. *Note:\
\ if the `ids` parameter is present in the query string, any IDs\
\ listed here in the body will be ignored.*"
items:
type: string
required: false
responses:
default:
$ref: '#/components/responses/ErrorResponse'
Expand Down Expand Up @@ -2747,6 +2762,21 @@ paths:
required: false
schema:
type: string
requestBody:
content:
application/json:
schema:
type: object
properties:
ids:
type: array
description: "A JSON array of the [Spotify IDs](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids).\
\ \nA maximum of 50 items can be specified in one request. *Note:\
\ if the `ids` parameter is present in the query string, any IDs\
\ listed here in the body will be ignored.*"
items:
type: string
required: false
responses:
default:
$ref: '#/components/responses/ErrorResponse'
Expand Down
2 changes: 1 addition & 1 deletion spotify-web-api-parser/response-types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ category-library:
- type: "Array[Boolean]"
status: 200
endpoint-get-users-saved-episodes:
md5Hash: 8c34757f341b78f13871c0642765aa84
md5Hash: 80f3e189edc6742d8348ebee029f2a6d
responseTypes:
- type: "PagingObject[SavedEpisodeObject]"
status: 200
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.sonallux.spotify.parser;

import de.sonallux.spotify.core.model.SpotifyWebApiCategory;
import de.sonallux.spotify.core.model.SpotifyWebApiEndpoint;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
Expand All @@ -18,6 +19,8 @@ static void fixApiEndpoints(SortedMap<String, SpotifyWebApiCategory> categories)
fixGetUsersSavedShowsScope(categories);
fixCheckUsersSavedShowsScope(categories);
fixReplaceAndReorderPlaylistTrackUrisParameter(categories);
fixSaveShowsForCurrentUserBodyParameter(categories);
fixRemoveUsersSavedShowsBodyParameter(categories);
}

private static void fixChangePlaylistsDetails(SortedMap<String, SpotifyWebApiCategory> categories) {
Expand All @@ -29,9 +32,9 @@ private static void fixChangePlaylistsDetails(SortedMap<String, SpotifyWebApiCat
.orElse(null);
if (paramPath == null) {
log.warn("change-playlist-details wrong playlist_id parameter type has been fixed");
} else {
paramPath.setType("String");
return;
}
paramPath.setType("String");
}

private static void fixGetInfoAboutUsersCurrentPlayback(SortedMap<String, SpotifyWebApiCategory> categories) {
Expand All @@ -43,9 +46,9 @@ private static void fixGetInfoAboutUsersCurrentPlayback(SortedMap<String, Spotif
}
if (endpoint.getScopes().size() != 0) {
log.warn("endpoint-get-information-about-the-users-current-playback missing scope has been fixed");
} else {
endpoint.getScopes().add("user-read-playback-state");
return;
}
endpoint.getScopes().add("user-read-playback-state");
}

private static void fixStartAUsersPlayback(SortedMap<String, SpotifyWebApiCategory> categories) {
Expand Down Expand Up @@ -100,19 +103,19 @@ private static void fixGetUsersSavedShowsScope(SortedMap<String, SpotifyWebApiCa
.getEndpoints().get("endpoint-get-users-saved-shows");
if (!endpoint.getScopes().contains("user-libary-read")) {
log.warn("endpoint-get-users-saved-shows scope user-libary-read has been fixed");
} else {
endpoint.setScopes(List.of("user-library-read"));
return;
}
endpoint.setScopes(List.of("user-library-read"));
}

private static void fixCheckUsersSavedShowsScope(SortedMap<String, SpotifyWebApiCategory> categories) {
var endpoint = categories.get("category-library")
.getEndpoints().get("endpoint-check-users-saved-shows");
if (!endpoint.getScopes().contains("user-libary-read")) {
log.warn("endpoint-check-users-saved-shows scope user-libary-read has been fixed");
} else {
endpoint.setScopes(List.of("user-library-read"));
return;
}
endpoint.setScopes(List.of("user-library-read"));
}

private static void fixReplaceAndReorderPlaylistTrackUrisParameter(SortedMap<String, SpotifyWebApiCategory> categories) {
Expand All @@ -125,8 +128,10 @@ private static void fixReplaceAndReorderPlaylistTrackUrisParameter(SortedMap<Str
if (urisBodyParameter == null) {
log.warn("Can not find uris body parameter in endpoint-reorder-or-replace-playlists-tracks");
return;
} else if (!urisBodyParameter.getDescription().isBlank()) {
}
if (!urisBodyParameter.getDescription().isBlank()) {
log.warn("Missing description on uris body parameter in endpoint-reorder-or-replace-playlists-tracks has been fixed");
return;
}

var urisQueryParameter = endpoint.getParameters().stream()
Expand All @@ -139,4 +144,42 @@ private static void fixReplaceAndReorderPlaylistTrackUrisParameter(SortedMap<Str

urisBodyParameter.setDescription(urisQueryParameter.getDescription());
}

private static void fixSaveShowsForCurrentUserBodyParameter(SortedMap<String, SpotifyWebApiCategory> categories) {
var endpoint = categories.get("category-library")
.getEndpoints().get("endpoint-save-shows-user");

if (endpoint.getParameters().stream().anyMatch(parameter -> parameter.getLocation() == BODY && "ids".equals(parameter.getName()))) {
log.warn("Missing body parameter for endpoint-save-shows-user has been fixed");
return;
}

endpoint.getParameters().add(new SpotifyWebApiEndpoint.Parameter(
BODY,
"ids",
"A JSON array of the [Spotify IDs](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids). \n" +
"A maximum of 50 items can be specified in one request. *Note: if the `ids` parameter is present in the query string, " +
"any IDs listed here in the body will be ignored.*",
"Array[String]",
false));
}

private static void fixRemoveUsersSavedShowsBodyParameter(SortedMap<String, SpotifyWebApiCategory> categories) {
var endpoint = categories.get("category-library")
.getEndpoints().get("endpoint-remove-shows-user");

if (endpoint.getParameters().stream().anyMatch(parameter -> parameter.getLocation() == BODY && "ids".equals(parameter.getName()))) {
log.warn("Missing body parameter for endpoint-remove-shows-user has been fixed");
return;
}

endpoint.getParameters().add(new SpotifyWebApiEndpoint.Parameter(
BODY,
"ids",
"A JSON array of the [Spotify IDs](https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids). \n" +
"A maximum of 50 items can be specified in one request. *Note: if the `ids` parameter is present in the query string, " +
"any IDs listed here in the body will be ignored.*",
"Array[String]",
false));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,20 +59,21 @@ private void addResponseTypes(SortedMap<String, SpotifyWebApiCategory> categorie
try {
if (isInteractive) {
responseTypeMapper.update(new ArrayList<>(categories.values()));
responseTypeMapper.save();
}

for (var category : categories.values()) {
for (var endpoint : category.getEndpointList()) {
var endpointResponse = responseTypeMapper.getEndpointResponse(category.getId(), endpoint.getId());
if (endpointResponse == null || endpointResponse.getResponseTypes().isEmpty()) {
var responseTypes = responseTypeMapper.getEndpointResponseTypes(category.getId(), endpoint);
if (responseTypes == null || responseTypes.isEmpty()) {
log.warn("Missing response type in {} for {} {} with response: \n{}\n", category.getId(),
endpoint.getHttpMethod(), endpoint.getId(), endpoint.getResponseDescription());
continue;
}
endpoint.setResponseTypes(endpointResponse.getResponseTypes());
endpoint.setResponseTypes(responseTypes);
}
}

responseTypeMapper.save();
} catch (IOException e) {
log.error("Failed to load missing response types", e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import java.util.Set;
import java.util.stream.Collectors;

public class Html2Markdown {
class Html2Markdown {

private static final FlexmarkHtmlConverter CONVERTER;

Expand All @@ -27,11 +27,11 @@ public class Html2Markdown {
.build();
}

public static String convert(Node node) {
static String convert(Node node) {
return CONVERTER.convert(node).trim();
}

public static String convert(List<? extends Node> nodes) {
static String convert(List<? extends Node> nodes) {
return nodes.stream()
.map(CONVERTER::convert)
.collect(Collectors.joining("\n"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.math.BigInteger;
Expand All @@ -19,14 +20,15 @@
import java.security.NoSuchAlgorithmException;
import java.util.*;

public class ResponseTypeMapper {
@Slf4j
class ResponseTypeMapper {

private final Path responseTypesFile;
private final Map<String, Map<String, EndpointResponse>> responseTypes;
private final MessageDigest md5Digest;
private final ObjectMapper objectMapper;

public ResponseTypeMapper(Path responseTypesFile) throws IOException, NoSuchAlgorithmException {
ResponseTypeMapper(Path responseTypesFile) throws IOException, NoSuchAlgorithmException {
this.responseTypesFile = responseTypesFile;
this.objectMapper = Yaml.create();
this.md5Digest = MessageDigest.getInstance("MD5");
Expand All @@ -39,13 +41,26 @@ private Map<String, Map<String, EndpointResponse>> load() throws IOException {
}
}

public void save() throws IOException {
List<SpotifyWebApiEndpoint.ResponseType> getEndpointResponseTypes(String categoryId, SpotifyWebApiEndpoint endpoint) {
var endpointResponse = getEndpointResponse(categoryId, endpoint.getId());
if (endpointResponse == null) {
return null;
}
var currentHash = calculateMD5Hash(endpoint);
if (!currentHash.equals(endpointResponse.getMd5Hash())) {
log.warn("Response description for endpoint {} has changed", endpoint.getId());
endpointResponse.setMd5Hash(currentHash);
}
return endpointResponse.getResponseTypes();
}

void save() throws IOException {
try (var outputStream = Files.newOutputStream(this.responseTypesFile)) {
objectMapper.writeValue(outputStream, responseTypes);
}
}

public void update(List<SpotifyWebApiCategory> categories) {
void update(List<SpotifyWebApiCategory> categories) {
var scanner = new Scanner(System.in);
for (var category : categories) {
for (var endpoint : category.getEndpointList()) {
Expand Down Expand Up @@ -104,7 +119,7 @@ private static int readInt(Scanner scanner, int defaultValue) {
}
}

public EndpointResponse getEndpointResponse(String categoryId, String endpointId) {
private EndpointResponse getEndpointResponse(String categoryId, String endpointId) {
var endpointTypes = responseTypes.get(categoryId);
if (endpointTypes == null) {
return null;
Expand Down Expand Up @@ -135,7 +150,7 @@ private String calculateMD5Hash(SpotifyWebApiEndpoint endpoint) {
@Setter
@AllArgsConstructor
@NoArgsConstructor
public static class EndpointResponse {
static class EndpointResponse {
private String md5Hash;
private List<SpotifyWebApiEndpoint.ResponseType> responseTypes = new ArrayList<>();
}
Expand Down