diff --git a/app/src/importer.js b/app/src/importer.js index b88f4bc..0c1af6c 100644 --- a/app/src/importer.js +++ b/app/src/importer.js @@ -3,6 +3,12 @@ const axios = require('axios'); const cheerio = require('cheerio'); const logger = require('./winston'); +function asyncWait(delay){ + return new Promise((resolve)=>{ + setTimeout(resolve, delay); + }); +} + class Importer extends EventEmitter { constructor(deezer) { super(); @@ -41,7 +47,7 @@ class Importer extends EventEmitter { this.tracks = []; try { //Fetch - let spotifyData = await Spotify.getEmbedData(uri); + let spotifyData = await Spotify.getPlaylist(uri); if (!spotifyData.tracks.items) throw Error("No items!"); for (let track of spotifyData.tracks.items) { @@ -52,15 +58,33 @@ class Importer extends EventEmitter { (track.track.album.images.length > 0) ? track.track.album.images[0].url : null ); //Match - try { + let errorCount = 0; + while(true){ let deezerData = await this.deezer.callPublicApi('track', 'isrc:' + track.track.external_ids.isrc); - if (deezerData.id.toString()) { - //Found track - out.id = deezerData.id.toString(); - out.ok = true; + if(deezerData.error){ + if(deezerData.error.message == 'Quota limit exceeded'){ + await asyncWait(5000); + errorCount++; + if(errorCount >= 5){ + logger.error(`Error importing: Spotify: ${track.track.id} ${deezerData.error.type}: ${deezerData.error.message}`); + break; + } + }else{ + logger.error(`Error importing: Spotify: ${track.track.id} ${deezerData.error.type}: ${deezerData.error.message}`); + break; + } + }else{ + try { + if (deezerData.id.toString()) { + //Found track + out.id = deezerData.id.toString(); + out.ok = true; + } + } catch (e) { + logger.error(`Error importing: Spotify: ${track.track.id} ${e}`); + } + break; } - } catch (e) { - logger.error(`Error importing: Spotify: ${track.track.id} ${e}`); } //Send back this.emit('imported', out); @@ -96,6 +120,35 @@ class ImporterTrack { class Spotify { constructor() {} + static async getPlaylist(uri){ + const playlistID = uri.split(':')[2]; + + const tokenRequest = await axios.get('https://open.spotify.com/get_access_token?reason=transport', {responseType: 'json'}); + const token = tokenRequest.data.accessToken; + + const playlistDataRequest = await axios.get(`https://api.spotify.com/v1/playlists/${playlistID}`, { + responseType: 'json', + headers: { + 'authorization': 'Bearer ' + token + } + }); + const playlistData = playlistDataRequest.data; + + let next = playlistData.tracks.next + while(next){ + const nextItemsRequest = await axios.get(next, { + responseType: 'json', + headers: { + 'authorization': 'Bearer ' + token + } + }); + next = nextItemsRequest.data.next; + playlistData.tracks.items.push(...nextItemsRequest.data.items); + } + + return playlistData; + } + //Fetch JSON data from embeded spotify static async getEmbedData(uri) { //Fetch diff --git a/app/src/server.js b/app/src/server.js index b6efd2f..2e4ca7c 100644 --- a/app/src/server.js +++ b/app/src/server.js @@ -550,8 +550,27 @@ app.post('/import', async (req, res) => { description: i.description, title: i.title, status: 1, - songs: i.tracks.map(t => [parseInt(t.id, 10)]) + songs: [] }); + + let songIDs = i.tracks.map(t => [parseInt(t.id, 10), 0]) + console.log('Adding', songIDs.length, 'to playlist', i.title); + while(songIDs.length > 1){ + let songSelection = songIDs.splice(0, 10); + let resp = await deezer.callApi('playlist.addSongs', { + offset: -1, + playlist_id: playlistRaw.results, + songs: songSelection + }); + if(resp.error.length > 0) logger.error(`Error adding to playlist: ${resp.error.type}: ${resp.error.message}`); + } + + // let playlistRaw = await deezer.callApi('playlist.create', { + // description: i.description, + // title: i.title, + // status: 1, + // songs: i.tracks.map(t => [parseInt(t.id, 10), 0]) + // }); //Download if (type == 'download') { //Fetch playlist