Skip to content

Commit 12ec65b

Browse files
committed
Working websocket connection
1 parent 8f34864 commit 12ec65b

File tree

6 files changed

+110
-12
lines changed

6 files changed

+110
-12
lines changed

Dockerfile

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
FROM alpine:latest as certs
2+
RUN apk --update add ca-certificates
3+
14
FROM golang:latest as builder
25
WORKDIR /go/src/gitea.auttaja.io/kubecord/ws
36
RUN go get github.com/gorilla/websocket \
@@ -9,5 +12,6 @@ COPY . .
912
RUN CGO_ENABLED=0 go build -installsuffix 'static' -o /app .
1013

1114
FROM scratch as final
15+
COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
1216
COPY --from=builder /app /app
1317
ENTRYPOINT ["/app"]

constants.go

+2
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ const (
1818
)
1919

2020
const FailedHeartbeatAcks = 5 * time.Millisecond
21+
22+
const APIBase = "https://discordapp.com/api/v6"

http.go

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package main
2+
3+
import (
4+
"encoding/json"
5+
"github.com/labstack/gommon/log"
6+
"io/ioutil"
7+
"net/http"
8+
"strings"
9+
"time"
10+
)
11+
12+
func (s *Shard) GatewayBot() (st *GatewayBotResponse, err error) {
13+
14+
client := &http.Client{Timeout: time.Second * 10}
15+
16+
req, err := http.NewRequest("GET", APIBase+"/gateway/bot", nil)
17+
18+
req.Header.Set("Authorization", "Bot "+s.Token)
19+
20+
response, err := client.Do(req)
21+
if err != nil {
22+
log.Fatal("Error getting Gateway data: ", err)
23+
return
24+
}
25+
26+
defer func() {
27+
err := response.Body.Close()
28+
if err != nil {
29+
return
30+
}
31+
}()
32+
33+
body, err := ioutil.ReadAll(response.Body)
34+
if err != nil {
35+
log.Fatal("error reading gateway response body ", err)
36+
}
37+
38+
err = json.Unmarshal(body, &st)
39+
if err != nil {
40+
return
41+
}
42+
43+
// Ensure the gateway always has a trailing slash.
44+
// MacOS will fail to connect if we add query params without a trailing slash on the base domain.
45+
if !strings.HasSuffix(st.URL, "/") {
46+
st.URL += "/"
47+
}
48+
49+
return
50+
}

main.go

+33-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,38 @@
11
package main
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
"github.com/labstack/gommon/log"
6+
"os"
7+
"os/signal"
8+
"syscall"
9+
)
410

511
func main() {
6-
fmt.Println("Testing")
12+
log.SetLevel(log.INFO)
13+
token := os.Getenv("TOKEN")
14+
client := Shard{Token: token}
15+
GatewayData, err := client.GatewayBot()
16+
if err != nil {
17+
log.Fatal("Unable to get GatewayBot data")
18+
}
19+
shards := make([]Shard, GatewayData.Shards)
20+
initSequence := int64(0)
21+
for sid, shard := range shards {
22+
shard.Sequence = &initSequence
23+
shard.SessionID = ""
24+
shard.Token = token
25+
shard.ShardCount = GatewayData.Shards
26+
shard.ShardId = sid
27+
_ = shard.Open(GatewayData.URL)
28+
}
29+
30+
// Wait here until CTRL-C or other term signal is received.
31+
fmt.Println("Bot is now running. Press CTRL-C to exit.")
32+
sc := make(chan os.Signal, 1)
33+
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill)
34+
<-sc
35+
36+
// Cleanly close down the Discord session.
37+
_ = client.Close()
738
}

structs.go

+5
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,11 @@ type ResumePayload struct {
8989
Data ResumeData `json:"d"`
9090
}
9191

92+
type GatewayBotResponse struct {
93+
URL string `json:"url"`
94+
Shards int `json:"shards"`
95+
}
96+
9297
/* Gateway objects */
9398

9499
type User struct {

ws.go

+16-10
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,15 @@ func (s *Shard) Open(gateway string) error {
4747
return ErrWSAlreadyOpen
4848
}
4949
s.Gateway = gateway
50-
gateway = gateway + "?v=6&encoding=json&compress=zlib-stream"
50+
gateway = gateway + "?v=6&encoding=json"
5151

52-
log.Info("Shard %d connecting to gateway", s.ShardId)
52+
log.Infof("Shard %d connecting to gateway", s.ShardId)
5353
header := http.Header{}
5454
header.Add("accept-encoding", "zlib")
5555

5656
s.Conn, _, err = websocket.DefaultDialer.Dial(gateway, header)
5757
if err != nil {
58-
log.Warn("error connecting to gateway on shard %d", err)
58+
log.Warnf("error connecting to gateway on shard %d", err)
5959
s.Conn = nil
6060
return err
6161
}
@@ -176,6 +176,7 @@ func (s *Shard) onPayload(wsConn *websocket.Conn, listening <-chan interface{})
176176
s.RUnlock()
177177

178178
if sameConnection {
179+
log.Warnf("error reading from gateway on shard %d: %s", s.ShardId, err)
179180
err := s.Close()
180181
if err != nil {
181182
log.Warn("error closing connection, %s", err)
@@ -203,30 +204,34 @@ func (s *Shard) Dispatch(messageType int, message []byte) (*GatewayPayload, erro
203204
var err error
204205
var e *GatewayPayload
205206
buffer = bytes.NewBuffer(message)
206-
207+
log.Debugf("Got event on shard %d", s.ShardId)
207208
if messageType == websocket.BinaryMessage {
208209
decompressor, zerr := zlib.NewReader(buffer)
209210
if zerr != nil {
210-
log.Error("error decompressing message: %s", zerr)
211+
log.Errorf("error decompressing message: %s", zerr)
212+
return nil, zerr
211213
}
212214

213215
defer func() {
214216
zerr := decompressor.Close()
215217
if zerr != nil {
216-
log.Warn("error closing zlib: %s", zerr)
218+
log.Warnf("error closing zlib: %s", zerr)
219+
return
217220
}
218221
}()
219222

220223
buffer = decompressor
221224
}
222225

226+
log.Debugf("Decompressed message on shard %d", s.ShardId)
227+
223228
decoder := json.NewDecoder(buffer)
224229
if err = decoder.Decode(&e); err != nil {
225230
log.Error("error decoding message: %s", err)
226231
return e, err
227232
}
228233

229-
log.Debug("Op: %d, Seq: %d, Type: %s, Data: %s\n\n", e.Op, e.Sequence, e.Event, string(e.Data))
234+
log.Debugf("Op: %d, Seq: %d, Type: %s, Data: %s\n\n", e.Op, e.Sequence, e.Event, string(e.Data))
230235

231236
switch e.Op {
232237
case OP_HEARTBEAT:
@@ -246,7 +251,7 @@ func (s *Shard) Dispatch(messageType int, message []byte) (*GatewayPayload, erro
246251
case OP_INVALID_SESSION:
247252
err = s.Identify()
248253
if err != nil {
249-
log.Error("error identifying with gateway: %s", err)
254+
log.Errorf("error identifying with gateway: %s", err)
250255
return e, err
251256
}
252257
return e, nil
@@ -256,14 +261,15 @@ func (s *Shard) Dispatch(messageType int, message []byte) (*GatewayPayload, erro
256261
s.Lock()
257262
s.LastHeartbeatAck = time.Now().UTC()
258263
s.Unlock()
259-
log.Debug("got heartbeat ACK")
264+
log.Debugf("got heartbeat ACK")
260265
return e, nil
261266
case OP_DISPATCH:
262267
// Dispatch the message
263268
atomic.StoreInt64(s.Sequence, e.Sequence)
269+
log.Debugf("Got event %s on shard %d", e.Event, s.ShardId)
264270
return e, nil
265271
default:
266-
log.Warn("Unknown Op: %d", e.Op)
272+
log.Warnf("Unknown Op: %d", e.Op)
267273
return e, nil
268274
}
269275
}

0 commit comments

Comments
 (0)