Files
jackboxpartypack-gamepicker/scripts/jackbox-player-count.go

113 lines
2.8 KiB
Go
Raw Normal View History

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
}