gavalink/player.go

211 lines
4.8 KiB
Go
Raw Normal View History

2018-08-24 01:24:20 +00:00
package gavalink
import (
"strconv"
)
// Player is a Lavalink player
type Player struct {
2019-10-13 03:57:59 +00:00
guildID string
2019-10-13 04:04:01 +00:00
sessionID string
2019-10-13 03:57:59 +00:00
time int
position int
paused bool
vol int
track string
manager *Lavalink
node *Node
lastVoiceServerUpdate VoiceServerUpdate
2018-08-24 01:24:20 +00:00
}
// GuildID returns this player's Guild ID
func (player *Player) GuildID() string {
return player.guildID
}
2018-08-24 01:24:20 +00:00
// Play will play the given track completely
func (player *Player) Play(track string) error {
return player.PlayAt(track, 0, 0)
}
// PlayAt will play the given track at the specified start and end times
//
// Setting a time to 0 will omit it.
func (player *Player) PlayAt(track string, startTime int, endTime int) error {
player.paused = false
player.track = track
2018-08-24 01:24:20 +00:00
start := strconv.Itoa(startTime)
end := strconv.Itoa(endTime)
2019-01-13 23:37:38 +00:00
msg := playMessage{
2018-08-24 01:24:20 +00:00
Op: opPlay,
GuildID: player.guildID,
Track: track,
StartTime: start,
EndTime: end,
}
2019-01-13 23:37:38 +00:00
return player.node.writeMessage(msg)
2018-08-24 01:24:20 +00:00
}
// Track returns the player's current track
func (player *Player) Track() string {
return player.track
}
2018-08-24 01:24:20 +00:00
// Stop will stop the currently playing track
func (player *Player) Stop() error {
player.track = ""
2019-01-13 23:37:38 +00:00
msg := basicMessage{
2018-08-24 01:24:20 +00:00
Op: opStop,
GuildID: player.guildID,
}
2019-01-13 23:37:38 +00:00
return player.node.writeMessage(msg)
2018-08-24 01:24:20 +00:00
}
// Pause will pause or resume the player, depending on the pause parameter
func (player *Player) Pause(pause bool) error {
player.paused = pause
2019-01-13 23:37:38 +00:00
msg := pauseMessage{
2018-08-24 01:24:20 +00:00
Op: opPause,
GuildID: player.guildID,
2019-01-13 23:37:38 +00:00
Pause: pause,
2018-08-24 01:24:20 +00:00
}
2019-01-13 23:37:38 +00:00
return player.node.writeMessage(msg)
2018-08-24 01:24:20 +00:00
}
// Paused returns whether or not the player is currently paused
func (player *Player) Paused() bool {
return player.paused
}
// Seek will seek the player to the speicifed position, in millis
func (player *Player) Seek(position int) error {
2019-01-13 23:37:38 +00:00
msg := seekMessage{
2018-08-24 01:24:20 +00:00
Op: opSeek,
GuildID: player.guildID,
Position: &position,
}
2019-01-13 23:37:38 +00:00
return player.node.wsConn.WriteJSON(msg)
2018-08-24 01:24:20 +00:00
}
// Position returns the player's position, as reported by Lavalink
func (player *Player) Position() int {
return player.position
}
// Volume will set the player's volume to the specified value
//
// volume must be within [0, 1000]
func (player *Player) Volume(volume int) error {
if volume < 0 || volume > 1000 {
return errVolumeOutOfRange
}
2018-08-26 02:24:56 +00:00
player.vol = volume
2019-01-13 23:37:38 +00:00
msg := volumeMessage{
2018-08-24 01:24:20 +00:00
Op: opVolume,
GuildID: player.guildID,
2019-01-13 23:37:38 +00:00
Volume: volume,
2018-08-24 01:24:20 +00:00
}
2019-01-13 23:37:38 +00:00
return player.node.wsConn.WriteJSON(msg)
2018-08-24 01:24:20 +00:00
}
2018-08-26 02:24:56 +00:00
// GetVolume gets the player's volume level
func (player *Player) GetVolume() int {
return player.vol
}
2019-02-04 00:31:53 +00:00
// Listen will override the listening settings for the user
func (player *Player) Listen(userId string, override bool) error {
msg := listenMessage{
2019-10-13 01:13:23 +00:00
Op: opUserListen,
2019-02-04 00:31:53 +00:00
GuildID: player.guildID,
2019-10-13 01:13:23 +00:00
UserID: userId,
Listen: override,
}
return player.node.wsConn.WriteJSON(msg)
}
// Join will notify the player that a user has joined the channel
func (player *Player) UserJoin(userId string) error {
msg := userMessage{
Op: opUserJoin,
GuildID: player.guildID,
UserID: userId,
}
return player.node.wsConn.WriteJSON(msg)
}
// Leave will notify the player that a user has left the channel
func (player *Player) UserLeave(userId string) error {
msg := userMessage{
Op: opUserLeave,
GuildID: player.guildID,
UserID: userId,
2019-02-04 00:31:53 +00:00
}
return player.node.wsConn.WriteJSON(msg)
}
2018-08-24 01:24:20 +00:00
// Forward will forward a new VOICE_SERVER_UPDATE to a Lavalink node for
// this player.
//
// This should always be used if a VOICE_SERVER_UPDATE is received for
// a guild which already has a player.
//
// To move a player to a new Node, first player.Destroy() it, and then
// create a new player on the new node.
func (player *Player) Forward(sessionID string, event VoiceServerUpdate) error {
2019-10-13 04:04:01 +00:00
player.sessionID = sessionID
2019-01-13 23:37:38 +00:00
msg := voiceUpdateMessage{
2018-08-24 01:24:20 +00:00
Op: opVoiceUpdate,
GuildID: player.guildID,
SessionID: sessionID,
Event: &event,
}
2019-01-13 23:37:38 +00:00
2019-10-13 03:57:59 +00:00
player.lastVoiceServerUpdate = event
2019-01-13 23:37:38 +00:00
return player.node.wsConn.WriteJSON(msg)
2018-08-24 01:24:20 +00:00
}
2019-10-13 03:57:59 +00:00
func (player *Player) ChangeNode(node *Node) error {
player.node = node
if err := player.Forward(player.sessionID, player.lastVoiceServerUpdate); err != nil {
return err
}
2019-10-13 04:04:01 +00:00
2019-10-13 03:57:59 +00:00
return player.PlayAt(player.track, player.position, 0)
}
2018-08-24 01:24:20 +00:00
// Destroy will destroy this player
func (player *Player) Destroy() error {
if player.node != nil && player.node.wsConn != nil {
msg := basicMessage{
Op: opDestroy,
GuildID: player.guildID,
}
// We don't actually care if this goes through, since the node/connection may be invalid anyway.
player.node.wsConn.WriteJSON(msg)
2018-08-24 01:24:20 +00:00
}
2019-01-13 23:37:38 +00:00
player.manager.playersMu.Lock()
defer player.manager.playersMu.Unlock()
2018-11-03 03:29:50 +00:00
delete(player.manager.players, player.guildID)
2018-08-24 01:24:20 +00:00
return nil
}