All sent JSON data now using structs

This commit is contained in:
Bruce Marriner 2015-12-20 00:13:19 -06:00
parent 0fbfc66554
commit b87add9152

View file

@ -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
}