[Java][Slack] JBot Slash Commands for Slack

2017.03.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

前回ようやくECSでWebアプリケーションを公開しました。これでようやくBotのエンドポイントURLを確定できたので引き続きSlash Commandsを設定してみます。

Slash Commandsとは

Slackには / から始まるコマンドがいくつか設定されています。/invite @userId でチャンネルへの招待をするなど様々な操作を行うことができます。このコマンドをカスタマイズすることができます。Jbotではこの Slash Commands の機能も搭載しています。少々複雑な処理や引数をとって動作を変更したい場合等に利用することができるのではないでしょうか。

動作イメージは以下になります。 *1 /slash-command を実行すると指定されたエンドポイントへPOSTリクエストが発行されます。

スクリーンショット 2017-03-01 23.18.49

Slash Commandsを設定する

Slackのメニューから Apps & Integrations を選択します。

スクリーンショット 2017-03-01 20.26.35

Slash Commands を検索します。

スクリーンショット 2017-03-01 20.26.51

発見しました。設定を追加しましょう。

スクリーンショット 2017-03-01 22.26.04

Configurationを設定していきます。Integration Settings を以下の値で設定します。

パラメータ名 備考
Command /slash-command Slackで呼び出すコマンド
URL http://jbot-app-elb-xxxxxxxx.us-east-1.elb.amazonaws.com/slash-command 前回作成したALBに /slash-command を付与
Method POST
Token <表示されているトークン> こちらのトークンを application.propertiesslashCommandToken に予め入力しておく必要があります。
Customize Name slash-command コマンドの名前を入力します
Show this command in the autocomplete list チェック コマンドの説明などのHelpを表示します。
Description Call Slash Command for JBot Sample appliction 引数がある場合、 /invite @userid 等の凡例を入力します。
Usage hint /slash-command コマンドの引数などの凡例を入力します。

最後に Save Integration をクリックすると設定が保存されます。

動作を確認する

適当なチャンネルで /slash-c と打ってみます。Recommendされました。

スクリーンショット_2017-03-01_22_27_32

実行してみます。ECSへあげたアプリケーションの方が反応できたようです。

スクリーンショット 2017-03-01 22.29.59

Javaのコードを確認する

最後になりましたが、Javaのコードを確認してみましょう。 example.jbot.slack.SlackSlashCommand.java を確認します。

インタフェース

@RequestMapping(value = "/slash-command",
            method = RequestMethod.POST,
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    public RichMessage onReceiveSlashCommand(@RequestParam("token") String token,
                                             @RequestParam("team_id") String teamId,
                                             @RequestParam("team_domain") String teamDomain,
                                             @RequestParam("channel_id") String channelId,
                                             @RequestParam("channel_name") String channelName,
                                             @RequestParam("user_id") String userId,
                                             @RequestParam("user_name") String userName,
                                             @RequestParam("command") String command,
                                             @RequestParam("text") String text,
                                             @RequestParam("response_url") String responseUrl)

value = "/slash-command" はRequestMappingの設定です。こちらがSlash Commandsで呼び出されるURLのパスとなります。/slash-command で実行されるメソッドです。多くの入力値がありますが、こちらはSlackのAPIインタフェースに合わせて定義してあります。Slash Commandsのインタフェース定義は こちら を参照します。

凡例から読み解いてみます。

パラメータ名 説明
token Slash Commandのトークン。設定画面で生成したトークンが入力されます
team_id チームID。チームを特定する際に利用できるようです
team_domain チームドメイン?(コレは何に使うんだろう・・・)
channel_id チャンネルID。呼び出したチャンネルのIDが入力されています。
channel_name チャンネル名
user_id コマンドを呼び出したユーザーID
user_name ユーザー名
command 呼び出したコマンドの文字列
text コマンドと共に入力されたテキスト
response_url レスポンスを返却するためのURL。30秒以内にレスポンスを返せない場合は、こちらのHook用のURLへレスポンスを返却するようにします。

これらが入力値の全てになります。これらの情報から必要なものを利用して、様々なタスクを実行します。

トークンの検証

// validate token
if (!token.equals(slackToken)) {
    return new RichMessage("Sorry! You're not lucky enough to use our slack command.");
}

メソッドの先頭で、設定されたトークンとコマンドで入力されたトークンを比較します。トークンが一致しない場合は、 Sorry! You're not lucky enough to use our slack command. と表示されるのみです。

メッセージを作成する

RichMessage richMessage = new RichMessage("The is Slash Commander!");
richMessage.setResponseType("in_channel");

// set attachments
Attachment[] attachments = new Attachment[1];
attachments[0] = new Attachment();
attachments[0].setText("I will perform all tasks for you.");
richMessage.setAttachments(attachments);

setResponsetType("in_channel)") でレスポンスをどこへ返却するかを指定しています。こちらは呼び出されたチャンネルへレスポンスを返却しています。他には ephemeral が指定できるようです。

Attachment

Attachment ではメッセージの引用部分を設定できるようです。サンプルではテキストのみを指定していますが、それ以外にも設定出来る値があるようです。Attachmentの定義を見てみましょう。

public class Attachment {
    private String fallback;
    private String color;
    private String pretext;
    @JsonProperty("author_name")
    private String authorName;
    @JsonProperty("author_link")
    private String authorLink;
    @JsonProperty("author_icon")
    private String authorIcon;
    private String title;
    @JsonProperty("title_link")
    private String titleLink;
    private String text;
    private Field[] fields;
    @JsonProperty("image_url")
    private String imageUrl;
    @JsonProperty("thumb_url")
    private String thumbUrl;
    private String footer;
    @JsonProperty("footer_icon")
    private String footerIcon;
    private String ts;

イメージやアイコン、サムネイルなど色々と設定ができそうです。

レスポンスを返却

return richMessage.encodedMessage(); // don't forget to send the encoded message to Slack

最後に必ず encodedMessage() でエンコードしてメッセージを返却します。今回のサンプルでは30秒を超えないため、responseUrl は利用していません。

まとめ

response_urlが30分でexpireしてしまうため、30分以内に完了する必要がありますが、カスタムしたSlash Commandsを利用することで、時間のかかるタスクでもSlackから実行できるようになりそうです。

ちょっと工夫してあげると、AWSのリソースの操作やCloudFormationの実行などをSlackから気軽に実行してレスポンスを取得できるようになるのではないでしょうか。

参照

脚注

  1. 便宜上、AmazonECSやALBの存在は消しました・・・