Created
February 21, 2020 01:10
-
-
Save aynik/3a1c26f14113974cd33b400e401aa4e9 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
// discogs2spotify <spotify-playlist-id> <start-year>-<end-year> [discogs search params] | |
const args = require("minimist")(process.argv); | |
const Spotify = require("spotify-web-api-node"); | |
const Discogs = require("disconnect").Client; | |
const Confirm = require("prompt-confirm"); | |
const Prompt = require("prompt-base"); | |
const DISCOGS_USER_TOKEN = "<DISCOGS_USER_TOKEN>"; | |
const SPOTIFY_CLIENT_ID = "<SPOTIFY_CLIENT_ID>"; | |
const SPOTIFY_CLIENT_SECRET = "<SPOTIFY_CLIENT_SECRET>"; | |
const kvargs = Object.entries(args).reduce( | |
(result, [key, value]) => | |
key !== "_" ? { ...result, [key]: value } : result, | |
{} | |
); | |
const session = Object.entries(kvargs).reduce( | |
(result, [key, value], n) => | |
`${result}${n === 0 ? "" : " | "}${key}: ${value}`, | |
"" | |
); | |
const PLAYLIST_ID = process.argv[2]; | |
const START_YEAR = parseInt(process.argv[3].split("-")[0], 10); | |
const END_YEAR = parseInt(process.argv[3].split("-")[1] || START_YEAR, 10); | |
const YEARS = new Array(END_YEAR - START_YEAR + 1) | |
.fill(0) | |
.map((_, offset) => START_YEAR + offset); | |
const spotify = new Spotify({ | |
clientId: SPOTIFY_CLIENT_ID, | |
clientSecret: SPOTIFY_CLIENT_SECRET, | |
redirectUri: "https://httpbin.org/get" | |
}); | |
const discogs = new Discogs({ | |
userToken: DISCOGS_USER_TOKEN | |
}); | |
const db = discogs.database(); | |
const collection = discogs.user().collection(); | |
const query = { | |
type: "master", | |
...kvargs | |
}; | |
const sleep = () => new Promise(resolve => setTimeout(resolve, 1000)); | |
async function authorizeSpotify() { | |
console.log( | |
`> ${spotify.createAuthorizeURL([ | |
"playlist-modify-private", | |
])}\n\n` | |
); | |
const code = await new Prompt("Spotify access code").run(); | |
try { | |
const { | |
body: { | |
access_token: spotifyAccessToken, | |
refresh_token: spotifyRefreshToken | |
} | |
} = await spotify.authorizationCodeGrant(code); | |
spotify.setAccessToken(spotifyAccessToken); | |
spotify.setRefreshToken(spotifyRefreshToken); | |
} catch (err) { | |
console.error("Spotify auth error:", err); | |
process.exit(1); | |
} | |
} | |
async function run() { | |
const prompt = new Confirm(`[${YEARS.join(", ")}] ${session}, ok?`); | |
if (!(await prompt.run())) { | |
process.exit(0); | |
} | |
await authorizeSpotify(); | |
const years = YEARS.slice(); | |
while (years.length) { | |
const year = years.shift(); | |
await sleep(); | |
console.log(`Adding from ${session} | year: ${year}`); | |
let { pagination, results: masters } = await db.search("", { | |
...query, | |
year, | |
per_page: 100 | |
}); | |
await sleep(); | |
while (pagination.page < pagination.pages) { | |
const { | |
pagination: nextPagination, | |
results: nextMasters | |
} = await db.search("", { | |
...query, | |
year, | |
page: pagination.page + 1, | |
per_page: 100 | |
}); | |
await sleep(); | |
pagination = nextPagination; | |
masters = masters.concat(nextMasters); | |
} | |
console.log("masters:", masters.length); | |
while (masters.length) { | |
const master = masters.pop(); | |
try { | |
const { | |
body: { albums } | |
} = await spotify.searchAlbums(master.title); | |
if (!albums.items.length) { | |
await sleep(); | |
continue; | |
} | |
const { | |
body: { tracks } | |
} = await spotify.getAlbum(albums.items[0].id); | |
if (!tracks.items.length) { | |
await sleep(); | |
continue; | |
} | |
await spotify.addTracksToPlaylist( | |
PLAYLIST_ID, | |
tracks.items.map(track => track.uri) | |
); | |
console.log("Added", master.title, PLAYLIST_ID); | |
await sleep(); | |
} catch (err) { | |
console.log("Errored", master.title, err); | |
process.exit(0); | |
} | |
} | |
} | |
} | |
run(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment