Advertisement
Guest User

Untitled

a guest
Nov 9th, 2019
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Go 6.91 KB | None | 0 0
  1. package main
  2.  
  3. import (
  4.     "bufio"
  5.     "bytes"
  6.     "encoding/binary"
  7.     "errors"
  8.     "flag"
  9.     "io"
  10.  
  11.     //"bufio"
  12.     "fmt"
  13.  
  14.     "github.com/bwmarrin/dgvoice"
  15.     "github.com/bwmarrin/discordgo"
  16.  
  17.     "log"
  18.     "os"
  19.  
  20.     "io/ioutil"
  21.     "os/signal"
  22.     "strings"
  23.     "syscall"
  24.     "time"
  25.  
  26.     "github.com/youpy/go-wav"
  27.     "gopkg.in/hraban/opus.v2"
  28. )
  29.  
  30. const (
  31.     audioFormatPCM       = 1
  32.     audioFormatIEEEFloat = 3
  33. )
  34.  
  35. var (
  36.     // Token ...
  37.     Token string
  38.     // VoiceChannel ...
  39.     VoiceChannel  string
  40.     adminid       string
  41.     chrx          chan byte
  42.     numSamples    uint32 = 2
  43.     numChannels   uint16 = 2
  44.     sampleRate    uint32 = 44100
  45.     bitsPerSample uint16 = 16
  46. )
  47.  
  48. func init() {
  49.     chrx = make(chan byte, 128)
  50.     flag.StringVar(&Token, "t", "", "Bot Token")
  51.     flag.StringVar(&VoiceChannel, "v", "", "Default voice channel to connect to")
  52.     flag.Parse()
  53. }
  54.  
  55. func guildCreate(s *discordgo.Session, event *discordgo.GuildCreate) {
  56.  
  57.     if event.Guild.Unavailable {
  58.         return
  59.     }
  60.     fmt.Println(event.Channels)
  61.     if event.Name == "ggg" {
  62.         for _, vs := range event.VoiceStates {
  63.             if vs.UserID == adminid {
  64.                 go records(s, event.ID, vs.ChannelID)
  65.                 return
  66.             }
  67.         }
  68.     }
  69. }
  70.  
  71. type filecfg struct {
  72.     Wfilep string
  73. }
  74.  
  75. func readInt16(data []byte) (ret int16) {
  76.     buf := bytes.NewBuffer(data)
  77.     binary.Read(buf, binary.LittleEndian, &ret)
  78.     return
  79. }
  80.  
  81. func newfilecfg() *filecfg {
  82.     nowtime := time.Now()
  83.     //msk,_:=time.LoadLocation('MSK')
  84.     //lt=timf
  85.     var (
  86.         n       int
  87.         channel int
  88.     )
  89.     fname := fmt.Sprintf("./tmp/%s", nowtime.Format("2006-01-02_15:04:05")+".opus")
  90.     f, err := os.Open(fname + ".opus")
  91.     if err != nil {
  92.         fmt.Println("failed to open ", fname, " with error:\n", err)
  93.     }
  94.     s, err := opus.NewStream(f)
  95.     if err != nil {
  96.         fmt.Println("failed to open opus stream with error:\n", err)
  97.     }
  98.     defer s.Close()
  99.     outfile, err := ioutil.TempFile("/tmp", fname+".wav")
  100.     if err != nil {
  101.         fmt.Printf("Failed to start ioutil")
  102.     }
  103.     writer := wav.NewWriter(outfile, numSamples, numChannels, sampleRate, bitsPerSample)
  104.     buf := make([]int16, 16384)
  105.  
  106.     for {
  107.         n, err = s.Read(buf)
  108.         if err == io.EOF {
  109.             break
  110.         }
  111.         pcm := buf[:n*channel]
  112.         buffer := new(bytes.Buffer)
  113.         err := binary.Write(buffer, binary.LittleEndian, pcm)
  114.         w, err := writer.Write(buffer.Bytes())
  115.         if err != nil {
  116.             fmt.Println("failed to write .wav \n", err)
  117.         }
  118.         fmt.Printf(string(w))
  119.     }
  120.  
  121.     outfile.Close()
  122.     return &filecfg{Wfilep: fname}
  123. }
  124.  
  125. func records(s *discordgo.Session, guid string, vch string) {
  126.  
  127.     vc, vcerr := s.ChannelVoiceJoin(guid, vch, false, false)
  128.     if vcerr != nil {
  129.         log.Printf("vcerr %s", vcerr)
  130.     }
  131.     lfilecfgg := newfilecfg()
  132.     go recordexec(s, guid, vch, vc, lfilecfgg)
  133. }
  134.  
  135. func messageCreate(s *discordgo.Session, m *discordgo.MessageCreate) {
  136.  
  137.     // Ignore all messages created by the bot itself
  138.     // This isn't required in this specific example but it's a good practice.
  139.     if m.Author.ID == s.State.User.ID {
  140.         fmt.Println()
  141.         return
  142.     }
  143.  
  144.     if m.Content == "ping" {
  145.         s.ChannelMessageSend(m.ChannelID, "Pong!")
  146.     }
  147.  
  148.     if strings.HasPrefix(m.Content, "!record") {
  149.  
  150.         // Find the channel that the message came from.
  151.         c, err := s.State.Channel(m.ChannelID)
  152.         if err != nil {
  153.             // Could not find channel.
  154.             fmt.Println(err)
  155.             return
  156.         }
  157.  
  158.         // Find the guild for that channel.
  159.         g, err := s.State.Guild(c.GuildID)
  160.         if err != nil {
  161.             // Could not find guild.
  162.             return
  163.         }
  164.         s.ChannelMessageSend(c.ID, "starting ffmpeg")
  165.         // Look for the message sender in that guild's current voice states.
  166.         for _, vs := range g.VoiceStates {
  167.             if vs.UserID == m.Author.ID {
  168.                 go records(s, g.ID, vs.ChannelID)
  169.                 return
  170.             }
  171.         }
  172.     }
  173.  
  174.     if strings.HasPrefix(m.Content, "!echo") {
  175.  
  176.         // Find the channel that the message came from.
  177.         c, err := s.State.Channel(m.ChannelID)
  178.         if err != nil {
  179.             // Could not find channel.
  180.             return
  181.         }
  182.  
  183.         // Find the guild for that channel.
  184.         g, err := s.State.Guild(c.GuildID)
  185.         if err != nil {
  186.             // Could not find guild.
  187.             return
  188.         }
  189.         s.ChannelMessageSend(c.ID, "starting echo")
  190.         // Look for the message sender in that guild's current voice states.
  191.         for _, vs := range g.VoiceStates {
  192.             if vs.UserID == m.Author.ID {
  193.                 vc, _ := s.ChannelVoiceJoin(vs.GuildID, vs.ChannelID, false, false)
  194.                 go echo(vc)
  195.                 return
  196.             }
  197.         }
  198.     }
  199. }
  200.  
  201. // func guildChannels(session *discordgo.Session) (guildID string) {
  202. //  st, err :=
  203. //   []*Channel, err error
  204. // }
  205.  
  206. func joinUserVoiceChannel(session *discordgo.Session, userID string) (*discordgo.VoiceConnection, error) {
  207.     // Find a user's current voice channel
  208.     vs, err := findUserVoiceState(session, userID)
  209.     if err != nil {
  210.         return nil, err
  211.     }
  212.  
  213.     // Join the user's channel and start unmuted and deafened.
  214.     return session.ChannelVoiceJoin(vs.GuildID, vs.ChannelID, false, true)
  215. }
  216.  
  217. func findUserVoiceState(session *discordgo.Session, userid string) (*discordgo.VoiceState, error) {
  218.     for _, guild := range session.State.Guilds {
  219.         for _, vs := range guild.VoiceStates {
  220.             if vs.UserID == userid {
  221.                 return vs, nil
  222.             }
  223.         }
  224.     }
  225.     return nil, errors.New("Could not find user's voice state")
  226. }
  227.  
  228. func ready(s *discordgo.Session, event *discordgo.Ready) {
  229.  
  230.     // Set the playing status.
  231.     s.UpdateStatus(0, ":thinking:")
  232. }
  233.  
  234. func recordexec(s *discordgo.Session, guid string, vch string, vc *discordgo.VoiceConnection, filecfg *filecfg) {
  235.     fmt.Printf("record start\n")
  236.     sc := make(chan byte, 128)
  237.  
  238.     recv := make(chan *discordgo.Packet, 2)
  239.     go dgvoice.ReceivePCM(vc, recv)
  240.     fd, ferr := os.OpenFile(filecfg.Wfilep, os.O_CREATE|os.O_WRONLY, os.ModePerm)
  241.     if ferr != nil {
  242.         log.Fatalln(ferr)
  243.     }
  244.     defer fd.Close()
  245.     for {
  246.         log.Println("start dg voice recieve")
  247.  
  248.         data, ok := <-recv
  249.         if !ok {
  250.             log.Fatalln("chan closed")
  251.             break
  252.         }
  253.         log.Printf("ssrc %d", data.SSRC)
  254.         wr := bufio.NewWriter(fd)
  255.         err := binary.Write(wr, binary.LittleEndian, data.Opus)
  256.  
  257.         if err != nil {
  258.             fmt.Println("binary.Write failed:", err)
  259.         }
  260.         <-sc
  261.     }
  262.     <-chrx
  263.  
  264. }
  265.  
  266. func echo(v *discordgo.VoiceConnection) {
  267.  
  268.     recv := make(chan *discordgo.Packet, 2)
  269.     go dgvoice.ReceivePCM(v, recv)
  270.  
  271.     send := make(chan []int16, 2)
  272.     go dgvoice.SendPCM(v, send)
  273.  
  274.     v.Speaking(true)
  275.     defer v.Speaking(false)
  276.  
  277.     for {
  278.  
  279.         p, ok := <-recv
  280.         if !ok {
  281.             log.Print("ne ok")
  282.             return
  283.         }
  284.  
  285.         send <- p.PCM
  286.     }
  287. }
  288.  
  289. func main() {
  290.  
  291.     dg, err := discordgo.New("Bot " + Token)
  292.     if err != nil {
  293.         fmt.Println("Error creating Discord session: ", err)
  294.         return
  295.     }
  296.     dg.LogLevel = 10
  297.  
  298.     // Register guildCreate as a callback for the guildCreate events.
  299.     dg.AddHandler(ready)
  300.     dg.AddHandler(guildCreate)
  301.     dg.AddHandler(messageCreate)
  302.     // dg.AddHandler(joinUserVoiceChannel)
  303.  
  304.     // Open the websocket and begin listening.
  305.     err = dg.Open()
  306.     if err != nil {
  307.         fmt.Println("Error opening Discord session: ", err)
  308.     }
  309.     skc := make(chan os.Signal, 1)
  310.     signal.Notify(skc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
  311.     <-skc
  312.  
  313.     // Cleanly close down the Discord session.
  314.     dg.Close()
  315.  
  316. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement