slackのIncoming webhookが新しくなっていたのでまとめてみた

会社では通知したい情報をIncoming Webhook経由でSlackに通知しているのですが、項目を変更しようと思ってドキュメントを調べたところ、Webhook周りの方針がいつの間にか変更になっていたようです。

思ったより苦戦したので（とりわけドキュメントが英語しかなく）、把握できたところをまとめてみました。

# 1. Webhookの設定方法の変更

まず全体的な方針変更として、Incoming Webhookの設定方法が「Webhookアプリによるインテグレーション」から「個別アプリからの登録」に変更になったようです。

## 旧方式

これまでWebhookは
https://{workspace-name}.slack.com/apps
のアプリ画面からWebhookアプリにアクセスし、各チャンネルに対してカスタムインテグレーションなるもので設定するようなフローでした。

<img width="1395" alt="App_管理___VISITS_Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/c5a8540c-0a64-60ca-8f22-858d68b5b26e.png">

<img width="1382" alt="Incoming_Webhook___Slack_App_ディレクトリ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/a62b90ac-e581-3d92-cef8-5c5b6a076864.png">

この方式ではインテグレーションはデフォルトのチャンネルやユーザー名・アイコンなどを設定しますが、jsonを送りさえすればデフォルトは色々切り替えられるようになっていました。

なのでインテグレーションのチャンネルの紐づけは曖昧で、ただ作成者がその仕組みを把握していないと良くわからないインテグレーションが乱立することになります。
（実際今の会社でもそうですし、前の会社でもそうでした）

## 新方式

新方式では、上記のWebhookアプリのインテグレーションではなく、任意の個別アプリにおいてIncoming Webhookを有効化してそのアプリ経由で通知するように変更になったようです。

Slackアプリは
https://api.slack.com/apps
から見るように変更になっており、Activate Incoming Webhooksで有効化する方式になってます。

<img width="1418" alt="Slack_API__Applications___VISITS_Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/b6d59afe-f86c-c8c8-1776-e429c0a3a20f.png">

有効化した後はチャンネルごとにwebhookを追加していきます。

<img width="647" alt="Slack_API__Applications___VISITS_Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/d2a485cd-0d94-260d-c2f0-1434d87011cd.png">

一つ大きな変更として、Webhook設定が厳密になっており、1つのWebhook URLからは設定したチャンネルにのみ送るという運用になったようです。

これまでと同じくwebhookは複数設定できるので複数のチャンネルへ送ることは可能ですが、json payloadのchannelを指定しての送信先切り替えはできません。

また送信元アプリについても、jsonでusernameやicon_emoji/icon_urlなどを指定してもユーザ名やアイコンは変えられません。

※[ドキュメント](https://api.slack.com/incoming-webhooks)には以下のように言及あり
<img width="630" alt="スクリーンショット 2019-06-20 13.51.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/b570568a-798b-48be-0527-40b5ca672793.png">

ということでコードやPOSTから送信元アプリや送信先を切り替えることができなくなりました。

とはいえ、むしろ今まで自由にできていたのが気持ち悪かったので、きれいなところに落ち着いたという印象です。

詳しい設定手順は[ドキュメント](https://api.slack.com/incoming-webhooks)に記載があるのでそちらに譲りたいと思いますが、概略だけ言うと以下の4手順で送信の設定が出来ます。

1. slack appの作成(持っていない場合)
2. Incoming Webhookの有効化
3. Incoming Webhookの作成
4. メッセージのpost

# 2. json payloadの変更

メッセージを送信する際のpayloadも変更点があります。

https://api.slack.com/reference/messaging/payload

<img width="640" alt="スクリーンショット 2019-06-20 14.08.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/432bdb15-5b01-a22a-e3e3-7b21e392a0e7.png">

上で述べたように、channel/username/icon_emoji/icon_urlは使えなくなっています。

また、二段組にしたり細かいカスタマイズができた`attachments`については`legacy`として非推奨になり、代わりに`blocks`を使えということになっているようです。

attachmentsからblocksへの切り替えについては、公式でも手順を紹介しているのでそちらを参考にしてみるといいかもしれません。
https://api.slack.com/messaging/attachments-to-blocks

## color

今後はblocksに移った方がいいとのことですが、唯一新記法ではcolorが使えないので、colorを使いたい場合はattachmentsを使うしかありません。

![attachment_color.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/9bcd3561-4f1f-f556-4b2a-0a30f0c5cab8.png)
（[Slack公式のイメージ](https://api.slack.com/docs/message-attachments)を拝借）

公式にも例外の一つとして書かれていました。
<img width="640" alt="Transforming_your_legacy_message_compositions_with_blocks___Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/5f1e70ba-d2e4-1b42-6807-7b131fe83f5b.png">

ただ、attachmentsにはcolorとblocksを含めて書くことができ、blocksは新記法でもきちんと表示されるので、色以外の部分は概ね新しいblocks記法で書くのが良さそうです。

<img width="639" alt="Reference__Secondary_attachments___Slack.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/7e1bb918-99b6-d9d2-79c2-4d645967de35.png">

※ちなみに新方式だと、good/warning/dangerはうまく色をつけてくれませんでした。カラーコードの指定はうまく出来たので今後はカラーコードを指定すると良さそうです。

あってるか分かりませんが、近い色を出したければ以下のカラーコードをお使いください。（正しい色をご存知の方いたらコメントいただけると嬉しいです。）

| Color | Code |
|:--------|:--------|
| good (green)      | `#2EB886` |
| warning (yellow?) | `#DAA038` |
| danger (red)      | `#A30100` |

※2019/07/30追記
@takahnozさんに正しいカラーコードを教えていただきまして修正しました。

※2020/06/23追記
@nekonenene さんに新しいカラーコードを教えていただきまして更新しました。

## blocks

[blocks](https://api.slack.com/reference/messaging/blocks)の中には主に5種類のコンポーネントを含められるようになっています。

- Section
- Image
- Context
- Actions
- Dividor

各項目の簡単な説明はこの後触れますが、画面上でjsonを確認できるモックページも用意されているので、初めにここを触ってみるのをおすすめします。
https://api.slack.com/tools/block-kit-builder

<img width="1438" alt="スクリーンショット 2019-07-04 14.12.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/9061052b-76aa-58de-413a-9d492ffb3d3d.png">

### Section

テキスト系を表示するときは`section`を使います。
<img width="606" alt="スクリーンショット 2019-07-04 14.14.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/46727b44-d2d9-011e-b3de-a04f73168ca6.png">

```json
{
    "type": "section",
    "text": {
        "type": "mrkdwn",
        "text": "This is a mrkdwn section block :ghost: *this is bold*, and ~this is crossed out~, and <https://google.com|this is a link>"
    }
}
```

上の図のように、太字や取り消し線やリンク、iconなどが表示できます。

また、以前にもあったfieldsを使うことで段組みも実現することができます。
この辺は以前と変わりはないですが、`section`の中で`accessory`という要素を入れることで段組みした横にボタンをつけることもできます。
<img width="623" alt="スクリーンショット 2019-07-04 14.34.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/711f5343-51a4-9507-69b6-61d58d76378d.png">

```json
{
    "type": "section",
    "fields": [
        {
            "type": "mrkdwn",
            "text": "*this is plain_text text1*"
        },
        {
            "type": "mrkdwn",
            "text": "*this is plain_text text2*"
        },
        {
            "type": "plain_text",
            "text": "*this is plain_text text3*",
            "emoji": true
        },
        {
            "type": "plain_text",
            "text": "*this is plain_text text4*",
            "emoji": true
        },
        {
            "type": "mrkdwn",
            "text": "*this is plain_text text5*"
        }
    ],
    "accessory": {
        "type": "button",
        "text": {
            "type": "plain_text",
            "text": "Button",
            "emoji": true
        },
        "value": "click_me_123"
    }
}

```

`accessory`でつけられるのは`block element`というやつです。ボタンや日付選択など、インタラクティブな操作をする要素をくっつけることができます。
後述のActionsと違い、accessoryでは一つしかくっつけられません。

### Image

言わずとしれた画像
<img width="635" alt="スクリーンショット 2019-07-04 14.39.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/6502a0b9-90b2-39d3-35c4-b9ca7f2b3c98.png">

```json
{
    "type": "image",
    "title": {
        "type": "plain_text",
        "text": "image1",
        "emoji": true
    },
    "image_url": "https://api.slack.com/img/blocks/bkb_template_images/beagle.png",
    "alt_text": "image1"
}
```

### Context

脚注とかに使えそうな小さいテキスト表示
<img width="207" alt="スクリーンショット 2019-07-04 14.39.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/bac95eae-5f68-dbe7-6ab8-de44b7c77ef6.png">

```json
{
    "type": "context",
    "elements": [
        {
            "type": "mrkdwn",
            "text": "*Author:* T. M. Schwartz"
        }
    ]
}
```

### Actions

`section`における`accessory`と違い、複数のインタラクティブなコンポーネントを管理できるblockです。
インタラクティブ・コンポーネントは以前にはなかった機能と書いてありました（が、自分はそこまで古い仕様を知らないので正しいかは分かりません。）

ボタンにURLを貼ってリンクにすることもできますし、図のようにselect Boxを作れたりするみたいです。
なお、・・・となっているのは、overflowというelementのようです。
細かいelementについては[こちら](https://api.slack.com/reference/messaging/block-elements)をご参照ください。
<img width="627" alt="スクリーンショット 2019-07-04 14.57.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/12a55165-a794-0da8-4beb-74893e85b0f1.png">
ちゃんと調べられていませんが、`Select menu with external data source`というelementを使うことで動的に中身を切り替えたselect boxを用意することもできるようです。

```json
{
    "type": "actions",
    "elements": [
        {
            "type": "button",
            "text": {
                "type": "plain_text",
                "text": "Google",
                "emoji": true
            },
            "value": "click_me_123",
            "url": "https://google.com"
        },
        {
            "type": "datepicker",
            "initial_date": "1990-04-28",
            "placeholder": {
                "type": "plain_text",
                "text": "Select a date",
                "emoji": true
            }
        },
        {
            "type": "conversations_select",
            "placeholder": {
                "type": "plain_text",
                "text": "Select a conversation",
                "emoji": true
            }
        },
        {
            "type": "channels_select",
            "placeholder": {
                "type": "plain_text",
                "text": "Select a channel",
                "emoji": true
            }
        },
        {
            "type": "users_select",
            "placeholder": {
                "type": "plain_text",
                "text": "Select a user",
                "emoji": true
            }
        },
        {
            "type": "static_select",
            "placeholder": {
                "type": "plain_text",
                "text": "Select an item",
                "emoji": true
            },
            "options": [
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Excellent item 1",
                        "emoji": true
                    },
                    "value": "value-0"
                },
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Fantastic item 2",
                        "emoji": true
                    },
                    "value": "value-1"
                },
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Nifty item 3",
                        "emoji": true
                    },
                    "value": "value-2"
                },
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Pretty good item 4",
                        "emoji": true
                    },
                    "value": "value-3"
                }
            ]
        },
        {
            "type": "overflow",
            "options": [
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Option 1",
                        "emoji": true
                    },
                    "value": "value-0"
                },
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Option 2",
                        "emoji": true
                    },
                    "value": "value-1"
                },
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Option 3",
                        "emoji": true
                    },
                    "value": "value-2"
                },
                {
                    "text": {
                        "type": "plain_text",
                        "text": "Option 4",
                        "emoji": true
                    },
                    "value": "value-3"
                }
            ]
        }            
    ]
}
```

### Dividor

横線
<img width="635" alt="スクリーンショット 2019-07-04 14.44.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5964/963bfd6c-c82d-512d-c912-baa1d0c4dd3c.png">

```json
{
	"type": "divider"
}
```

# おわりに

ということで新方式のslack incoming webhookの紹介でした。

特にjson部分に関しては以前の方式でメッセージを作っても新しい方式で動くのですが、slack公式としてはメッセージの作り方は変わったから新方式を理解して書いてねということのようなので、これからincoming webhook使う方は新方式で行くのが良さそうです。

というか変わったの分かりづらい！