sclass WebBotTester implements AutoCloseable { S botURL; // without the "/incremental" S cookie = "test_" + aGlobalID(); int n; // number of messages grabbed Thread grabThread; volatile bool closed; LS allHtml = syncList(); new L msgs; double readTimeout = 120.0, sendTimeout = 20.0; double waitForMessagesTimeout = 20.0; SS params = new LinkedHashMap; *(S botID) { botURL = "https://botcompany.de/" + psI(botID) + "/raw"; } public void close { set closed; cancelAndInterruptThread(grabThread); } selfType start() { if (grabThread == null) grabThread = startThread(r _grabLoop); this; } void _grabLoop { while (!closed) { S html = loadPageWithTimeout(botURL + "/incremental" + hquery(mapPlus(params, +cookie, a := n)), readTimeout); allHtml.add(html); printWithIndent("> ", html); msgs.addAll(webBotTester_extractMsgs(html)); S comment = first(getHTMLComments(html)); int n = parseFirstIntOrMinus1(comment); if (n >= 0) this.n = n; sleepSeconds(1); } } void sendMsg(S message) { print(doPostWithTimeout(mapPlus(params, +cookie, +message), botURL + "/msg", toMS_int(sendTimeout))); } void waitForMessages(int n) { waitUntil(50, waitForMessagesTimeout, () -> l(msgs) >= n); } }