Lyrics Class
The Lyrics class provides functionality to fetch and display lyrics for currently playing tracks in Moonlink.js.
player.lyrics.getLyrics()
The lyrics functionality requires a NodeLink server. Standard Lavalink servers do not support this feature.
Overview
Properties
Core properties of the Lyrics class.
Available Properties
Property | Type | Description |
---|---|---|
player | Player | Reference to the player instance that owns this lyrics handler |
Methods
Methods
Methods available in the Lyrics class.
Available Methods
getLyrics
getLyricsmethod
Get Lyrics
Fetches lyrics for the currently playing track.
Parameters
This method takes no parameters.
Returns & Example
Returns
• Promise<IRESTGetLyrics | null>
- Lyrics data or null if no track is playing or NodeLink is not available
// Basic usage
const lyrics = await player.lyrics.getLyrics();
if (lyrics && lyrics.loadType === 'track') {
console.log(`Song: ${lyrics.data.name}`);
console.log(`Synchronized: ${lyrics.data.synced}`);
for (const line of lyrics.data.data) {
console.log(`[${formatTime(line.startTime)}] ${line.text}`);
}
}
::
Response Structure
Lyrics Response Structure
The structure of the lyrics response object.
interface IRESTGetLyrics {
loadType: string; // 'track' if lyrics found
data: {
name: string; // Song name
synced: boolean; // Whether lyrics are time-synchronized
data: Array<{
startTime: number; // Start time in milliseconds
endTime: number; // End time in milliseconds
text: string; // Lyrics line text
}>;
rtl: boolean; // Right-to-left text direction
};
}
Usage Examples
Advanced Usage Examples
Comprehensive examples of implementing lyrics functionality.
Discord Bot with Lyrics Display
async function displayLyrics(message) {
const player = manager.players.get(message.guild.id);
if (!player?.playing) {
return message.channel.send('⚠️ No track is currently playing!');
}
const loadingMsg = await message.channel.send('🔍 Fetching lyrics...');
try {
const lyrics = await player.lyrics.getLyrics();
if (!lyrics || lyrics.loadType !== 'track') {
return loadingMsg.edit('❌ No lyrics found for this track.');
}
const { name, synced, data } = lyrics.data;
const currentTrack = player.current;
// Create embeds for paginated lyrics display
const embeds = [];
let currentPage = '';
let lineCount = 0;
for (const line of data) {
const timestamp = synced ? `\[${formatTimestamp(line.startTime)}\]` : '';
const lineText = `${timestamp}${line.text}\n`;
if ((currentPage + lineText).length > 4000 || lineCount >= 15) {
embeds.push({
title: `📝 Lyrics for ${currentTrack.title}`,
description: currentPage,
color: 0x3498db,
footer: {
text: `${synced ? 'Synchronized' : 'Unsynchronized'} lyrics | Page ${embeds.length + 1}`
}
});
currentPage = lineText;
lineCount = 1;
} else {
currentPage += lineText;
lineCount++;
}
}
// Add the last page if there's remaining content
if (currentPage.length > 0) {
embeds.push({
title: `📝 Lyrics for ${currentTrack.title}`,
description: currentPage,
color: 0x3498db,
footer: {
text: `${synced ? 'Synchronized' : 'Unsynchronized'} lyrics | Page ${embeds.length + 1}`
}
});
}
// Setup pagination buttons
const row = new Discord.ActionRowBuilder()
.addComponents(
new Discord.ButtonBuilder()
.setCustomId('prev')
.setLabel('Previous')
.setStyle('Primary')
.setEmoji('⬅️'),
new Discord.ButtonBuilder()
.setCustomId('next')
.setLabel('Next')
.setStyle('Primary')
.setEmoji('➡️')
);
let currentIndex = 0;
const initialMessage = await loadingMsg.edit({
content: null,
embeds: [embeds[0]],
components: [row]
});
// Handle pagination
const collector = initialMessage.createMessageComponentCollector({
time: 300000 // 5 minutes
});
collector.on('collect', async (interaction) => {
if (interaction.customId === 'prev') {
currentIndex = Math.max(0, currentIndex - 1);
} else if (interaction.customId === 'next') {
currentIndex = Math.min(embeds.length - 1, currentIndex + 1);
}
await interaction.update({
embeds: [embeds[currentIndex]],
components: [row]
});
});
collector.on('end', () => {
initialMessage.edit({ components: [] });
});
} catch (error) {
console.error('Error fetching lyrics:', error);
loadingMsg.edit('❌ An error occurred while fetching lyrics.');
}
}
// Helper function to format timestamps
function formatTimestamp(ms) {
const minutes = Math.floor(ms / 60000);
const seconds = ((ms % 60000) / 1000).toFixed(0);
return `${minutes}:${seconds.padStart(2, '0')}`;
}
// Command handler
client.on('messageCreate', async (message) => {
if (message.content === '!lyrics') {
await displayLyrics(message);
}
});
Real-time Lyrics Display
class LyricsDisplay {
constructor(player) {
this.player = player;
this.lyrics = null;
this.currentLineIndex = 0;
this.displayInterval = null;
}
async start() {
try {
this.lyrics = await this.player.lyrics.getLyrics();
if (!this.lyrics?.data?.synced) {
console.log('❌ No synchronized lyrics available');
return;
}
this.displayInterval = setInterval(() => {
this.updateDisplay();
}, 100);
// Stop display when track ends
this.player.once('trackEnd', () => this.stop());
} catch (error) {
console.error('Error starting lyrics display:', error);
}
}
updateDisplay() {
if (!this.lyrics || !this.player.playing) return;
const currentTime = this.player.position;
const lines = this.lyrics.data.data;
// Find current line based on timestamp
const newLineIndex = lines.findIndex((line, index) => {
return currentTime >= line.startTime &&
(index === lines.length - 1 || currentTime < lines[index + 1].startTime);
});
if (newLineIndex !== -1 && newLineIndex !== this.currentLineIndex) {
this.currentLineIndex = newLineIndex;
// Display current line and next line
console.clear();
console.log('🎵 Now Playing:', this.player.current.title);
console.log('\nCurrent Line:');
console.log(lines[this.currentLineIndex].text);
if (lines[this.currentLineIndex + 1]) {
console.log('\nNext Line:');
console.log(lines[this.currentLineIndex + 1].text);
}
}
}
stop() {
if (this.displayInterval) {
clearInterval(this.displayInterval);
this.displayInterval = null;
}
this.lyrics = null;
this.currentLineIndex = 0;
}
}
// Usage
player.on('trackStart', async () => {
const lyricsDisplay = new LyricsDisplay(player);
await lyricsDisplay.start();
});