106 Zeilen
2.7 KiB
JavaScript
106 Zeilen
2.7 KiB
JavaScript
/**
|
|
* WebSocket-Client für Echtzeit-Updates.
|
|
*/
|
|
const WS = {
|
|
socket: null,
|
|
reconnectDelay: 2000,
|
|
maxReconnectDelay: 30000,
|
|
_handlers: {},
|
|
_pingInterval: null,
|
|
|
|
connect() {
|
|
const token = localStorage.getItem('osint_token');
|
|
if (!token) return;
|
|
|
|
const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
|
|
const url = `${protocol}//${window.location.host}/api/ws`;
|
|
|
|
try {
|
|
this.socket = new WebSocket(url);
|
|
} catch (e) {
|
|
console.error('WebSocket-Verbindungsfehler:', e);
|
|
this._scheduleReconnect();
|
|
return;
|
|
}
|
|
|
|
this.socket.onopen = () => {
|
|
// Token als erste Nachricht senden (nicht in URL)
|
|
this.socket.send(token);
|
|
};
|
|
|
|
this.socket.onmessage = (event) => {
|
|
if (event.data === 'pong') return;
|
|
if (event.data === 'authenticated') {
|
|
console.log('WebSocket verbunden');
|
|
this.reconnectDelay = 2000;
|
|
this._startPing();
|
|
return;
|
|
}
|
|
try {
|
|
const msg = JSON.parse(event.data);
|
|
this._dispatch(msg);
|
|
} catch (e) {
|
|
console.error('WebSocket Parse-Fehler:', e);
|
|
}
|
|
};
|
|
|
|
this.socket.onclose = () => {
|
|
console.log('WebSocket getrennt');
|
|
this._stopPing();
|
|
this._scheduleReconnect();
|
|
};
|
|
|
|
this.socket.onerror = () => {};
|
|
},
|
|
|
|
disconnect() {
|
|
this._stopPing();
|
|
if (this.socket) {
|
|
this.socket.close();
|
|
this.socket = null;
|
|
}
|
|
},
|
|
|
|
on(type, handler) {
|
|
if (!this._handlers[type]) {
|
|
this._handlers[type] = [];
|
|
}
|
|
this._handlers[type].push(handler);
|
|
},
|
|
|
|
_dispatch(msg) {
|
|
const handlers = this._handlers[msg.type] || [];
|
|
handlers.forEach(h => h(msg));
|
|
|
|
// Globale Handler
|
|
const allHandlers = this._handlers['*'] || [];
|
|
allHandlers.forEach(h => h(msg));
|
|
},
|
|
|
|
_startPing() {
|
|
this._pingInterval = setInterval(() => {
|
|
if (this.socket && this.socket.readyState === WebSocket.OPEN) {
|
|
this.socket.send('ping');
|
|
}
|
|
}, 30000);
|
|
},
|
|
|
|
_stopPing() {
|
|
if (this._pingInterval) {
|
|
clearInterval(this._pingInterval);
|
|
this._pingInterval = null;
|
|
}
|
|
},
|
|
|
|
_scheduleReconnect() {
|
|
setTimeout(() => {
|
|
if (!this.socket || this.socket.readyState === WebSocket.CLOSED) {
|
|
this.connect();
|
|
}
|
|
}, this.reconnectDelay);
|
|
|
|
this.reconnectDelay = Math.min(this.reconnectDelay * 1.5, this.maxReconnectDelay);
|
|
},
|
|
|
|
};
|