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)