8
|
1 package socket
|
|
2
|
|
3 import (
|
|
4 "encoding/json"
|
|
5 "log"
|
|
6 "net/url"
|
|
7 "os"
|
|
8 "os/signal"
|
|
9 "strings"
|
|
10 "time"
|
|
11
|
|
12 "github.com/denniscmcom/pacobot/bot"
|
|
13 "github.com/denniscmcom/pacobot/event"
|
|
14 "github.com/gorilla/websocket"
|
|
15 )
|
|
16
|
|
17 func Connect(authToken string) {
|
|
18 interrupt := make(chan os.Signal, 1)
|
|
19 signal.Notify(interrupt, os.Interrupt)
|
|
20
|
|
21 baseUrl := url.URL{Scheme: "wss", Host: "eventsub.wss.twitch.tv", Path: "/ws"}
|
|
22
|
|
23 log.Println("socket: connecting...")
|
|
24 conn, _, err := websocket.DefaultDialer.Dial(baseUrl.String(), nil)
|
|
25
|
|
26 if err != nil {
|
|
27 log.Fatal(err)
|
|
28 }
|
|
29
|
|
30 defer conn.Close()
|
|
31
|
|
32 log.Println("socket: connected")
|
|
33
|
|
34 var timeout time.Ticker
|
10
|
35 done := make(chan struct{})
|
8
|
36
|
|
37 go readMsg(done, conn, &timeout, authToken)
|
|
38
|
|
39 for {
|
|
40 select {
|
|
41 case <-interrupt:
|
|
42 closeConn(conn)
|
|
43
|
|
44 select {
|
|
45 case <-done:
|
|
46 case <-time.After(time.Second):
|
|
47 }
|
|
48 return
|
|
49 case <-done:
|
|
50 log.Println("socket: connection closed by server")
|
|
51 Connect(authToken)
|
|
52 case <-timeout.C:
|
|
53 log.Println("socket: connection lost")
|
|
54 timeout.Stop()
|
|
55 Connect(authToken)
|
|
56 }
|
|
57 }
|
|
58 }
|
|
59
|
10
|
60 func readMsg(done chan struct{}, conn *websocket.Conn, timeout *time.Ticker, authToken string) {
|
|
61 defer close(done)
|
8
|
62 var timeout_secs time.Duration
|
|
63
|
|
64 for {
|
|
65 log.Println("socket: waiting for msg...")
|
|
66 _, msg, err := conn.ReadMessage()
|
|
67
|
|
68 if err != nil {
|
|
69 break
|
|
70 }
|
|
71
|
|
72 var resMetadata Res_Metadata
|
|
73
|
|
74 if err := json.Unmarshal(msg, &resMetadata); err != nil {
|
|
75 log.Fatal(err)
|
|
76 }
|
|
77
|
|
78 msgType := resMetadata.Metadata.MsgType
|
|
79 log.Printf("socket: %s msg received", msgType)
|
|
80
|
|
81 switch msgType {
|
|
82 case "session_welcome":
|
|
83 var resWelcome Res_Welcome
|
|
84
|
|
85 if err := json.Unmarshal(msg, &resWelcome); err != nil {
|
|
86 log.Fatal(err)
|
|
87 }
|
|
88
|
|
89 timeout_secs = time.Duration(resWelcome.Payload.Session.KeepaliveTimeout+3) * time.Second
|
|
90 timeout = time.NewTicker(timeout_secs)
|
|
91 defer timeout.Stop()
|
|
92
|
|
93 event.ChannelChatMsgSub(authToken, resWelcome.Payload.Session.Id)
|
|
94
|
|
95 case "session_keepalive":
|
|
96 timeout.Reset(timeout_secs)
|
|
97 log.Println("socket: timeout resetted")
|
|
98
|
|
99 case "notification":
|
|
100 var resMetadataNotif Res_Metadata_Notif
|
|
101
|
|
102 if err := json.Unmarshal(msg, &resMetadataNotif); err != nil {
|
|
103 log.Fatal(err)
|
|
104 }
|
|
105
|
|
106 subType := resMetadataNotif.Metadata.SubType
|
|
107 log.Printf("socket: %s event received", subType)
|
|
108
|
|
109 switch subType {
|
|
110 case "channel.chat.message":
|
|
111 var resNotifChannelChatMsg Res_Notif_ChannelChatMsg
|
|
112
|
|
113 if err := json.Unmarshal(msg, &resNotifChannelChatMsg); err != nil {
|
|
114 log.Fatal(err)
|
|
115 }
|
|
116
|
|
117 chatMsg := resNotifChannelChatMsg.Payload.Event.Msg.Text
|
|
118
|
|
119 if strings.HasPrefix(chatMsg, "!") {
|
11
|
120 if resNotifChannelChatMsg.Payload.Event.ChatterUserName == "denniscmartin" {
|
|
121 go bot.HandleCmd(strings.Split(chatMsg[1:], " "))
|
|
122 }
|
8
|
123 }
|
|
124 }
|
|
125 default:
|
10
|
126 log.Fatalf("socket: %s message type not implemented", msgType)
|
8
|
127 }
|
|
128 }
|
|
129 }
|
|
130
|
|
131 func closeConn(conn *websocket.Conn) {
|
|
132 err := conn.WriteMessage(
|
|
133 websocket.CloseMessage,
|
|
134 websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
|
135
|
|
136 if err != nil {
|
|
137 log.Fatal(err)
|
|
138 }
|
|
139
|
|
140 log.Println("socket: connection closed")
|
|
141 }
|
|
142
|
|
143 // func test() {
|
|
144 // var res Response
|
|
145
|
|
146 // // Deserializas
|
|
147 // err := json.Unmarshal([]byte(jsonData), &res)
|
|
148
|
|
149 // if err != nil {
|
|
150 // fmt.Println("Error al deserializar:", err)
|
|
151 // return
|
|
152 // }
|
|
153
|
|
154 // // Conviertes la estructura nuevamente a JSON formateado
|
|
155
|
|
156 // formattedJSON, err := json.MarshalIndent(res, "", " ")
|
|
157
|
|
158 // if err != nil {
|
|
159 // fmt.Println("Error al formatear JSON:", err)
|
|
160 // return
|
|
161 // }
|
|
162 // }
|