How do I make an audio player with the Spotify Web API? - javascript

I was trying to make an audio player by starting with a play button. In my HTMl code i made a button:
Play
Then I used this code to make it play a song, but it doesnt seem to work.
document.getElementById('play').addEventListener('click', function() {
$.ajax({
url: 'https://api.spotify.com/v1/me/player/play',
type: 'PUT',
headers: {
'Authorization': 'Bearer ' + access_token
},
dataType: "json",
contentType: "application/json",
data: JSON.stringify({
"uris": ["spotify:track:"] + apiData.item.id,
"position_ms": apiData.progress_ms
})
});
});
apiData.item.id refers to the id of the currently playing track
apiData.progress_ms refers to the progress in milliseconds of currently playing track.
When I run my code and click on the play button, nothing happens. I don't know what I did wrong.
But I tried making a pause button by first making a button with an id called 'pause'. Then I did the following:
document.getElementById('pause').addEventListener('click', function() {
$.ajax({
url: 'https://api.spotify.com/v1/me/player/pause',
type: 'PUT',
headers: {
'Authorization': 'Bearer ' + access_token
},
dataType: "json",
contentType: "application/json",
data: JSON.stringify({
"uris": ["spotify:track:"] + apiData.item.id,
"position_ms": apiData.progress_ms
})
});
});
This is actually working! But I don't understand why the play button doesn't work and the pause button does.
Here is the documentation I used for both buttons:
https://developer.spotify.com/documentation/web-api/reference/player/start-a-users-playback/
https://developer.spotify.com/documentation/web-api/reference/player/pause-a-users-playback/
For the play button I got this error in the console log:
error 400
Can somebody help me out?

tl;dr: Working snippets at the bottom of this answer!
The uris field takes an array containing Spotify uris. This "uris": ["spotify:track:"] + apiData.item.id doesn't resolve to an array but to a string which is not what the endpoint awaits. Using [`spotify:track:${id}`] will work therefore.
This snippet shows the difference between the two.
console.log(["spotify:track:"] + id);
// Output with id = 1234: "spotify:track:1234" -> String
console.log([`spotify:track:${id}`]);
// Output with id = 1234: ["spotify:track:1234"] -> Array of strings
The reason the stop button works is that Spotify's pause endpoint doesn't use any of the data you passed in. The pause endpoint only has one optional query parameter called device_id. The data you passed along with it just gets ignored therefore. So the Ajax call for pause can be simplified as seen in the following snippets.
Here are two working snippets given that an access token is used that has the user-modify-playback-state scope authorized.
Play
$.ajax({
url: 'https://api.spotify.com/v1/me/player/play',
type: 'PUT',
headers: {
'Authorization': 'Bearer ' + access_token
},
dataType: "json",
contentType: "application/json",
data: JSON.stringify({
"uris": [`spotify:track:${apiData.item.id}`],
"position_ms": apiData.progress_ms
})
});
Pause
$.ajax({
url: 'https://api.spotify.com/v1/me/player/pause',
type: 'PUT',
headers: {
'Authorization': 'Bearer ' + access_token
}
});

Related

Best practice for nesting ajax calls

I am creating a simple app using Spotify REST API and JQuery where users can find an artist, and then it will show info about the artist, related artists, and most listened to songs on-page. I created 3 ajax calls which u can see below and everything works, but I think that it can be written in a better way (promises maybe?).
The first ajax call gets id from the server and create some DOM elements. The second two ajax calls need id to run and also create DOM elements. There is also a delete button that should delete DOM elements built from the data of each ajax call.
Is it possible to have it nested using the best practice or this is the only way possible?
artistForm.submit((e) => {
e.preventDefault();
let inputSearchQuery = artistInput.val();
let searchQuery = encodeURI(inputSearchQuery);
$.ajax({
url: `${baseUrl}search?q=${searchQuery}&type=artist`,
type: 'GET',
datatype: 'json',
headers: {
'Authorization': 'Bearer ' + accessToken
}
}).done((resp) => {
const artistId = (resp.artists.items[0].id);
// working with data and appending them on DOM
$.ajax({
url: `${baseUrl}artists/${artistId}/top-tracks?country=CZ`,
type: 'GET',
datatype: 'json',
headers: {
'Authorization': 'Bearer ' + accessToken
}
}).done((resp) => {
// working with data and appending them on DOM
$.ajax({
url: `${baseUrl}artists/${artistId}/related-artists`,
type: 'GET',
datatype: 'json',
headers: {
'Authorization': 'Bearer ' + accessToken
}
}).done((resp) => {
// working with data and appending them on DOM
deleteArtist.click(() => {
// need to have acces to data from every ajax call.
})
});
});
});
});
Given your work case, you could consider the following method:
artistForm.submit(async (e) => {
e.preventDefault();
let inputSearchQuery = artistInput.val();
let searchQuery = encodeURI(inputSearchQuery);
let artist = await $.ajax({
url: `${baseUrl}search?q=${searchQuery}&type=artist`,
type: 'GET',
datatype: 'json',
headers: {
'Authorization': 'Bearer ' + accessToken
}
});
const artistId = artists.items[0].id;
let topTracks = await $.ajax({
url: `${baseUrl}artists/${artistId}/top-tracks?country=CZ`,
type: 'GET',
datatype: 'json',
headers: {
'Authorization': 'Bearer ' + accessToken
}
});
let relatedArtists = await $.ajax({
url: `${baseUrl}artists/${artistId}/related-artists`,
type: 'GET',
datatype: 'json',
headers: {
'Authorization': 'Bearer ' + accessToken
}
});
deleteArtist.click(() => {
// need to have access to data from every ajax call.
});
});
This is assuming you are using jQuery 3.0 or higher. If not you can find a nice wrapper function here.
If you want to learn more about promises and async await I recommend the following video's: JavaScript Promises In 10 Minutes - by Web Dev Simplified
and The Async Await Episode I Promised - by Fireship.
If you have questions about the code above, please add a comment.
I hope this helps you continue with your project (and that you've learn something along the way 👍).

Error Parsing JSON when trying POST request on Spotify API

I'm currently developing a web application using JavaScript which the web app will create a new playlist then save it to user's Spotify account. Now, I'm facing the issue of "Error Parsing JSON" whenever I tried POST request. Below is my code:
var urlString = 'https://api.spotify.com/v1/users/' + userID + '/playlists';
app.createPlaylist = (urlString) => $.ajax({
url: urlString,
method: 'POST',
headers: {
'Authorization': 'Bearer ' + accessToken
},
contentType: 'application/json',
body: JSON.stringify({
name: "test",
public: true
}),
dataType: 'json',
});
Can anyone tell me what's the problem? I've tried surfing this website, and none of the possible answers to my question helped my situation.

Delete item from SharePoint List using JavaScript and REST

I have some JavaScript (physical file located in /SiteAssets library) that should delete an item in a SharePoint list.
We have existing JavaScript code that retrieves data from the list - it looks like this:
(notice that since the JavaScript runs on a PDP in context of the current user, we don't need a specific access token for the request)
var data = $.ajax({
url: projSiteUrl + "/_api/lists/getbytitle('<listname>')/items,
type: "GET",
dataType: "json",
async: false,
headers: {
Accept: "application/json;odata=verbose"
}
});
So I thought that I could write similar code to delete an item from the list again. I read on https://msdn.microsoft.com/en-us/library/office/jj164022.aspx#HTTPOps that the REST endpoint of SharePoint supports the "normal" REST verbs, so I wrote this, using the DELETE HTTP verb.
var restUrl = spSiteUrl + '/_api/web/lists/GetByTitle(\'' + listTitle + '\')/items(' + itemId + ')';
jQuery.ajax({
url: restUrl,
type: "DELETE",
headers: {
Accept: "application/json;odata=verbose"
}
})
But I am getting a 403 (FORBIDDEN) when requesting.
I guess the question is: Am I wrong in assuming that the DELETE verb is supported?
Thanks :-)
Ok, so apparently I do need the digest when doing modifications - but not for simple data retrieval.
If I change my code to
jQuery.ajax({
url: restUrl,
type: "DELETE",
headers: {
Accept: "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
"IF-MATCH": "*"
}
}).
... it works with a simple AJAX request using the REST HTTP verb DELETE :-)

How do I update the public read-write OData feed at services.odata.org?

I am currently trying to get a simple demo going of a crud app using the public OData feed at http://services.odata.org/V4/(S(jskq43fsvrxbzaf2jzhboo13))/OData/OData.svc/Products
GET-ting data works, however I am unable to update the data by clicking the button, and get a 501 (Not Implemented) error. I believe it deals with the need to enable CORS. Please see my fiddle. Thanks in advance!
var requestSettings = {
url: "http://services.odata.org/V3/(S(ettihtez1pypsghekhjamb1u))/OData/OData.svc/Products(" + key + ")",
method: "POST",
headers: {
"X-Http-Method": "PATCH",
'accept': "application/json;odata=verbose"
},
'contentType': "application/json; charset=utf-8", //content-length not required
datatype: 'json',
data: JSON.stringify(values),
success: function updateSuccess() {
deferred.resolve();
alert("successful update");
},
error: function updateError() {
deferred.reject();
alert("un-successful update");
}
};
$.ajax(requestSettings);
I have a JSFiddle here:
https://jsfiddle.net/jf713jf/ybLg1b4h/4/
Consider to use DevExpress.data.ODataStore that provides logic to access OData service.
Since you're working with fourth version of OData service, the ODataStore constructor options would like that:
new DevExpress.data.ODataStore({
url: "http://services.odata.org/V4/(S(jskq43fsvrxbzaf2jzhboo13))/OData/OData.svc/Products",
key: "ID",
keyType: "Int32",
version: 4,
// To overcome the cross-origin issue
jsonp: true
});
Hope it helps.

Youtube Upload JS with API -> get 405 Method not allowed

I can't upload videos to youTube with Javascript anymore. If I call the URL
$.ajax({
url: VIDEOS_UPLOAD_SERVICE_URL,
method: 'POST',
contentType: 'application/json',
headers: {
Authorization: 'Bearer ' + accessToken,
'x-upload-content-length': file.size,
'x-upload-content-type': file.type
},
data: JSON.stringify(metadata)
}).done(function (data, textStatus, jqXHR) {
...DO SOMETHING
}
})
I get an Error 405 Method not allowed, but a few days/weeks ago everything works fine :-(
The VIDEOS_UPLOAD_SERVICE_URL is https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet
But if I call the ajax Request to fetch the categories that works fine...

Categories

Resources