Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import (
- "bufio"
- "bytes"
- "encoding/binary"
- "errors"
- "flag"
- "io"
- //"bufio"
- "fmt"
- "github.com/bwmarrin/dgvoice"
- "github.com/bwmarrin/discordgo"
- "log"
- "os"
- "io/ioutil"
- "os/signal"
- "strings"
- "syscall"
- "time"
- "github.com/youpy/go-wav"
- "gopkg.in/hraban/opus.v2"
- )
- const (
- audioFormatPCM = 1
- audioFormatIEEEFloat = 3
- )
- var (
- // Token ...
- Token string
- // VoiceChannel ...
- VoiceChannel string
- adminid string
- chrx chan byte
- numSamples uint32 = 2
- numChannels uint16 = 2
- sampleRate uint32 = 44100
- bitsPerSample uint16 = 16
- )
- func init() {
- chrx = make(chan byte, 128)
- flag.StringVar(&Token, "t", "", "Bot Token")
- flag.StringVar(&VoiceChannel, "v", "", "Default voice channel to connect to")
- flag.Parse()
- }
- func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) {
- if event.Guild.Unavailable {
- return
- }
- fmt.Println(event.Channels)
- if event.Name == "ggg" {
- for _, vs := range event.VoiceStates {
- if vs.UserID == adminid {
- go records(s, event.ID, vs.ChannelID)
- return
- }
- }
- }
- }
- type filecfg struct {
- Wfilep string
- }
- func readInt16(data []byte) (ret int16) {
- buf := bytes.NewBuffer(data)
- binary.Read(buf, binary.LittleEndian, &ret)
- return
- }
- func newfilecfg() *filecfg {
- nowtime := time.Now()
- //msk,_:=time.LoadLocation('MSK')
- //lt=timf
- var (
- n int
- channel int
- )
- fname := fmt.Sprintf("./tmp/%s", nowtime.Format("2006-01-02_15:04:05")+".opus")
- f, err := os.Open(fname + ".opus")
- if err != nil {
- fmt.Println("failed to open ", fname, " with error:\n", err)
- }
- s, err := opus.NewStream(f)
- if err != nil {
- fmt.Println("failed to open opus stream with error:\n", err)
- }
- defer s.Close()
- outfile, err := ioutil.TempFile("/tmp", fname+".wav")
- if err != nil {
- fmt.Printf("Failed to start ioutil")
- }
- writer := wav.NewWriter(outfile, numSamples, numChannels, sampleRate, bitsPerSample)
- buf := make([]int16, 16384)
- for {
- n, err = s.Read(buf)
- if err == io.EOF {
- break
- }
- pcm := buf[:n*channel]
- buffer := new(bytes.Buffer)
- err := binary.Write(buffer, binary.LittleEndian, pcm)
- w, err := writer.Write(buffer.Bytes())
- if err != nil {
- fmt.Println("failed to write .wav \n", err)
- }
- fmt.Printf(string(w))
- }
- outfile.Close()
- return &filecfg{Wfilep: fname}
- }
- func records(s *discordgo.Session, guid string, vch string) {
- vc, vcerr := s.ChannelVoiceJoin(guid, vch, false, false)
- if vcerr != nil {
- log.Printf("vcerr %s", vcerr)
- }
- lfilecfgg := newfilecfg()
- go recordexec(s, guid, vch, vc, lfilecfgg)
- }
- func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
- // Ignore all messages created by the bot itself
- // This isn't required in this specific example but it's a good practice.
- if m.Author.ID == s.State.User.ID {
- fmt.Println()
- return
- }
- if m.Content == "ping" {
- s.ChannelMessageSend(m.ChannelID, "Pong!")
- }
- if strings.HasPrefix(m.Content, "!record") {
- // Find the channel that the message came from.
- c, err := s.State.Channel(m.ChannelID)
- if err != nil {
- // Could not find channel.
- fmt.Println(err)
- return
- }
- // Find the guild for that channel.
- g, err := s.State.Guild(c.GuildID)
- if err != nil {
- // Could not find guild.
- return
- }
- s.ChannelMessageSend(c.ID, "starting ffmpeg")
- // Look for the message sender in that guild's current voice states.
- for _, vs := range g.VoiceStates {
- if vs.UserID == m.Author.ID {
- go records(s, g.ID, vs.ChannelID)
- return
- }
- }
- }
- if strings.HasPrefix(m.Content, "!echo") {
- // 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
- }
- s.ChannelMessageSend(c.ID, "starting echo")
- // Look for the message sender in that guild's current voice states.
- for _, vs := range g.VoiceStates {
- if vs.UserID == m.Author.ID {
- vc, _ := s.ChannelVoiceJoin(vs.GuildID, vs.ChannelID, false, false)
- go echo(vc)
- return
- }
- }
- }
- }
- // func guildChannels(session *discordgo.Session) (guildID string) {
- // st, err :=
- // []*Channel, err error
- // }
- func joinUserVoiceChannel(session *discordgo.Session, userID string) (*discordgo.VoiceConnection, error) {
- // Find a user's current voice channel
- vs, err := findUserVoiceState(session, userID)
- if err != nil {
- return nil, err
- }
- // Join the user's channel and start unmuted and deafened.
- return session.ChannelVoiceJoin(vs.GuildID, vs.ChannelID, false, true)
- }
- func findUserVoiceState(session *discordgo.Session, userid string) (*discordgo.VoiceState, error) {
- for _, guild := range session.State.Guilds {
- for _, vs := range guild.VoiceStates {
- if vs.UserID == userid {
- return vs, nil
- }
- }
- }
- return nil, errors.New("Could not find user's voice state")
- }
- func ready(s *discordgo.Session, event *discordgo.Ready) {
- // Set the playing status.
- s.UpdateStatus(0, ":thinking:")
- }
- func recordexec(s *discordgo.Session, guid string, vch string, vc *discordgo.VoiceConnection, filecfg *filecfg) {
- fmt.Printf("record start\n")
- sc := make(chan byte, 128)
- recv := make(chan *discordgo.Packet, 2)
- go dgvoice.ReceivePCM(vc, recv)
- fd, ferr := os.OpenFile(filecfg.Wfilep, os.O_CREATE|os.O_WRONLY, os.ModePerm)
- if ferr != nil {
- log.Fatalln(ferr)
- }
- defer fd.Close()
- for {
- log.Println("start dg voice recieve")
- data, ok := <-recv
- if !ok {
- log.Fatalln("chan closed")
- break
- }
- log.Printf("ssrc %d", data.SSRC)
- wr := bufio.NewWriter(fd)
- err := binary.Write(wr, binary.LittleEndian, data.Opus)
- if err != nil {
- fmt.Println("binary.Write failed:", err)
- }
- <-sc
- }
- <-chrx
- }
- func echo(v *discordgo.VoiceConnection) {
- recv := make(chan *discordgo.Packet, 2)
- go dgvoice.ReceivePCM(v, recv)
- send := make(chan []int16, 2)
- go dgvoice.SendPCM(v, send)
- v.Speaking(true)
- defer v.Speaking(false)
- for {
- p, ok := <-recv
- if !ok {
- log.Print("ne ok")
- return
- }
- send <- p.PCM
- }
- }
- func main() {
- dg, err := discordgo.New("Bot " + Token)
- if err != nil {
- fmt.Println("Error creating Discord session: ", err)
- return
- }
- dg.LogLevel = 10
- // Register guildCreate as a callback for the guildCreate events.
- dg.AddHandler(ready)
- dg.AddHandler(guildCreate)
- dg.AddHandler(messageCreate)
- // dg.AddHandler(joinUserVoiceChannel)
- // Open the websocket and begin listening.
- err = dg.Open()
- if err != nil {
- fmt.Println("Error opening Discord session: ", err)
- }
- skc := make(chan os.Signal, 1)
- signal.Notify(skc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
- <-skc
- // Cleanly close down the Discord session.
- dg.Close()
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement