Created
July 20, 2018 04:54
-
-
Save lon9/42e342893ffa82ebc7688a86a12c4f11 to your computer and use it in GitHub Desktop.
Discord voice bot
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"os" | |
"os/signal" | |
"strings" | |
"sync" | |
"syscall" | |
"time" | |
"github.com/bwmarrin/discordgo" | |
) | |
const ( | |
MaxQueueSize int = 6 | |
) | |
var ( | |
queues = make(map[string][]*PlayRequest) | |
dg *discordgo.Session | |
err error | |
m sync.Mutex | |
) | |
type PlayRequest struct { | |
ChannelID string | |
GuildID string | |
Sound uint | |
} | |
func main() { | |
token := os.Getenv("BOT_TOKEN") | |
dg, err = discordgo.New("Bot " + token) | |
if err != nil { | |
panic(err) | |
} | |
dg.LogLevel = discordgo.LogDebug | |
dg.AddHandler(messageCreate) | |
err = dg.Open() | |
if err != nil { | |
panic(err) | |
} | |
fmt.Println("Airhorn is now running. Press CTRL-C to exit.") | |
sc := make(chan os.Signal, 1) | |
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) | |
<-sc | |
dg.Close() | |
} | |
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { | |
if m.Author.ID == s.State.User.ID { | |
return | |
} | |
if strings.HasPrefix(m.Content, "!join") { | |
c, err := s.State.Channel(m.ChannelID) | |
if err != nil { | |
// Could not find channel. | |
return | |
} | |
g, err := s.State.Guild(c.GuildID) | |
if err != nil { | |
// Could not find guild. | |
return | |
} | |
for _, vs := range g.VoiceStates { | |
if vs.UserID == m.Author.ID { | |
requestPlaySound(g.ID, vs.ChannelID, 1) | |
return | |
} | |
} | |
} | |
} | |
func requestPlaySound(guildID, channelID string, soundID uint) { | |
item := &PlayRequest{ | |
ChannelID: channelID, | |
GuildID: guildID, | |
Sound: soundID, | |
} | |
// If there is a queue setup there is alaso a player running, so just add it to the queue then | |
m.Lock() | |
if queue, ok := queues[guildID]; ok { | |
if len(queue) < MaxQueueSize { | |
queues[guildID] = append(queue, item) | |
} | |
} else { | |
queues[guildID] = []*PlayRequest{item} | |
go runPlayer(guildID) | |
} | |
m.Unlock() | |
} | |
func runPlayer(guildID string) { | |
var lastChannel string | |
var vc *discordgo.VoiceConnection | |
for { | |
m.Lock() | |
var item *PlayRequest | |
// Get the next item in the queue or quit life | |
if queue, ok := queues[guildID]; ok && len(queue) > 0 { | |
item = queue[0] | |
queues[guildID] = queue[1:] | |
} else { | |
break | |
} | |
m.Unlock() | |
// Should probably to changechannel but eh.. | |
if lastChannel != item.ChannelID && vc != nil { | |
vc.Disconnect() | |
vc = nil | |
} | |
var err error | |
vc, err = playSound(vc, dg, item) | |
if err != nil { | |
log.Println(err) | |
} | |
lastChannel = item.ChannelID | |
} | |
if vc != nil { | |
vc.Disconnect() | |
} | |
// When we break out, playqueuemutex is locked | |
delete(queues, guildID) | |
m.Unlock() | |
} | |
func playSound(vc *discordgo.VoiceConnection, session *discordgo.Session, item *PlayRequest) (*discordgo.VoiceConnection, error) { | |
// Either use the passed voice connection, or create a new one | |
if vc == nil || !vc.Ready { | |
vc, err = session.ChannelVoiceJoin(item.GuildID, item.ChannelID, false, true) | |
if err != nil { | |
return nil, err | |
} | |
vc.Speaking(true) | |
} | |
// Sending voice mock | |
time.Sleep(time.Second) | |
return vc, nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment