1
1
package gchatmeow
2
2
3
3
import (
4
- _ "bytes"
5
4
"context"
6
5
"encoding/base64"
7
6
"encoding/binary"
@@ -18,7 +17,6 @@ import (
18
17
"strconv"
19
18
"strings"
20
19
"time"
21
- _ "unicode/utf16"
22
20
"unicode/utf8"
23
21
24
22
"go.mau.fi/util/pblite"
45
43
lenRegex = regexp .MustCompile (lenRegexPattern )
46
44
)
47
45
48
- // Channel represents a BrowserChannel client
49
46
type Channel struct {
50
47
session * Session
51
48
maxRetries int
@@ -65,12 +62,10 @@ type Channel struct {
65
62
OnReceiveArray * Event
66
63
}
67
64
68
- // ChunkParser parses data from the backward channel into chunks
69
65
type ChunkParser struct {
70
66
buf []byte
71
67
}
72
68
73
- // NewChunkParser creates a new ChunkParser instance
74
69
func NewChunkParser () * ChunkParser {
75
70
return & ChunkParser {
76
71
buf : make ([]byte , 0 ),
@@ -181,12 +176,10 @@ func NewChannel(session *Session, maxRetries, retryBackoffBase int) (*Channel, e
181
176
}, nil
182
177
}
183
178
184
- // IsConnected returns whether the channel is currently connected
185
179
func (c * Channel ) IsConnected () bool {
186
180
return c .isConnected
187
181
}
188
182
189
- // Listen listens for messages on the backwards channel
190
183
func (c * Channel ) Listen (ctx context.Context , maxAge time.Duration ) error {
191
184
retries := 0
192
185
skipBackoff := false
@@ -205,12 +198,12 @@ func (c *Channel) Listen(ctx context.Context, maxAge time.Duration) error {
205
198
}
206
199
207
200
if retries > 0 && ! skipBackoff {
208
- backoffSeconds := time .Duration (pow (c .retryBackoffBase , retries )) * time .Second
209
- log .Printf ("Backing off for %v seconds" , backoffSeconds )
201
+ backoffTime := time .Duration (pow (c .retryBackoffBase , retries )) * time .Second
202
+ log .Printf ("Backing off for %v seconds" , backoffTime )
210
203
select {
211
204
case <- ctx .Done ():
212
205
return ctx .Err ()
213
- case <- time .After (backoffSeconds ):
206
+ case <- time .After (backoffTime ):
214
207
}
215
208
}
216
209
skipBackoff = false
@@ -250,13 +243,12 @@ func (c *Channel) Listen(ctx context.Context, maxAge time.Duration) error {
250
243
return fmt .Errorf ("ran out of retries for long-polling request" )
251
244
}
252
245
253
- // register registers a new channel and returns the csessionid
254
246
func (c * Channel ) register (ctx context.Context ) (string , error ) {
255
247
c .sidParam = ""
256
248
c .aid = 0
257
249
c .ofs = 0
258
250
259
- resp , err := c .session .FetchRaw (ctx , "GET" , channelURLBase + "register?ignore_compass_cookie=1" , nil , http.Header {
251
+ resp , err := c .session .FetchRaw (ctx , http . MethodGet , channelURLBase + "register?ignore_compass_cookie=1" , nil , http.Header {
260
252
"Content-Type" : {"application/x-protobuf" },
261
253
}, true , nil )
262
254
if err != nil {
@@ -281,13 +273,13 @@ func (c *Channel) register(ctx context.Context) (string, error) {
281
273
return "" , nil
282
274
}
283
275
284
- func (c * Channel ) sendStreamEvent (ctx context.Context , request proto.StreamEventsRequest ) error {
276
+ func (c * Channel ) sendStreamEvent (ctx context.Context , request * proto.StreamEventsRequest ) error {
285
277
params := url.Values {
286
278
"VER" : []string {"8" }, // channel protocol version
287
279
"RID" : []string {fmt .Sprintf ("%d" , c .rid )}, // request identifier
288
280
"t" : []string {"1" }, // trial
289
281
"SID" : []string {c .sidParam }, // session ID
290
- "AID" : []string {string (c .aid )}, // last acknowledged id
282
+ "AID" : []string {strconv . Itoa (c .aid )}, // last acknowledged id
291
283
}
292
284
c .rid ++
293
285
@@ -296,7 +288,7 @@ func (c *Channel) sendStreamEvent(ctx context.Context, request proto.StreamEvent
296
288
"Content-Type" : []string {"application/x-www-form-urlencoded" },
297
289
}
298
290
299
- protoBytes , err := pblite .Marshal (& request )
291
+ protoBytes , err := pblite .Marshal (request )
300
292
if err != nil {
301
293
return fmt .Errorf ("failed to marshal events request: %w" , err )
302
294
}
@@ -314,7 +306,7 @@ func (c *Channel) sendStreamEvent(ctx context.Context, request proto.StreamEvent
314
306
}
315
307
c .ofs ++
316
308
317
- res , err := c .session .FetchRaw (ctx , "POST" , channelURLBase + "events" , params , headers , true , []byte (formData .Encode ()))
309
+ res , err := c .session .FetchRaw (ctx , http . MethodPost , channelURLBase + "events" , params , headers , true , []byte (formData .Encode ()))
318
310
if err != nil {
319
311
return err
320
312
}
@@ -328,10 +320,9 @@ func (c *Channel) sendInitialPing(ctx context.Context) error {
328
320
interactiveState := proto .PingEvent_INTERACTIVE
329
321
notificationsEnabled := true
330
322
event := proto.PingEvent {State : & state , ApplicationFocusState : & focusState , ClientInteractiveState : & interactiveState , ClientNotificationsEnabled : & notificationsEnabled }
331
- return c .sendStreamEvent (ctx , proto.StreamEventsRequest {PingEvent : & event })
323
+ return c .sendStreamEvent (ctx , & proto.StreamEventsRequest {PingEvent : & event })
332
324
}
333
325
334
- // longPollRequest opens a long-polling request and receives arrays
335
326
func (c * Channel ) longPollRequest (ctx context.Context ) error {
336
327
params := url.Values {
337
328
"VER" : {strconv .Itoa (protocolVersion )},
@@ -353,7 +344,7 @@ func (c *Channel) longPollRequest(ctx context.Context) error {
353
344
params .Set ("SID" , c .sidParam )
354
345
}
355
346
356
- resp , err := c .session .FetchRaw (ctx , "GET" , channelURLBase + "events" , params , http.Header {
347
+ resp , err := c .session .FetchRaw (ctx , http . MethodGet , channelURLBase + "events" , params , http.Header {
357
348
"referer" : {"https://chat.google.com/" },
358
349
}, true , nil )
359
350
if err != nil {
@@ -389,14 +380,14 @@ func (c *Channel) longPollRequest(ctx context.Context) error {
389
380
"VER" : []string {"8" },
390
381
"RID" : []string {"rpc" },
391
382
"SID" : []string {c .sidParam },
392
- "AID" : []string {string (c .aid )},
383
+ "AID" : []string {strconv . Itoa (c .aid )},
393
384
"CI" : []string {"0" },
394
385
"TYPE" : []string {"xmlhttp" },
395
386
"zx" : []string {uniqueID ()},
396
387
"t" : []string {"1" },
397
388
}
398
389
399
- if _ , err := c .session .FetchRaw (ctx , "GET" , channelURLBase + "events" , params , nil , true , nil ); err != nil {
390
+ if _ , err := c .session .FetchRaw (ctx , http . MethodGet , channelURLBase + "events" , params , nil , true , nil ); err != nil {
400
391
return fmt .Errorf ("failed to acknowledge sid" )
401
392
}
402
393
@@ -432,14 +423,10 @@ func (c *Channel) longPollRequest(ctx context.Context) error {
432
423
}
433
424
}
434
425
435
- // OnPushData handles incoming push data and triggers appropriate events
436
426
func (c * Channel ) onPushData (dataBytes []byte ) error {
437
427
// Log received chunk
438
428
log .Printf ("Received chunk:\n %s" , string (dataBytes ))
439
429
440
- // Update metrics
441
- // c.receivedChunks.Add(float64(len(dataBytes)))
442
-
443
430
// Process chunks
444
431
chunks := c .chunkParser .GetChunks (dataBytes )
445
432
@@ -478,7 +465,7 @@ func (c *Channel) onPushData(dataBytes []byte) error {
478
465
479
466
dataArray := innerArray [1 ]
480
467
481
- log .Printf ("Chunk contains data array with id %d :\n %v" , arrayID , dataArray )
468
+ log .Printf ("Chunk contains data array with id %f :\n %v" , arrayID , dataArray )
482
469
483
470
// Fire receive array event
484
471
c .OnReceiveArray .Fire (dataArray )
@@ -491,7 +478,6 @@ func (c *Channel) onPushData(dataBytes []byte) error {
491
478
return nil
492
479
}
493
480
494
- // Helper functions (implementations not shown for brevity)
495
481
func uniqueID () string {
496
482
// Implementation of _unique_id from Python code
497
483
return base64 .RawURLEncoding .EncodeToString ([]byte (fmt .Sprintf ("%d" , rand .Int63 ())))
0 commit comments