sclass CruddieFollower { S cookie; int n; double timeout = 70; swappable void newDialog() {} swappable void botUtterance(S html) { print("Bot said (HTML): " + html); vmBus_send cruddieSaid(cookie, html); } swappable void onUserUtterance(S html) {} // TODO swappable void onBotUtterance(S html) {} *(S cookie) { this(cookie, false); } *(S *cookie, bool withHistory) { if (!withHistory) n = parseInt(loadPageWithParamsSilently("https://cruddie.site/bot/n", +cookie); } // may block for 60 seconds. returns HTML public S get() { // TODO: I think cruddie.site doesn't close existing connections when rebooting (?) S src = loadPageWithTimeoutAndParamsSilently(timeout, "https://cruddie.site/bot/incremental", +cookie, a := zeroToNull(n)); S newN = firstIntAsString_regexp(src); if (nempty(newN)) { n = parseInt(newN); if (cic(src, "NEW DIALOG -->")) newDialog(); else doForEach botUtterance(regexpAllFirstGroups( [[bot-utterance">(.*?)<]], src)); } ret src; } }