Published
Edited
Mar 18, 2021
1 star
Insert cell
Insert cell
viewof token = getTokenView('8c26955dad904a51a0af788da7deb34e')
Insert cell
html`
<div style="height:500px;overflow:auto;">
<table>
<tr>
<th>Art</th>
<th>Album</th>
<th>Track</th>
</tr>
${albumRows}
</table>
</div>
`
Insert cell
async function* asynchronouslyGenerateAllMyTracks() {
const pageSize = 50;

function get50Tracks(off, lim = pageSize) {
return api.getMySavedTracks({
limit: lim,
offset: off
});
}

const head = await get50Tracks(0);

yield* head.body.items;

const pages = Math.floor(head.body.total / pageSize);

const offsets = Array(pages)
.fill(0)
.map((e, i) => i + 1)
.map(x => x * pageSize);

const remainingGetTrackCalls = offsets.map(offset => get50Tracks(offset));

for await (const pageRequest of remainingGetTrackCalls) {
yield* pageRequest.body.items;
}
}
Insert cell
{
return Promise.all([asynchronouslyGenerateAllMyTracks()]).then(([tracks]) => {
return tracks;
})
}
Insert cell
async function asyncGeneratorToArray(asyncGenerator) {
let items = new Array();
for await (let item of asyncGenerator) {
items.push(item);
}
return items;
}
Insert cell
songs = asyncGeneratorToArray(asynchronouslyGenerateAllMyTracks())
Insert cell
likedSongsByAlbum = ramda.groupBy(x => x.track.album.uri)(songs)
Insert cell
likedSongsGroupAndSortedByAlbums = Object.entries(likedSongsByAlbum).map(x => ({
album: {
name: ramda.prop(1)(x)[0].track.album.name,
images: ramda.prop(1)(x)[0].track.album.images
},
tracks: ramda
.prop(1)(x)
.map(x => x.track)
.sort((f, s) => (f.track_number > s.track_number ? 1 : -1))
.map(x => ({ track: x.track_number, name: x.name, preview: x.preview_url }))
}))
Insert cell
albumRows = likedSongsGroupAndSortedByAlbums.map(x => {
var tracks = x.tracks.flatMap(x => {
var linkedName = x.preview
? `<a href="${x.preview}" target="_blank">${x.name}<a/>`
: x.name;

return html`<div>${x.track}. ${linkedName}</div>`;
});

return html`
<tr>
<td>
<p>//TODO images</p>
</td>
<td>
${x.album.name}
</td>
<td style="white-space:pre-wrap;">
${tracks}
</td>
</tr>
`;
})
Insert cell
rows = songs
.sort((first, second) => {
const name1 = first.track.album.name.toUpperCase();
const name2 = second.track.album.name.toUpperCase();
return name1 > name2 ? 1 : -1;
})
.map(x => {
var name = x.track.preview_url
? (name = `<a href="${x.track.preview_url}" target="_blank">${x.track.name}<a/>`)
: (name = x.track.name);
return html`
<tr>
<td>
<p>//TODO (images)</p>
</td>
<td>
${x.track.album.name}
</td>
<td>
${name}
</td>
</tr>
`;
})
Insert cell
ramda = require('ramda')
Insert cell
api = {
const SpotifyWebApi = await require('https://bundle.run/spotify-web-api-node@4.0.0');
const api = new SpotifyWebApi({
clientId: '8c26955dad904a51a0af788da7deb34e',
clientSecret: 'ebc2c64cbdc3418fb09b8047dacd6155',
redirectUri: document.baseURI
});
api.setAccessToken(token);
return api;
}
Insert cell
bonjour = "bonejaw"
Insert cell
import { text } from "@jashkenas/inputs"
Insert cell
import { getTokenView } from "@computron/spotify-auth"
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more