all repos — disgord @ 788b481ce887db1dccfc707bc18e508405fdd809

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) *Queue {
 25	q, ok := queues[vc.GuildID]
 26	if !ok {
 27		q = &Queue{vc: vc}
 28		queues[vc.GuildID] = q
 29	}
 30
 31	return q
 32}
 33
 34// GetQueue returns either nil or the queue for the requested guild
 35func GetQueue(guildID string) *Queue {
 36	q, ok := queues[guildID]
 37	if ok {
 38		return q
 39	}
 40	return nil
 41}
 42
 43// AddVideo adds a new video to the queue
 44func (q *Queue) AddVideo(video *youtube.Video) {
 45	q.items = append(q.items, video)
 46	if q.nowPlaying == nil {
 47		q.PlayNext()
 48	}
 49}
 50
 51// AddVideos adds a list of videos to the queue
 52func (q *Queue) AddVideos(videos []*youtube.Video) {
 53	q.items = append(q.items, videos...)
 54	if q.nowPlaying == nil {
 55		q.PlayNext()
 56	}
 57}
 58
 59// PlayNext starts playing the next video in the queue
 60func (q *Queue) PlayNext() (err error) {
 61	if q.audioStream != nil {
 62		q.audioStream.Stop()
 63	}
 64
 65	if len(q.items) == 0 {
 66		q.nowPlaying = nil
 67		return q.vc.Disconnect()
 68	}
 69
 70	q.nowPlaying = q.items[0]
 71	q.items = q.items[1:]
 72
 73	formats := q.nowPlaying.Formats.WithAudioChannels().Type("audio/webm")
 74	if len(formats) == 0 {
 75		logger.Debug("no formats with audio channels available for video " + q.nowPlaying.ID)
 76		return q.PlayNext()
 77	}
 78
 79	q.audioStream, err = NewAudio(formats[0].URL, q.vc)
 80	if err != nil {
 81		return
 82	}
 83
 84	q.audioStream.Monitor(func() { q.PlayNext() })
 85	return
 86}
 87
 88// Stop stops the player and clears the queue
 89func (q *Queue) Stop() error {
 90	q.Clear()
 91	q.nowPlaying = nil
 92	q.audioStream.Stop()
 93	return q.vc.Disconnect()
 94}
 95
 96// Pause pauses the player
 97func (q *Queue) Pause() {
 98	q.audioStream.Pause()
 99}
100
101// Resume resumes the player
102func (q *Queue) Resume() {
103	q.audioStream.Resume()
104}
105
106// Clear clears the video queue
107func (q *Queue) Clear() {
108	q.items = []*youtube.Video{}
109}
110
111// Videos returns all videos in the queue including the now playing one
112func (q *Queue) Videos() []*youtube.Video {
113	if q.nowPlaying != nil {
114		return append([]*youtube.Video{q.nowPlaying}, q.items...)
115	}
116	return q.items
117}
118
119func (q *Queue) VoiceChannelID() string {
120	return q.vc.ChannelID
121}