gavalink/model.go

198 lines
4.3 KiB
Go

package gavalink
import (
"encoding/json"
"io"
"net/http"
"os"
"time"
)
const (
// TrackLoaded is a Tracks Type for a succesful single track load
TrackLoaded = "TRACK_LOADED"
// PlaylistLoaded is a Tracks Type for a succseful playlist load
PlaylistLoaded = "PLAYLIST_LOADED"
// SearchResult is a Tracks Type for a search containing many tracks
SearchResult = "SEARCH_RESULT"
// NoMatches is a Tracks Type for a query yielding no matches
NoMatches = "NO_MATCHES"
// LoadFailed is a Tracks Type for an internal Lavalink error
LoadFailed = "LOAD_FAILED"
)
// Tracks contains data for a Lavalink Tracks response
type Tracks struct {
// Type contains the type of response
//
// This will be one of TrackLoaded, PlaylistLoaded, SearchResult,
// NoMatches, or LoadFailed
Type string `json:"loadType"`
PlaylistInfo *PlaylistInfo `json:"playlistInfo"`
Tracks []*Track `json:"tracks"`
}
// PlaylistInfo contains information about a loaded playlist
type PlaylistInfo struct {
// Name is the friendly of the playlist
Name string `json:"name"`
// SelectedTrack is the index of the track that loaded the playlist,
// if one is present.
SelectedTrack int `json:"selectedTrack"`
}
// Track contains information about a loaded track
type Track struct {
// Data contains the base64 encoded Lavaplayer track
Data string `json:"track"`
Info *TrackInfo `json:"info"`
}
// TrackInfo contains more data about a loaded track
type TrackInfo struct {
Identifier string `json:"identifier"`
Title string `json:"title"`
Author string `json:"author"`
URI string `json:"uri"`
Seekable bool `json:"isSeekable"`
Stream bool `json:"isStream"`
Length time.Duration `json:"length"`
Position int `json:"position"`
}
func (t *TrackInfo) MarshalJSON() ([]byte, error) {
type Alias TrackInfo
return json.Marshal(&struct {
Length int64 `json:"length"`
*Alias
}{
Length: int64(t.Length / time.Millisecond),
Alias: (*Alias)(t),
})
}
func (t *TrackInfo) UnmarshalJSON(data []byte) error {
type Alias TrackInfo
aux := &struct {
Length int64 `json:"length"`
*Alias
}{
Alias: (*Alias)(t),
}
if err := json.Unmarshal(data, &aux); err != nil {
return err
}
t.Length = time.Duration(aux.Length) * time.Millisecond
return nil
}
const (
opVoiceUpdate = "voiceUpdate"
opUserJoin = "userJoin"
opUserLeave = "userLeave"
opUserListen = "userListen"
opPlay = "play"
opStop = "stop"
opPause = "pause"
opSeek = "seek"
opVolume = "volume"
opDestroy = "destroy"
opPlayerUpdate = "playerUpdate"
opEvent = "event"
opStats = "stats"
eventTrackStart = "TrackStartEvent"
eventTrackEnd = "TrackEndEvent"
eventTrackException = "TrackExceptionEvent"
eventTrackStuck = "TrackStuckEvent"
eventVoiceProcessed = "VoiceProcessedEvent"
)
// Exception is a message from the Lavalink server
type Exception struct {
Message string
Severity string
Cause string
}
// VoiceServerUpdate is a raw Discord VOICE_SERVER_UPDATE event
type VoiceServerUpdate struct {
GuildID string `json:"guild_id"`
Endpoint string `json:"endpoint"`
Token string `json:"token"`
}
// VoiceProcessingData is an event containing methods to easily download captured voice data
type VoiceProcessingData struct {
io.ReadCloser
node *Node
UserID string
URL string
File string
res *http.Response
}
func (v *VoiceProcessingData) open() error {
req, err := http.NewRequest(http.MethodGet, v.URL, nil)
req.Header.Set("Authorization", v.node.config.Password)
res, err := v.node.client.Do(req)
if err != nil {
return err
}
v.res = res
return nil
}
func (v *VoiceProcessingData) Close() error {
if v.res != nil {
return v.res.Body.Close()
}
return nil
}
func (v *VoiceProcessingData) Read(buf []byte) (n int, err error) {
if v.res == nil {
err = v.open()
if err != nil {
return
}
}
n, err = v.res.Body.Read(buf)
return
}
func (v *VoiceProcessingData) SaveTo(file string) error {
f, err := os.Create(file)
if err != nil {
return err
}
defer f.Close()
if v.res == nil {
err = v.open()
if err != nil {
return err
}
}
defer v.res.Body.Close()
_, err = io.Copy(f, v.res.Body)
return err
}