all repos — disgord @ 9c341e2c3316e8d34a3ce9cc4c99af9fe8fbe934

A simple Discord bot in Go.

src/music/queue.go (view raw)

  1package music
  2
  3import (
  4	"os"
  5
  6	"github.com/birabittoh/disgord/src/mylog"
  7	"github.com/bwmarrin/discordgo"
  8	"github.com/kkdai/youtube/v2"
  9)
 10
 11var logger = mylog.NewLogger(os.Stdin, "music", mylog.DEBUG)
 12
 13type Queue struct {
 14	nowPlaying  *youtube.Video
 15	items       []*youtube.Video
 16	audioStream *Audio
 17	vc          *discordgo.VoiceConnection
 18}
 19
 20// queues stores all guild queues
 21var queues = map[string]*Queue{}
 22
 23// GetOrCreateQueue fetches or creates a new queue for the guild
 24func GetOrCreateQueue(vc *discordgo.VoiceConnection) (q *Queue) {
 25	q, ok := queues[vc.GuildID]
 26	if !ok {
 27		q = &Queue{vc: vc}
 28		queues[vc.GuildID] = q
 29		return
 30	}
 31
 32	if !q.vc.Ready {
 33		q.vc = vc
 34	}
 35	return
 36}
 37
 38// GetQueue returns either nil or the queue for the requested guild
 39func GetQueue(guildID string) *Queue {
 40	q, ok := queues[guildID]
 41	if ok {
 42		return q
 43	}
 44	return nil
 45}
 46
 47// AddVideo adds a new video to the queue
 48func (q *Queue) AddVideo(video *youtube.Video) {
 49	q.items = append(q.items, video)
 50	if q.nowPlaying == nil {
 51		q.PlayNext()
 52	}
 53}
 54
 55// AddVideos adds a list of videos to the queue
 56func (q *Queue) AddVideos(videos []*youtube.Video) {
 57	q.items = append(q.items, videos...)
 58	if q.nowPlaying == nil {
 59		err := q.PlayNext()
 60		if err != nil {
 61			logger.Error(err)
 62		}
 63	}
 64}
 65
 66// PlayNext starts playing the next video in the queue
 67func (q *Queue) PlayNext() (err error) {
 68	if q.audioStream != nil {
 69		q.audioStream.Stop()
 70	}
 71
 72	if len(q.items) == 0 {
 73		q.nowPlaying = nil
 74		return q.vc.Disconnect()
 75	}
 76
 77	q.nowPlaying = q.items[0]
 78	q.items = q.items[1:]
 79
 80	formats := q.nowPlaying.Formats.Type("audio")
 81	if len(formats) == 0 {
 82		logger.Debug("no formats with audio channels available for video " + q.nowPlaying.ID)
 83		return q.PlayNext()
 84	}
 85
 86	q.audioStream, err = NewAudio(formats[0].URL, q.vc)
 87	if err != nil {
 88		return
 89	}
 90
 91	q.audioStream.Monitor(func() { q.PlayNext() })
 92	return
 93}
 94
 95// Stop stops the player and clears the queue
 96func (q *Queue) Stop() error {
 97	q.Clear()
 98	q.nowPlaying = nil
 99
100	if q.audioStream != nil {
101		q.audioStream.Stop()
102	}
103
104	if q.vc != nil {
105		return q.vc.Disconnect()
106	}
107
108	return nil
109}
110
111// Pause pauses the player
112func (q *Queue) Pause() {
113	q.audioStream.Pause()
114}
115
116// Resume resumes the player
117func (q *Queue) Resume() {
118	q.audioStream.Resume()
119}
120
121// Clear clears the video queue
122func (q *Queue) Clear() {
123	q.items = []*youtube.Video{}
124}
125
126// Videos returns all videos in the queue including the now playing one
127func (q *Queue) Videos() []*youtube.Video {
128	if q.nowPlaying != nil {
129		return append([]*youtube.Video{q.nowPlaying}, q.items...)
130	}
131	return q.items
132}
133
134func (q *Queue) VoiceChannelID() string {
135	return q.vc.ChannelID
136}
137
138func (q *Queue) AudioStream() *Audio {
139	return q.audioStream
140}
141
142func (q *Queue) VoiceConnection() *discordgo.VoiceConnection {
143	return q.vc
144}
145
146func (q *Queue) NowPlaying() *youtube.Video {
147	return q.nowPlaying
148}