sclass GazelleTalkToBot {
  long botID; // Gazelle post ID
  S cookie = "test_" + aGlobalID();
  int n; // number of messages loaded
  double timeout = 70;
  new L<Msg> msgs;
  
  *(long *botID) {}

  swappable void onNewDialog() {}
  swappable void onNewMsg(Msg msg) {}
  
  // may block for timeout seconds
  void get() {
    // TODO: I think cruddie.site doesn't close existing connections when rebooting (?)
    S json = loadPageWithTimeoutAndParamsSilently(timeout, "https://gazelle.rocks/incremental",
      +cookie,
      _botConfig := "codePost=" + botID,
      json := 1,
      a := zeroToNull(n));
    
    Map map = decodeJSONMap(json);
    onResult(map);
  }
  
  swappable void onResult(Map map) {
    if (map.containsKey("n")) n = toInt(map.get("n"));
    if (isTrue(map.get("newDialog"))) onNewDialog();
    fOr (Map m : (L<Map>) map.get("msgs")) {
      new Msg msg;
      msg.fromUser = isTrue(m.get("fromUser"));
      msg.text = (S) m.get("text");
      msg.time = toLong(m.get("time"));
      msgs.add(msg);
      pcall { onNewMsg(msg); }
    }
  }
}