A fast and rich-featured lavalink wrapper for node.js
- Easy-to-use
- Performant
NPM (Stable) => npm install lavacoffee
Github (Dev) => npm install Azusfin/lavacoffee#main
Download the latest binaries from the CI Server (Dev)
Put an application.yml in your working directory.
Run with java -jar Lavalink.jar
Docker images are available on the Docker hub
Init lava client
Add some nodes
Play track
Grab some coffee ☕
npm run test
// Importing lava instance constructor
import { CoffeeLava } from "lavacoffee"
// Construct the lava instance
const lava = new CoffeeLava(lavaOptions)
// Init the lava instance
lava.init(clientID)
// Adding a node
lava.add(nodeOptions)
// More nodes
lava.add(nodeOptions1)
lava.add(nodeOptions2)
...
// Payload can be a voice state update payload or a voice server update payload
lava.updateVoiceData(payload)
https://azusfin.github.io/lavacoffee/interfaces/LavaEvents.html
lava.on(eventName, (...args) => { ... })
/**
* Lavalink got a feature
* which will allow for resuming
* a session after it got
* disconnected
*/
/**
* After v1.2.0, lavacoffee
* added support for this feature,
* allowing for resuming lavalink session
* incase of bot restarted
*/
// Create the resume configuration
const config = {
// The resume custom key for resuming lavalink session
key: "somekey",
// The timeout for the session, if timeout is passed before resumed, it can't be resumed anymore
timeout: 60, // 60 seconds
// Incase of player resumed, it must be handled manually by the user
handle(lava, guildID, callback) {
// Creating the player
const player = lava.create({ guildID })
// Redo the player state, e.g getting the player queue from database
...
// Call callback to indicate as done
callback(player)
}
}
// Creating lava instance
const lava = new CoffeeLava({
resumeConfig: config,
/** other lava options */
})
...
https://github.com/freyacodes/Lavalink/blob/master/IMPLEMENTATION.md#routeplanner-api
// RoutePlanner instance is available within Node instance
const node = lava.nodes.get(nodeName)
const { routePlanner } = node
// Get routePlanner status
// If no routePlanner is set on node-side, it will return undefined
await routePlanner.status()
// Unmark a failed address
// Return true if success, otherwise false
await routePlanner.freeAddress(address)
// Unmark all failed address
// Return true if success, otherwise false
await routePlanner.freeAllAddress()
Plugins are managed in the lavalink server itself.
but you can make managing plugins in the node more spicier and stricter in lavacoffee
/**
* Using required plugins option
* on the lava instance make sure
* all nodes have the plugins
* otherwise they will be ignored
*/
// Incase if one of your worker messed up the plugins on the server...
// Example when creating the instance
const lava = new CoffeeLava({
requiredPlugins: ["Spotify-Plugin"],
send: (guildID, payload) => { ... }
})
/**
* Using required plugins option
* on search query make sure the searching
* doesn't use node that doesn't have
* the plugins
*/
// Example
const searchResult = await lava.search({
query: url,
requiredPlugins: ["Spotify-Plugin"]
}, author)
/**
* Using required plugins option
* on player make sure the player
* doesn't use node that doesn't have
* the plugins
*/
// Example
const player = lava.create({
guildID: guild.id,
requiredPlugins: ["Spotify-Plugin"]
})
Decoding and encoding tracks are also available locally
// Import decoder and encoder from utils
import { Utils } from "lavacoffee"
const { TrackUtils } = Utils
// Decode track
const track = TrackUtils.decodeTrack(rawTrack)
// Encode it back
TrackUtils.encodeTrack(track)
With more details:
// Decode spotify track from spotify-plugin
const spotifyTrack = TrackUtils.decodeTrack<{
isrc?: string,
artworkUrl?: string
}>(
rawSpotifyTrack,
(_, data) => ({
isrc: data.readNullableText(),
artworkUrl: data.readNullableText()
})
)
// Encode it back
TrackUtils.encodeTrack<{
isrc?: string,
artworkUrl?: string
}>(
spotifyTrack,
(track, data) => {
data.writeNullableText(track.isrc)
data.writeNullableText(track.artworkUrl)
}
)
// THis will create a new player or get an existing if exist
const player = lava.create(playerOptions)
// Connect to voice channel
player.options.voiceID = voiceChannelID
player.connect()
// Adding tracks
player.queue.add(tracks)
// Play
player.play()
...
// Use this if you only want to get a player without creating it
const player = lava.get(guildID)
if (!player) return
// Getting queue
const queue = player.queue
// Getting current track
const track = player.queue.current
...
/**
* When player is disconnected from node
* it will automatically move to another node
* then replay the track on current position
* you can disable this behaviour by setting
* the `autoReplay` option to false in LavaOptions
*/
// Replay events
// When successfully replayed
lava.on("playerReplay", player => { ... })
// When there's an error while replaying
lava.on("replayError", (player, error) => { ... })
...
/**
* LavaCoffee also supports lavalink filters
* it also got filters builder to manage filters easier
*/
// Importing filters builder
import { CoffeeFilters } from "lavacoffee"
// Creating filters
const filters = new CoffeeFilters()
// Example on setting equalizer
filters.equalizers
.setBand(2, 0.25)
.setBand(6, -0.25)
// Example to enable karaoke filter
filters.karaoke.enabled = true
// Example on setting 2x speed and half pitch
filters.timescale
.setSpeed(2)
.setPitch(0.5)
// Example on setting vibrato filter
filters.vibrato
.setFrequency(2)
.setDepth(0.5)
// Example on setting the audio to only left channel
filters.channelMix
.setRightToLeft(1)
.setRightToRight(0)
// Set the filters
player.setFilters(filters)
/**
* You can make an unknown track
* from unknown source, and resolve it
* once it playing
*/
// Importing unresolved track
import { UnresolvedTrack } from "lavacoffee"
// Creating the track
const track = new UnresolvedTrack(title, author, duration, requester)
// Adding the track
player.queue.add(track)