!7 static Map wsToState = weakHashMap(); static int interval = 200, initialChars = 65536; //static long timeout = 10*60000L; // larger timeout since we have no idle mechanism yet (todo) static long timeout = 30000+10000; // idle time + latency static File fileToLog() { ret mechVersionsLog(); } p { webSocketManager = new WebSocketManager { void onNewWebSocket(O ws, S uri) { super.onNewWebSocket(ws, uri); set(ws, 'timeout, timeout); } void onWebSocketMessage(O ws, S s) { File f = fileToLog(); long len = fileSize(f); new Matches m; if "look back * chars pw *" // TODO: filter if it appears in Eleu log if (neq(masterPW(), $2)) { call(ws, 'send, "bad pw"); call(ws, 'close); } else wsToState.put(ws, max(0, len-parseLong($1))); } }; doEvery(interval, f update); } html { ret "Use WebSocket: " + subBot_myWebSocketURI(); } svoid update { if (webSocketManager.isEmpty()) ret; File f = fileToLog(); long len = fileSize(f); for (O ws : webSocketManager.webSockets()) { Long l = wsToState.get(ws); if (l != null && len > l) { // no cmd yet? ignore S newStuff = unquoteAllLines(loadTextFilePart(f, l, len)); wsToState.put(ws, len); call(ws, 'send, "+" + newStuff); } } }