initial actual player count implementation
This commit is contained in:
112
scripts/jackbox-player-count.go
Normal file
112
scripts/jackbox-player-count.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/chromedp/chromedp"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
fmt.Println("Usage: go run jackbox-player-count.go <ROOM_CODE>")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
roomCode := strings.ToUpper(os.Args[1])
|
||||
count, err := getPlayerCount(roomCode)
|
||||
if err != nil {
|
||||
fmt.Printf("Error: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("%d\n", count)
|
||||
}
|
||||
|
||||
func getPlayerCount(roomCode string) (int, error) {
|
||||
// Suppress cookie errors
|
||||
opts := append(chromedp.DefaultExecAllocatorOptions[:],
|
||||
chromedp.Flag("headless", true),
|
||||
)
|
||||
|
||||
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
|
||||
defer cancel()
|
||||
|
||||
ctx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(func(s string, i ...interface{}) {
|
||||
msg := fmt.Sprintf(s, i...)
|
||||
if !strings.Contains(msg, "cookie") {
|
||||
log.Printf(msg)
|
||||
}
|
||||
}))
|
||||
defer cancel()
|
||||
|
||||
ctx, cancel = context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
|
||||
var playerCount int
|
||||
|
||||
err := chromedp.Run(ctx,
|
||||
chromedp.Navigate("https://jackbox.tv/"),
|
||||
chromedp.WaitVisible(`input[placeholder*="ENTER 4-LETTER CODE"]`),
|
||||
|
||||
// Inject WebSocket hook BEFORE joining
|
||||
chromedp.ActionFunc(func(ctx context.Context) error {
|
||||
return chromedp.Evaluate(`
|
||||
window.__jackboxPlayerCount = null;
|
||||
const OriginalWebSocket = window.WebSocket;
|
||||
window.WebSocket = function(...args) {
|
||||
const ws = new OriginalWebSocket(...args);
|
||||
const originalAddEventListener = ws.addEventListener;
|
||||
ws.addEventListener = function(type, listener, ...rest) {
|
||||
if (type === 'message') {
|
||||
const wrappedListener = function(event) {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.opcode === 'client/welcome' && data.result && data.result.here) {
|
||||
window.__jackboxPlayerCount = Object.keys(data.result.here).length;
|
||||
}
|
||||
} catch (e) {}
|
||||
return listener.call(this, event);
|
||||
};
|
||||
return originalAddEventListener.call(this, type, wrappedListener, ...rest);
|
||||
}
|
||||
return originalAddEventListener.call(this, type, listener, ...rest);
|
||||
};
|
||||
return ws;
|
||||
};
|
||||
`, nil).Do(ctx)
|
||||
}),
|
||||
|
||||
// Now join
|
||||
chromedp.SendKeys(`input[placeholder*="ENTER 4-LETTER CODE"]`, roomCode+"\n\n"),
|
||||
|
||||
// Poll for the value
|
||||
chromedp.ActionFunc(func(ctx context.Context) error {
|
||||
for i := 0; i < 60; i++ { // Try for 30 seconds
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
var count int
|
||||
err := chromedp.Evaluate(`window.__jackboxPlayerCount || -1`, &count).Do(ctx)
|
||||
if err == nil && count > 0 {
|
||||
playerCount = count
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("timeout waiting for player count")
|
||||
}),
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if playerCount < 0 {
|
||||
return 0, fmt.Errorf("could not find player count")
|
||||
}
|
||||
|
||||
return playerCount, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user