Files
KefinTweaks/helpers/websocketHelper.js
T

129 lines
4.6 KiB
JavaScript

(function() {
'use strict';
const LOG = (...args) => console.log('[KefinTweaks WebSocketHelper]', ...args);
const WARN = (...args) => console.warn('[KefinTweaks WebSocketHelper]', ...args);
const ERR = (...args) => console.error('[KefinTweaks WebSocketHelper]', ...args);
// Registry of event listeners: MessageType -> array of callbacks
const listeners = {};
// Track initialization state
let isInitialized = false;
let retries = 0;
const maxRetries = 10;
/**
* Initialize WebSocket monitoring by hooking into ApiClient's WebSocket
*/
function initialize() {
try {
// Grab the actual socket
const socket = (window.ApiClient && (window.ApiClient.webSocket || window.ApiClient._webSocket)) || null;
if (!socket) {
if (retries >= maxRetries) {
ERR('Max retries reached, giving up on WebSocket initialization');
return false;
}
retries++;
setTimeout(() => {
if (!isInitialized) {
initialize();
}
}, 1000);
return;
}
// Store original handler if it exists
const originalHandler = socket.onmessage;
// Hook into onmessage
socket.onmessage = function(event) {
try {
// Pass it through so Jellyfin still works normally
if (originalHandler) {
originalHandler.call(this, event);
}
// Parse the message data
const messageData = event.Data || event.data;
const data = typeof messageData === 'string' ? JSON.parse(messageData) : messageData;
// Get the MessageType
const messageType = data.MessageType;
if (messageType && listeners[messageType]) {
// Fire all callbacks for this message type
listeners[messageType].forEach(callback => {
try {
callback(data);
} catch (err) {
ERR(`Error in WebSocket listener for ${messageType}:`, err);
}
});
}
} catch (err) {
// Log parse errors but don't break the original handler
WARN('WebSocket message parse error:', err);
}
};
isInitialized = true;
LOG('WebSocket monitoring initialized');
return true;
} catch (err) {
ERR('Error initializing WebSocket monitoring:', err);
return false;
}
}
/**
* Register a callback to listen for a specific WebSocket message type
* @param {string} messageType - The MessageType to listen for (e.g., 'UserDataChanged', 'PlaybackStopped')
* @param {Function} callback - Function to call when the message type is received. Receives the parsed message data.
*/
function listen(messageType, callback) {
if (typeof messageType !== 'string' || !messageType) {
ERR('listen() requires a non-empty string messageType');
return;
}
if (typeof callback !== 'function') {
ERR('listen() requires a callback function');
return;
}
// Initialize listeners array for this message type if it doesn't exist
if (!listeners[messageType]) {
listeners[messageType] = [];
}
// Add the callback
listeners[messageType].push(callback);
LOG(`Registered listener for message type: ${messageType} (${listeners[messageType].length} total listeners)`);
// Ensure WebSocket is initialized
if (!isInitialized) {
initialize();
}
}
// Expose the API globally
window.websocketHelper = {
listen: listen
};
// Try to initialize immediately
if (!initialize()) {
// If WebSocket isn't available yet, retry after a short delay
// This can happen if the page loads before the WebSocket connection is established
setTimeout(() => {
if (!isInitialized) {
initialize();
}
}, 1000);
}
})();