forked from bwmarrin/discordgo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request bwmarrin#181 from iopred/develop
Add a new example that acts like airhorn.solutions
- Loading branch information
Showing
4 changed files
with
228 additions
and
0 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<img align="right" src="http://bwmarrin.github.io/discordgo/img/discordgo.png"> | ||
Airhorn Example | ||
==== | ||
|
||
This example demonstrates how to utilize DiscordGo to listen to an !airhorn | ||
command in a channel and play a sound to that users current voice channel. | ||
|
||
### Build | ||
|
||
This assumes you already have a working Go environment setup and that | ||
DiscordGo is correctly installed on your system. | ||
|
||
```sh | ||
go install github.com/bwmarrin/discordgo/examples/airhorn | ||
cd $GOPATH/bin | ||
cp ../src/github.com/bwmarrin/discordgo/examples/airhorn/airhorn.dca . | ||
``` | ||
|
||
### Usage | ||
|
||
``` | ||
Usage of ./airhorn: | ||
-t string | ||
Account Token | ||
``` | ||
|
||
The below example shows how to start the bot. | ||
|
||
```sh | ||
./airhorn -t <bot token> | ||
``` | ||
|
||
### Creating sounds | ||
|
||
Airhorn bot uses DCA files that are pre-computed files that are easy to send to Discord. | ||
|
||
If you would like to create your own DCA files, please use [https://github.com/bwmarrin/dca/tree/master/cmd/dca](DCA). | ||
|
||
```sh | ||
./dca -i <input wav file> -raw > <output file> | ||
``` |
Binary file not shown.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/binary" | ||
"flag" | ||
"fmt" | ||
"io" | ||
"os" | ||
"strings" | ||
"time" | ||
|
||
"github.com/bwmarrin/discordgo" | ||
) | ||
|
||
func init() { | ||
flag.StringVar(&token, "t", "", "Account Token") | ||
flag.Parse() | ||
} | ||
|
||
var token string | ||
var buffer = make([][]byte, 0) | ||
|
||
func main() { | ||
if token == "" { | ||
fmt.Println("No token provided. Please run: airhorn -t <bot token>") | ||
return | ||
} | ||
|
||
// Load the sound file. | ||
err := loadSound() | ||
if err != nil { | ||
fmt.Println("Error loading sound: ", err) | ||
fmt.Println("Please copy $GOPATH/src/github.com/bwmarrin/examples/airhorn/airhorn.dca to this directory.") | ||
return | ||
} | ||
|
||
// Create a new Discord session using the provided token. | ||
dg, err := discordgo.New(token) | ||
if err != nil { | ||
fmt.Println("Error creating Discord session: ", err) | ||
return | ||
} | ||
|
||
// Register ready as a callback for the ready events. | ||
dg.AddHandler(ready) | ||
|
||
// Register messageCreate as a callback for the messageCreate events. | ||
dg.AddHandler(messageCreate) | ||
|
||
// Register guildCreate as a callback for the guildCreate events. | ||
dg.AddHandler(guildCreate) | ||
|
||
// Open the websocket and begin listening. | ||
err = dg.Open() | ||
if err != nil { | ||
fmt.Println("Error opening Discord session: ", err) | ||
} | ||
|
||
fmt.Println("Airhorn is now running. Press CTRL-C to exit.") | ||
// Simple way to keep program running until CTRL-C is pressed. | ||
<-make(chan struct{}) | ||
return | ||
} | ||
|
||
func ready(s *discordgo.Session, event *discordgo.Ready) { | ||
// Set the playing status. | ||
s.UpdateStatus(0, "!airhorn") | ||
} | ||
|
||
// This function will be called (due to AddHandler above) every time a new | ||
// message is created on any channel that the autenticated bot has access to. | ||
func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) { | ||
if strings.HasPrefix(m.Content, "!airhorn") { | ||
// Find the channel that the message came from. | ||
c, err := s.State.Channel(m.ChannelID) | ||
if err != nil { | ||
// Could not find channel. | ||
return | ||
} | ||
|
||
// Find the guild for that channel. | ||
g, err := s.State.Guild(c.GuildID) | ||
if err != nil { | ||
// Could not find guild. | ||
return | ||
} | ||
|
||
// Look for the message sender in that guilds current voice states. | ||
for _, vs := range g.VoiceStates { | ||
if vs.UserID == m.Author.ID { | ||
err = playSound(s, g.ID, vs.ChannelID) | ||
if err != nil { | ||
fmt.Println("Error playing sound:", err) | ||
} | ||
|
||
return | ||
} | ||
} | ||
} | ||
} | ||
|
||
// This function will be called (due to AddHandler above) every time a new | ||
// guild is joined. | ||
func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) { | ||
if event.Guild.Unavailable != nil { | ||
return | ||
} | ||
|
||
for _, channel := range event.Guild.Channels { | ||
if channel.ID == event.Guild.ID { | ||
s.ChannelMessageSend(channel.ID, "Airhorn is ready! Type !airhorn while in a voice channel to play a sound.") | ||
return | ||
} | ||
} | ||
} | ||
|
||
// loadSound attempts to load an encoded sound file from disk. | ||
func loadSound() error { | ||
file, err := os.Open("airhorn.dca") | ||
|
||
if err != nil { | ||
fmt.Println("Error opening dca file :", err) | ||
return err | ||
} | ||
|
||
var opuslen int16 | ||
|
||
for { | ||
// Read opus frame length from dca file. | ||
err = binary.Read(file, binary.LittleEndian, &opuslen) | ||
|
||
// If this is the end of the file, just return. | ||
if err == io.EOF || err == io.ErrUnexpectedEOF { | ||
return nil | ||
} | ||
|
||
if err != nil { | ||
fmt.Println("Error reading from dca file :", err) | ||
return err | ||
} | ||
|
||
// Read encoded pcm from dca file. | ||
InBuf := make([]byte, opuslen) | ||
err = binary.Read(file, binary.LittleEndian, &InBuf) | ||
|
||
// Should not be any end of file errors | ||
if err != nil { | ||
fmt.Println("Error reading from dca file :", err) | ||
return err | ||
} | ||
|
||
// Append encoded pcm data to the buffer. | ||
buffer = append(buffer, InBuf) | ||
} | ||
} | ||
|
||
// playSound plays the current buffer to the provided channel. | ||
func playSound(s *discordgo.Session, guildID, channelID string) (err error) { | ||
// Join the provided voice channel. | ||
vc, err := s.ChannelVoiceJoin(guildID, channelID, false, false) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Sleep for a specified amount of time before playing the sound | ||
time.Sleep(250 * time.Millisecond) | ||
|
||
// Start speaking. | ||
vc.Speaking(true) | ||
|
||
// Send the buffer data. | ||
for _, buff := range buffer { | ||
vc.OpusSend <- buff | ||
} | ||
|
||
// Stop speaking | ||
vc.Speaking(false) | ||
|
||
// Sleep for a specificed amount of time before ending. | ||
time.Sleep(250 * time.Millisecond) | ||
|
||
// Disconnect from the provided voice channel. | ||
vc.Disconnect() | ||
|
||
return nil | ||
} |
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