Moonlink.js emits various events that you can listen to in order to react to changes in the state of players, nodes, and tracks. These events are essential for creating an interactive and responsive music bot.
All events are emitted by the Manager
object. You can listen to these events using the on()
or once()
method.
Listening to Events
To listen to events, you can use the on()
method of the Manager
:
// Create the Manager
const manager = new Manager({
// ... options
});
// Listen to an event
manager.on('trackStart', (player, track) => {
console.log(`Now playing: ${track.title}`);
});
Debug Events
debug
Debug
Emitted when debug information is available.
Parameters
Usage Example
manager.on('debug', (...args) => {
console.log('[DEBUG]', {
timestamp: new Date().toISOString(),
info: args
});
});
[DEBUG] {
timestamp: "2024-03-15T12:34:56.789Z",
info: ["Connecting to node", "Node-1", { host: "localhost", port: 2333 }]
}
autoLeaved
Auto Leaved
Emitted when a player automatically leaves a voice channel.
Parameters
Usage Example
manager.on('autoLeaved', (player, track) => {
console.log(`[AUTO] Player left:`, {
guild: player.guildId,
track: {
title: track.title,
author: track.author
},
channel: player.voiceChannelId
});
const embed = new EmbedBuilder()
.setColor('#ff6b6b')
.setTitle('🚪 Auto Leave')
.setDescription(`Left voice channel due to inactivity while playing **${track.title}**`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) {
channel.send({ embeds: [embed] });
}
});
[AUTO] Player left: {
guild: "123456789012345678",
track: {
title: "Never Gonna Give You Up",
author: "Rick Astley"
},
channel: "123456789012345678"
}
Node Events
nodeCreate
Node Create
Emitted when a new node is created.
Parameters
Usage Example
manager.on('nodeCreate', (node) => {
console.log(`[NODE] New node created:`, {
identifier: node.identifier,
host: node.host,
port: node.port,
secure: node.secure
});
const embed = new EmbedBuilder()
.setColor('#4ade80')
.setTitle('🆕 Node Created')
.setDescription(`New node ${node.identifier} created at ${node.host}:${node.port}`);
// Notify admin channel
const adminChannel = client.channels.cache.get('ADMIN_CHANNEL_ID');
if (adminChannel) {
adminChannel.send({ embeds: [embed] });
}
});
[NODE] New node created: {
identifier: "Node-1",
host: "localhost",
port: 2333,
secure: false
}
nodeReady
Node Ready
Emitted when a node is ready.
Parameters
Usage Example
manager.on('nodeReady', (node, stats) => {
console.log(`Node ${node.identifier} is ready`, stats);
});
[NODE] Node-1 is ready {
players: 5,
cpu: 0.5,
memory: {
free: 1000000000,
used: 500000000,
allocated: 1500000000
}
}
nodeConnected
Node Connected
Emitted when a node successfully connects.
Parameters
Usage Example
manager.on('nodeConnected', (node) => {
console.log(`Node ${node.identifier} connected`);
});
[NODE] Node-1 connected
nodeError
Node Error
Emitted when a node encounters an error.
Parameters
Usage Example
manager.on('nodeError', (node, error) => {
console.log(`[NODE] Error occurred:`, {
identifier: node.identifier,
error: {
name: error.name,
message: error.message,
stack: error.stack
}
});
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('⚠️ Node Error')
.setDescription(`Error on node ${node.identifier}\n\`\`\`\n${error.message}\n\`\`\``);
// Notify admin channel
const adminChannel = client.channels.cache.get('ADMIN_CHANNEL_ID');
if (adminChannel) {
adminChannel.send({ embeds: [embed] });
}
});
[NODE] Error occurred: {
identifier: "Node-1",
error: {
name: "Error",
message: "Failed to connect to Lavalink server",
stack: "Error: Failed to connect..."
}
}
nodeReconnect
Node Reconnect
Emitted when a node attempts to reconnect.
Parameters
Usage Example
manager.on('nodeReconnect', (node) => {
console.log(`[NODE] Reconnection attempt:`, {
identifier: node.identifier,
attempt: node.reconnectAttempts,
timeout: node.reconnectTimeout
});
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('🔄 Node Reconnecting')
.setDescription(`Node ${node.identifier} is attempting to reconnect\nAttempt: ${node.reconnectAttempts}`);
// Notify admin channel
const adminChannel = client.channels.cache.get('ADMIN_CHANNEL_ID');
if (adminChannel) {
adminChannel.send({ embeds: [embed] });
}
});
[NODE] Reconnection attempt: {
identifier: "Node-1",
attempt: 1,
timeout: 5000
}
nodeDisconnect
Node Disconnect
Emitted when a node disconnects.
Parameters
Usage Example
manager.on('nodeDisconnect', (node, code, reason) => {
console.log(`[NODE] Disconnected:`, {
identifier: node.identifier,
code: code,
reason: reason,
reconnecting: node.reconnecting
});
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('🔌 Node Disconnected')
.setDescription(`Node ${node.identifier} disconnected\nCode: ${code}\nReason: ${reason}`);
// Notify admin channel
const adminChannel = client.channels.cache.get('ADMIN_CHANNEL_ID');
if (adminChannel) {
adminChannel.send({ embeds: [embed] });
}
});
[NODE] Disconnected: {
identifier: "Node-1",
code: 1006,
reason: "Connection closed abnormally",
reconnecting: true
}
nodeDestroy
Node Destroy
Emitted when a node is destroyed.
Parameters
Usage Example
manager.on('nodeDestroy', (node) => {
console.log(`[NODE] Destroyed:`, {
identifier: node.identifier,
timestamp: new Date().toISOString()
});
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('💥 Node Destroyed')
.setDescription(`Node ${node.identifier} has been destroyed`);
// Notify admin channel
const adminChannel = client.channels.cache.get('ADMIN_CHANNEL_ID');
if (adminChannel) {
adminChannel.send({ embeds: [embed] });
}
});
[NODE] Destroyed: {
identifier: "Node-1",
timestamp: "2024-03-15T12:34:56.789Z"
}
::
nodeAutoResumed
Node Auto Resumed
Emitted when a node automatically resumes its players.
Parameters
Usage Example
manager.on('nodeAutoResumed', (node, players) => {
console.log(`[NODE] Auto-resumed:`, {
identifier: node.identifier,
playersCount: players.length,
players: players.map(p => ({
guild: p.guildId,
track: p.queue.current?.title
}))
});
const embed = new EmbedBuilder()
.setColor('#4ade80')
.setTitle('♻️ Players Resumed')
.setDescription(`${players.length} players resumed on node ${node.identifier}`);
// Notify players about resumption
players.forEach(player => {
const channel = client.channels.cache.get(player.textChannelId);
if (channel) {
channel.send('✅ Player resumed after node reconnection');
}
});
});
[NODE] Auto-resumed: {
identifier: "Node-1",
playersCount: 2,
players: [
{
guild: "123456789012345678",
track: "Never Gonna Give You Up"
},
{
guild: "876543210987654321",
track: "Despacito"
}
]
}
Player Events
playerCreate
Player Create
Emitted when a new player is created.
Parameters
Usage Example
manager.on('playerCreate', (player) => {
console.log(`[PLAYER] Created:`, {
guild: player.guildId,
node: player.node.identifier,
voiceChannel: player.voiceChannelId,
textChannel: player.textChannelId
});
const embed = new EmbedBuilder()
.setColor('#4ade80')
.setTitle('🎵 Player Created')
.setDescription(`Music player created in <#${player.voiceChannelId}>`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) {
channel.send({ embeds: [embed] });
}
});
[PLAYER] Created: {
guild: "123456789012345678",
node: "Node-1",
voiceChannel: "123456789012345678",
textChannel: "876543210987654321"
}
playerUpdate
Player Update
Emitted when a player is updated.
Parameters
Usage Example
manager.on('playerUpdate', (player, track, payload) => {
console.log(`Player updated: ${player.guildId}`, payload);
});
[PLAYER] Updated: {
guild: "123456789012345678",
track: {
title: "Never Gonna Give You Up",
author: "Rick Astley"
},
payload: {
volume: 1.0,
loop: false,
autoplay: true
}
}
playerDestroy
Player Destroy
Emitted when a player is destroyed.
Parameters
Usage Example
manager.on('playerDestroy', (player) => {
console.log(`[PLAYER] Destroyed:`, {
guild: player.guildId,
node: player.node.identifier,
reason: player.state
});
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('👋 Player Destroyed')
.setDescription('Music player has been destroyed');
const channel = client.channels.cache.get(player.textChannelId);
if (channel) {
channel.send({ embeds: [embed] });
}
// Cleanup any resources
player.queue.clear();
});
[PLAYER] Destroyed: {
guild: "123456789012345678",
node: "Node-1",
reason: "disconnected"
}
playerSwitchedNode
Player Switched Node
Emitted when a player switches to a different node.
Parameters
Usage Example
manager.on('playerSwitchedNode', (player, oldNode, newNode) => {
console.log(`Player switched from node ${oldNode.identifier} to ${newNode.identifier}`);
});
[PLAYER] Switched node: {
guild: "123456789012345678",
oldNode: "Node-1",
newNode: "Node-2"
}
Player Control Events
playerTriggeredPlay
Player Triggered Play
Emitted when a player starts playing.
Parameters
Usage Example
manager.on('playerTriggeredPlay', (player, track) => {
console.log(`Player started playing: ${track.title}`);
});
[PLAYER] Started playing: {
guild: "123456789012345678",
track: {
title: "Never Gonna Give You Up",
author: "Rick Astley"
}
}
playerTriggeredPause
Player Triggered Pause
Emitted when a player is paused.
Parameters
Usage Example
manager.on('playerTriggeredPause', (player) => {
console.log(`Player paused: ${player.guildId}`);
});
[PLAYER] Paused: {
guild: "123456789012345678"
}
::
playerTriggeredResume
Player Triggered Resume
Emitted when a player resumes playing.
Parameters
Usage Example
manager.on('playerTriggeredResume', (player) => {
console.log(`Player resumed: ${player.guildId}`);
});
[PLAYER] Resumed: {
guild: "123456789012345678"
}
playerTriggeredStop
Player Triggered Stop
Emitted when a player stops playing.
Parameters
Usage Example
manager.on('playerTriggeredStop', (player) => {
console.log(`Player stopped: ${player.guildId}`);
});
[PLAYER] Stopped: {
guild: "123456789012345678"
}
Filter Events
filterUpdate
Filter Update
Emitted when audio filters are updated.
Parameters
Usage Example
manager.on('filterUpdate', (player, filters) => {
console.log(`[FILTER] Updated:`, {
guild: player.guildId,
filters: {
volume: filters.volume,
equalizer: filters.equalizer,
karaoke: filters.karaoke,
timescale: filters.timescale,
tremolo: filters.tremolo,
vibrato: filters.vibrato,
rotation: filters.rotation,
distortion: filters.distortion,
channelMix: filters.channelMix,
lowPass: filters.lowPass
}
});
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('🎛️ Filters Updated')
.setDescription('Audio filters have been updated')
.addFields(
Object.entries(filters)
.filter(([_, value]) => value !== null && value !== undefined)
.map(([key, value]) => ({
name: key.charAt(0).toUpperCase() + key.slice(1),
value: typeof value === 'object' ? 'Applied' : String(value),
inline: true
}))
);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) {
channel.send({ embeds: [embed] });
}
});
[FILTER] Updated: {
guild: "123456789012345678",
filters: {
volume: 1.0,
equalizer: [
{ band: 0, gain: 0.2 },
{ band: 1, gain: 0.15 }
],
karaoke: null,
timescale: { speed: 1.1, pitch: 1.0, rate: 1.0 },
tremolo: null,
vibrato: null,
rotation: null,
distortion: null,
channelMix: null,
lowPass: null
}
}
::
Events
playerTriggeredSkip
Player Triggered Skip
Emitido quando uma track é pulada.Parâmetros:
player: Player
- O playeroldTrack: Record<string, any>
- Track anteriorcurrentTrack: Track
- Nova trackposition: number
- Posição atual
manager.on('playerTriggeredSkip', (player, oldTrack, currentTrack, position) => {
console.log(`Track pulada: ${oldTrack.title} -> ${currentTrack.title} (Posição: ${position})`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('⏭️ Track Pulada')
.setDescription(`Pulou **${oldTrack.title}**\nAgora tocando: **${currentTrack.title}**`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerTriggeredSeek
Player Triggered Seek
Emitido quando a posição da track é alterada.Parâmetros:
player: Player
- O playerposition: number
- Nova posição em milissegundos
manager.on('playerTriggeredSeek', (player, position) => {
const timeString = new Date(position).toISOString().substr(11, 8);
console.log(`Posição alterada para ${timeString}`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('⏩ Posição Alterada')
.setDescription(`Avançou para ${timeString}`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerTriggeredShuffle
Player Triggered Shuffle
Emitido quando a fila é embaralhada.Parâmetros:
player: Player
- O playeroldQueue: Record<string, any>
- Fila anteriorcurrentQueue: Track[]
- Nova fila
manager.on('playerTriggeredShuffle', (player, oldQueue, currentQueue) => {
console.log(`Fila embaralhada: ${currentQueue.length} tracks`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('🔀 Fila Embaralhada')
.setDescription(`${currentQueue.length} tracks na fila`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerChangedVolume
Player Changed Volume
Emitido quando o volume é alterado.Parâmetros:
player: Player
- O playeroldVolume: number
- Volume anteriorvolume: number
- Novo volume
manager.on('playerChangedVolume', (player, oldVolume, volume) => {
console.log(`Volume alterado: ${oldVolume} -> ${volume}`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('🔊 Volume Alterado')
.setDescription(`Volume: ${volume}%`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerChangedLoop
Player Changed Loop
Emitido quando o modo de loop é alterado.Parâmetros:
player: Player
- O playeroldLoop: TPlayerLoop
- Modo anteriorloop: TPlayerLoop
- Novo modo
manager.on('playerChangedLoop', (player, oldLoop, loop) => {
console.log(`Loop alterado: ${oldLoop} -> ${loop}`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('🔁 Loop Alterado')
.setDescription(`Modo: ${loop}`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerAutoPlaySet
Player Auto Play Set
Emitido quando o autoplay é alterado.Parâmetros:
player: Player
- O playerautoPlay: boolean
- Novo estado
manager.on('playerAutoPlaySet', (player, autoPlay) => {
console.log(`Autoplay ${autoPlay ? 'ativado' : 'desativado'}`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('🎵 Autoplay')
.setDescription(`Autoplay ${autoPlay ? 'ativado' : 'desativado'}`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerAutoLeaveSet
Player Auto Leave Set
Emitido quando o autoleave é alterado.Parâmetros:
player: Player
- O playerautoLeave: boolean
- Novo estado
manager.on('playerAutoLeaveSet', (player, autoLeave) => {
console.log(`Autoleave ${autoLeave ? 'ativado' : 'desativado'}`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('👋 Auto Leave')
.setDescription(`Auto leave ${autoLeave ? 'ativado' : 'desativado'}`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerTextChannelIdSet
Player Text Channel ID Set
Emitido quando o canal de texto é alterado.Parâmetros:
player: Player
- O playeroldChannel: string
- Canal anteriornewChannel: string
- Novo canal
manager.on('playerTextChannelIdSet', (player, oldChannel, newChannel) => {
console.log(`Canal de texto alterado: ${oldChannel} -> ${newChannel}`);
});
playerVoiceChannelIdSet
Player Voice Channel ID Set
Emitido quando o canal de voz é alterado.Parâmetros:
player: Player
- O playeroldChannel: string
- Canal anteriornewChannel: string
- Novo canal
manager.on('playerVoiceChannelIdSet', (player, oldChannel, newChannel) => {
console.log(`Canal de voz alterado: ${oldChannel} -> ${newChannel}`);
});
playerNodeSet
Player Node Set
Emitido quando o node do player é alterado.Parâmetros:
player: Player
- O playeroldNode: string
- Node anteriornewNode: string
- Novo node
manager.on('playerNodeSet', (player, oldNode, newNode) => {
console.log(`Node alterado: ${oldNode} -> ${newNode}`);
});
playerConnected
Player Connected
Emitido quando um player conecta.Parâmetros:
player: Player
- O player conectado
manager.on('playerConnected', (player) => {
console.log(`Player conectado em ${player.guildId}`);
const embed = new EmbedBuilder()
.setColor('#4ade80')
.setTitle('🔌 Conectado')
.setDescription(`Conectado ao canal de voz`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerDisconnected
Player Disconnected
Emitido quando um player desconecta.Parâmetros:
player: Player
- O player desconectado
manager.on('playerDisconnected', (player) => {
console.log(`Player desconectado em ${player.guildId}`);
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('🔌 Desconectado')
.setDescription(`Desconectado do canal de voz`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerMoved
Player Moved
Emitido quando um player muda de canal.Parâmetros:
player: Player
- O player movidooldChannel: string
- Canal anteriornewChannel: string
- Novo canal
manager.on('playerMoved', (player, oldChannel, newChannel) => {
console.log(`Player movido: ${oldChannel} -> ${newChannel}`);
const embed = new EmbedBuilder()
.setColor('#fbbf24')
.setTitle('↔️ Canal Alterado')
.setDescription(`Movido para <#${newChannel}>`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
playerDestroyed
Player Destroyed
Emitido quando um player é destruído.Parâmetros:
player: Player
- O player destruído
manager.on('playerDestroyed', (player) => {
console.log(`Player destruído em ${player.guildId}`);
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('💥 Player Destruído')
.setDescription(`O player foi destruído`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
trackStart
Track Start
Emitido quando uma track começa a tocar.Parâmetros:
player: Player
- O playertrack: Track
- A track iniciada
manager.on('trackStart', (player, track) => {
console.log(`Tocando: ${track.title}`);
const embed = new EmbedBuilder()
.setColor('#4ade80')
.setTitle('🎵 Tocando Agora')
.setDescription(`**${track.title}**`)
.addFields(
{ name: 'Artista', value: track.author, inline: true },
{ name: 'Duração', value: formatTime(track.duration), inline: true }
)
.setThumbnail(track.artworkUrl);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
trackEnd
Track End
Emitido quando uma track termina.Parâmetros:
player: Player
- O playertrack: Track
- A track finalizadatype: TTrackEndType
- Tipo de finalizaçãopayload?: any
- Dados adicionais
manager.on('trackEnd', (player, track, type, payload) => {
console.log(`Track finalizada: ${track.title} (${type})`);
const embed = new EmbedBuilder()
.setColor('#94a3b8')
.setTitle('🎵 Track Finalizada')
.setDescription(`**${track.title}** terminou`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
trackStuck
Track Stuck
Emitido quando uma track trava.Parâmetros:
player: Player
- O playertrack: Track
- A track travadathreshold: number
- Limite de tempo
manager.on('trackStuck', (player, track, threshold) => {
console.log(`Track travou: ${track.title} (${threshold}ms)`);
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('⚠️ Track Travada')
.setDescription(`**${track.title}** travou\nTempo limite: ${threshold}ms`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
trackException
Track Exception
Emitido quando ocorre um erro na track.Parâmetros:
player: Player
- O playertrack: Track
- A track com erroexception: any
- O erro ocorrido
manager.on('trackException', (player, track, exception) => {
console.log(`Erro na track ${track.title}:`, exception);
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('❌ Erro na Track')
.setDescription(`Erro ao tocar **${track.title}**\n\`${exception.message}\``);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
queueEnd
Queue End
Emitido quando a fila termina.Parâmetros:
player: Player
- O playertrack?: any
- Última track tocada
manager.on('queueEnd', (player, track) => {
console.log(`Fila finalizada em ${player.guildId}`);
const embed = new EmbedBuilder()
.setColor('#94a3b8')
.setTitle('🎵 Fila Finalizada')
.setDescription('Todas as tracks foram tocadas');
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});
socketClosed
Socket Closed
Emitido quando o socket é fechado.Parâmetros:
player: Player
- O playercode: number
- Código de fechamentoreason: string
- Motivo do fechamentobyRemote: boolean
- Se foi fechado remotamente
manager.on('socketClosed', (player, code, reason, byRemote) => {
console.log(`Socket fechado: ${reason} (${code})`);
const embed = new EmbedBuilder()
.setColor('#ef4444')
.setTitle('🔌 Conexão Fechada')
.setDescription(`Conexão fechada: ${reason}\nCódigo: ${code}`);
const channel = client.channels.cache.get(player.textChannelId);
if (channel) channel.send({ embeds: [embed] });
});