From 25a1b2ea48344a1dc8d4700fb63e162da85daf74 Mon Sep 17 00:00:00 2001 From: Chris Rhodes Date: Sat, 23 Jan 2016 20:24:52 -0800 Subject: [PATCH 1/4] Close. --- wsapi.go | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/wsapi.go b/wsapi.go index ff9cfc1..376c274 100644 --- a/wsapi.go +++ b/wsapi.go @@ -11,8 +11,14 @@ package discordgo import ( + "bytes" + "compress/flate" + "encoding/json" "errors" "fmt" + "io" + "io/ioutil" + "net/http" "runtime" "time" @@ -31,6 +37,7 @@ type handshakeData struct { Version int `json:"v"` Token string `json:"token"` Properties handshakeProperties `json:"properties"` + Compress bool `json:"compress"` } type handshakeOp struct { @@ -58,14 +65,17 @@ func (s *Session) Open() (err error) { return } + header := http.Header{} + header.Add("accept-encoding", "gzip, deflate") + // TODO: See if there's a use for the http response. // conn, response, err := websocket.DefaultDialer.Dial(session.Gateway, nil) - s.wsConn, _, err = websocket.DefaultDialer.Dial(g, nil) + s.wsConn, _, err = websocket.DefaultDialer.Dial(g, header) if err != nil { return } - err = s.wsConn.WriteJSON(handshakeOp{2, handshakeData{3, s.Token, handshakeProperties{runtime.GOOS, "Discordgo v" + VERSION, "", "", ""}}}) + err = s.wsConn.WriteJSON(handshakeOp{2, handshakeData{3, s.Token, handshakeProperties{runtime.GOOS, "Discordgo v" + VERSION, "", "", ""}, true}}) if err != nil { return } @@ -261,14 +271,27 @@ func (s *Session) event(messageType int, message []byte) (err error) { printJSON(message) } + var reader io.Reader + reader = bytes.NewBuffer(message) + + if messageType == 2 { + ioutil.WriteFile("ready", message, 0644) + f := flate.NewReader(reader) + defer f.Close() + reader = f + } + + decoder := json.NewDecoder(reader) + var e *Event - if err = unmarshal(message, &e); err != nil { + if err = decoder.Decode(&e); err != nil { fmt.Println(err) return } switch e.Type { case "READY": + fmt.Println(messageType, e) var st *Ready if err = unmarshalEvent(e, &st); err == nil { go s.heartbeat(s.wsConn, s.listening, st.HeartbeatInterval) From a08dde42625d52ce6009fcfd9ccc858f7ddcd391 Mon Sep 17 00:00:00 2001 From: Chris Rhodes Date: Sat, 23 Jan 2016 21:09:30 -0800 Subject: [PATCH 2/4] Support zlib compression. --- util.go | 6 ++++++ wsapi.go | 38 +++++++++++++++++++------------------- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/util.go b/util.go index 00ccb9d..20ab084 100644 --- a/util.go +++ b/util.go @@ -17,6 +17,12 @@ import ( "fmt" ) +// printEvent prints out a WSAPI event. +func printEvent(e *Event) { + fmt.Println(fmt.Sprintf("Event. Type: %s, State: %d Operation: %d Direction: %d", e.Type, e.State, e.Operation, e.Direction)) + printJSON(e.RawData) +} + // printJSON is a helper function to display JSON data in a easy to read format. func printJSON(body []byte) { var prettyJSON bytes.Buffer diff --git a/wsapi.go b/wsapi.go index 376c274..bea580b 100644 --- a/wsapi.go +++ b/wsapi.go @@ -12,12 +12,11 @@ package discordgo import ( "bytes" - "compress/flate" + "compress/zlib" "encoding/json" "errors" "fmt" "io" - "io/ioutil" "net/http" "runtime" "time" @@ -66,7 +65,7 @@ func (s *Session) Open() (err error) { } header := http.Header{} - header.Add("accept-encoding", "gzip, deflate") + header.Add("accept-encoding", "zlib") // TODO: See if there's a use for the http response. // conn, response, err := websocket.DefaultDialer.Dial(session.Gateway, nil) @@ -252,8 +251,8 @@ func (s *Session) UpdateStatus(idle int, game string) (err error) { func unmarshalEvent(event *Event, i interface{}) (err error) { if err = unmarshal(event.RawData, i); err != nil { - fmt.Println(event.Type, err) - printJSON(event.RawData) // TODO: Better error loggingEvent. + fmt.Println("Unable to unmarshal event data.") + printEvent(event) } return } @@ -266,32 +265,33 @@ func unmarshalEvent(event *Event, i interface{}) (err error) { // Events will be handled by any implemented handler in Session. // All unhandled events will then be handled by OnEvent. func (s *Session) event(messageType int, message []byte) (err error) { - - if s.Debug { - printJSON(message) - } - var reader io.Reader reader = bytes.NewBuffer(message) if messageType == 2 { - ioutil.WriteFile("ready", message, 0644) - f := flate.NewReader(reader) - defer f.Close() - reader = f + z, err1 := zlib.NewReader(reader) + if err1 != nil { + err = err1 + fmt.Println(err) + return + } + defer z.Close() + reader = z } - decoder := json.NewDecoder(reader) - var e *Event + decoder := json.NewDecoder(reader) if err = decoder.Decode(&e); err != nil { fmt.Println(err) return } + if s.Debug { + printEvent(e) + } + switch e.Type { case "READY": - fmt.Println(messageType, e) var st *Ready if err = unmarshalEvent(e, &st); err == nil { go s.heartbeat(s.wsConn, s.listening, st.HeartbeatInterval) @@ -626,8 +626,8 @@ func (s *Session) event(messageType int, message []byte) (err error) { return } default: - fmt.Println("UNKNOWN EVENT: ", e.Type) - printJSON(message) + fmt.Println("Unknown Event.") + printEvent(e) } // if still here, send to generic OnEvent From 5a3740df0ca4b7a2a8a2f2f5f369c93f78a78528 Mon Sep 17 00:00:00 2001 From: Chris Rhodes Date: Sat, 23 Jan 2016 21:12:57 -0800 Subject: [PATCH 3/4] :poop: --- wsapi.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/wsapi.go b/wsapi.go index bea580b..99f0426 100644 --- a/wsapi.go +++ b/wsapi.go @@ -271,9 +271,8 @@ func (s *Session) event(messageType int, message []byte) (err error) { if messageType == 2 { z, err1 := zlib.NewReader(reader) if err1 != nil { - err = err1 - fmt.Println(err) - return + fmt.Println(err1) + return err1 } defer z.Close() reader = z From fd32614a632daf0e6b94ccc089c23eda4f2c47e9 Mon Sep 17 00:00:00 2001 From: Chris Rhodes Date: Sun, 24 Jan 2016 09:49:41 -0800 Subject: [PATCH 4/4] Make compression optional, clean up some comments and unused fields. --- structs.go | 22 +++++++++------------- wsapi.go | 2 +- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/structs.go b/structs.go index 762c27d..27b16e3 100644 --- a/structs.go +++ b/structs.go @@ -72,28 +72,24 @@ type Session struct { VoiceReady bool // Set to true when Voice Websocket is ready UDPReady bool // Set to true when UDP Connection is ready - // Other.. + // The websocket connection. wsConn *websocket.Conn - //TODO, add bools for like. - // are we connnected to websocket? - // have we authenticated to login? - // lets put all the general session - // tracking and infos here.. clearly - // Everything below here is used for Voice testing. - // This stuff is almost guarenteed to change a lot - // and is even a bit hackish right now. - Voice *Voice // Stores all details related to voice connections + // Stores all details related to voice connections + Voice *Voice // Managed state object, updated with events. - State *State - StateEnabled bool - StateMaxMessageCount int + State *State + StateEnabled bool // When nil, the session is not listening. listening chan interface{} + // Should the session reconnect the websocket on errors. ShouldReconnectOnError bool + + // Should the session request compressed websocket data. + Compress bool } // A VoiceRegion stores data for a specific voice region server. diff --git a/wsapi.go b/wsapi.go index 99f0426..03d987a 100644 --- a/wsapi.go +++ b/wsapi.go @@ -74,7 +74,7 @@ func (s *Session) Open() (err error) { return } - err = s.wsConn.WriteJSON(handshakeOp{2, handshakeData{3, s.Token, handshakeProperties{runtime.GOOS, "Discordgo v" + VERSION, "", "", ""}, true}}) + err = s.wsConn.WriteJSON(handshakeOp{2, handshakeData{3, s.Token, handshakeProperties{runtime.GOOS, "Discordgo v" + VERSION, "", "", ""}, s.Compress}}) if err != nil { return }