static ServerError fromJSON(String jsonContent) {
   Object obj = JSONValue.parse(jsonContent);
   Map<?, ?> map = (Map) obj;
   if (map == null) return new ServerError();
   String condition = EncodingUtils.getJSON(map, JSON_COND);
   String text = EncodingUtils.getJSON(map, JSON_TEXT);
   return new ServerError(condition, text);
 }
  private static Message rawMessage(MessageContent content, Chat chat, boolean encrypted) {
    Message smackMessage = new Message();

    // text
    String text = content.getPlainText();
    if (!text.isEmpty()) smackMessage.setBody(content.getPlainText());

    // attachment
    MessageContent.Attachment att = content.getAttachment().orElse(null);
    if (att != null) {
      OutOfBandData oobData =
          new OutOfBandData(att.getURL().toString(), att.getMimeType(), att.getLength(), encrypted);
      smackMessage.addExtension(oobData);

      MessageContent.Preview preview = content.getPreview().orElse(null);
      if (preview != null) {
        String data = EncodingUtils.bytesToBase64(preview.getData());
        BitsOfBinary bob = new BitsOfBinary(preview.getMimeType(), data);
        smackMessage.addExtension(bob);
      }
    }

    // group command
    if (chat instanceof KonGroupChat) {
      KonGroupChat groupChat = (KonGroupChat) chat;
      KonGroupData gid = groupChat.getGroupData();
      MessageContent.GroupCommand groupCommand = content.getGroupCommand().orElse(null);
      smackMessage.addExtension(
          groupCommand != null
              ? ClientUtils.groupCommandToGroupExtension(groupChat, groupCommand)
              : new GroupExtension(gid.id, gid.owner.string()));
    }

    return smackMessage;
  }
  public OutMessage(Chat chat, List<Contact> contacts, MessageContent content, boolean encrypted) {
    super(
        chat,
        "Kon_" + EncodingUtils.randomString(8),
        content,
        Optional.empty(),
        Status.PENDING,
        encrypted ? CoderStatus.createToEncrypt() : CoderStatus.createInsecure());

    Set<Transmission> ts = new HashSet<>();
    contacts.forEach(
        contact -> {
          boolean succ = ts.add(new Transmission(contact, contact.getJID(), mID));
          if (!succ) LOGGER.warning("duplicate contact: " + contact);
        });
    mTransmissions = Collections.unmodifiableSet(ts);
  }
 private String toJSON() {
   JSONObject json = new JSONObject();
   EncodingUtils.putJSON(json, JSON_COND, condition);
   EncodingUtils.putJSON(json, JSON_TEXT, text);
   return json.toJSONString();
 }
 public String getFingerprint() {
   return EncodingUtils.bytesToHex(mAuthKey.getPublicKey().getFingerprint());
 }