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 🙏

© 2026 – Pkg Stats / Ryan Hefner

magmastream-spotify

v0.2.2

Published

A Spotify plugin for Magmastream.

Readme

magmastream-spotify

A MagmaStream plugin that transparently intercepts Spotify track, album, and playlist URLs and resolves them into playable tracks using direct playback sources like Deezer, YouTube, VK Music, Qobuz, Yandex, and Jiosaavn.

It uses a Spotify Resolver API, so no Spotify credentials are required.


Features

  • 🎵 Supports Spotify tracks, albums, and playlists
  • 🔑 No Spotify Client ID / Secret required
  • 🎯 Uses ISRC-first matching when available for better accuracy
  • 🔀 Supports fully custom source resolution order
  • 🧩 Includes built-in resolution strategy presets
  • 🏷️ Injects Spotify metadata into resolved tracks
  • ⚡ Resolves playlists and albums in concurrent batches
  • 🧠 Includes optional Redis caching
  • 🚫 Supports negative caching for failed lookups
  • 🔌 Drop-in plugin that patches Manager#search() automatically
  • 🛠️ Includes cache invalidation helpers for manual cache control

Installation

npm install magmastream-spotify

Peer dependency

magmastream = 2.10.2-aplha.11

Quick Start

JavaScript

// This example shows Discord.js
const { DiscordJSManager } = require("magmastream");
const { MagmastreamSpotifyPlugin, ResolutionStrategyPreset } = require("magmastream-spotify");

const manager = new DiscordJSManager({
	enabledPlugins: [
		new MagmastreamSpotifyPlugin({
			resolutionStrategyPreset: ResolutionStrategyPreset.DeezerFirst,
		}),
	],
});

TypeScript

// This example shows Discord.js
import { DiscordJSManager } from "magmastream";
import { MagmastreamSpotifyPlugin, ResolutionStrategyPreset } from "magmastream-spotify";

const manager = new DiscordJSManager({
	enabledPlugins: [
		new MagmastreamSpotifyPlugin({
			resolutionStrategyPreset: ResolutionStrategyPreset.DeezerFirst,
		}),
	],
});

Your normal calls such as:

manager.search(spotifyUrl, requester);

will automatically resolve Spotify URLs through the plugin.


Options

| Option | Type | Default | Description | | -------------------------- | -------------------------- | -------------------------------------- | ------------------------------------------------------------------------- | | resolverApiUrl | string | "http://eu.leonodes.xyz:2450" | Base URL of the Spotify Resolver API | | resolutionStrategyPreset | ResolutionStrategyPreset | ResolutionStrategyPreset.DeezerFirst | Built-in preset used when sourceOrder is not provided | | sourceOrder | SpotifyResolverSource[] | [] | Custom ordered list of sources to try. Overrides the preset when provided | | playlistLimit | number | 100 | Maximum number of tracks to resolve from playlists or albums | | debug | boolean | false | Enables plugin debug logging | | redis | RedisCacheOptions | undefined | Optional Redis cache configuration |


Redis Cache Options

The plugin can cache resolver responses, track lookups, playlist/album results, and failed lookups.

| Option | Type | Default | Description | | --------------- | -------- | ----------------------- | ------------------------------------------------------- | | client | Redis | required | An existing ioredis client instance | | prefix | string | "ms:spotify-resolver" | Prefix for all Redis keys used by the plugin | | resolveTtl | number | 21600 | TTL in seconds for resolver API payloads | | searchTtl | number | 43200 | TTL in seconds for resolved single-track search results | | collectionTtl | number | 21600 | TTL in seconds for playlist/album search results | | negativeTtl | number | 900 | TTL in seconds for failed resolver/search lookups |

Redis Example

import Redis from "ioredis";
import { MagmastreamSpotifyPlugin, ResolutionStrategyPreset } from "magmastream-spotify";

const redis = new Redis({
	host: "127.0.0.1",
	port: 6379,
});

const plugin = new MagmastreamSpotifyPlugin({
	resolutionStrategyPreset: ResolutionStrategyPreset.DeezerFirst,
	redis: {
		client: redis,
		prefix: "ms:spotify-resolver",
		resolveTtl: 60 * 60 * 6,
		searchTtl: 60 * 45,
		collectionTtl: 60 * 30,
		negativeTtl: 60 * 15,
	},
});

Resolution Strategy Presets

The plugin includes several built-in presets.

| Preset | Behavior | | -------------- | ----------------------------------------------------- | | DeezerFirst | Try Deezer first, then YouTube | | YouTubeFirst | Try YouTube first, then Deezer | | DirectOnly | Try all direct playback sources in the built-in order | | DirectFirst | Try all direct playback sources in the built-in order |

Example

new MagmastreamSpotifyPlugin({
	resolutionStrategyPreset: ResolutionStrategyPreset.DirectOnly,
});

Note: in the current implementation, DirectOnly and DirectFirst resolve to the same built-in source order.


Custom Source Order

You can fully control the resolution order by providing sourceOrder.

When sourceOrder is set, it overrides resolutionStrategyPreset.

Example

import { MagmastreamSpotifyPlugin, SpotifyResolverSource } from "magmastream-spotify";

new MagmastreamSpotifyPlugin({
	sourceOrder: [SpotifyResolverSource.Qobuz, SpotifyResolverSource.Deezer, SpotifyResolverSource.YouTube],
});

Another Example

new MagmastreamSpotifyPlugin({
	sourceOrder: [SpotifyResolverSource.Jiosaavn, SpotifyResolverSource.VKMusic, SpotifyResolverSource.Deezer],
});

Duplicate sources are automatically removed while preserving order.


Supported Sources

The plugin supports these source values through the SpotifyResolverSource enum:

| Source | Description | | ---------- | ---------------------- | | Deezer | Direct playback source | | YouTube | Common fallback source | | VKMusic | Direct playback source | | Qobuz | Direct playback source | | Jiosaavn | Direct playback source |

These map internally to the corresponding SearchPlatform values from MagmaStream.


How It Works

  1. The plugin patches Manager#search().
  2. If the query is not a Spotify URL, it passes through untouched.
  3. If the query is a Spotify URL, the plugin calls:
GET /api/resolve?url=<spotifyUrl>
  1. The Resolver API returns normalized metadata such as:

    • title
    • artist
    • ISRC
    • artwork
    • playlist or album items
  2. The plugin builds a fallback search chain like:

isrc:<code>
Artist - Title
Title Artist
Title
  1. Each query is tried against the configured source order until a playable result is found.
  2. The resolved track is enriched with Spotify metadata and returned as a normal MagmaStream search result.

For playlists and albums, tracks are resolved in concurrent batches of 5.


Supported URL Formats

Tracks

https://open.spotify.com/track/<id>

Albums

https://open.spotify.com/album/<id>

Playlists

https://open.spotify.com/playlist/<id>

Locale URLs

https://open.spotify.com/intl-fr/track/<id>
https://open.spotify.com/intl-en/album/<id>
https://open.spotify.com/intl-de/playlist/<id>

Any non-Spotify query is passed directly to MagmaStream.


Accessing Spotify Metadata

Resolved tracks include a magmastreamPlugin object with Spotify metadata.

manager.on("trackStart", (player, track) => {
	const meta = track.magmastreamPlugin;

	console.log(`Playing: ${meta.spotifyArtist} - ${meta.spotifyTitle}`);
	console.log(`ISRC: ${meta.spotifyIsrc ?? "none"}`);
	console.log(`Spotify URL: ${meta.spotifyUrl ?? "none"}`);
	console.log(`Resolved by: ${meta.resolvedBy}`);
});

Available fields

track.magmastreamPlugin.spotifyTitle;
track.magmastreamPlugin.spotifyArtist;
track.magmastreamPlugin.spotifyIsrc;
track.magmastreamPlugin.spotifyUrl;
track.magmastreamPlugin.resolvedBy;

The plugin also sets the track source to:

TrackSourceTypes.Spotify;

so the resolved track keeps Spotify context even if playback came from another provider.


Cache Invalidation Helpers

When Redis is enabled, the plugin exposes helper methods for clearing cached entries.

Invalidate a Spotify URL cache entry

Clears resolver and collection cache for a specific Spotify URL.

await plugin.invalidateSpotifyUrlCache("https://open.spotify.com/track/...");

Invalidate a single resolved track cache entry

Clears the cached resolved track for normalized metadata.

await plugin.invalidateTrackCache({
	title: "Song Title",
	artist: "Artist Name",
	isrc: "USRC17607839",
	spotifyUrl: "https://open.spotify.com/track/...",
});

Clear the full plugin cache

Clears all plugin-managed cache entries under the configured Redis prefix.

const deleted = await plugin.clearAllSpotifyResolverCache();
console.log(`Deleted ${deleted} keys`);

This uses SCAN when available and falls back to KEYS if needed.


Negative Caching

The plugin stores failed resolver and search lookups using a shorter TTL.

This helps reduce repeated requests for:

  • broken Spotify URLs
  • empty resolver responses
  • tracks that could not be matched
  • unsuccessful playlist/album resolutions

By default, failed lookups are cached for 15 minutes.


Debug Logging

Enable debug mode to print plugin messages and emit them through the manager debug event.

new MagmastreamSpotifyPlugin({
	debug: true,
});

When enabled, the plugin logs things like:

  • intercepted Spotify URLs
  • resolver API calls
  • Redis hits and misses
  • source search attempts
  • collection resolution progress
  • cache invalidation activity

Example Command

async execute(client, interaction) {
	const url = interaction.options.getString("url");

	const player = client.manager.create({
		guildId: interaction.guildId,
		voiceChannelId: interaction.member.voice.channelId,
		textChannelId: interaction.channelId,
	});

	const result = await client.manager.search(url, interaction.user);

	if (!("tracks" in result) || !result.tracks.length) {
		return interaction.reply("No results found.");
	}

	player.queue.add(result.tracks[0]);

	if (!player.playing) {
		player.play();
	}

	return interaction.reply(`Now playing: **${result.tracks[0].title}**`);
}

Notes

  • This plugin does not access Spotify directly
  • All Spotify metadata is obtained through the configured Resolver API
  • Your MagmaStream/Lavalink setup must support the playback sources you want to use
  • Redis caching is optional but recommended for production use
  • Failed lookups are cached separately using a shorter negative TTL
  • The plugin transparently falls back to the original manager.search() when the query is not a Spotify URL

License

Apache