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}