npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

scrobbles

v0.3.0

Published

A Node.js library to read last.fm "scrobbled" for a given user

Downloads

14

Readme

Scrobbles

npm version Node.js CI codecov JavaScript Style Guide

A Node.js library to fetch last.fm "scrobbled" for a given user.

"Scrobble" is a last.fm term to indicate a songs that a user has listened to at a given moment in time. It is effectively a record of a person listening to a specific song!

This library can be useful to explore the entire muscial history of a given user. If you need a few possible use cases, there you go:

  • Do some musical analytics. What the most listened song among your friends?
  • Backup your entire music listening history somewhere "safe" (for some definition of "safe").
  • Search for that one song that you can't fully remember (maybe you just remember the artist or some keyword in the title)!

Installation

As with any other Node.js package, this is as easy as:

npm install --save scrobbles

Example

Note: In order to use this library you will need to get an API key from Last.fm.

Print all the musical listening history (from latest to oldest) of the user loige:

import { RecentTracks } from 'scrobbles'

async function getAllPages () {
  const reader = new RecentTracks({
    apikey: process.env.API_KEY,
    user: 'loige'
  })

  reader.on('retry', ({ error, message, retryNum, retryAfterMs, url }) => {
    console.error(`Failure (${retryNum}) ${url}: ${message}. Retrying in ${retryAfterMs}`)
  })

  reader.on('progress', console.log)

  for await (const page of reader) {
    for (const song of page) {
      console.log(song)
    }
  }
}

getAllPages().catch((err) => {
  console.error(err)
  process.exit(1)
})

More examples available in the examples folder.

API & Configuration

The library exposes the RecentTracks reader class. This class is both an event emitter and an Async Iterator.

Initialization options

You can instantiate a new reader you can use the RecentTracks constructor which accepts a configuration object:

const reader = new RecentTracks({
  apikey,           // mandatory - the last.fm API key
  user,             // mandatory - the name of the last.fm user
  limit,            // optional - the number of songs to fetch per page. Between 1 and 200. Default: 50
  from,             // optional - a unix timestamp that indicates the earliest point in time to include 
                    //            in the list of results. Default: unbound (earliest song ever scrobbled for that user)
  to,               // optional - a unix timestamp that indicates the latest point in time to include in 
                    //            the list of results. Default: unbound (essentially "now")
  extended,         // optional - a boolean indicating wheter every record should contain extended information 
                    //            (e.g. cover pictures) or not. Default: false
  mapTrack,         // optional - a function to remap the raw response from last.fm. See next sections for more details 
  maxRetries,       // optional - the number of retries in case of failure. Default: 5
  retryDelayBaseMs, // optional - the base delay in milliseconds. Default: 100
  retryBase,        // optional - the exponent to calculate the delay before the next retry: Default: 2
})

Retry logic

Last.fm APIs will sometime throw random errors, so this library provides a built in retry mechanism that can be configured with the options mentioned above.

The wait time before a consecutive retry is calculated with the formula retryBase ** retryNum * retryDelayBaseMs (exponential fallback).

If the number of consecutive max retries is reached then an error is thrown.

If a successful response is received after a retry, the retry counter is reset.

Custom track mapping

By default, iterating over a reader will give you a list of pages. Every page contains a chunk of "scrobbled" tracks. Every track will contain the following fields:

{
  "album": "The Music That Died Alone",
  "artist": "The Tangent",
  "date": 1618997643,
  "name": "Up-hill From Here",
  "url": "https://www.last.fm/music/The+Tangent/_/Up-hill+From+Here",
}

In reality, last.fm APIs will contain a lot more information (especially if setting the extended option to true). If you want to provide your own custom mapping you can do that by passing a custom mapping function using the mapTrack parameter of the constructor configuration object.

For example:

const reader = new RecentTracks({
  apiKey: 'mysupersecretapikey',
  user: 'mariobros',
  mapTrack: (rawTrack) => ({
    date: Number(rawTrack.date.uts),
    artist: rawTrack.artist['#text'],
    name: rawTrack.name,
    album: rawTrack.album['#text'],
    url: rawTrack.url,
    cover: rawTrack.image.find((i) => i.size === 'extralarge')['#text'],
  }),
}

To learn more about all the fields exposed by last.fm, check out the official documentation for the user.getRecentTracks API.

Events

A RecentTracks instance emits the following events:

progress

Emitted for every successful api call when a page is fetched. It gives indications about the current progress.

reader.on('progress', e => console.log(e))

Will print something like this:

{
  "perPage": 4, // how many elements per page
  "remainingPages": 2, // how many pages are left to fetch
  "progress": 0.3333333333333333, // the allover progress in percentage
}

retry

In case of error, when a retry is about to happen.

reader.on('retry', e => console.log(e))

Will print something like this:

{
  "error": 1, // error code
  "maxRetries": 6, // the number of max retries configured
  "message": "Unexpected Server Error", // the error message
  "retryAfterMs": 1600, // when the next retry is going to happen
  "retryNum": 4, // the number of consecutive retries so far
  "url": "https://ws.audioscrobbler.com/2.0/?api_key=atestapikey&user=loige&limit=4&extended=0&method=user.getrecenttracks&format=json", // the URL of the request that failed
}

CLI usage

scrobbles ships also with a convenient CLI that you can use to easily export data from a given Last.fm account.

You can install the CLI helper globally in your system with:

npm i -g scrobbles

Then it will be available as an executable with the name of `scrobbles.

Alternatively you can install and invoke the executably dynamically through npx by just running:

npx scrobbles

Here's an example on how to use scrobbles (replace npx scrobbles with scrobbles if you already installed it globally):

SCROBBLES_APIKEY=xxx npx scrobbles -u loige -f 1998-01-01 -t 2022-03-14 -F csv > lastfm_export.csv

The above example exports all the tracks from 1998-01-01 to 2022-03-14 for user loige in CSV format

You can use the following command to see all the supported options:

npx scrobbles --help

Contributing

Everyone is very welcome to contribute to this project. You can contribute just by submitting bugs or suggesting improvements by opening an issue on GitHub.

License

Licensed under MIT License. © Luciano Mammino.