Skip to content

disgoorg/disgolink

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Go Reference Go Report Go Version License Disgolink Version Support Discord

discord gopher

DisGoLink

DisGoLink is a Lavalink Client written in Golang which supports the latest Lavalink 4.0.0+ release and the new plugin system.

While DisGoLink can be used with any Discord Library DisGo is the best fit for it as usage with other Libraries can be a bit annoying due to different Snowflake implementations.

This Library uses the Disgo Snowflake package like DisGo

Getting Started

Installing

go get github.com/disgoorg/disgolink/v3

Usage

Setup

First create a new lavalink instance. You can do this either with

import (
	"github.com/disgoorg/snowflake/v2"
	"github.com/disgoorg/disgolink/v3/disgolink"
)

var userID = snowflake.ID(1234567890)
lavalinkClient := disgolink.New(userID)

You also need to forward the VOICE_STATE_UPDATE and VOICE_SERVER_UPDATE events to DisGoLink. Just register an event listener for those events with your library and call lavalinkClient.OnVoiceStateUpdate (make sure to only forward your bots voice update event!) and lavalinkClient.OnVoiceServerUpdate

For DisGo this would look like this

client, err := disgo.New(Token,
    bot.WithEventListenerFunc(b.onVoiceStateUpdate),
    bot.WithEventListenerFunc(b.onVoiceServerUpdate),
)

func onVoiceStateUpdate(event *events.GuildVoiceStateUpdate) {
    // filter all non bot voice state updates out
    if event.VoiceState.UserID != client.ApplicationID() {
        return
    }
    lavalinkClient.OnVoiceStateUpdate(context.TODO(), event.VoiceState.GuildID, event.VoiceState.ChannelID, event.VoiceState.SessionID)
}

func onVoiceServerUpdate(event *events.VoiceServerUpdate) {
    lavalinkClient.OnVoiceServerUpdate(context.TODO(), event.GuildID, event.Token, *event.Endpoint)
}

Then you add your lavalink nodes. This directly connects to the nodes and is a blocking call

node, err := lavalinkClient.AddNode(context.TODO(), lavalink.NodeConfig{
		Name:      "test", // a unique node name
		Address:   "localhost:2333",
		Password:  "youshallnotpass",
		Secure:    false, // ws or wss
		SessionID: "", // only needed if you want to resume a previous lavalink session
})

after this you can play songs from lavalinks supported sources.

Loading a track

To play a track you first need to resolve the song. For this you need to call the Lavalink rest loadtracks endpoint which returns a result with various track instances. Those tracks can then be played.

query := "ytsearch:Rick Astley - Never Gonna Give You Up"

var toPlay *lavalink.Track
lavalinkClient.BestNode().LoadTracksHandler(context.TODO(), query, disgolink.NewResultHandler(
	func(track lavalink.Track) {
		// Loaded a single track
		toPlay = &track
	},
	func(playlist lavalink.Playlist) {
		// Loaded a playlist
	},
	func(tracks []lavalink.Track) {
		// Loaded a search result
	},
	func() {
		// nothing matching the query found
	},
	func(err error) {
		// something went wrong while loading the track
	},
))

Playing a track

To play a track we first need to connect to the voice channel. Connecting to a voice channel differs with every lib but here are some quick usages with some

// DisGo
err := client.UpdateVoiceState(context.TODO(), guildID, channelID, false, false)

// DiscordGo
err := session.ChannelVoiceJoinManual(guildID, channelID, false, false)

after this you can get/create your player and play the track

player := lavalinkClient.Player("guild_id") // This will either return an existing or new player

// toPlay is from result handler in the example above
err := player.Update(context.TODO(), lavalink.WithTrack(*toPlay))

now audio should start playing

Listening for events

You can listen for following lavalink events

  • PlayerUpdateMessage Emitted every x seconds (default 5) with the current player state
  • PlayerPause Emitted when the player is paused
  • PlayerResume Emitted when the player is resumed
  • TrackStart Emitted when a track starts playing
  • TrackEnd Emitted when a track ends
  • TrackException Emitted when a track throws an exception
  • TrackStuck Emitted when a track gets stuck
  • WebsocketClosed Emitted when the voice gateway connection to lavalink is closed

for this add and event listener for each event to your Client instance when you create it or with Client.AddEventListener

lavalinkClient := disgolink.New(userID,
    disgolink.WithListenerFunc(onPlayerUpdate),
    disgolink.WithListenerFunc(onPlayerPause),
	disgolink.WithListenerFunc(onPlayerResume),
	disgolink.WithListenerFunc(onTrackStart),
	disgolink.WithListenerFunc(onTrackEnd),
	disgolink.WithListenerFunc(onTrackException),
	disgolink.WithListenerFunc(onTrackStuck),
	disgolink.WithListenerFunc(onWebSocketClosed),
)

func onPlayerUpdate(player disgolink.Player, event lavalink.PlayerUpdateMessage) {
    // do something with the event
}

func onPlayerPause(player disgolink.Player, event lavalink.PlayerPauseEvent) {
    // do something with the event
}

func onPlayerResume(player disgolink.Player, event lavalink.PlayerResumeEvent) {
    // do something with the event
}

func onTrackStart(player disgolink.Player, event lavalink.TrackStartEvent) {
    // do something with the event
}

func onTrackEnd(player disgolink.Player, event lavalink.TrackEndEvent) {
    // do something with the event
}

func onTrackException(player disgolink.Player, event lavalink.TrackExceptionEvent) {
    // do something with the event
}

func onTrackStuck(player disgolink.Player, event lavalink.TrackStuckEvent) {
    // do something with the event
}

func onWebSocketClosed(player disgolink.Player, event lavalink.WebSocketClosedEvent) {
    // do something with the event
}

Plugins

Lavalink added plugins in v3.5 . DisGoLink exposes a similar API for you to use. With that you can create plugins which require server & client work. To see what you can do with plugins see here

You register plugins when creating the client instance like this

lavalinkClient := disgolink.New(userID, disgolink.WithPlugins(yourPlugin))

Here is a list of plugins(you can pr your own to here):

Examples

You can find examples under

Troubleshooting

For help feel free to open an issue or reach out on Discord

Contributing

Contributions are welcomed but for bigger changes please first reach out via Discord or create an issue to discuss your intentions and ideas.

License

Distributed under the License. See LICENSE for more information.