93 lines
3.0 KiB
JavaScript
93 lines
3.0 KiB
JavaScript
|
|
// Jackbox Chat Tracker - Injected Script v3.2.0
|
||
|
|
// This script intercepts Kosmi's WebSocket connection to capture chat messages
|
||
|
|
// NOTE: This runs in the PAGE CONTEXT, not extension context!
|
||
|
|
|
||
|
|
// Store original WebSocket constructor
|
||
|
|
const OriginalWebSocket = window.WebSocket;
|
||
|
|
|
||
|
|
// Hook WebSocket constructor to capture Kosmi's WebSocket
|
||
|
|
window.WebSocket = function(url, protocols) {
|
||
|
|
const socket = new OriginalWebSocket(url, protocols);
|
||
|
|
|
||
|
|
// Check if this is Kosmi's GraphQL WebSocket
|
||
|
|
if (url.includes('engine.kosmi.io') || url.includes('gql-ws')) {
|
||
|
|
console.log('[Jackbox Chat Tracker] WebSocket hook active');
|
||
|
|
|
||
|
|
// Notify content script that we found the socket
|
||
|
|
window.postMessage({
|
||
|
|
type: 'JACKBOX_TRACKER_SOCKET_FOUND',
|
||
|
|
url: url
|
||
|
|
}, '*');
|
||
|
|
|
||
|
|
// Method 1: Hook addEventListener (for event listeners added later)
|
||
|
|
const originalAddEventListener = socket.addEventListener.bind(socket);
|
||
|
|
socket.addEventListener = function(type, listener, options) {
|
||
|
|
if (type === 'message') {
|
||
|
|
const wrappedListener = function(event) {
|
||
|
|
// Forward to content script
|
||
|
|
try {
|
||
|
|
const data = JSON.parse(event.data);
|
||
|
|
window.postMessage({
|
||
|
|
type: 'JACKBOX_TRACKER_WS_MESSAGE',
|
||
|
|
data: data
|
||
|
|
}, '*');
|
||
|
|
} catch (e) {
|
||
|
|
// Not JSON, skip
|
||
|
|
}
|
||
|
|
|
||
|
|
// Then forward to original listener
|
||
|
|
return listener.call(this, event);
|
||
|
|
};
|
||
|
|
return originalAddEventListener(type, wrappedListener, options);
|
||
|
|
}
|
||
|
|
return originalAddEventListener(type, listener, options);
|
||
|
|
};
|
||
|
|
|
||
|
|
// Method 2: Intercept the onmessage property setter (for direct assignment)
|
||
|
|
let realOnMessage = null;
|
||
|
|
const descriptor = Object.getOwnPropertyDescriptor(WebSocket.prototype, 'onmessage');
|
||
|
|
|
||
|
|
Object.defineProperty(socket, 'onmessage', {
|
||
|
|
get: function() {
|
||
|
|
return realOnMessage;
|
||
|
|
},
|
||
|
|
set: function(handler) {
|
||
|
|
// Create wrapped handler
|
||
|
|
realOnMessage = function(event) {
|
||
|
|
// Forward to content script
|
||
|
|
try {
|
||
|
|
const data = JSON.parse(event.data);
|
||
|
|
window.postMessage({
|
||
|
|
type: 'JACKBOX_TRACKER_WS_MESSAGE',
|
||
|
|
data: data
|
||
|
|
}, '*');
|
||
|
|
} catch (e) {
|
||
|
|
// Not JSON, skip
|
||
|
|
}
|
||
|
|
|
||
|
|
// ALWAYS call original handler
|
||
|
|
if (handler) {
|
||
|
|
handler.call(socket, event);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// Actually set it on the underlying WebSocket using the original descriptor
|
||
|
|
if (descriptor && descriptor.set) {
|
||
|
|
descriptor.set.call(socket, realOnMessage);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
configurable: true
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return socket;
|
||
|
|
};
|
||
|
|
|
||
|
|
// Preserve the original constructor properties
|
||
|
|
window.WebSocket.prototype = OriginalWebSocket.prototype;
|
||
|
|
window.WebSocket.CONNECTING = OriginalWebSocket.CONNECTING;
|
||
|
|
window.WebSocket.OPEN = OriginalWebSocket.OPEN;
|
||
|
|
window.WebSocket.CLOSING = OriginalWebSocket.CLOSING;
|
||
|
|
window.WebSocket.CLOSED = OriginalWebSocket.CLOSED;
|
||
|
|
|