master
1package main
2
3import (
4 "encoding/json"
5 "github.com/gorilla/websocket"
6 "go.uber.org/zap"
7 "strconv"
8 "time"
9)
10
11type GeneralsIO struct {
12 *websocket.Conn
13 Updates chan<- Update
14 Games chan<- Game
15}
16
17const (
18 ENGINEIO_OPEN = 0
19 ENGINEIO_CLOSE = 1
20 ENGINEIO_PING = 2
21 ENGINEIO_PONG = 3
22 ENGINEIO_MESSAGE = 4
23 SOCKETIO_CONNECT = 0
24 SOCKETIO_EVENT = 2
25)
26
27// Packet > Message > Event
28
29type Packet struct {
30 Type int
31 MessageType int
32 Payload []byte
33}
34
35func (g *GeneralsIO) Connect() (err error) {
36 dialer := &websocket.Dialer{}
37 dialer.EnableCompression = false
38 generals_url := "ws://botws.generals.io/socket.io/?EIO=3&transport=websocket"
39 conn, _, err := dialer.Dial(generals_url, nil)
40 if err != nil {
41 return err
42 }
43 g.Conn = conn
44 return err
45}
46
47func (g *GeneralsIO) Emit(msg ...interface{}) error {
48 w, err := g.NextWriter(websocket.TextMessage)
49 if err != nil {
50 return err
51 }
52 _, err = w.Write([]byte("42"))
53 j := json.NewEncoder(w)
54 return j.Encode(msg)
55}
56
57func (g *GeneralsIO) Ping(t int) {
58 for range time.Tick(time.Duration(t) * time.Second) {
59 l.Debug("Ping")
60 w, err := g.NextWriter(websocket.TextMessage)
61 if err != nil {
62 l.Fatal(err)
63 }
64 _, err = w.Write([]byte("2ping"))
65 if err != nil {
66 l.Fatal(err)
67 }
68 }
69}
70
71func DecodePacket(b []byte) (p Packet, err error) {
72 // TODO: b > 0
73 t, err := strconv.Atoi(string(b[0]))
74 if err != nil {
75 return p, err
76 }
77
78 switch t {
79 case ENGINEIO_OPEN, ENGINEIO_CLOSE, ENGINEIO_PING, ENGINEIO_PONG:
80 p.Type = t
81 p.Payload = b[1:]
82 case ENGINEIO_MESSAGE:
83 p.Type = t
84 mt, err := strconv.Atoi(string(b[1]))
85 if err != nil {
86 return p, err
87 }
88 p.MessageType = mt
89 p.Payload = b[2:]
90 }
91 return
92}
93
94func (g *GeneralsIO) RecievePackets() {
95 for {
96 _, packet, err := g.ReadMessage()
97 if err != nil {
98 l.Fatal(err)
99 }
100 p, err := DecodePacket(packet)
101 if err != nil {
102 l.Fatal(err)
103 }
104 switch p.Type {
105 case ENGINEIO_PONG:
106 l.Debug("Pong")
107 case ENGINEIO_OPEN:
108 l.Info("Open", zap.String("packet", string(p.Payload)))
109 case ENGINEIO_MESSAGE:
110 switch p.MessageType {
111 case SOCKETIO_CONNECT:
112 l.Debug("Connected")
113 case SOCKETIO_EVENT:
114 // generals.go
115 err = DecodeEvent(p.Payload, g.Updates, g.Games)
116 if err != nil {
117 l.Error("Unhandled Event", zap.String("packet", string(packet)), zap.Error(err))
118 }
119 default:
120 l.Error("Unhandled Message", zap.String("packet", string(packet)))
121 }
122 default:
123 l.Error("Unhandled Packet", zap.String("packet", string(packet)))
124 }
125
126 }
127
128}