How to handle loading spotify playlists with > 100 items?

When loading music using the following query snippet, it only loads the first 100 songs of a spotify playlist. If i recall this is because the spotify api paginates. Does moonlink handle this pagination?
const result = await client.music.search({
query,
requester: message.author
});
const result = await client.music.search({
query,
requester: message.author
});
Thank you in advance!
Solution:
Not that I’m aware of
Jump to solution
46 Replies
1Lucas1.apk
1Lucas1.apk•4mo ago
GitHub
moonlink.js/src/typings/Interfaces.ts at v4 Ā· Ecliptia/moonlink.js
MoonLink.js is a simple package for lavalink client, perfect for you to create your discord bot with songs, and very simple and easy to use. - Ecliptia/moonlink.js
1Lucas1.apk
1Lucas1.apk•4mo ago
If you are using source inside the package you have these limitation options But if it is lavasrc, there is no limitation on the client side, you must configure it on the server side, I don't know if there is a limitation, if not, in the next version I will provide these limitations But server will anyway load all tracks
MaxTechnics
MaxTechnicsOP•4mo ago
I've tried setting those earlier, however that didn't seem to impact anything. I'll try again with lower values to see if there are any limits. I'm not sure which spotify endpoint moonlink uses. When trying the following endpoint, the limit is 100 https://developer.spotify.com/documentation/web-api/reference/get-playlists-tracks setting the limit to 101 there throws an error
{
"error": {
"status": 400,
"message": "Invalid limit"
}
}
{
"error": {
"status": 400,
"message": "Invalid limit"
}
}
Just checked with the following configuration
options: {
spotify: {
clientId: client.config.spotifyClientID,
clientSecret: client.config.spotifyToken,
limitLoadPlaylist: 200,
limitLoadSearch: 200
}
}
options: {
spotify: {
clientId: client.config.spotifyClientID,
clientSecret: client.config.spotifyToken,
limitLoadPlaylist: 200,
limitLoadSearch: 200
}
}
It still only loads 100 tracks. Note i forgot to add in the previous message, i'm not using LavaSrc since i don't entirely know how to set it up (yet)
ComicallyBad
ComicallyBad•4mo ago
if you're running lavalink yourself, I can send an application.yml for LavaSrc and it's config not sure if there's much to configure though, there's an albumLoadLimit and playlistLoadLimit, not sure if there's a track limit this way. I believe I've queued playlists with 100+ songs, I can test it out
MaxTechnics
MaxTechnicsOP•4mo ago
I am self-hosting, and have a plugin installed being the youtube plugin.
MaxTechnics
MaxTechnicsOP•4mo ago
I'll add the command structure here:
if (!LavaManager.nodeChecks(client, message)) return;
if (!vcChecks(message)) return;

// If there is an exising player and it is paused, resume instead
const existingPlayer = getPlayer(client, message);
if (existingPlayer && existingPlayer.paused) {
existingPlayer.resume();
return await message.react('šŸ‘Œ');
}

if (!args[0]) {
const noQueryEmbed = new EmbedBuilder()
.setColor(tofuOrange)
.setDescription('To play a song, you need to specify which song you want to play!');

return message.channel.send({ embeds: [noQueryEmbed] });
}

let shouldSendQueuedEmbed = true;
const embed = new EmbedBuilder();
const query = args.slice(0).join(' ');

const player = existingPlayer ? existingPlayer : client.music.createPlayer({
guildId: message.guild.id,
voiceChannelId: message.member.voice.channel.id,
textChannelId: message.channel.id,
autoPlay: false
});

if (player.queue.tracks.length === 0) shouldSendQueuedEmbed = false; // if this is the first one we don't send queued message

player.connect({ setDeaf: true });

const result = await client.music.search({
query,
requester: message.author
});

musicLog(result);

if (!result.tracks.length) return message.reply('No results found!');

switch (result.loadType) {
case 'playlist':
shouldSendQueuedEmbed = true; // We do want to send play if more than 1 track is queued
player.queue.add(result.tracks);
musicLog('Youtube list given');
embed.setColor(tofuGreen);
embed.setDescription(`Queued ${result.tracks.length} tracks`);
break;
case 'track':
case 'search':
musicLog('Youtube track given');
// const [track] = results.tracks;
// tracks = [track];
const track = result.tracks[0];
player.queue.add(track);
embed.setColor(tofuGreen);
embed.setDescription(`Queued [${track.title}](${track.url}) [${message.author}]`);
break;
case 'empty':
musicLog('Nothing found');
embed.setColor(tofuError);
embed.setDescription('No matches found!');
break;
case 'error':
default:
console.log(result);
embed.setColor(tofuError);
embed.setDescription('Tofu choked :headstone:');
embed.setFooter({ text: 'Please try again later' });
embed.setTimestamp();
return;
}

if (!player.playing) player.play();
if (shouldSendQueuedEmbed) message.channel.send({ embeds: [embed] });
}
if (!LavaManager.nodeChecks(client, message)) return;
if (!vcChecks(message)) return;

// If there is an exising player and it is paused, resume instead
const existingPlayer = getPlayer(client, message);
if (existingPlayer && existingPlayer.paused) {
existingPlayer.resume();
return await message.react('šŸ‘Œ');
}

if (!args[0]) {
const noQueryEmbed = new EmbedBuilder()
.setColor(tofuOrange)
.setDescription('To play a song, you need to specify which song you want to play!');

return message.channel.send({ embeds: [noQueryEmbed] });
}

let shouldSendQueuedEmbed = true;
const embed = new EmbedBuilder();
const query = args.slice(0).join(' ');

const player = existingPlayer ? existingPlayer : client.music.createPlayer({
guildId: message.guild.id,
voiceChannelId: message.member.voice.channel.id,
textChannelId: message.channel.id,
autoPlay: false
});

if (player.queue.tracks.length === 0) shouldSendQueuedEmbed = false; // if this is the first one we don't send queued message

player.connect({ setDeaf: true });

const result = await client.music.search({
query,
requester: message.author
});

musicLog(result);

if (!result.tracks.length) return message.reply('No results found!');

switch (result.loadType) {
case 'playlist':
shouldSendQueuedEmbed = true; // We do want to send play if more than 1 track is queued
player.queue.add(result.tracks);
musicLog('Youtube list given');
embed.setColor(tofuGreen);
embed.setDescription(`Queued ${result.tracks.length} tracks`);
break;
case 'track':
case 'search':
musicLog('Youtube track given');
// const [track] = results.tracks;
// tracks = [track];
const track = result.tracks[0];
player.queue.add(track);
embed.setColor(tofuGreen);
embed.setDescription(`Queued [${track.title}](${track.url}) [${message.author}]`);
break;
case 'empty':
musicLog('Nothing found');
embed.setColor(tofuError);
embed.setDescription('No matches found!');
break;
case 'error':
default:
console.log(result);
embed.setColor(tofuError);
embed.setDescription('Tofu choked :headstone:');
embed.setFooter({ text: 'Please try again later' });
embed.setTimestamp();
return;
}

if (!player.playing) player.play();
if (shouldSendQueuedEmbed) message.channel.send({ embeds: [embed] });
}
However it is 4am here at this point, so will likely be signing off soon. From what i've understood when using LavaSrc, you also need to query differently, or am I wrong there?
MEE6
MEE6•4mo ago
GG @MaxTechnics, you just advanced to level 1!
ComicallyBad
ComicallyBad•4mo ago
it should be the same, as spotify isn't actually used to play songs though, they will all be queued through another source
ComicallyBad
ComicallyBad•4mo ago
it did queue fine for me
No description
MaxTechnics
MaxTechnicsOP•4mo ago
I am aware that spotify streams are impossible. But it matches (most often with youtube) instead Perhaps its a limitation in the default matching algorithm, maybe it does not handle the pagination?
ComicallyBad
ComicallyBad•4mo ago
possibly, with LavaSrc though it seems to handle fine. So it may be worth trying. I don't believe you'd have to change any of your code either I also am using a spotify clientID & clientSecret, so that could be why I don't have issues
MaxTechnics
MaxTechnicsOP•4mo ago
So am i, though not on the lavalink side
MaxTechnics
MaxTechnicsOP•4mo ago
Thank you for the pointers and setup! I'll be looking into it first thing tomorrow. and will get back to the post here
ComicallyBad
ComicallyBad•4mo ago
yeah no problem, I'm guessing you may be right, could be an issue with the pagination currently
MaxTechnics
MaxTechnicsOP•4mo ago
Last I worked directly with the Spotify api was in 2021 (trying to actually pull audio from their service, which of course was impossible). Which led me to believe the 100 song limit was pagination related. I did expect it to error when setting the Moonlink Manger config to invalid limits (like 100+), maybe there are some protections against it?
ComicallyBad
ComicallyBad•4mo ago
I haven't done much with the spotify api directly, I'd have to test it out. I can try to see if there are any limits though
MaxTechnics
MaxTechnicsOP•4mo ago
The link in my first post to the docs has a built in little playground to interact with the api
ComicallyBad
ComicallyBad•4mo ago
huh, I see what you mean yeah, the direct API call cuts off at 100 exactly
MaxTechnics
MaxTechnicsOP•4mo ago
I've tried the application.yml you provided. I got all the tokens put in, however the player still only loads 100 tracks. I'll be looking into some docs to see if code modifications are required
SREERAJ SK
SREERAJ SK•4mo ago
Code your own spotify playlist fetcher and use it to get playlist data , then send the info to lavalink..
SREERAJ SK
SREERAJ SK•4mo ago
this works ig
MaxTechnics
MaxTechnicsOP•4mo ago
That would work, though isn't it better to implement the pagination in moonlink itself? I'll try it later today
SREERAJ SK
SREERAJ SK•4mo ago
this way you can save your playlist too soo no need to get link everytime.. idk if its possible with moonlink/lavalink
MaxTechnics
MaxTechnicsOP•4mo ago
I know moonlink supports database storage, though haven't looked into that myself either
MEE6
MEE6•4mo ago
GG @MaxTechnics, you just advanced to level 2!
SREERAJ SK
SREERAJ SK•4mo ago
oh i didn't know that... i use this setup no issues so far.. tested with playlist having 1k+ songs works fine
MaxTechnics
MaxTechnicsOP•4mo ago
I tried it and it does in fact work, Though it would be cool to see this handling in moonlink itself.
SREERAJ SK
SREERAJ SK•4mo ago
btw is there any limit to how many songs i can queue ??
MaxTechnics
MaxTechnicsOP•4mo ago
I don't think so, as long as you respect api ratelimits
SREERAJ SK
SREERAJ SK•4mo ago
hmm i use custom queue in my bot .. planning to switch to inbuilt queue
MaxTechnics
MaxTechnicsOP•4mo ago
i am currently migrating to moonlink from lavaclient And trying to recreate the feel of groovy bot
1Lucas1.apk
1Lucas1.apk•4mo ago
No description
1Lucas1.apk
1Lucas1.apk•4mo ago
what I find strangest It's because it's not splitting.
MaxTechnics
MaxTechnicsOP•4mo ago
I took a quick look at the source in moonlink, it does not seem to have any pagination logic.
How do you query the playlist in your bot? The standard manager.search does not fix the 100song issue. Im suspecting it does not make use of lavasrc
1Lucas1.apk
1Lucas1.apk•4mo ago
I don't use it, and there is logic, when the songs are searched, it does a split of 0, the limit defined in all that loads as playlists in spotify, I just reinforced to do a global
MaxTechnics
MaxTechnicsOP•4mo ago
I see, wouldn't it make sense to have pagination on the endpoints that do that though? Not sure how the other endpoints differ
1Lucas1.apk
1Lucas1.apk•4mo ago
Yes, the Spotify endpoint delivers per page This logic is a bit strange indeed. But I'll do it by track, for me it's better than counting Spotify pages without understanding correctly
MaxTechnics
MaxTechnicsOP•4mo ago
I think the api endpoint's response has all that info included, as well as the url for the next page
MaxTechnics
MaxTechnicsOP•4mo ago
next and previous are endpoint urls for next pages. I don't think it'd be too complicated to check if (next) Loadfrompage(next)
No description
1Lucas1.apk
1Lucas1.apk•4mo ago
Now I understand, I'll commit and correct it
MaxTechnics
MaxTechnicsOP•4mo ago
If you'd like i can test before you release
Solution
ComicallyBad
ComicallyBad•4mo ago
Not that I’m aware of
MaxTechnics
MaxTechnicsOP•4mo ago
Just switched back to release, and can confirm that loading now works as expected. So for those reading, make sure to update to https://github.com/Ecliptia/moonlink.js/releases/tag/v4.60.4 or later. To all here, thank you very much for your help and the quick update!
GitHub
Release v4.60.4 Ā· Ecliptia/moonlink.js
What's Changed Add qodana CI checks by @qodana-cloud[bot] in #162 sync: v4 with dev by @1Lucas1apk in #163 sync: v4 with dev by @1Lucas1apk in #164 Full Changelog: v4.52.2...v4.60.4 ✨ New Fea...

Did you find this page helpful?