package net.bavrd.faces;
import java.util.Collections;
import org.vertx.java.core.Handler;
import org.vertx.java.core.MultiMap;
import org.vertx.java.core.buffer.Buffer;
import org.vertx.java.core.eventbus.Message;
import org.vertx.java.core.http.HttpClient;
import org.vertx.java.core.http.HttpClientResponse;
import org.vertx.java.core.http.HttpServerRequest;
import org.vertx.java.core.json.JsonObject;
import com.google.common.escape.Escaper;
import com.google.common.net.UrlEscapers;
import net.bavrd.core.EventEnum;
import net.bavrd.core.Face;
import net.bavrd.core.FaceMessage;
import net.bavrd.utils.VertxHandlers;
public class SlackFace extends Face {
private int port;
private String route;
private String botName;
private String token;
private String icon;
@Override
public void startBavrd() {
port = container.config().getInteger("port", 8080);
route = container.config().getString("route", "/incoming/slack/");
botName = container.config().getString("botName", "bavrd");
token = container.config().getString("api_token", "");
icon = container.config().getString("bot_icon", null);
vertx.createHttpServer()
.requestHandler(new Handler<HttpServerRequest>() {
@Override
public void handle(final HttpServerRequest req) {
if (!req.path().equalsIgnoreCase(route)
|| !req.method().equals("POST")) {
req.response().setStatusCode(404).end();
} else {
req.expectMultiPart(true);
req.bodyHandler(new Handler<Buffer>() {
@Override
public void handle(Buffer buffer) {
String payload = buffer.toString();
container.logger().debug(payload);
MultiMap attributes = req.formAttributes();
String trigger = attributes.get("trigger_word");
String message = attributes.get("text");
message = message.replaceFirst(trigger, "").trim();
String userId = attributes.get("user_id");
String userName = attributes.get("user_name");
String channelName = attributes.get("channel_name");
String channelId = attributes.get("channel_id");
//TODO verifications
FaceMessage incoming = FaceMessage.incoming(userId, userName, channelId, channelName, message);
vertx.eventBus().publish(EventEnum.INCOMING.vertxEndpoint, incoming.asJson());
req.response().end();
}
});
}
}
})
.listen(port);
final HttpClient slack = vertx.createHttpClient()
.setSSL(true)
.setTrustAll(true)
.setPort(443)
.setHost("slack.com");
vertx.eventBus().registerHandler(EventEnum.OUTGOING.vertxEndpoint, new Handler<Message<JsonObject>>() {
@Override
public void handle(Message<JsonObject> m) {
Escaper esc = UrlEscapers.urlFormParameterEscaper();
FaceMessage body = FaceMessage.decodeFrom(m.body());
//sanitize the text and convert to Slack formatting
String formattedText = formatText(body.message.trim());
StringBuffer payload = new StringBuffer()
.append("token=")
.append(esc.escape(token))
.append("&text=")
.append(esc.escape(formattedText))
.append("&username=")
.append(esc.escape(botName));
if (icon != null) {
if (icon.startsWith(":"))
payload.append("&icon_emoji=");
else
payload.append("&icon_url=");
payload.append(esc.escape(icon));
}
if (body.isReply && body.isPrivate)
payload.append("&channel=").append(esc.escape("@"+body.userId));
else
payload.append("&channel=").append(esc.escape(body.channelId));
Handler<HttpClientResponse> responseHandler;
if (container.logger().isDebugEnabled())
responseHandler = new Handler<HttpClientResponse>() {
@Override
public void handle(HttpClientResponse response) {
container.logger().debug(response.statusCode() + " : " + response.statusMessage());
}
};
else
responseHandler = VertxHandlers.noOpHandler();
slack.post("/api/chat.postMessage", responseHandler)
.putHeader("Content-Type", "application/x-www-form-urlencoded")
.end(payload.toString());
}
});
}
@Override
protected String formatBold(String text) {
return "*"+text+"*";
}
@Override
protected String formatItalic(String text) {
return "_"+text+"_";
}
@Override
protected String formatCode(String text) {
return "`"+text+"`";
}
@Override
protected String formatImg(String imageSrc, String imageAlt) {
//no image support in Slack, try to give a link to image with alt text as label if possible
if (imageAlt.length() > 0)
return "<"+imageSrc+"|"+imageAlt+">";
return imageSrc;
}
@Override
protected String formatNewLine() {
return "\n";
}
@Override
public java.util.Map<String, String> getHelp() {
return Collections.emptyMap();
}
}