116 lines
3.5 KiB
JavaScript
116 lines
3.5 KiB
JavaScript
"use strict";
|
|
self.importScripts("/static/scripts/v5shoutbox_irc.js");
|
|
|
|
function log(...args) {
|
|
const time = new Date().toISOString();
|
|
console.log(`[${time}]`, ...args);
|
|
}
|
|
|
|
let irc = null;
|
|
let clients = [];
|
|
|
|
function broadcast(obj) {
|
|
log(obj.type === "log" ? obj.text : obj);
|
|
obj.ircState = irc.state();
|
|
clients.forEach(c => c.postMessage(obj));
|
|
}
|
|
|
|
function activate() {
|
|
if(irc !== null)
|
|
return;
|
|
|
|
log("activating!");
|
|
irc = new IRCClient("wss://irc.planet-casio.com:443");
|
|
|
|
// TODO: Send certain messages only to specific clients
|
|
// (ie. history)
|
|
|
|
irc.onDebugLog = (ctgy, message) =>
|
|
broadcast({ type: "onDebugLog", ctgy: ctgy, message: message });
|
|
|
|
irc.onConnChanged = (conn) =>
|
|
broadcast({ type: "onConnChanged", conn: conn });
|
|
|
|
irc.onAuthResult = (successful) =>
|
|
broadcast({ type: "onAuthResult", successful: successful });
|
|
|
|
irc.onChannelChanged = (channel, info) =>
|
|
broadcast({ type: "onChannelChanged", channel: channel, info: info });
|
|
|
|
irc.onNewMessage = (id, channel, date, author, message) =>
|
|
broadcast({
|
|
type: "onNewMessage",
|
|
id: id,
|
|
channel: channel,
|
|
date: date,
|
|
author: author,
|
|
message: message,
|
|
});
|
|
|
|
irc.onHistoryReceived = (channel, history) =>
|
|
broadcast({
|
|
type: "onHistoryReceived",
|
|
channel: channel,
|
|
history: history,
|
|
});
|
|
}
|
|
|
|
|
|
/* Activate eagerly as soon as the worker gets updated. Normally, when a worker
|
|
is updated, the previous version still gets to control new pages until all
|
|
of its controlled pages are closed simultaneously. We skip this, so new
|
|
pages will get the latest shoutbox service worker as soon as possible. */
|
|
self.addEventListener("install", (e) => {
|
|
log("installing!");
|
|
/* This promise is guaranteed OK to ignore by API */
|
|
self.skipWaiting();
|
|
});
|
|
|
|
/* As soon as the worker activates, we claim existing clients. This means that
|
|
not only new pages will use the updated worker, but running ones will also
|
|
transition to it, giving us transparent background updates. We handle
|
|
protocol differences manually; if the main script cannot handle the new
|
|
shoutbox version it will simply ask for a reload. Doing this allows us to
|
|
take control of the shoutbox without a page refresh when it is loaded for
|
|
the first time. */
|
|
self.addEventListener("activate", (e) => {
|
|
activate();
|
|
e.waitUntil(self.clients.claim());
|
|
});
|
|
|
|
self.addEventListener("message", (e) => {
|
|
/* Messages handled by the worker itself */
|
|
if(e.data.type == "handshake") {
|
|
activate();
|
|
clients.push(e.source);
|
|
log(`New client: ${e.source.id} (total ${clients.length})`);
|
|
log("All clients:", clients);
|
|
e.source.postMessage({ type: "welcome", ircState: irc.state() });
|
|
}
|
|
// TODO: Add a mechanism to filter with self.clients.matchAll() since
|
|
// sometimes this message does not arrive and we have ghost clients
|
|
else if(e.data.type == "leave") {
|
|
clients = clients.filter(c => c.id != e.source.id);
|
|
log(`Client left: ${e.source.id} (remains ${clients.length})`);
|
|
log("All clients:", clients);
|
|
}
|
|
|
|
/* Messages that are forwarded directly to the IRC client */
|
|
else if(e.data.type == "connect") {
|
|
log("<connect call, not shown>");
|
|
irc.connect(e.data.login, e.data.password);
|
|
}
|
|
else if(e.data.type == "postMessage") {
|
|
log(e);
|
|
irc.postMessage(e.data.channel, e.data.message);
|
|
}
|
|
else if(e.data.type == "disconnect") {
|
|
log("Disconnect requested");
|
|
irc.disconnect();
|
|
}
|
|
else if(e.data.type == "getHistory") {
|
|
log(`History request for ${e.data.channel}`);
|
|
irc.getHistory(e.data.channel);
|
|
}
|
|
});
|