summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--commands.go39
-rw-r--r--config.example.json2
-rw-r--r--downloader/download_manager.go82
-rw-r--r--downloader/downloader.go29
-rw-r--r--thulani.go24
-rw-r--r--util.go6
-rw-r--r--wav/wav.go6
7 files changed, 114 insertions, 74 deletions
diff --git a/commands.go b/commands.go
index 0157adb..428e87a 100644
--- a/commands.go
+++ b/commands.go
@@ -4,40 +4,35 @@ import "github.com/mammothbane/thulani-go/downloader"
var cmdMap = map[string]func(*messageCtx){
"help": printHelp,
- "skip": commandNotImplemented,
- "pause": commandNotImplemented,
- "resume": commandNotImplemented,
- "sudoku": commandNotImplemented,
- "die": commandNotImplemented,
- "list": commandNotImplemented,
- "queue": commandNotImplemented,
+ "skip": skip,
+ "pause": pause,
+ "resume": resume,
+ "sudoku": stop,
+ "die": stop,
+ "list": list,
+ "queue": list,
}
func printHelp(c *messageCtx) {
c.sendMessage(help, c.Tts)
}
-func commandNotImplemented(c *messageCtx) {
- log.Errorf("%q not implemented", c.Command)
- c.sendMessage("not implemented", c.Tts)
+func skip(_ *messageCtx) {
+ manager.PlayState <- downloader.Play
}
-func skip(c *messageCtx) {
- log.Error("skip not implemented")
+func resume(_ *messageCtx) {
+ manager.PlayState <- downloader.Play
}
-func resume(c *messageCtx) {
- log.Error("skip not implemented")
+func pause(_ *messageCtx) {
+ manager.PlayState <- downloader.Pause
}
-func pause(c *messageCtx) {
- log.Error("skip not implemented")
+func stop(_ *messageCtx) {
+ manager.PlayState <- downloader.Clear
}
-func stop(c *messageCtx) {
- log.Error("skip not implemented")
-}
-
-func list(c *messageCtx) {
- log.Error("skip not implemented")
+func list(_ *messageCtx) {
+ log.Error("list not implemented")
}
diff --git a/config.example.json b/config.example.json
index 5387493..e4a7d79 100644
--- a/config.example.json
+++ b/config.example.json
@@ -2,7 +2,7 @@
"trigger": "bot",
"queue_size": 5,
"admin_user_id": 12345,
- "op_role": "bot-op",
+ "op_role_id": 12345,
"guild_id": 12345,
"voice_channel_id": 12345,
"token": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
diff --git a/downloader/download_manager.go b/downloader/download_manager.go
index c0ceecb..16054ae 100644
--- a/downloader/download_manager.go
+++ b/downloader/download_manager.go
@@ -12,6 +12,7 @@ const (
Clear DlMessage = iota
Pause
Play
+ Skip
)
type playBundle struct {
@@ -43,50 +44,61 @@ func NewManager(s *discordgo.Session, guildID string, voiceChanID string) *Downl
}
func (m *DownloadManager) playFromQueue() {
- for dl := range m.dls {
- conn, 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
- }
+ for {
+ select {
+ case <-m.PlayState: // ignore play state updates while not playing anything
+ case dl := <-m.dls:
+ conn, 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
+ }
- out, _ := dl.Start()
+ m.session.UpdateStatus(0, dl.info.Url.Host)
+ out := dl.Start()
- playState := Play
- conn.Speaking(true)
+ playState := Play
+ conn.Speaking(true)
- cleanup := func() {
- conn.Speaking(false)
- conn.Disconnect()
- }
+ cleanup := func() {
+ conn.Speaking(false)
+ conn.Disconnect()
+ m.session.UpdateStatus(0, "literally nothing")
+ }
- inner:
- for {
- switch playState {
- case Clear:
- for {
- select {
- case <-m.PlayState:
- default:
- }
- }
- break inner
- case Pause:
- playState = <-m.PlayState
- case Play:
- select { // first check if we have a state update message coming in
- case playState = <-m.PlayState:
- case elem, ok := <-out:
- if !ok {
- break inner
+ inner:
+ for {
+ switch playState {
+ case Clear:
+ dl.Stop()
+ for {
+ select {
+ case dl := <-m.dls:
+ dl.Stop()
+ dl.Start() // this is a hacky way of ensuring all the wavs are closed and cleaned up
+ default:
+ }
}
+ break inner
+ case Skip:
+ break inner
+ case Pause:
+ playState = <-m.PlayState
+ case Play:
+ select { // first check if we have a state update message coming in
+ case playState = <-m.PlayState:
+ case elem, ok := <-out:
+ if !ok {
+ break inner
+ }
- conn.OpusSend <- elem
+ conn.OpusSend <- elem
+ }
}
}
+ cleanup()
}
- cleanup()
}
}
diff --git a/downloader/downloader.go b/downloader/downloader.go
index 6abe7f0..b7645da 100644
--- a/downloader/downloader.go
+++ b/downloader/downloader.go
@@ -62,13 +62,21 @@ func (d *downloader) Stop() {
})
}
-func (d *downloader) Start() (<-chan []byte, <-chan struct{}) {
+func (d *downloader) Start() <-chan []byte {
out := make(chan []byte, 1024)
- done := make(chan struct{}, 1)
go func() {
- defer close(done)
defer close(out)
+ select {
+ case <-d.done:
+ for wavB := range d.pb {
+ wavB.wav.Stop()
+ wavB.cleanup()
+ }
+ return
+ default:
+ }
+
for wavB := range d.pb {
wavB.wav.Start(out)
@@ -78,17 +86,22 @@ func (d *downloader) Start() (<-chan []byte, <-chan struct{}) {
wavB.cleanup()
case <-wavB.wav.Done:
- break
}
}
}()
- return out, done
+ return out
}
func (d *downloader) schedule() {
defer close(d.pb)
for i := 0; ; i++ {
+ select {
+ case <-d.done:
+ return
+ default:
+ }
+
clipStart := time.Duration(i)*clipTime + d.StartTime
clipEnd := time.Duration(i+1)*clipTime + d.StartTime
@@ -107,7 +120,11 @@ func (d *downloader) schedule() {
return
}
- d.pb <- wavb
+ select {
+ case d.pb <- wavb:
+ case <-d.done:
+ return
+ }
}
}
diff --git a/thulani.go b/thulani.go
index d4a222d..1acde39 100644
--- a/thulani.go
+++ b/thulani.go
@@ -68,12 +68,14 @@ func onGuildCreate(s *discordgo.Session, m *discordgo.GuildCreate) {
perms := 0
+ //log.Debugf("listing roles for %v", m.Name)
for _, role := range m.Roles {
+ //log.Debugf("%q (%v)", role.Name, role.ID)
for _, mRole := range member.Roles {
if role.ID == mRole {
perms |= role.Permissions
- log.Infof("discovered role: %v (%v)", role.Name, role.ID)
+ log.Infof("discovered own role: %v (%v)", role.Name, role.ID)
}
}
}
@@ -125,15 +127,20 @@ func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
fn, ok := cmdMap[strings.ToLower(ctx.Command)]
if ok {
- authorized := false
+ log.Debugf("message matched a known command: %q", strings.ToLower(ctx.Command))
- for _, role := range ctx.Guild.Roles {
- for _, v := range ctx.Member.Roles {
- if v != role.Name {
- continue
- }
+ authorized := ctx.Author.ID == config.AdminStr()
+
+ if !authorized {
+ authorMember, err := ctx.GuildMember(ctx.Guild.ID, ctx.Author.ID)
+ if err != nil {
+ log.Errorf("unable to get guild member for id %q", ctx.Author.Username)
+ ctx.sendMessage("who the fuck are you?", true)
+ return
+ }
- if role.Name == config.OpRole {
+ for _, v := range authorMember.Roles {
+ if v == config.OpRoleStr() {
authorized = true
}
}
@@ -145,6 +152,7 @@ func onMessage(s *discordgo.Session, m *discordgo.MessageCreate) {
return
}
+ log.Debugf("user was authorized for %q. executing.", strings.ToLower(ctx.Command))
fn(ctx)
return
}
diff --git a/util.go b/util.go
index ec6d803..b4a806d 100644
--- a/util.go
+++ b/util.go
@@ -31,7 +31,7 @@ type Config struct {
Trigger string `json:"trigger"`
QueueSize uint `json:"queue_size"`
AdminID uint `json:"admin_id"`
- OpRole string `json:"op_role"`
+ OpRoleID uint `json:"op_role_id"`
GuildID uint `json:"guild_id"`
VoiceChannelID uint `json:"voice_channel_id"`
Token string `json:"token"`
@@ -51,6 +51,10 @@ func (c *Config) AdminStr() string {
return strconv.Itoa(int(c.AdminID))
}
+func (c *Config) OpRoleStr() string {
+ return strconv.Itoa(int(c.OpRoleID))
+}
+
func handle(err error) {
if err != nil {
log.Fatal(err)
diff --git a/wav/wav.go b/wav/wav.go
index 089466e..acd7841 100644
--- a/wav/wav.go
+++ b/wav/wav.go
@@ -110,8 +110,12 @@ func (w *Wav) Start(ch chan<- []byte) {
select {
case <-w.Done:
return
+ default:
+ }
+ select {
+ case <-w.Done:
+ return
case ch <- b:
-
}
}