@Override
  public SlackMessageHandle sendMessage(
      SlackChannel channel,
      String message,
      SlackAttachment attachment,
      SlackChatConfiguration chatConfiguration) {
    SlackMessageHandleImpl handle = new SlackMessageHandleImpl(getNextMessageId());
    Map<String, String> arguments = new HashMap<>();
    arguments.put("token", authToken);
    arguments.put("channel", channel.getId());
    arguments.put("text", message);
    if (chatConfiguration.asUser) {
      arguments.put("as_user", "true");
    }
    if (chatConfiguration.avatar == Avatar.ICON_URL) {
      arguments.put("icon_url", chatConfiguration.avatarDescription);
    }
    if (chatConfiguration.avatar == Avatar.EMOJI) {
      arguments.put("icon_emoji", chatConfiguration.avatarDescription);
    }
    if (chatConfiguration.userName != null) {
      arguments.put("username", chatConfiguration.userName);
    }
    if (attachment != null) {
      arguments.put(
          "attachments", SlackJSONAttachmentFormatter.encodeAttachments(attachment).toString());
    }

    postSlackCommand(arguments, CHAT_POST_MESSAGE_COMMAND, handle);
    return handle;
  }
 @Override
 public SlackMessageHandle leaveChannel(SlackChannel channel) {
   SlackMessageHandleImpl handle = new SlackMessageHandleImpl(getNextMessageId());
   Map<String, String> arguments = new HashMap<>();
   arguments.put("token", authToken);
   arguments.put("channel", channel.getId());
   postSlackCommand(arguments, CHANNELS_LEAVE_COMMAND, handle);
   return handle;
 }
 @Override
 public SlackMessageHandle deleteMessage(String timeStamp, SlackChannel channel) {
   SlackMessageHandleImpl handle = new SlackMessageHandleImpl(getNextMessageId());
   Map<String, String> arguments = new HashMap<>();
   arguments.put("token", authToken);
   arguments.put("channel", channel.getId());
   arguments.put("ts", timeStamp);
   postSlackCommand(arguments, CHAT_DELETE_COMMAND, handle);
   return handle;
 }
 @Override
 public SlackMessageHandle addReactionToMessage(
     SlackChannel channel, String messageTimeStamp, String emojiCode) {
   SlackMessageHandleImpl handle = new SlackMessageHandleImpl(getNextMessageId());
   Map<String, String> arguments = new HashMap<>();
   arguments.put("token", authToken);
   arguments.put("channel", channel.getId());
   arguments.put("timestamp", messageTimeStamp);
   arguments.put("name", emojiCode);
   postSlackCommand(arguments, REACTIONS_ADD_COMMAND, handle);
   return handle;
 }
 @Override
 public SlackMessageHandle sendMessageOverWebSocket(
     SlackChannel channel, String message, SlackAttachment attachment) {
   SlackMessageHandleImpl handle = new SlackMessageHandleImpl(getNextMessageId());
   try {
     JSONObject messageJSON = new JSONObject();
     messageJSON.put("type", "message");
     messageJSON.put("channel", channel.getId());
     messageJSON.put("text", message);
     if (attachment != null) {
       messageJSON.put("attachments", SlackJSONAttachmentFormatter.encodeAttachments(attachment));
     }
     websocketSession.getBasicRemote().sendText(messageJSON.toJSONString());
   } catch (Exception e) {
     // TODO : improve exception handling
     e.printStackTrace();
   }
   return handle;
 }