summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Perry <avaglir@gmail.com>2017-07-29 16:39:57 -0400
committerNathan Perry <avaglir@gmail.com>2017-07-29 16:39:57 -0400
commiteb12be6f8315973bfb3e39c259c00d325889c32c (patch)
treeedf28ba06a7184ff630401ea5ef967524b5fc596
parentb562764a74caa986b99b523dbf78beced6fc1e88 (diff)
refactor works
-rw-r--r--config.example.json6
-rw-r--r--downloader/download_manager.go51
-rw-r--r--downloader/downloader.go79
-rw-r--r--thulani.go32
-rw-r--r--util.go30
-rw-r--r--wav/wav.go45
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),
diff --git a/thulani.go b/thulani.go
index fe69338..d177f64 100644
--- a/thulani.go
+++ b/thulani.go
@@ -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
}
diff --git a/util.go b/util.go
index 8e6de1e..ec6d803 100644
--- a/util.go
+++ b/util.go
@@ -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) {
diff --git a/wav/wav.go b/wav/wav.go
index c505a32..089466e 100644
--- a/wav/wav.go
+++ b/wav/wav.go
@@ -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