Releases: Ecliptia/moonlink.js
v5.2.0
What's Changed
-
feat(voice):
channelIdin voice payload for Lavalink by @UnschooledGamer in #173 -
Merge dev into main with unrelated histories by @1Lucas1apk in #174
-
@UnschooledGamer made their first contribution in #173
Full Changelog: https://github.com/Ecliptia/moonlink.js/commits/v5.2.0
v5.0.0
What's Changed
- sync: v5 to dev by @1Lucas1apk in #167
- chore: add .npmignore file to exclude unnecessary files from npm package by @1Lucas1apk in #168
- Dev by @1Lucas1apk in #169
Full Changelog: v4.60.18...v5.0.0
v4.60.24
Full Changelog: v4.60.21...v4.60.24
v4.60.21
Full Changelog: v4.60.18...v4.60.21
v4.60.18
Full Changelog: v4.60.4...v4.60.18
Moonlink.js v4.60.18: Critical Bun.js Fix & Major Stability Upgrades (from v4.60.4)
The centerpiece of this update is a critical fix for an issue that affected users running their bots on
Bun.js. Thanks to detailed bug reports from our community, particularly from efekos
(https://github.com/efekos) and Duckie (aiden4419), we were able to resolve a Malformed_HTTP_Response
error caused by a keep-alive header conflict. To address this, the WebSocket service in
src/services/WebSocket.ts has been fundamentally re-engineered. It is now runtime-aware, featuring a new
connectBun() method that utilizes the native globalThis.WebSocket when Bun is detected. The previous
Node.js-based implementation remains in connectNode(), ensuring continued stability for Node.js users. As
part of this refactor, the non-standard addEventListener method was removed in favor of the standard on()
and once() from Node's EventEmitter for better code consistency.
Player reliability has been drastically improved with the introduction of a new Player Health Check
system. Previously, players could get "stuck" silently due to network or Lavalink issues. The Player class
in src/entities/Player.ts now includes checkHealth() and scheduleHealthCheck() methods. This system
proactively monitors player state and, if it detects an unresponsive player, will automatically attempt to
recover by restarting the track or skipping to the next. This is supported by new events like playerStale
and trackStale that give developers hooks into this recovery process.
Voice connection state management has also been completely rewritten for better robustness. The
Manager.packetUpdate() and _handleVoiceStateUpdate() functions in src/core/Manager.ts now handle complex
scenarios like channel moves, disconnects, and server changes with much greater accuracy. This update also
adds handling for the CHANNEL_DELETE event, ensuring a player is properly destroyed if its voice channel
is removed, which prevents "ghost" players.
Finally, to enhance the developer experience, the PlayerManager in src/management/PlayerManager.ts now
features a new autoJoin() method. This utility function streamlines the process of creating or getting a
player and connecting it to a voice channel, significantly reducing boilerplate code in your commands.
What's Changed
- sync: dev with v4 by @1Lucas1apk in #165
v4.60.4
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 Features
- Granular Control for Spotify Playlist/Album Loading: You can now control the number of tracks fetched per
API request from Spotify, separate from the total number of tracks to be loaded. This is useful for
managing API usage and initial load times. - Global Playlist Track Limit: A new global option, playlistLoadLimit, has been introduced to set a default
maximum number of tracks to load from any playlist, which can be overridden on a per-call basis.
🐛 Improvements & Bug Fixes
- Spotify URI Support: The Spotify source now correctly parses both standard URLs (e.g.,
https://open.spotify.com/...) and Spotify URIs (e.g., spotify:track:...) for all content types. - Player State Synchronization:
- Fixed an issue where a player's track position could be incorrectly reset to 0 during a playerUpdate
event. The position is now only updated if the new position is greater than 0 or if the track has
just started. - The track position is now correctly initialized from the TrackStartEvent payload, ensuring accurate
starting points.
- Fixed an issue where a player's track position could be incorrectly reset to 0 during a playerUpdate
- Node Management: The NodeManager has been refactored to more reliably filter and select available and
connected nodes, improving stability in multi-node environments. - Deezer & Spotify Load Control: The search and load functions for both Deezer and Spotify sources now
allow for passing a limit option to override the default limits set in the manager configuration.
🛠️ API Changes & Technical Details
- Manager Options (
IOptionsManager)
The following properties have been added to the manager configuration interface:
- playlistLoadLimit?: number;
- Description: Sets a global default for the maximum number of tracks to load from a playlist across
all sources. Defaults to undefined (no limit).
- Description: Sets a global default for the maximum number of tracks to load from a playlist across
- spotify.limitLoadPlaylistPage?: number;
- Description: Sets the number of tracks to fetch per API request for Spotify playlists.
- Default: 100.
- spotify.limitLoadAlbumPage?: number;
- Description: Sets the number of tracks to fetch per API request for Spotify albums.
- Default: 50.
- Manager Class
-
Manager.search()
The options object for the search method now accepts a limit property to override the global
playlistLoadLimit.- New Signature:
1 search(options: {
2 query: string;
3 source?: TSearchSources;
4 node?: string;
5 requester?: unknown;
6 fallbackSources?: TSearchSources[];
7 limit?: number; // <-- New parameter
8 }): Promise
- NodeManager Class (
src/management/NodeManager.ts)
New utility methods have been added to improve node handling:
-
getConnected()- Description: Returns an array of all Node instances that are currently connected.
- Signature: public getConnected(): Node[]
-
hasConnected()- Description: Returns a boolean (true/false) indicating if there is at least one connected node.
- Signature: public hasConnected(): boolean
-
Internal Refactor: The methods getNodeWithCapability() and sortByUsage() now use getConnected()
internally to ensure they only operate on active nodes, making node selection more reliable.
- Spotify Source (
src/sources/Spotify.ts)
-
load()Method:- The method now accepts an options object to specify a limit.
- New Signature: public async load(rawUrl: string, options?: { limit?: number }): Promise
- Logic: Implemented a while loop to handle pagination. It now uses limitLoadPlaylistPage or
limitLoadAlbumPage for each API request and continues fetching pages until the options.limit or the
global playlistLoadLimit is reached.
-
search()Method:- The method now accepts an options object to specify a limit.
- New Signature: public async search(query: string, options?: { limit?: number }): Promise
-
getLinkType()Method:- The regular expressions have been updated to support Spotify URIs.
- Example (Track): /(?:open\.spotify\.com\/(?:intl-[^/]+\/)?track\/|spotify:track:)(\w+)/
- Deezer Source (
src/sources/Deezer.ts)
-
load()Method:- The method now accepts an options object to specify a limit.
- New Signature: public async load(query: string, options?: { limit?: number }): Promise
-
search()Method:- The method now accepts an options object to specify a limit.
- New Signature: public async search(query: string, options?: { limit?: number }): Promise
v4.52.2
📦 What's Changed
This release brings major enhancements to Moonlink.js, focusing on a more flexible database system, robust player state management, expanded lyrics integration, and advanced queue control.
🚀 New Features
-
Flexible Database System
Introduced a fully customizable database layer with support for MongoDB (MongooseDB),LocalDB(WAL-based file storage), andMemoryDB. Users can now choose their preferred provider and storage path, enabling persistent player and queue data across restarts.
(Contributed by @Nevercold) -
Advanced Queue Operations
Added powerful new async methods to theQueuefor greater control:moveRange: move a range of tracksremoveRange: remove a range of tracksduplicate: duplicate a trackjump: jump to a specific track
All queue operations now ensure reliable data persistence.
-
Expanded Lyrics Integration
Reworked lyrics handling with new methods for both static and synchronized (live) lyrics. Improved plugin selection logic ensures the best available provider (LavaLyrics, Lyrics.kt, or JavaLyricsPlugin) is used automatically. -
Node Health Monitoring
Implemented periodic health checks in theNodeManagerto detect unhealthy nodes and automatically migrate players, ensuring seamless performance and uptime. -
Text-to-Speech (TTS) Support
Added a newplayer.speak()method with support for multiple TTS providers (Flowery TTS, Google Cloud TTS, Skybot), enabling dynamic voice interactions in your bot. -
Queue Deduplication
IntroducedremoveDuplicates()in theQueueto prevent duplicate tracks, solving long-standing issues with repeated entries.
(Contributed by 1lucas1apk)
🛠 Improvements
-
Persistent Player State
Player and queue data are now consistently stored using the new database layer, ensuring state is retained across bot restarts. -
Improved Player Lifecycle Management
Enhanced player creation and node selection logic, including better handling of node capabilities per source and intelligent fallbacks for uninterrupted playback. -
Flexible Requester Handling
UpdatedTrackandPlayerclasses to supportrequesteras either a string or an object, offering more flexibility when identifying who requested a track.
(Contributed by @comicallybad) -
Track Enhancements
ImprovedTrackstructure with enhanced requester support and neworigintracking for smarter routing and source resolution. -
Documentation Updates
Revamped the introduction and added a detailed troubleshooting guide to help developers resolve common issues more easily. -
Internal Refinements
Numerous internal improvements and optimizations for better stability, performance, and maintainability.
🐛 Bug Fixes
- Paused State Handling
Fixed an issue where theplayer.pausedstate was being incorrectly reset by Lavalink'splayerUpdateevent. User-initiated pauses are now reliably preserved.
👥 Contributors
- @Nevercold — for the new flexible database system and provider support.
- @comicallybad — for improving
requesterhandling in theTrackandPlayerclasses.
v4.44.4
What's Changed
- fix: update validation logic in Player class methods by @comicallybad in #154
- Fix/Feature: Validation Logic, and Backtrack History Handling in Player by @comicallybad in #155
- feat(spotify): add clientId and clientSecret options for Spotify API by @comicallybad in #156
- sync: v4 with dev by @1Lucas1apk in #157
- sync: v4 with dev by @1Lucas1apk in #158
Full Changelog: v4.28.34...v4.44.4