Files
jackboxpartypack-gamepicker/chrome-extension/content.js

154 lines
4.5 KiB
JavaScript

// Jackbox Chat Tracker for Kosmi - Content Script v3.2.0
// This version intercepts the WebSocket connection directly
// Inject the hook script ASAP (before page JavaScript runs)
const script = document.createElement('script');
script.src = chrome.runtime.getURL('inject.js');
script.onload = function() {
this.remove();
};
(document.head || document.documentElement).appendChild(script);
let isTracking = false;
let votes = [];
let socketFound = false;
let socketUrl = null;
// Listen for messages from inject script (different JavaScript context!)
window.addEventListener('message', (event) => {
// Only accept messages from same origin
if (event.source !== window) return;
if (event.data.type === 'JACKBOX_TRACKER_SOCKET_FOUND') {
console.log('[Jackbox Chat Tracker] WebSocket connected');
socketFound = true;
socketUrl = event.data.url;
} else if (event.data.type === 'JACKBOX_TRACKER_WS_MESSAGE') {
// Message from WebSocket - only process if tracking
if (isTracking) {
handleGraphQLMessage(event.data.data);
}
}
});
// Initialize storage
chrome.storage.local.get(['isTracking', 'votes'], (result) => {
// Always default to NOT tracking on page load
isTracking = false;
votes = result.votes || [];
// Clear tracking state in storage (user must manually start)
chrome.storage.local.set({ isTracking: false });
});
// Listen for commands from popup
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.action === 'startTracking') {
startTracking();
sendResponse({ success: true });
} else if (request.action === 'stopTracking') {
stopTracking();
sendResponse({ success: true });
} else if (request.action === 'getVotes') {
sendResponse({ votes: votes });
} else if (request.action === 'resetVotes') {
votes = [];
chrome.storage.local.set({ votes: [] });
sendResponse({ success: true });
} else if (request.action === 'getStatus') {
sendResponse({ isTracking: isTracking, voteCount: votes.length });
}
return true; // Keep channel open for async response
});
let startTrackingAttempts = 0;
const MAX_TRACKING_ATTEMPTS = 10; // Try for max 10 seconds
function startTracking() {
try {
if (!socketFound) {
startTrackingAttempts++;
if (startTrackingAttempts >= MAX_TRACKING_ATTEMPTS) {
console.error('[Jackbox Chat Tracker] WebSocket not found. Please refresh the page and try again.');
startTrackingAttempts = 0;
notifyPopup();
return;
}
setTimeout(startTracking, 1000);
return;
}
// Found the WebSocket!
startTrackingAttempts = 0;
isTracking = true;
chrome.storage.local.set({ isTracking: true });
console.log('[Jackbox Chat Tracker] Tracking started - ready to capture votes');
notifyPopup();
} catch (error) {
console.error('[Jackbox Chat Tracker] Error starting tracking:', error);
startTrackingAttempts = 0;
notifyPopup();
}
}
function stopTracking() {
isTracking = false;
startTrackingAttempts = 0;
chrome.storage.local.set({ isTracking: false });
console.log('[Jackbox Chat Tracker] Tracking stopped');
notifyPopup();
}
function handleGraphQLMessage(data) {
if (!isTracking) return;
try {
// Check if this is a newMessage event
if (data.type === 'next' &&
data.payload &&
data.payload.data &&
data.payload.data.newMessage) {
const message = data.payload.data.newMessage;
const body = message.body;
const username = message.user.displayName || message.user.username || 'Unknown';
const timestamp = new Date(message.time * 1000).toISOString(); // Convert UNIX timestamp to ISO
// Check if message contains thisgame++ or thisgame--
if (/thisgame\+\+/i.test(body) || /thisgame--/i.test(body)) {
console.log('[Jackbox Chat Tracker] Vote detected:', username);
const vote = {
username: username,
message: body,
timestamp: timestamp
};
votes.push(vote);
chrome.storage.local.set({ votes: votes });
notifyPopup();
}
}
} catch (error) {
console.error('[Jackbox Chat Tracker] Error processing message:', error);
}
}
function notifyPopup() {
// Send update to popup if it's open
chrome.runtime.sendMessage({
action: 'votesUpdated',
votes: votes,
isTracking: isTracking
}).catch(() => {
// Popup is closed, ignore error
});
}