Add song player handler
This commit is contained in:
parent
17db60dea1
commit
8b5673434a
7 changed files with 179 additions and 17 deletions
|
@ -1,5 +1,13 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 4.1.0 - 2019-07-28
|
||||||
|
### Added
|
||||||
|
- Song player handler
|
||||||
|
|
||||||
|
## 4.0.2 - 2019-07-28
|
||||||
|
### Changed
|
||||||
|
- Info about 7th subday
|
||||||
|
|
||||||
## 4.0.1 - 2019-07-22
|
## 4.0.1 - 2019-07-22
|
||||||
### Changed
|
### Changed
|
||||||
- Twitch chat library version from v1 to v2
|
- Twitch chat library version from v1 to v2
|
||||||
|
|
2
go.mod
2
go.mod
|
@ -5,7 +5,7 @@ require (
|
||||||
github.com/gempir/go-twitch-irc/v2 v2.2.0
|
github.com/gempir/go-twitch-irc/v2 v2.2.0
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/stretchr/testify v1.3.0 // indirect
|
github.com/stretchr/testify v1.3.0 // indirect
|
||||||
go.uber.org/atomic v1.3.2 // indirect
|
go.uber.org/atomic v1.3.2
|
||||||
go.uber.org/dig v1.7.0 // indirect
|
go.uber.org/dig v1.7.0 // indirect
|
||||||
go.uber.org/fx v1.9.0
|
go.uber.org/fx v1.9.0
|
||||||
go.uber.org/goleak v0.10.0 // indirect
|
go.uber.org/goleak v0.10.0 // indirect
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
package discord
|
package discord
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
"galched-bot/modules/settings"
|
"galched-bot/modules/settings"
|
||||||
"galched-bot/modules/subday"
|
"galched-bot/modules/subday"
|
||||||
|
|
||||||
|
"go.uber.org/atomic"
|
||||||
|
|
||||||
"github.com/bwmarrin/discordgo"
|
"github.com/bwmarrin/discordgo"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
@ -31,6 +36,16 @@ func New(s *settings.Settings, subday *subday.Subday) (*Discord, error) {
|
||||||
processor.AddHandler(subdayHandler)
|
processor.AddHandler(subdayHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
polka, err := loadSong(s.PolkaPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "cannot read polka song")
|
||||||
|
}
|
||||||
|
processor.AddHandler(&polkaHandler{
|
||||||
|
polka: polka,
|
||||||
|
voiceChannel: s.DiscordVoiceChannel,
|
||||||
|
lock: atomic.NewBool(false),
|
||||||
|
})
|
||||||
|
|
||||||
log.Printf("discord: added %d message handlers", len(processor.handlers))
|
log.Printf("discord: added %d message handlers", len(processor.handlers))
|
||||||
if len(processor.handlers) > 0 {
|
if len(processor.handlers) > 0 {
|
||||||
for i := range processor.handlers {
|
for i := range processor.handlers {
|
||||||
|
@ -45,6 +60,48 @@ func New(s *settings.Settings, subday *subday.Subday) (*Discord, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadSong(path string) ([][]byte, error) {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "error opening dca file")
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
opuslen int16
|
||||||
|
buffer = make([][]byte, 0)
|
||||||
|
)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buffer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "error reading from dca file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
return nil, errors.Wrap(err, "error reading from dca file")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append encoded pcm data to the buffer.
|
||||||
|
buffer = append(buffer, InBuf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func LogMessage(m *discordgo.MessageCreate) {
|
func LogMessage(m *discordgo.MessageCreate) {
|
||||||
log.Printf("discord: msg [%s]: %s", m.Author.Username, m.Content)
|
log.Printf("discord: msg [%s]: %s", m.Author.Username, m.Content)
|
||||||
}
|
}
|
||||||
|
|
92
modules/discord/polkahandler.go
Normal file
92
modules/discord/polkahandler.go
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
package discord
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/bwmarrin/discordgo"
|
||||||
|
"go.uber.org/atomic"
|
||||||
|
)
|
||||||
|
|
||||||
|
type polkaHandler struct {
|
||||||
|
polka [][]byte
|
||||||
|
voiceChannel string
|
||||||
|
lock *atomic.Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *polkaHandler) Signature() string {
|
||||||
|
return "!song"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *polkaHandler) Description() string {
|
||||||
|
return "сыграть гимн галчед (только для избранных)"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *polkaHandler) IsValid(msg string) bool {
|
||||||
|
return msg == "!song"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *polkaHandler) Handle(s *discordgo.Session, m *discordgo.MessageCreate) {
|
||||||
|
if m.Author.Username != "YoMedved" && m.Author.Username != "Rummy_Quamox" && m.Author.Username != "Lidiya_owl" {
|
||||||
|
log.Printf("discord: unathorized polka message from %s", m.Author.Username)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 guild's current voice states.
|
||||||
|
LogMessage(m)
|
||||||
|
if h.lock.CAS(false, true) {
|
||||||
|
defer h.lock.Store(false)
|
||||||
|
err = h.playSound(s, g.ID, h.voiceChannel)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("discord: error playing sound:", err)
|
||||||
|
}
|
||||||
|
time.Sleep(10 * time.Second)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// playSound plays the current buffer to the provided channel.
|
||||||
|
func (h *polkaHandler) playSound(s *discordgo.Session, guildID, channelID string) (err error) {
|
||||||
|
|
||||||
|
// Join the provided voice channel.
|
||||||
|
vc, err := s.ChannelVoiceJoin(guildID, channelID, false, true)
|
||||||
|
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 h.polka {
|
||||||
|
vc.OpusSend <- buff
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop speaking
|
||||||
|
vc.Speaking(false)
|
||||||
|
|
||||||
|
// Sleep for a specified amount of time before ending.
|
||||||
|
time.Sleep(250 * time.Millisecond)
|
||||||
|
|
||||||
|
// Disconnect from the provided voice channel.
|
||||||
|
vc.Disconnect()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -153,7 +153,8 @@ func (h *SubdayHistoryHandler) Handle(s *discordgo.Session, m *discordgo.Message
|
||||||
"**22.12.18**: _True Crime: Streets of LA_ -> _Serious Sam 3_ -> _Kholat_\n" +
|
"**22.12.18**: _True Crime: Streets of LA_ -> _Serious Sam 3_ -> _Kholat_\n" +
|
||||||
"**26.01.19**: _Disney’s Aladdin_ -> _~~Gothic~~_ -> _Scrapland_ -> _Donut County_\n" +
|
"**26.01.19**: _Disney’s Aladdin_ -> _~~Gothic~~_ -> _Scrapland_ -> _Donut County_\n" +
|
||||||
"**24.02.19**: _Tetris 99_ -> _~~Bully~~_ -> _~~GTA: Vice City~~_\n" +
|
"**24.02.19**: _Tetris 99_ -> _~~Bully~~_ -> _~~GTA: Vice City~~_\n" +
|
||||||
"**02.06.19**: _Spec Ops: The Line_ -> _Escape from Tarkov_\n"
|
"**02.06.19**: _Spec Ops: The Line_ -> _Escape from Tarkov_\n" +
|
||||||
|
"**28.07.19**: _Crypt of the Necrodancer_ -> _My Friend Pedro_ -> _Ape Out_\n"
|
||||||
SendMessage(s, m, message)
|
SendMessage(s, m, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "4.0.1"
|
version = "4.1.0"
|
||||||
twitchUser = "galchedbot"
|
twitchUser = "galchedbot"
|
||||||
twitchIRCRoom = "galched"
|
twitchIRCRoom = "galched"
|
||||||
discordTokenPath = "./tokens/.discordtoken"
|
discordTokenPath = "./tokens/.discordtoken"
|
||||||
|
@ -29,6 +29,8 @@ type (
|
||||||
TwitchToken string
|
TwitchToken string
|
||||||
SubdayDataPath string
|
SubdayDataPath string
|
||||||
PermittedRoles []string
|
PermittedRoles []string
|
||||||
|
PolkaPath string
|
||||||
|
DiscordVoiceChannel string
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,6 +51,8 @@ func New() (*Settings, error) {
|
||||||
TwitchUser: twitchUser,
|
TwitchUser: twitchUser,
|
||||||
TwitchIRCRoom: twitchIRCRoom,
|
TwitchIRCRoom: twitchIRCRoom,
|
||||||
SubdayDataPath: subdayDataPath,
|
SubdayDataPath: subdayDataPath,
|
||||||
|
PolkaPath: "songs/polka.dca",
|
||||||
|
DiscordVoiceChannel: "301793085522706432",
|
||||||
PermittedRoles: []string{subRole1, subRole2, galchedRole, smorcRole},
|
PermittedRoles: []string{subRole1, subRole2, galchedRole, smorcRole},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
0
songs/.gitkeep
Normal file
0
songs/.gitkeep
Normal file
Loading…
Reference in a new issue