Procházet zdrojové kódy

All sent JSON data now using structs

Bruce Marriner před 9 roky
rodič
revize
b87add9152
1 změnil soubory, kde provedl 61 přidání a 22 odebrání
  1. 61 22
      voice.go

+ 61 - 22
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
 	}