package gavalink import ( "strconv" ) // Player is a Lavalink player type Player struct { guildID string sessionID string time int position int paused bool vol int track string manager *Lavalink node *Node lastVoiceServerUpdate VoiceServerUpdate } // GuildID returns this player's Guild ID func (player *Player) GuildID() string { return player.guildID } // 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 start := strconv.Itoa(startTime) end := strconv.Itoa(endTime) msg := playMessage{ Op: opPlay, GuildID: player.guildID, Track: track, StartTime: start, EndTime: end, } return player.node.writeMessage(msg) } // Track returns the player's current track func (player *Player) Track() string { return player.track } // Stop will stop the currently playing track func (player *Player) Stop() error { player.track = "" msg := basicMessage{ Op: opStop, GuildID: player.guildID, } return player.node.writeMessage(msg) } // Pause will pause or resume the player, depending on the pause parameter func (player *Player) Pause(pause bool) error { player.paused = pause msg := pauseMessage{ Op: opPause, GuildID: player.guildID, Pause: pause, } return player.node.writeMessage(msg) } // 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 { msg := seekMessage{ Op: opSeek, GuildID: player.guildID, Position: &position, } return player.node.wsConn.WriteJSON(msg) } // 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 } player.vol = volume msg := volumeMessage{ Op: opVolume, GuildID: player.guildID, Volume: volume, } return player.node.wsConn.WriteJSON(msg) } // GetVolume gets the player's volume level func (player *Player) GetVolume() int { return player.vol } // Listen will override the listening settings for the user func (player *Player) Listen(userId string, override bool) error { msg := listenMessage{ Op: opUserListen, GuildID: player.guildID, 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, } return player.node.wsConn.WriteJSON(msg) } // 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 { player.sessionID = sessionID msg := voiceUpdateMessage{ Op: opVoiceUpdate, GuildID: player.guildID, SessionID: sessionID, Event: &event, } player.lastVoiceServerUpdate = event return player.node.wsConn.WriteJSON(msg) } func (player *Player) ChangeNode(node *Node) error { player.node = node if err := player.Forward(player.sessionID, player.lastVoiceServerUpdate); err != nil { return err } return player.PlayAt(player.track, player.position, 0) } // 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) } player.manager.playersMu.Lock() defer player.manager.playersMu.Unlock() delete(player.manager.players, player.guildID) return nil }