Slack APIを使った投稿で、チルダ(~)で囲まれた文字列を取り消し線にしない方法

# やりたいこと
Slackのchat.postMessageでメッセージを投稿する際、`~Hello World!~`というメッセージが 「~~Hello World!~~」 と表示されてしまいます。
QiitaのMarkdownのようにチルダ2つであれば意図せず使われる機会は少ないと思いますが、Slackで使われているmrkdwnはチルダ1つであり、「鴨のロースト ~オレンジソースを添えて~」のように副題として使われるケースがあります。

このような際に取り消し線として表示されるのを防ぎたいというのが本記事の目的です。

# 結論
結論から言うと、以下の2つの方法で取り消し線になるのを防ぐことができます。

- `blocks` の `type` で `section` を選択し、`plain_text` として書く
- `blocks` の `type` で `rich_text` を選択し、`rich_text_section` の `element` として `text` を選択する

詳しく解説していきます。

# 解説の前に
Slackでメッセージを投稿するには、Appを作成し `chat.postMessage` APIを使用する方法と、Incoming Webhooksを使用する方法があります。
本記事では、`chat.postMessage` APIを使用した方法を使いますが、Incoming Webhooksでも同様に可能です。

Appの作成方法やtokenの取得方法については割愛しますが、[Your Apps](https://api.slack.com/apps) から `Create New App`を選んでアプリを作り、`OAuth & Permissions` から `Bot User OAuth Token` を生成してください。

tokenを取得すると、以下のようにメッセージを投稿できます。
```bash
curl -X POST \
  -H "Authorization: Bearer <Bot User OAuth Token>" \
  -H "Content-Type: application/json; charset=UTF-8" \
  -d '{
        "channel": "<Channel ID>",
        "text": "鴨のロースト ~オレンジソースを添えて~",
      }' \
  https://slack.com/api/chat.postMessage
```

このように、ただメッセージを `text` に入れるだけだと、チルダで囲まれた部分は取り消し線になってしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1796319/8f24f728-49ed-11c9-257d-880cc7074a30.png)

# `section`を使う場合
次のようにplain_textとして扱うことで、取り消し線にならずに投稿できます。

```bash
curl -X POST \
  -H "Authorization: Bearer <Bot User OAuth Token>" \
  -H "Content-Type: application/json; charset=UTF-8" \
  -d '{
        "channel": "<Channel ID>",
        "blocks": [
          {
            "type": "section",
            "text": {
              "type": "plain_text",
              "text": "鴨のロースト ~オレンジソースを添えて~"
            }
          }
        ]
      }' \
  https://slack.com/api/chat.postMessage
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1796319/eea9a9ba-b126-ee37-220d-03bfc15c018f.png)

ただし、この方法には1つ欠点があります。
それは、同じメッセージにリンクを含めたい場合です。

Slackのmrkdwnでは `<URL|Link Text>` の形式でリンクを表現できます。
しかし、`type` に `plain_text` を指定した場合、当然ながらリンクにはなりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1796319/b0f10a0a-9814-5503-cff7-a5bc39b6183f.png)

`type: "mrkdwn"`とした`section`に分けることでリンクにすることはできますが、`section`が別なので行間が空いてしまいます。
```bash
curl -X POST \
  -H "Authorization: Bearer <Bot User OAuth Token>" \
  -H "Content-Type: application/json; charset=UTF-8" \
  -d '{
        "channel": "<Channel ID>",
        "blocks": [
          {
            "type": "section",
            "text": {
              "type": "plain_text",
              "text": "鴨のロースト ~オレンジソースを添えて~"
            }
          },
          {
            "type": "section",
            "text": {
              "type": "mrkdwn",
              "text": "<http://www.example.com|Link Text>"
            }
          }
        ]
      }' \
  https://slack.com/api/chat.postMessage
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1796319/e1318d83-d143-e0e6-4b26-9cd08777b636.png)

この問題を解決する方法が次のrich_textです。

# `rich_text`を使う場合
`rich_text`を使うと、柔軟な記述が可能です。
以下のようにすることで、1つの `section` の中に複数の `type` を持つ `element` を定義できるため、先程の問題が解消できます。
```bash
curl -X POST \
  -H "Authorization: Bearer <Bot User OAuth Token>" \
  -H "Content-Type: application/json; charset=UTF-8" \
  -d '{
        "channel": "<Channel ID>",
        "blocks": [
          {
            "type": "rich_text",
            "elements": [
              {
                "type": "rich_text_section",
                "elements": [
                  {
                    "type": "text",
                    "text": "鴨のロースト ~オレンジソースを添えて~\n"
                  },
                  {
                    "type": "link",
                    "url": "http://www.example.com",
                    "text": "Link Text"
                  },
                ]
              }
            ]
          }
        ]
      }' \
  https://slack.com/api/chat.postMessage
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1796319/b11516e2-384d-0bb2-4bce-f5fa73c3643e.png)

リンクがmrkdwn形式ではなくなった点と、`section`が同じためテキストの後ろに `\n` が必要となった点に注意が必要です。
記述量が多くなりますが、`section`で要件を満たせない場合は`rich_text`を使うと良いでしょう。

また、このような複雑なメッセージを作成したい場合は、Slackが提供しているBlock Kit Builderを使うのが便利です。

https://app.slack.com/block-kit-builder


# 参考リンク
https://api.slack.com/reference/block-kit/blocks

https://api.slack.com/methods/chat.postMessage