diff --git a/config.template.json b/config.template.json new file mode 100644 index 0000000..5ec95d3 --- /dev/null +++ b/config.template.json @@ -0,0 +1,4 @@ +{ + "Token": "", + "Activator": "#" +} \ No newline at end of file diff --git a/dist/GoBot-linux b/dist/GoBot-linux new file mode 100755 index 0000000..365b850 Binary files /dev/null and b/dist/GoBot-linux differ diff --git a/dist/GoBot-windows.exe b/dist/GoBot-windows.exe new file mode 100755 index 0000000..6c4afd7 Binary files /dev/null and b/dist/GoBot-windows.exe differ diff --git a/dist/config.json b/dist/config.json new file mode 100644 index 0000000..5ec95d3 --- /dev/null +++ b/dist/config.json @@ -0,0 +1,4 @@ +{ + "Token": "", + "Activator": "#" +} \ No newline at end of file diff --git a/main.go b/main.go deleted file mode 100644 index d03fe81..0000000 --- a/main.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - "./bot" - "./config" - "./serverstatus" -) - -// Variables used for command line parameters -var ( - BotID string -) - -func main() { - config.Configure() - bot.Connect(config.Config.Token) - serverstatus.Start() - bot.Start() - -} diff --git a/makefile b/makefile new file mode 100644 index 0000000..ef7b194 --- /dev/null +++ b/makefile @@ -0,0 +1,17 @@ +run: clean linux copyconfig + @./dist/GoBot-linux + +windows: + @GOOS=windows GOARCH=386 go build -o ./dist/GoBot-windows.exe ./src/main.go + +linux: + @go build -o ./dist/GoBot-linux ./src/main.go + +clean: + @rm -rf ./dist + +copyconfig: + @cp config.template.json ./dist/config.json + +build: clean windows linux copyconfig + \ No newline at end of file diff --git a/readme.md b/readme.md index 98d3ec0..adc870b 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,3 @@ # GoBot My experimental Discord bot - -## Server Status - -This scans the Elysium PvP server checking to see if it is up. diff --git a/serverstatus/serverstatus.go b/serverstatus/serverstatus.go deleted file mode 100644 index df32cf5..0000000 --- a/serverstatus/serverstatus.go +++ /dev/null @@ -1,36 +0,0 @@ -package serverstatus - -import ( - "../bot" - "../config" - "github.com/anvie/port-scanner" - "time" -) - -const serverAddr string = "149.202.207.235" - -func Start() { - go loop() -} - -func loop() { - prevServerUp := true - elysiumPvP := portscanner.NewPortScanner(serverAddr, time.Second*2) - - for { - serverUp := elysiumPvP.IsOpen(8099) - - if serverUp && serverUp != prevServerUp { - sendMessage("@here Elysium PVP is now online!") - } else if !serverUp && serverUp != prevServerUp { - sendMessage("@here Elysium PVP is now offline!") - } - - prevServerUp = serverUp - time.Sleep(time.Second * 5) - } -} - -func sendMessage(message string) { - bot.Session.ChannelMessageSend(config.Config.AlertRoomID, message) -} diff --git a/sounds/airhorn.dca b/sounds/airhorn.dca new file mode 100644 index 0000000..39e7167 Binary files /dev/null and b/sounds/airhorn.dca differ diff --git a/bot/bot.go b/src/bot/bot.go similarity index 100% rename from bot/bot.go rename to src/bot/bot.go diff --git a/config/config.go b/src/config/config.go similarity index 85% rename from config/config.go rename to src/config/config.go index 2b50380..5013e80 100644 --- a/config/config.go +++ b/src/config/config.go @@ -11,8 +11,8 @@ import ( var Config configStruct type configStruct struct { - Token string `json:"Token"` - AlertRoomID string `json:"AlertRoomID"` + Token string `json:"Token"` + Activator string `json:"Activator"` } func Configure() { diff --git a/src/handlers/airhorn.go b/src/handlers/airhorn.go new file mode 100644 index 0000000..551ec3b --- /dev/null +++ b/src/handlers/airhorn.go @@ -0,0 +1,149 @@ +package handlers + +import ( + "../config" + "encoding/binary" + "errors" + "fmt" + "github.com/bwmarrin/discordgo" + "io" + "io/ioutil" + "os" + "strings" + "time" +) + +var sounds = make(map[string][][]byte, 0) + +const SOUNDS_DIR string = "./sounds/" + +func AirhornHandler(s *discordgo.Session, m *discordgo.MessageCreate) { + if strings.HasPrefix(m.Content, config.Config.Activator) { + // 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, strings.TrimPrefix(m.Content, config.Config.Activator)) + if err != nil { + fmt.Println("Error playing sound:", err) + } + + return + } + } + } +} + +// loadSound attempts to load an encoded sound file from disk. +func LoadSounds() error { + + files, _ := ioutil.ReadDir(SOUNDS_DIR) + + for _, file := range files { + fmt.Println(file.Name()) + err := loadFile(file.Name()) + + if err != nil { + fmt.Println(err.Error()) + } + + } + + return nil +} + +func loadFile(fileName string) error { + + trimmedName := strings.TrimSuffix(fileName, ".dca") + sounds[trimmedName] = make([][]byte, 0) + + file, err := os.Open(SOUNDS_DIR + fileName) + + 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 { + file.Close() + if err != nil { + return err + } + 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 + } + + sounds[trimmedName] = append(sounds[trimmedName], InBuf) + } + +} + +// playSound plays the current buffer to the provided channel. +func playSound(s *discordgo.Session, guildID, channelID string, sound string) (err error) { + + if _, ok := sounds[sound]; !ok { + return errors.New("Sound not found") + } + + // 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 sounds[sound] { + 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 +} diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..aa1c433 --- /dev/null +++ b/src/main.go @@ -0,0 +1,29 @@ +package main + +import ( + "./bot" + "./config" + "./handlers" +) + +// Variables used for command line parameters +var ( + BotID string +) + +func main() { + //read config file + config.Configure() + + //connect bot to account with token + bot.Connect(config.Config.Token) + + //load sound files into memory + handlers.LoadSounds() + + //add handlers + bot.AddHandler(handlers.AirhornHandler) + + //start websock to listen for messages + bot.Start() +}