Migrating from jquery.ajax to request
This commit is contained in:
@ -19,7 +19,19 @@ const sendRequest = (dispatch, getState, endpoint, params) => new Promise((resol
|
||||
const loader_key = helpers.generateGuid();
|
||||
dispatch(uiActions.startLoading(loader_key, `discogs_${endpoint}`));
|
||||
|
||||
const checkRateLimit = (request) => {
|
||||
const config = {
|
||||
method: 'GET',
|
||||
timeout: 30000,
|
||||
mode: 'cors',
|
||||
headers: {
|
||||
'User-Agent': 'Iris/1.0',
|
||||
'Authorization': `Discogs key=${key}, secret=${secret}`
|
||||
},
|
||||
};
|
||||
|
||||
function status(response) {
|
||||
dispatch(uiActions.stopLoading(loader_key));
|
||||
|
||||
const rate = {
|
||||
limit: request.getResponseHeader('X-Discogs-Ratelimit'),
|
||||
remaining: request.getResponseHeader('X-Discogs-Ratelimit-Remaining'),
|
||||
@ -33,38 +45,23 @@ const sendRequest = (dispatch, getState, endpoint, params) => new Promise((resol
|
||||
description: `Discogs rate limit exceeded, try again in a few minutes.`
|
||||
}));
|
||||
}
|
||||
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return Promise.resolve(response)
|
||||
} else {
|
||||
return Promise.reject(new Error(response.statusText))
|
||||
}
|
||||
}
|
||||
|
||||
const config = {
|
||||
method: 'GET',
|
||||
cache: true,
|
||||
timeout: 30000,
|
||||
url: url,
|
||||
crossDomain: true,
|
||||
headers: {
|
||||
'User-Agent': 'Iris/1.0',
|
||||
'Authorization': `Discogs key=${key}, secret=${secret}`
|
||||
},
|
||||
};
|
||||
|
||||
$.ajax(config).then(
|
||||
(data, textStatus, request) => {
|
||||
dispatch(uiActions.stopLoading(loader_key));
|
||||
checkRateLimit(request);
|
||||
fetch(url, config)
|
||||
.then(status)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
resolve(data);
|
||||
},
|
||||
(xhr, status, error) => {
|
||||
dispatch(uiActions.stopLoading(loader_key));
|
||||
checkRateLimit(xhr);
|
||||
|
||||
reject({
|
||||
config,
|
||||
error,
|
||||
status,
|
||||
xhr,
|
||||
});
|
||||
},
|
||||
);
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
|
||||
export function getArtistImages(uri, artist) {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
|
||||
import axios from 'axios';
|
||||
const coreActions = require('../core/actions');
|
||||
const uiActions = require('../ui/actions');
|
||||
const helpers = require('../../helpers');
|
||||
@ -35,7 +34,6 @@ const sendRequest = (dispatch, getState, params, signed = false) => new Promise(
|
||||
const config = {
|
||||
method: http_method,
|
||||
timeout: 30000,
|
||||
cache: "force-cache",
|
||||
};
|
||||
|
||||
const loader_key = helpers.generateGuid();
|
||||
|
||||
@ -15,7 +15,7 @@ const helpers = require('../../helpers');
|
||||
* @param data mixed = request payload
|
||||
* @return Promise
|
||||
* */
|
||||
const request = (dispatch, getState, endpoint, method = 'GET', data = false) => {
|
||||
const request = (dispatch, getState, endpoint, method = 'GET', data = false) => {
|
||||
// Add reference to loader queue
|
||||
// We do this straight away so that even if we're refreshing the token, it still registers as
|
||||
// loading said endpoint
|
||||
@ -25,7 +25,7 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
|
||||
return new Promise((resolve, reject) => {
|
||||
getToken(dispatch, getState)
|
||||
.then(
|
||||
(response) => {
|
||||
(response) => {
|
||||
// prepend the API baseurl, unless the endpoint already has it (ie pagination requests)
|
||||
let url = `https://api.spotify.com/v1/${endpoint}`;
|
||||
if (endpoint.startsWith('https://api.spotify.com/')) {
|
||||
@ -35,7 +35,6 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
|
||||
// create our ajax request config
|
||||
const config = {
|
||||
method,
|
||||
url,
|
||||
cached: true,
|
||||
timeout: 30000,
|
||||
headers: {
|
||||
@ -53,33 +52,37 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
|
||||
}
|
||||
}
|
||||
|
||||
$.ajax(config).then(
|
||||
(response) => {
|
||||
dispatch(uiActions.stopLoading(loader_key));
|
||||
resolve(response);
|
||||
},
|
||||
(xhr, status, error) => {
|
||||
dispatch(uiActions.stopLoading(loader_key));
|
||||
function status(response) {
|
||||
dispatch(uiActions.stopLoading(loader_key));
|
||||
|
||||
// TODO: Rate limiting
|
||||
if (xhr.status == 429) {
|
||||
alert('You hit the Spotify API rate limiter');
|
||||
}
|
||||
// TODO: Rate limiting
|
||||
if (response.status == 429) {
|
||||
alert('You hit the Spotify API rate limiter');
|
||||
}
|
||||
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return Promise.resolve(response)
|
||||
} else {
|
||||
return Promise.reject(new Error(response.statusText))
|
||||
}
|
||||
}
|
||||
|
||||
fetch(url, config)
|
||||
.then(status)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
|
||||
// TODO: Instead of allowing request to fail before renewing the token, once refreshed
|
||||
// we should retry the original request(s)
|
||||
if (xhr.responseJSON && xhr.responseJSON.error && xhr.responseJSON.error.message == 'The access token expired') {
|
||||
if (data.error && data.error.message == 'The access token expired') {
|
||||
dispatch(refreshToken(dispatch, getState));
|
||||
}
|
||||
|
||||
reject({
|
||||
config,
|
||||
xhr,
|
||||
status,
|
||||
error,
|
||||
});
|
||||
},
|
||||
);
|
||||
resolve(data);
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
dispatch(coreActions.handleException(
|
||||
@ -99,7 +102,7 @@ const request = (dispatch, getState, endpoint, method = 'GET', data = false) =>
|
||||
* @return Promise
|
||||
* */
|
||||
function getToken(dispatch, getState) {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// token is okay for now, so just resolve with the current token
|
||||
if (getState().spotify.token_expiry && new Date().getTime() < getState().spotify.token_expiry) {
|
||||
resolve(getState().spotify.access_token);
|
||||
@ -111,7 +114,7 @@ function getToken(dispatch, getState) {
|
||||
// need to wait until it's done, and then return that
|
||||
|
||||
// We've already got a refresh in progress
|
||||
if (getState().ui.load_queue.spotify_refresh_token !== undefined) {
|
||||
if (getState().ui.load_queue.spotify_refresh_token !== undefined) {
|
||||
console.log("Already refreshing token, we'll wait 1000ms and try again");
|
||||
|
||||
// Re-check the queue periodically to see if it's finished yet
|
||||
@ -137,13 +140,13 @@ function getToken(dispatch, getState) {
|
||||
}
|
||||
|
||||
function refreshToken(dispatch, getState) {
|
||||
return new Promise((resolve, reject) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// add reference to loader queue
|
||||
const loader_key = helpers.generateGuid();
|
||||
dispatch(uiActions.startLoading(loader_key, 'spotify_refresh_token'));
|
||||
|
||||
// Fully-authorized, so we can use the local Spotify credentials
|
||||
if (getState().spotify.authorization) {
|
||||
if (getState().spotify.authorization) {
|
||||
var config = {
|
||||
method: 'GET',
|
||||
url: `${getState().spotify.authorization_url}?action=refresh&refresh_token=${getState().spotify.refresh_token}`,
|
||||
@ -178,7 +181,7 @@ function refreshToken(dispatch, getState) {
|
||||
|
||||
// Server-side authorized (with limited scope) so we need to refresh
|
||||
// using the Mopidy-Spotify credentials
|
||||
} else {
|
||||
} else {
|
||||
var config = {
|
||||
method: 'GET',
|
||||
url: `//${getState().mopidy.host}:${getState().mopidy.port}/iris/http/refresh_spotify_token`,
|
||||
@ -197,7 +200,7 @@ function refreshToken(dispatch, getState) {
|
||||
xhr,
|
||||
status,
|
||||
error: response.error,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const token = response.result.spotify_token;
|
||||
token.token_expiry = new Date().getTime() + (token.expires_in * 1000);
|
||||
@ -208,7 +211,7 @@ function refreshToken(dispatch, getState) {
|
||||
data: token,
|
||||
});
|
||||
resolve(token);
|
||||
}
|
||||
}
|
||||
},
|
||||
(xhr, status, error) => {
|
||||
dispatch(uiActions.stopLoading(loader_key));
|
||||
@ -221,7 +224,7 @@ function refreshToken(dispatch, getState) {
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -342,7 +345,7 @@ export function getLibraryTracks() {
|
||||
}
|
||||
|
||||
export function getFeaturedPlaylists() {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: 'SPOTIFY_FEATURED_PLAYLISTS_LOADED', data: false });
|
||||
|
||||
const date = new Date();
|
||||
@ -542,7 +545,7 @@ export function clearSearchResults() {
|
||||
}
|
||||
|
||||
export function getSearchResults(type, query, limit = 50, offset = 0) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
dispatch(uiActions.startProcess('SPOTIFY_GET_SEARCH_RESULTS_PROCESSOR', 'Searching Spotify'));
|
||||
|
||||
type = type.replace(/s+$/, '');
|
||||
@ -634,7 +637,7 @@ export function getSearchResults(type, query, limit = 50, offset = 0) {
|
||||
}
|
||||
|
||||
export function getAutocompleteResults(field_id, query, types = ['album', 'artist', 'playlist', 'track']) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: 'SPOTIFY_AUTOCOMPLETE_LOADING', field_id });
|
||||
|
||||
const genre_included = types.includes('genre');
|
||||
@ -712,12 +715,12 @@ export function clearAutocompleteResults(field_id = null) {
|
||||
}
|
||||
|
||||
export function following(uri, method = 'GET') {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
if (method == 'PUT') var is_following = true;
|
||||
if (method == 'DELETE') var is_following = false;
|
||||
|
||||
const asset_name = helpers.uriType(uri);
|
||||
let endpoint; let
|
||||
let endpoint; let
|
||||
data;
|
||||
switch (asset_name) {
|
||||
case 'track':
|
||||
@ -787,7 +790,7 @@ export function following(uri, method = 'GET') {
|
||||
* @param radio object
|
||||
* */
|
||||
export function resolveRadioSeeds(radio) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
if (radio.seed_artists.length > 0) {
|
||||
let artist_ids = '';
|
||||
for (var i = 0; i < radio.seed_artists.length; i++) {
|
||||
@ -855,7 +858,7 @@ export function resolveRadioSeeds(radio) {
|
||||
* @param uri string
|
||||
* */
|
||||
export function getFavorites(limit = 50, term = 'long_term') {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: 'SPOTIFY_FAVORITES_LOADED', artists: [], tracks: [] });
|
||||
|
||||
$.when(
|
||||
@ -888,7 +891,7 @@ export function getFavorites(limit = 50, term = 'long_term') {
|
||||
* @param uris = array of artist or track URIs or a genre string
|
||||
* */
|
||||
export function getRecommendations(uris = [], limit = 20, tunabilities = null) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
dispatch({ type: 'CLEAR_SPOTIFY_RECOMMENDATIONS' });
|
||||
|
||||
// build our starting point
|
||||
@ -899,7 +902,7 @@ export function getRecommendations(uris = [], limit = 20, tunabilities = null) {
|
||||
for (let i = 0; i < uris.length; i++) {
|
||||
const uri = uris[i];
|
||||
|
||||
switch (helpers.uriType(uri)) {
|
||||
switch (helpers.uriType(uri)) {
|
||||
case 'artist':
|
||||
artists_ids.push(helpers.getFromUri('artistid', uri));
|
||||
break;
|
||||
@ -1037,7 +1040,7 @@ export function getGenres() {
|
||||
* @param full boolean (whether we want a full artist object)
|
||||
* */
|
||||
export function getArtist(uri, full = false) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
// Start with an empty object
|
||||
// As each requests completes, they'll add to this object
|
||||
const artist = {};
|
||||
@ -1059,7 +1062,7 @@ export function getArtist(uri, full = false) {
|
||||
];
|
||||
|
||||
// Do we want a full artist, with all supporting material?
|
||||
if (full) {
|
||||
if (full) {
|
||||
requests.push(
|
||||
request(dispatch, getState, `artists/${helpers.getFromUri('artistid', uri)}/top-tracks?country=${getState().spotify.country}`)
|
||||
.then(
|
||||
@ -1093,7 +1096,7 @@ export function getArtist(uri, full = false) {
|
||||
}
|
||||
|
||||
// Run our requests
|
||||
$.when.apply($, requests).then(() => {
|
||||
$.when.apply($, requests).then(() => {
|
||||
if (artist.musicbrainz_id) {
|
||||
dispatch(lastfmActions.getArtist(artist.uri, false, artist.musicbrainz_id));
|
||||
} else {
|
||||
@ -1126,7 +1129,7 @@ export function getArtist(uri, full = false) {
|
||||
}
|
||||
|
||||
export function getArtists(uris) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
// now get all the artists for this album (full objects)
|
||||
let ids = '';
|
||||
for (let i = 0; i < uris.length; i++) {
|
||||
@ -1213,13 +1216,13 @@ export function getUser(uri) {
|
||||
}
|
||||
|
||||
export function getUserPlaylists(uri) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
// get the first page of playlists
|
||||
request(dispatch, getState, `users/${helpers.getFromUri('userid', uri)}/playlists?limit=40`)
|
||||
.then(
|
||||
(response) => {
|
||||
const playlists = [];
|
||||
for (const raw_playlist of response.items) {
|
||||
for (const raw_playlist of response.items) {
|
||||
let can_edit = false;
|
||||
if (getState().spotify.me && raw_playlist.owner.id == getState().spotify.me.id) {
|
||||
can_edit = true;
|
||||
@ -1259,11 +1262,11 @@ export function getUserPlaylists(uri) {
|
||||
* @oaram uri string
|
||||
* */
|
||||
export function getAlbum(uri) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
// get the album
|
||||
request(dispatch, getState, `albums/${helpers.getFromUri('albumid', uri)}`)
|
||||
.then(
|
||||
(response) => {
|
||||
(response) => {
|
||||
// dispatch our loaded artists (simple objects)
|
||||
dispatch(coreActions.artistsLoaded(response.artists));
|
||||
|
||||
@ -1308,7 +1311,7 @@ export function getAlbum(uri) {
|
||||
error,
|
||||
));
|
||||
},
|
||||
);
|
||||
);
|
||||
},
|
||||
(error) => {
|
||||
dispatch(coreActions.handleException(
|
||||
@ -1351,7 +1354,7 @@ export function toggleAlbumInLibrary(uri, method) {
|
||||
* */
|
||||
|
||||
export function createPlaylist(name, description, is_public, is_collaborative) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
const data = {
|
||||
name,
|
||||
description,
|
||||
@ -1371,7 +1374,7 @@ export function createPlaylist(name, description, is_public, is_collaborative) {
|
||||
can_edit: true,
|
||||
tracks: [],
|
||||
tracks_more: null,
|
||||
tracks_total: 0,
|
||||
tracks_total: 0,
|
||||
},
|
||||
});
|
||||
|
||||
@ -1393,7 +1396,7 @@ export function createPlaylist(name, description, is_public, is_collaborative) {
|
||||
}
|
||||
|
||||
export function savePlaylist(uri, name, description, is_public, is_collaborative, image) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
const data = {
|
||||
name,
|
||||
description,
|
||||
@ -1403,7 +1406,7 @@ export function savePlaylist(uri, name, description, is_public, is_collaborative
|
||||
|
||||
// Update the playlist fields
|
||||
request(
|
||||
dispatch, getState, `users/${getState().spotify.me.id}/playlists/${helpers.getFromUri('playlistid', uri)}`, 'PUT', data,
|
||||
dispatch, getState, `users/${getState().spotify.me.id}/playlists/${helpers.getFromUri('playlistid', uri)}`, 'PUT', data,
|
||||
)
|
||||
.then(
|
||||
(response) => {
|
||||
@ -1459,11 +1462,11 @@ export function savePlaylist(uri, name, description, is_public, is_collaborative
|
||||
}
|
||||
|
||||
export function getPlaylist(uri) {
|
||||
return (dispatch, getState) => {
|
||||
return (dispatch, getState) => {
|
||||
// get the main playlist object
|
||||
request(dispatch, getState, `playlists/${helpers.getFromUri('playlistid', uri)}?market=${getState().spotify.country}`)
|
||||
.then(
|
||||
(response) => {
|
||||
(response) => {
|
||||
// convert links in description
|
||||
let description = null;
|
||||
if (response.description) {
|
||||
@ -1523,7 +1526,7 @@ export function getLibraryTracksAndPlayProcessor(data) {
|
||||
return (dispatch, getState) => {
|
||||
request(dispatch, getState, data.next)
|
||||
.then(
|
||||
(response) => {
|
||||
(response) => {
|
||||
// Check to see if we've been cancelled
|
||||
if (getState().ui.processes.SPOTIFY_GET_LIBRARY_TRACKS_AND_PLAY_PROCESSOR !== undefined) {
|
||||
const processor = getState().ui.processes.SPOTIFY_GET_LIBRARY_TRACKS_AND_PLAY_PROCESSOR;
|
||||
@ -1607,7 +1610,7 @@ export function getAllPlaylistTracksProcessor(data) {
|
||||
return (dispatch, getState) => {
|
||||
request(dispatch, getState, data.next)
|
||||
.then(
|
||||
(response) => {
|
||||
(response) => {
|
||||
// Check to see if we've been cancelled
|
||||
if (getState().ui.processes.SPOTIFY_GET_ALL_PLAYLIST_TRACKS_PROCESSOR !== undefined) {
|
||||
const processor = getState().ui.processes.SPOTIFY_GET_ALL_PLAYLIST_TRACKS_PROCESSOR;
|
||||
@ -1654,7 +1657,7 @@ export function getAllPlaylistTracksProcessor(data) {
|
||||
uris,
|
||||
},
|
||||
));
|
||||
} else {
|
||||
} else {
|
||||
if (data.shuffle) {
|
||||
uris = helpers.shuffle(uris);
|
||||
}
|
||||
@ -1751,8 +1754,8 @@ export function deleteTracksFromPlaylist(uri, snapshot_id, tracks_indexes) {
|
||||
|
||||
export function reorderPlaylistTracks(uri, range_start, range_length, insert_before, snapshot_id) {
|
||||
return (dispatch, getState) => {
|
||||
request(dispatch, getState, `playlists/${helpers.getFromUri('playlistid', uri)}/tracks`, 'PUT', {
|
||||
uri, range_start, range_length, insert_before, snapshot_id,
|
||||
request(dispatch, getState, `playlists/${helpers.getFromUri('playlistid', uri)}/tracks`, 'PUT', {
|
||||
uri, range_start, range_length, insert_before, snapshot_id,
|
||||
})
|
||||
.then(
|
||||
(response) => {
|
||||
@ -1996,4 +1999,4 @@ export function getLibraryAlbumsProcessor(data) {
|
||||
},
|
||||
);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user