Upgrade v4 to v5
The definitive and detailed guide for migrating your Moonlink.js application from version 4 to version 5.
Moonlink.js v5 is a monumental update that redefines how the library handles internal requests and state management. This version focuses on 100% reliability for player commands by making them asynchronous and providing a much cleaner, more modular architecture.
1. Manager: Initialization & Setup
The initialization process in v5 is more flexible, offering a low-boilerplate approach via Connectors while maintaining the classic manual setup for granular control.
sendPayload ➜ send
In manual mode, the property used to send packets to Discord has been renamed from sendPayload to send.
Manual Mode vs. Connectors
Option A: Manual Mode (Classic)
If you prefer full control, manual mode is still fully supported. You must manually listen to ready and raw events and call manager.init().
Option B: Connector Mode (Recommended)
Connectors are a new v5 feature that automates the boilerplate. They handle init(), raw packet updates, and the send function internally.
Options Structure Refactoring
To improve clarity, root-level options from v4 have been grouped into logical category objects.
| Option | v4 Location | v5 Location |
|---|---|---|
| Max Queue Size | options.maxQueueSize | options.queue.maxSize |
| Auto Play | options.autoPlay | options.defaultPlayer.autoPlay |
| Auto Leave | options.autoLeave | options.defaultPlayer.autoLeave |
| Retry Amount | options.retryAmount | options.node.retryAmount |
| Retry Delay | options.retryDelay | options.node.retryDelay |
| Source Limit | options.playlistLoadLimit | options.search.playlistLoadLimit |
2. Player: The Async Revolution
In version 5, all playback control methods on the Player class are now asynchronous. This change was made to ensure that the library waits for a confirmation from the Lavalink/NodeLink server before proceeding, guaranteeing that your requests are processed with 100% reliability.
Updated Method Signatures
Every control method now returns a Promise. You must use await or .then() to ensure stable state management.
Methods that were synchronous in v4 but are now asynchronous in v5.
The Voice Class
The logic for managing voice states and gateway handshakes has been moved from the Player class into a dedicated Voice class, accessible via player.voice. This separation makes the player lighter and the voice handling more robust.
3. Track Object Changes
To align with standard Lavalink API naming conventions, the property representing the track URL has been changed.
- v4:
track.url - v5:
track.uri(Breaking Change!)
Update your embeds and logging logic to use 'uri'.
track.thumbnail
In v5, track.thumbnail is a smart getter. If the track object doesn't have an artworkUrl from the source, the getter will automatically attempt to generate a valid YouTube thumbnail URL if the source is identified as YouTube.
4. Synchronous Queue
In v4, Queue methods were asynchronous and returned Promises. In v5, they have been changed to be synchronous because the state is managed in-memory and synchronized with the internal database in background operations. You MUST remove await from these calls.
5. Filters: The New Preset System
In v4, filters were just raw data structures. In v5, we introduced a powerful preset system and a new way to apply effects.
Preset Support
You can now enable popular effects by name without knowing the underlying Lavalink configuration.
Custom Filter Definitions
You can define your own filters using a simple string-based syntax or objects in the Manager options.
6. Architecture: Voice & Node Management
v5 decouples internal logic into specialized classes for better maintenance and reliability.
The Voice Class
Player voice logic has moved from the Player class to a dedicated Voice class.
- Access:
player.voice - Responsibilities: Handling
VOICE_SERVER_UPDATE,VOICE_STATE_UPDATE, and connection state (DISCONNECTED,CONNECTING,CONNECTED).
NodeManager: Graceful Ejection
A new eject() method has been added to NodeManager to safely remove a node by moving all its players to other healthy nodes before disconnecting.
7. Removed Getters: Lyrics & Listen
In v5, the specialized getters player.lyrics and player.listen have been removed from the Player class core.
- Lyrics: Access lyrics directly via the
node.rest.getLyrics(trackId)instance. - Listen: Voice receiving logic has been moved to internal
Voicehandling and is no longer exposed through a dedicated getter on the Player.
7. Event Payload Standardization
Event signatures have been cleaned up to provide reason strings as direct arguments.
trackEnd Event
- v4:
(player, track, payload)(reason was hidden inside payload) - v5:
(player, track, reason, payload)(reason is now a direct argument)
New Events
socketClosed: Emitted when the voice WebSocket connection to Discord is closed.autoLeaved: Emitted when the bot automatically leaves a channel due to theautoLeavesetting.
8. SearchResult Class Overhaul
The SearchResult class has been completely redesigned for better usability and alignment with the new internal interfaces (IRESTLoadTracks).
New Helper Getters
You no longer need to manually compare strings. v5 introduces boolean getters for all load types:
Property Mapping Changes
| Feature | v4 (Old) | v5 (New) |
|---|---|---|
| Playlist Info | res.playlistInfo | res.playlistInfo (Now includes name, selectedTrack, and total duration) |
| Error Details | res.error | res.exception (Matches Lavalink standard) |
| LoadType | Loose string | LoadType Enum (mapped from 'track', 'playlist', 'search', 'empty', 'error') |
9. API Method Comparison
| Class | v4 Method | v5 Method | Change Type |
|---|---|---|---|
| Manager | sendPayload | send | Renamed |
| Player | connect() | await connect() | Async |
| Player | pause() | await pause() | Async |
| Player | resume() | await resume() | Async |
| Player | stop() | await stop() | Async |
| Player | seek() | await seek() | Async |
| Player | destroy() | await destroy() | Async |
| Player | filters.setX(...) | filters.setX(...) | Apply Required |
| Queue | await add() | add() | Sync |
| Queue | await shuffle() | shuffle() | Sync |
| Queue | await clear() | clear() | Sync |
| NodeManager | sortByUsage | findNode | Refined |
10. Full Implementation Example
Complete Bot Migration (v5)
This example combines all the major changes: Connectors, asynchronous Player methods, synchronous Queue methods, and the uri property.