diff options
| author | Nathan Perry <avaglir@gmail.com> | 2017-07-29 16:39:57 -0400 |
|---|---|---|
| committer | Nathan Perry <avaglir@gmail.com> | 2017-07-29 16:39:57 -0400 |
| commit | eb12be6f8315973bfb3e39c259c00d325889c32c (patch) | |
| tree | edf28ba06a7184ff630401ea5ef967524b5fc596 | |
| parent | b562764a74caa986b99b523dbf78beced6fc1e88 (diff) | |
refactor works
| -rw-r--r-- | config.example.json | 6 | ||||
| -rw-r--r-- | downloader/download_manager.go | 51 | ||||
| -rw-r--r-- | downloader/downloader.go | 79 | ||||
| -rw-r--r-- | thulani.go | 32 | ||||
| -rw-r--r-- | util.go | 30 | ||||
| -rw-r--r-- | wav/wav.go | 45 |
6 files changed, 105 insertions, 138 deletions
diff --git a/config.example.json b/config.example.json index 2b923b7..5387493 100644 --- a/config.example.json +++ b/config.example.json @@ -1,10 +1,10 @@ { "trigger": "bot", "queue_size": 5, - "admin": 12345, + "admin_user_id": 12345, "op_role": "bot-op", - "server": "example server", - "voice_channel": "General", + "guild_id": 12345, + "voice_channel_id": 12345, "token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "client_id": "abcd", "client_secret": "efgh" diff --git a/downloader/download_manager.go b/downloader/download_manager.go index 481fc4f..d6f3fa0 100644 --- a/downloader/download_manager.go +++ b/downloader/download_manager.go @@ -24,7 +24,9 @@ const ( type DownloadManager struct { conn *discordgo.VoiceConnection session *discordgo.Session - dls chan *Downloader + guildID string + voiceID string + dls chan *downloader PlayState chan DlMessage playStateChan chan DlMessage @@ -36,12 +38,14 @@ type DownloadManager struct { const proxyBufSize = 512 -func NewManager(s *discordgo.Session) *DownloadManager { +func NewManager(s *discordgo.Session, guildID string, voiceChanID string) *DownloadManager { dm := &DownloadManager{ session: s, - dls: make(chan *Downloader), + dls: make(chan *downloader), connUpdate: make(chan connUpdate, 1), PlayState: make(chan DlMessage), + guildID: guildID, + voiceID: voiceChanID, playStateChan: make(chan DlMessage), @@ -103,39 +107,54 @@ loop: if attachState == attach { select { - case upd := <-m.connUpdate: - attachState = upd + case attachState = <-m.connUpdate: case m.conn.OpusSend <- <-m.proxyChan: } } else { select { - case upd := <-m.connUpdate: - attachState = upd + case attachState = <-m.connUpdate: } } } } func (m *DownloadManager) playFromQueue() { -loop: + //timer := time.After(5*time.Second) + for { select { case dl := <-m.dls: - dl.SendOn(m.proxyChan) - select { - case <-dl.done: - continue loop - - case upd:=<-m.playStateChan: + if m.conn == nil { + ch, err := m.session.ChannelVoiceJoin(m.guildID, m.voiceID, false, false) + if err != nil { + log.Errorf("unable to connect to the voice channel: %q", err) + time.Sleep(1 * time.Second) + break + } + m.conn = ch + m.connUpdate <- attach } + m.conn.Speaking(true) + // todo: figure out how to do disconnection checking + dl.SendOn(m.proxyChan) + <-dl.done + m.conn.Speaking(false) + //case <-timer: + // if m.conn != nil { + // m.connUpdate<-detach + // if err := m.conn.Disconnect(); err != nil { + // log.Errorf("disconnecting from voice connection: %q", err) + // } + // m.conn = nil + // } } } } -func (m *DownloadManager) Enqueue(url string, startTime, endTime time.Duration) error { - dl, err := NewDownload(url, startTime, endTime) +func (m *DownloadManager) Enqueue(url string, startTime, duration time.Duration) error { + dl, err := newDownload(url, startTime, duration) if err != nil { return err } diff --git a/downloader/downloader.go b/downloader/downloader.go index cab561b..c9fc864 100644 --- a/downloader/downloader.go +++ b/downloader/downloader.go @@ -11,18 +11,17 @@ import ( "github.com/mammothbane/thulani-go/wav" ) -// Downloader handles a download for a particular song. -type Downloader struct { +// downloader handles a download for a particular song. +type downloader struct { Url string Start time.Duration Duration time.Duration End time.Duration - pause chan wav.State - once sync.Once - done chan struct{} - pb chan *wavBundle + once sync.Once + done chan struct{} + pb chan *wavBundle info videoInfo } @@ -30,7 +29,7 @@ type Downloader struct { const clipTime = 10 * time.Second const preloadCount = 5 -func NewDownload(url string, startTime, dur time.Duration) (*Downloader, error) { +func newDownload(url string, startTime, dur time.Duration) (*downloader, error) { vInfo, err := info(url) if err != nil { return nil, err @@ -40,17 +39,16 @@ func NewDownload(url string, startTime, dur time.Duration) (*Downloader, error) dur = vInfo.Duration - startTime } - dl := &Downloader{ + dl := &downloader{ Url: url, Start: startTime, Duration: dur, End: startTime + dur, - pause: make(chan wav.State), - done: make(chan struct{}, 1), - pb: make(chan *wavBundle, preloadCount), - info: *vInfo, + done: make(chan struct{}, 1), + pb: make(chan *wavBundle, preloadCount), + info: *vInfo, } go dl.schedule() @@ -58,21 +56,13 @@ func NewDownload(url string, startTime, dur time.Duration) (*Downloader, error) return dl, nil } -func (d *Downloader) Stop() { +func (d *downloader) Stop() { d.once.Do(func() { close(d.done) }) } -func (d *Downloader) Resume() { - d.pause <- wav.Resume -} - -func (d *Downloader) Pause() { - d.pause <- wav.Pause -} - -func (d *Downloader) SendOn(ch chan<- []byte) <-chan struct{} { +func (d *downloader) SendOn(ch chan<- []byte) <-chan struct{} { out := make(chan struct{}, 1) go func() { @@ -87,9 +77,6 @@ func (d *Downloader) SendOn(ch chan<- []byte) <-chan struct{} { case <-wavB.wav.Done: break - - case elem := <-d.pause: - wavB.wav.PlayState <- elem } } }() @@ -97,34 +84,32 @@ func (d *Downloader) SendOn(ch chan<- []byte) <-chan struct{} { return out } -func (d *Downloader) schedule() { - go func() { - defer close(d.pb) - for i := 0; ; i++ { - clipStart := time.Duration(i)*clipTime + d.Start - clipEnd := time.Duration(i+1)*clipTime + d.Start - - if clipStart >= d.End { - return - } +func (d *downloader) schedule() { + defer close(d.pb) + for i := 0; ; i++ { + clipStart := time.Duration(i)*clipTime + d.Start + clipEnd := time.Duration(i+1)*clipTime + d.Start - dur := clipTime - if clipEnd > d.End { - dur = d.End - clipStart - } + if clipStart >= d.End { + return + } - wavb, err := d.download(clipStart, dur) - if err != nil { - log.Errorf("error setting up download: %q", err) - return - } + dur := clipTime + if clipEnd > d.End { + dur = d.End - clipStart + } - d.pb <- wavb + wavb, err := d.downloadSegment(clipStart, dur) + if err != nil { + log.Errorf("error setting up download: %q", err) + return } - }() + + d.pb <- wavb + } } -func (d *Downloader) download(startTime, duration time.Duration) (*wavBundle, error) { +func (d *downloader) downloadSegment(startTime, duration time.Duration) (*wavBundle, error) { startSecond := int(startTime.Seconds()) args := []string{ "-ss", strconv.Itoa(startSecond), @@ -16,6 +16,7 @@ import ( var config *Config var regex *regexp.Regexp +var manager *downloader.DownloadManager func Run(conf *Config) { //defer profile.Start(profile.ProfilePath("."), profile.BlockProfile).Stop() @@ -45,7 +46,7 @@ func onReady(s *discordgo.Session, m *discordgo.Ready) { joined := false for _, v := range m.Guilds { - if v.Name == config.Server { + if v.ID != config.GuildStr() { joined = true break } @@ -54,6 +55,7 @@ func onReady(s *discordgo.Session, m *discordgo.Ready) { if !joined { log.Warningf("Server in config not available! Click here to enable thulani on your server: %v", oauthUrl()) } + manager = downloader.NewManager(s, config.GuildStr(), config.VoiceChannelStr()) } func onGuildCreate(s *discordgo.Session, m *discordgo.GuildCreate) { @@ -104,29 +106,9 @@ func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) { return } - for _, v := range ctx.Guild.Channels { - if v.Type == "voice" && v.Name == "General" { - conn, err := ctx.ChannelVoiceJoin(ctx.Guild.ID, v.ID, false, false) - if err != nil { - log.Errorf("unable to join voice channel: %q", err) - break - } - - conn.Speaking(true) - go func(conn *discordgo.VoiceConnection) { - defer conn.Speaking(false) - - dl, err := downloader.NewDownload("https://www.youtube.com/watch?v=_K13GJkGvDw", time.Duration(rand.Intn(10*60))*time.Second, 5*time.Second) - if err != nil { - log.Errorf("unable to download video: %q", err) - return - } - - <-dl.SendOn(conn.OpusSend) - }(conn) - - break - } + if err := manager.Enqueue("https://www.youtube.com/watch?v=_K13GJkGvDw", time.Duration(rand.Intn(10*60))*time.Second, 5*time.Second); err != nil { + log.Errorf("unable to enqueue video: %q", err) + return } for _, v := range extraMemes { @@ -143,7 +125,7 @@ func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) { return } - if ctx.Guild.Name != config.Server { + if ctx.Guild.ID != config.GuildStr() { log.Infof("Wrong guild. Ignoring.") return } @@ -28,15 +28,27 @@ commands: var log = logging.MustGetLogger("thulani") type Config struct { - Trigger string `json:"trigger"` - QueueSize uint `json:"queue_size"` - Admin uint `json:"admin"` - OpRole string `json:"op_role"` - Server string `json:"server"` - VoiceChannel string `json:"voice_channel"` - Token string `json:"token"` - ClientID string `json:"client_id"` - ClientSecret string `json:"client_secret"` + Trigger string `json:"trigger"` + QueueSize uint `json:"queue_size"` + AdminID uint `json:"admin_id"` + OpRole string `json:"op_role"` + GuildID uint `json:"guild_id"` + VoiceChannelID uint `json:"voice_channel_id"` + Token string `json:"token"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` +} + +func (c *Config) GuildStr() string { + return strconv.Itoa(int(c.GuildID)) +} + +func (c *Config) VoiceChannelStr() string { + return strconv.Itoa(int(c.VoiceChannelID)) +} + +func (c *Config) AdminStr() string { + return strconv.Itoa(int(c.AdminID)) } func handle(err error) { @@ -12,13 +12,6 @@ import ( "layeh.com/gopus" ) -type State int - -const ( - Pause State = iota - Resume -) - // number of individual samples per channel per batch const samplesPerChannelPerBatch = 1920 @@ -29,9 +22,6 @@ type Wav struct { enc *gopus.Encoder wav *C.drwav - PlayState chan State - curState State - once sync.Once Done <-chan struct{} done chan<- struct{} @@ -67,9 +57,6 @@ func New(filename string) (*Wav, error) { enc: enc, wav: wav, - PlayState: make(chan State), - curState: Resume, - done: done, Done: done, }, nil @@ -101,31 +88,7 @@ func (w *Wav) Start(ch chan<- []byte) { readIdx := 0 - inner: for { - // check to see if we should die or pause - if w.curState == Pause { // if paused wait to die or get resumed - select { - case st := <-w.PlayState: - w.curState = st - continue inner - - case <-w.Done: - return - } - - } else { - select { - case st := <-w.PlayState: - w.curState = st - continue inner - - case <-w.Done: - return - default: - } - } - batchSamplesToFill := samplesPerBatch - idx readSamplesRemaining := int(readSamples) - readIdx @@ -143,7 +106,13 @@ func (w *Wav) Start(ch chan<- []byte) { log.Errorf("error encoding pcm: %q", err) continue } - ch <- b + + select { + case <-w.Done: + return + case ch <- b: + + } } batchSamplesToFill := samplesPerBatch - idx |
