Last active
February 12, 2025 15:24
-
-
Save stedmanhalliday/910dbf4fe1193d2849966fe28bbc56c6 to your computer and use it in GitHub Desktop.
Display Spotify streaming stats for your favorite artist (hours, days, and unique songs listened with a list of top tracks). Place this file in the same directory as `Spotify Account Data` after downloading and unzipping your annual Spotify data. Customize the constants up top then run with Node.js.
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
const ARTIST = "Yung Skrrt"; // substitute any artist (ensure exact match) | |
const TOP_TRACKS = 10; // number of top trackx to display | |
// time conversion constants | |
const MS_IN_HR = 3600000; | |
const HRS_IN_DAY = 24; | |
// GOTTA HIT THE STORAGE SPOT, GET UP IN THE STASH! | |
// retreive and consolidate streaming data | |
const streams0 = require("./Spotify Account Data/StreamingHistory_music_0.json"); | |
const streams1 = require("./Spotify Account Data/StreamingHistory_music_1.json"); | |
const streams = streams0.concat(streams1); | |
// filter to streams of tracks by artist | |
const artistStreams = streams.filter(stream => stream.artistName === ARTIST); | |
// return play duration of all artist streams in milliseconds | |
function getDuration() { | |
let duration = 0; | |
artistStreams.forEach(stream => { | |
duration += stream.msPlayed; | |
}); | |
return duration; | |
} | |
// return duration in hours | |
function getDurationInHours() { | |
return (getDuration()/MS_IN_HR).round(); | |
} | |
// return duration in days | |
function getDurationInDays() { | |
return (getDuration()/MS_IN_HR/HRS_IN_DAY).round(); | |
} | |
// return a sorted (descending) Map<trackName, playCount> | |
function getTracksByPlayCount() { | |
const trackCounts = new Map(); | |
artistStreams.forEach(stream => { | |
if (!trackCounts.has(stream.trackName)) { | |
trackCounts.set(stream.trackName, 1); | |
} else { | |
let count = trackCounts.get(stream.trackName); | |
count++; | |
trackCounts.set(stream.trackName, count); | |
} | |
}); | |
const trackRanks = new Map([...trackCounts.entries()].sort((a, b) => b[1] - a[1])); | |
return trackRanks; | |
} | |
// return a string listing the first n top tracks | |
function listTopTracks() { | |
const trackCounts = getTracksByPlayCount().entries(); | |
let topTracksList = ""; | |
let rank = 1; | |
for (track of trackCounts) { | |
if (rank > TOP_TRACKS) { | |
break; | |
} | |
topTracksList += String(rank).padStart(2, '0') + ". \"" + | |
track[0] + "\" with " + track[1] + " plays \n"; | |
rank++; | |
} | |
return topTracksList; | |
} | |
// decimal rounding (to hundredths) | |
Number.prototype.round = function() { | |
const num = this; | |
return (Math.round(num * 100) / 100).toFixed(2); | |
} | |
// string formatter | |
String.prototype.format = function() { | |
var s = this, | |
i = arguments.length; | |
while (i--) { | |
s = s.replace(new RegExp('\\{' + i + '\\}', 'gm'), arguments[i]); | |
} | |
return s; | |
}; | |
// STATS UP, STATS UP! | |
// print artist stats | |
console.log( | |
"\n" + | |
"You listened to {0} for {1} hours. That's {2} days. \n".format(ARTIST, getDurationInHours(), getDurationInDays()) + | |
"\n" + | |
"You listened to {0} unique {1} songs. \n".format(getTracksByPlayCount().size, ARTIST) + | |
"\n" + | |
"Your top " + ARTIST + " tracks \n" + | |
"--------------------------\n" + | |
listTopTracks() + | |
"\n" | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment