All sent JSON data now using structs
This commit is contained in:
parent
0fbfc66554
commit
b87add9152
1 changed files with 61 additions and 22 deletions
83
voice.go
83
voice.go
|
@ -23,7 +23,7 @@ import (
|
|||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
// A VEvent is the inital structure for voice websocket events. I think
|
||||
// A VEvent is the initial structure for voice websocket events. I think
|
||||
// I can reuse the data websocket structure here.
|
||||
type VEvent struct {
|
||||
Type string `json:"t"`
|
||||
|
@ -41,15 +41,32 @@ type VoiceOP2 struct {
|
|||
HeartbeatInterval time.Duration `json:"heartbeat_interval"`
|
||||
}
|
||||
|
||||
type voiceHandshakeData struct {
|
||||
ServerID string `json:"server_id"`
|
||||
UserID string `json:"user_id"`
|
||||
SessionID string `json:"session_id"`
|
||||
Token string `json:"token"`
|
||||
}
|
||||
|
||||
type voiceHandshakeOp struct {
|
||||
Op int `json:"op"` // Always 0
|
||||
Data voiceHandshakeData `json:"d"`
|
||||
}
|
||||
|
||||
// VoiceOpenWS opens a voice websocket connection. This should be called
|
||||
// after VoiceChannelJoin is used and the data VOICE websocket events
|
||||
// are captured.
|
||||
func (s *Session) VoiceOpenWS() {
|
||||
|
||||
// Don't open a socket if one is already open
|
||||
if s.VwsConn != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var self User
|
||||
var err error
|
||||
|
||||
self, err = s.User("@me") // AGAIN, Move to @ login and store in session
|
||||
self, err = s.User("@me") // TODO: Move to @ login and store in session
|
||||
|
||||
// Connect to Voice Websocket
|
||||
vg := fmt.Sprintf("wss://%s", strings.TrimSuffix(s.VEndpoint, ":80"))
|
||||
|
@ -58,16 +75,7 @@ func (s *Session) VoiceOpenWS() {
|
|||
fmt.Println("VOICE cannot open websocket:", err)
|
||||
}
|
||||
|
||||
// Send initial handshake data to voice websocket. This is required.
|
||||
json := map[string]interface{}{
|
||||
"op": 0,
|
||||
"d": map[string]interface{}{
|
||||
"server_id": s.VGuildID,
|
||||
"user_id": self.ID,
|
||||
"session_id": s.VSessionID,
|
||||
"token": s.VToken,
|
||||
},
|
||||
}
|
||||
json := voiceHandshakeOp{0, voiceHandshakeData{s.VGuildID, self.ID, s.VSessionID, s.VToken}}
|
||||
|
||||
err = s.VwsConn.WriteJSON(json)
|
||||
if err != nil {
|
||||
|
@ -147,13 +155,29 @@ func (s *Session) VoiceEvent(messageType int, message []byte) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
type voiceUDPData struct {
|
||||
Address string `json:"address"` // Public IP of machine running this code
|
||||
Port uint16 `json:"port"` // UDP Port of machine running this code
|
||||
Mode string `json:"mode"` // plain or ? (plain or encrypted)
|
||||
}
|
||||
|
||||
type voiceUDPD struct {
|
||||
Protocol string `json:"protocol"` // Always "udp" ?
|
||||
Data voiceUDPData `json:"data"`
|
||||
}
|
||||
|
||||
type voiceUDPOp struct {
|
||||
Op int `json:"op"` // Always 1
|
||||
Data voiceUDPD `json:"d"`
|
||||
}
|
||||
|
||||
// VoiceOpenUDP opens a UDP connect to the voice server and completes the
|
||||
// initial required handshake. This connect is left open in the session
|
||||
// and can be used to send or receive audio.
|
||||
func (s *Session) VoiceOpenUDP() {
|
||||
|
||||
// TODO: add code to convert hostname into an IP address to avoid problems
|
||||
// with frequent DNS lookups.
|
||||
// with frequent DNS lookups. ??
|
||||
|
||||
udpHost := fmt.Sprintf("%s:%d", strings.TrimSuffix(s.VEndpoint, ":80"), s.Vop2.Port)
|
||||
serverAddr, err := net.ResolveUDPAddr("udp", udpHost)
|
||||
|
@ -182,6 +206,7 @@ func (s *Session) VoiceOpenUDP() {
|
|||
fmt.Println("Voice RLEN should be 70 but isn't")
|
||||
}
|
||||
|
||||
// TODO need serious changes, this will likely not work on all IPs!
|
||||
ip := string(rb[4:16]) // must be a better way. TODO: NEEDS TESTING
|
||||
port := make([]byte, 2)
|
||||
port[0] = rb[68]
|
||||
|
@ -190,10 +215,9 @@ func (s *Session) VoiceOpenUDP() {
|
|||
|
||||
// Take the parsed data from above and send it back to Discord
|
||||
// to finalize the UDP handshake.
|
||||
json := fmt.Sprintf(`{"op":1,"d":{"protocol":"udp","data":{"address":"%s","port":%d,"mode":"plain"}}}`, ip, p)
|
||||
jsonb := []byte(json)
|
||||
jsondata := voiceUDPOp{1, voiceUDPD{"udp", voiceUDPData{ip, p, "plain"}}}
|
||||
|
||||
err = s.VwsConn.WriteMessage(websocket.TextMessage, jsonb)
|
||||
err = s.VwsConn.WriteJSON(jsondata)
|
||||
if err != nil {
|
||||
fmt.Println("error:", err)
|
||||
return
|
||||
|
@ -209,6 +233,16 @@ func (s *Session) VoiceCloseUDP() {
|
|||
s.UDPConn.Close()
|
||||
}
|
||||
|
||||
type voiceSpeakingData struct {
|
||||
Speaking bool `json:"speaking"`
|
||||
Delay int `json:"delay"`
|
||||
}
|
||||
|
||||
type voiceSpeakingOp struct {
|
||||
Op int `json:"op"` // Always 5
|
||||
Data voiceSpeakingData `json:"d"`
|
||||
}
|
||||
|
||||
func (s *Session) VoiceSpeaking() {
|
||||
|
||||
if s.VwsConn == nil {
|
||||
|
@ -217,8 +251,8 @@ func (s *Session) VoiceSpeaking() {
|
|||
return
|
||||
}
|
||||
|
||||
jsonb := []byte(`{"op":5,"d":{"speaking":true,"delay":0}}`)
|
||||
err := s.VwsConn.WriteMessage(websocket.TextMessage, jsonb)
|
||||
json := voiceSpeakingOp{5, voiceSpeakingData{true, 0}}
|
||||
err := s.VwsConn.WriteJSON(json)
|
||||
if err != nil {
|
||||
fmt.Println("error:", err)
|
||||
return
|
||||
|
@ -284,6 +318,11 @@ func (s *Session) VoiceUDPKeepalive(i time.Duration) {
|
|||
}
|
||||
}
|
||||
|
||||
type voiceHeartbeatOp struct {
|
||||
Op int `json:"op"` // Always 3
|
||||
Data int `json:"d"`
|
||||
}
|
||||
|
||||
// VoiceHeartbeat sends regular heartbeats to voice Discord so it knows the client
|
||||
// is still connected. If you do not send these heartbeats Discord will
|
||||
// disconnect the websocket connection after a few seconds.
|
||||
|
@ -292,15 +331,15 @@ func (s *Session) VoiceHeartbeat(i time.Duration) {
|
|||
ticker := time.NewTicker(i * time.Millisecond)
|
||||
for {
|
||||
timestamp := int(time.Now().Unix())
|
||||
err := s.VwsConn.WriteJSON(map[string]int{
|
||||
"op": 3,
|
||||
"d": timestamp,
|
||||
})
|
||||
json := voiceHeartbeatOp{3, timestamp}
|
||||
|
||||
err := s.VwsConn.WriteJSON(json)
|
||||
if err != nil {
|
||||
s.VoiceReady = false
|
||||
fmt.Println(err)
|
||||
return // log error?
|
||||
}
|
||||
|
||||
s.VoiceReady = true
|
||||
<-ticker.C
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue