81
89

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

slackで単純なボタン付きメッセージを送る

Last updated at Posted at 2017-06-24

この記事では

  • slackの任意のチャンネルにボタン付きメッセージを送る
  • ボタンの操作結果をwebサーバーで受け取る
    という単純なサンプルについてメモを書いておきます

前提

  • slackをすでに利用している
  • httpsの利用可能なwebサーバーを公開できる

公式 Document
https://api.slack.com/docs/message-buttons
https://api.slack.com/interactive-messages
https://api.slack.com/docs/message-guidelines

#1. slackのアプリを作成する
ボタン付きメッセージを送るだけならアプリを作成する必要はありませんが、ボタンをクリックした結果を任意のwebサーバー側で受け取る場合はアプリを作成する必要があります。

##1-1. アプリの作成
https://api.slack.com/apps
にアクセスし、create new app からアプリを作成します。
「App Name」に任意の名前
「Development Slack Team」にはボタン付きメッセージを送りたいチャンネルのあるチームを選択します。

##1-2. Incoming Webhooksの設定
Incoming Webhooksを設定すると任意のslackチャンネルにメッセージを送ることができるようになります。

メニューのIncoming Webhooksをクリックし、Activate Incoming Webhooksの右にあるボタンをクリックしてActiavteをOnにします。

次に Incoming Webhooksのページ下部にある「Add New Webhook to Team」のボタンをクリックします。
「Post to」にメッセージを送りたいチャンネル名を入力し、「install」をクリックします。
installが終わるとIncoming Webhooksのページに戻り、設定したチャンネルへメッセージを送るためのWebhook URLが表示されます。

##1-3. Interactive Messagesの設定
Interactive Messagesを設定するとslackメッセージのボタン操作結果を任意のWebサーバーで受け取ることができます。
メニューのInteractive Messagesをクリックし、「Enable Interactive Messages」のボタンをクリックします。
Request URLに任意のURLを入力して「Enable Interactive Messages」のボタンをクリックします。設定したURLにslackでボタンを押した結果がリクエスト(http post)されるようになります。

#2. ボタン付きメッセージの送信
slackにボタン付きメッセージを送信します。宛先のチャンネルは1-2で設定したチャンネルとなります。

##2-1 curlを使ったサンプル
curlを使ったサンプル(下記はURLの一部伏字にしてますが、1-2で設定したWebhook URLとなります)

curl  https://hooks.slack.com/services/***/***/*** -d'payload=
{
    "text": "Slack Message Sample Text",
    "attachments": [
        {
            "fallback": "fallback string",
            "title": "title string",
            "callback_id": "callback_id value",
            "color": "#FF0000",
            "attachment_type": "default",
            "actions": [
                {
                    "name": "btn1Name",
                    "text": "btn1",
                    "type": "button",
                    "style":"default",
                    "value": "btn1Value"
                },
                {
                    "name": "btn2Name",
                    "text": "btn2",
                    "type": "button",
                    "style":"danger",
                    "value": "btn2Value"
                },
                {
                    "name": "btn3Name",
                    "text": "btn3",
                    "type": "button",
                    "style":"primary",
                    "value": "btn2Value"
                }
            ]
        }
    ]
}'

成功すると下記のようなメッセージが送信されます
スクリーンショット 2017-06-24 15.08.59.png

#3. ボタンクリックの結果をハンドリング
ボタンを押した結果はWebhook URLに http POSTされてきます。

##3-1 ボタンクリック時のリクエストをログに出してみる
下記のようなJavaのコントローラを用意し、リクエストを受け取ってログ出力してみます。

SlackReceiveController
package org.hoge.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("slackReceive")
public class SlackReceiveController {

    private Logger logger = LoggerFactory.getLogger(SlackReceiveController.class);
    
    @PostMapping(value = "", consumes = "application/x-www-form-urlencoded")
    ResponseEntity buttonAction(HttpServletRequest request, @RequestParam(value = "payload", required = true) String json) {
        logger.info(json);
        return new ResponseEntity(HttpStatus.OK);
    }
}

ログの結果は以下です(btn1をクリックしています)
みづらいので整形した内容を記載します(idは全て伏字)

result.json
{
  "actions": [
    {
      "name": "btn1Name",
      "type": "button",
      "value": "btn1Value"
    }
  ],
  "callback_id": "callback_id value",
  "team": {
    "id": "*****",
    "domain": "*****"
  },
  "channel": {
    "id": "*****",
    "name": "******"
  },
  "user": {
    "id": "*****",
    "name": "*****"
  },
  "action_ts": "1498286982.378198",
  "message_ts": "1498286913.724083",
  "attachment_id": "1",
  "token": "*****",
  "is_app_unfurl": false,
  "original_message": {
    "text": "Slack Message Sample Text",
    "bot_id": "*****",
    "attachments": [
      {
        "callback_id": "callback_id value",
        "fallback": "fallback string",
        "title": "title string",
        "id": 1,
        "color": "FF0000",
        "actions": [
          {
            "id": "1",
            "name": "btn1Name",
            "text": "btn1",
            "type": "button",
            "value": "btn1Value",
            "style": "default"
          },
          {
            "id": "2",
            "name": "btn2Name",
            "text": "btn2",
            "type": "button",
            "value": "btn2Value",
            "style": "danger"
          },
          {
            "id": "3",
            "name": "btn3Name",
            "text": "btn3",
            "type": "button",
            "value": "btn2Value",
            "style": "primary"
          }
        ]
      }
    ],
    "type": "message",
    "subtype": "bot_message",
    "ts": "1498286913.724083"
  },
  "response_url": "https://hooks.slack.com/actions/***/***/***"
}

actionsにクリックしたボタンの情報がありますので、こちらを利用することで処理の分岐が可能です。

##3-2 ボタンクリック時のリクエストを受けて元のメッセージを編集する
ボタンクリック時のリクエストに対し、webサーバー側(SlackReceiveController)からのresponse bodyにjsonを設定することで元のメッセージを書き換えることが可能です。
クリックしたボタンに応じて元のメッセージを書き換えるサンプルは下記の通り

SlackReceiveController
package org.hoge.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.cloudfoundry.com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

@Controller
@RequestMapping("slackReceive")
public class SlackReceiveController {

    private Logger logger = LoggerFactory.getLogger(SlackReceiveController.class);

    @PostMapping(value = "", consumes = "application/x-www-form-urlencoded")
    ResponseEntity buttonAction(HttpServletRequest request, @RequestParam(value = "payload", required = true) String json) {

        //json文字列を雑にMap objectに変換
        ObjectMapper mapper = new ObjectMapper();
        HashMap<String, Object> payloadMap = null;
        try {
            payloadMap = mapper.readValue(json, HashMap.class);
        } catch (IOException e) {
            return new ResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR);
        }

        //クリックされたactionsの取り出し
        List<HashMap<String, String>> actions = (List<HashMap<String, String>>) payloadMap.get("actions");
        String clickedBtn = actions.get(0).get("name");

        //オリジナルメッセージの取り出しと書き換え
        LinkedHashMap<String, Object> original_message;
        original_message = (LinkedHashMap) payloadMap.get("original_message");
        original_message.put("text", "Clicked: " + clickedBtn);

        //bodyを設定
        return new ResponseEntity(original_message, HttpStatus.OK);
    }
}

元々のメッセージ
スクリーンショット 2017-06-24 16.25.39.png

btn1 クリック後
スクリーンショット 2017-06-24 16.25.54.png

btn2 クリック後
スクリーンショット 2017-06-24 16.26.07.png

btn3 クリック後
スクリーンショット 2017-06-24 16.27.22.png

81
89
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
81
89

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?