/
youtubejoinplugin.go
150 lines (120 loc) · 3.52 KB
/
youtubejoinplugin.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package youtubejoinplugin
import (
"encoding/json"
"errors"
"log"
"sync"
"google.golang.org/api/youtube/v3"
"github.com/iopred/bruxism"
)
// YouTubeJoinPlugin is a plugin that monitors channels, and when they go live, will join the service
type YouTubeJoinPlugin struct {
sync.RWMutex
youtube *bruxism.YouTube
ytLiveChannel *bruxism.YTLiveChannel
liveVideoChan chan *youtube.Video
Channels map[string]bool
}
// Help returns a list of help strings that are printed when the user requests them.
func (p *YouTubeJoinPlugin) Help(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message, detailed bool) []string {
return nil
}
// Message handler.
func (p *YouTubeJoinPlugin) Message(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) {
defer bruxism.MessageRecover()
if service.IsChannelOwner(message) && bruxism.MatchesCommand(service, "leave", message) {
channel, ok := p.youtube.ChannelIDForVideoID(message.Channel())
if ok {
p.Unmonitor(channel)
}
}
}
// Load will load plugin state from a byte array.
func (p *YouTubeJoinPlugin) Load(bot *bruxism.Bot, service bruxism.Service, data []byte) error {
if service.Name() != bruxism.YouTubeServiceName {
panic("YouTubeJoin plugin only supports YouTube.")
}
if data != nil {
if err := json.Unmarshal(data, p); err != nil {
log.Println("Error loading data", err)
}
}
p.youtube = service.(*bruxism.YouTube)
for channel, _ := range p.Channels {
p.monitor(channel, false)
}
go p.Run(bot, service)
return nil
}
// Run will poll YouTube for channels going live and send messages.
func (p *YouTubeJoinPlugin) Run(bot *bruxism.Bot, service bruxism.Service) {
p.RLock()
lvc := p.liveVideoChan
p.RUnlock()
for {
v := <-lvc
p.RLock()
if p.Channels[v.Snippet.ChannelId] && v.LiveStreamingDetails != nil && v.LiveStreamingDetails.ActiveLiveChatId != "" {
p.youtube.JoinVideo(v)
}
p.RUnlock()
}
}
func (p *YouTubeJoinPlugin) monitor(channel string, announce bool) error {
if p.youtube == nil {
return nil
}
v, err := p.youtube.GetLiveVideos(channel)
if err == nil {
for _, video := range v {
if announce {
p.youtube.JoinVideoAnnounce(video)
} else {
p.youtube.JoinVideo(video)
}
}
}
return p.ytLiveChannel.Monitor(channel, p.liveVideoChan)
}
func (p *YouTubeJoinPlugin) Monitor(channel string) error {
p.Lock()
defer p.Unlock()
if p.Channels[channel] {
return errors.New("already tracking that channel")
}
p.Channels[channel] = true
return p.monitor(channel, true)
}
func (p *YouTubeJoinPlugin) Unmonitor(channel string) error {
p.Lock()
defer p.Unlock()
if !p.Channels[channel] {
return errors.New("not tracking that channel")
}
delete(p.Channels, channel)
p.youtube.LeaveAll(channel)
return p.ytLiveChannel.Unmonitor(channel, p.liveVideoChan)
}
func (p *YouTubeJoinPlugin) Check(channel string) bool {
return p.Channels[channel]
}
// Save will save plugin state to a byte array.
func (p *YouTubeJoinPlugin) Save() ([]byte, error) {
return json.Marshal(p)
}
// Stats will return the stats for a plugin.
func (p *YouTubeJoinPlugin) Stats(bot *bruxism.Bot, service bruxism.Service, message bruxism.Message) []string {
return nil
}
// Name returns the name of the plugin.
func (p *YouTubeJoinPlugin) Name() string {
return "YouTubeJoin"
}
// New will create a new YouTubeLive plugin.
func New(ytLiveChannel *bruxism.YTLiveChannel) *YouTubeJoinPlugin {
return &YouTubeJoinPlugin{
ytLiveChannel: ytLiveChannel,
liveVideoChan: make(chan *youtube.Video),
Channels: map[string]bool{},
}
}