slackのchat.postMessageを使いこなす

# この記事でわかること
- slack apiの`chat.postMessage`で使える便利な機能
    - メンションをつける
    - スレッドに返信する
    - メッセージを共有する
    - ~~Button付きメッセージのボタンを押した後に、元メッセージを書き換える~~←いずれ書きます

# この記事ではわからないこと
- slack apiの基本的な使い方

slack apiのtokenなどの設定が知りたい方は別の記事を参照してください。

# プレーンなchat.postMessage
ただメッセージを送るだけならこれだけでできる。
サンプルコードはpython

```postMessage.py
from slackclient import SlackClient
sc = SlackClient("xoxp-********************************")
   "chat.postMessage",
   channel="#general", 
   text="送信したいメッセージ"
)
```

# メンションをつける
## @channel/@hereメンションをつける
`text`の中に`<!channel>` or `<!here>`を書く。

```postMessage.py
from slackclient import SlackClient
sc = SlackClient("xoxp-********************************")
   "chat.postMessage",
   channel="#general", 
   text="<!channel>\n送信したいメッセージ"
)
```

以前は普通に`@channel`でメンションがついたらしいが、今はそれでは正常に通知が飛ばないので注意

## @userメンションをつける
`text`の中に`<@userId>`を書く。
`userId`とは`W012A3CDE`のようなユーザごとのid
slackが用意している[users.list api](https://api.slack.com/methods/users.list)を叩くことで得られるユーザ一覧の中に書いてある。
このapiを叩く前にtokenに対して適切な[権限を与える](https://api.slack.com/docs/oauth-scopes)ことを忘れないように(以下、どのapiを使うときも同様)

```menberList.json
{
    "ok": true,
    "members": [
        {
            "id": "W012A3CDE", ← これ!!!!!
            "team_id": "T012AB3C4",
            "name": "spengler",
            "deleted": false,
            "color": "9f69e7",
            "real_name": "spengler",
            "tz": "America/Los_Angeles",
            "tz_label": "Pacific Daylight Time",
            "tz_offset": -25200,
            "profile": {
               ~省略~
    ],
    "cache_ts": 1498777272,
    "response_metadata": {
        "next_cursor": "dXNlcjpVMEc5V0ZYTlo="
    }
}
```

## @groupメンションをつける
`text`の中に`<!subteam^groupId>`を書く。
`groupId`とは`S0614TZR7`のようなユーザグループごとのid
slackが用意している[usergroups.list api](https://api.slack.com/methods/usergroups.list)を叩くことで得られるグループ一覧の中に書いてある。

```groupList.json
{
    "ok": true,
    "usergroups": [
        {
            "id": "S0614TZR7",　← これ!!!!!
            "team_id": "T060RNRCH",
            "is_usergroup": true,
            "name": "Team Admins",
            "description": "A group of all Administrators on your team.",
            "handle": "admins",
            "is_external": false,
            "date_create": 1446598059,
            "date_update": 1446670362,
            "date_delete": 0,
            "auto_type": "admin",
            "created_by": "USLACKBOT",
            "updated_by": "U060RNRCZ",
            "deleted_by": null,
            "prefs": {
                "channels": [],
                "groups": []
            },
            "user_count": "2"
        },
        
        ~省略~
    ]
}
```

# スレッドに返信する
`thread_ts`にスレッドの開始にしたいメッセージの`ts`を指定する。
`channel`はスレッドの開始にしたいメッセージと同じチャンネルを指定する。

`ts`とはslackのメッセージに割り振られるidのような役割のもの。
(slackはメッセージをidではなく、`channel`と`ts` = timestampの組み合わせで識別している)

```postMessage.py
from slackclient import SlackClient
sc = SlackClient("xoxp-********************************")
   "chat.postMessage",
   channel="#general", 
   text="送信したいメッセージ",
   thread_ts = "1234567890.123456",
   reply_broadcast = True
)
```
`reply_broadcast`は任意。
デフォルトはFalse。　Trueにするとチャンネル全体にも投稿される。

`ts`を知る方法はいくつかある。
一つは`chat.postMessage`のresponse。

```response.json
{
    "ok": true,
    "channel": "C1H9RESGL",
    "ts": "1503435956.000247", 　← これ！！！
    "message": {
        "text": "Here's a message for you",
        "username": "ecto1",
        "bot_id": "B19LU7CSY",
        "type": "message",
        "subtype": "bot_message",
        "ts": "1503435956.000247"
    }
}
```

あるいは[channels.history api](https://api.slack.com/methods/channels.history)でチャンネルの投稿履歴を取得して、そこから。

```history.json
{
    "ok": true,
    "messages": [
        {
            "type": "message",
            "ts": "1358546515.000008", 　← これとか！！！
            "user": "U2147483896",
            "text": "Hello"
        },
        {
            "type": "message",
            "ts": "1358546515.000007", 　← これ！！！
            ~~省略~
        }
    ],
    "has_more": false
}
```
ちなみに`channels.history`を叩くときに指定する`channel`名は`#general`のように名前のママではエラーになる。`chat.postMessage`のresponseから取得できる`channelId`で指定する必要がある。
（あるいはブラウザでslackの該当チャンネルを開いた時のURL`https://hogehoge.slack.com/messages/C8XNGGH7W`の最後の部分からもわかる）



# slackのメッセージを共有する
いわゆるこれと似たような機能を実現する
<img width="433" alt="スクリーンショット 2019-04-09 2.04.58.png" src="https://qiita-image-store.s3.amazonaws.com/0/268579/b85e91f1-646c-a015-0f20-c26800e1fa4d.png">


## 1.メッセージのリンクを手に入れる
[chat.getPermalink](https://api.slack.com/methods/chat.getPermalink)を使って共有したいメッセージのリンクを手に入れる

```getPermalink.py
from slackclient import SlackClient
sc = SlackClient("xoxp-********************************")
permalinkResponse = sc.api_call(
    "chat.getPermalink",
    channel= "C1H9RESGL",
    message_ts = "1358546515.000008"
)
permalink = permalinkResponse["permalink"]
```
このときもやはり`channel`の指定は`channelId`で指定しなければエラーになる。

## 2.textにリンクを含めたメッセージをpostする

```postMessage.py
from slackclient import SlackClient
sc = SlackClient("xoxp-********************************")
   "chat.postMessage",
   channel="#general", 
   text="%s ← このメッセージを共有します" % permalink,
   unfurl_links = True
)
```
`unfurl_links`をTrueにすることで、リンクのプレビューが表示され、メッセージを共有した感がよりでる（デフォルトではFalse)

あるメッセージを再通知したいときに、そのメッセージのスレッドに対して@channelをつけても通知が飛ばない。
そのようなときは上記の方法を使い、そのメッセージを共有することで@channelの通知付きで再通知可能。

# まとめ
- post.chatMessageだけでも色々遊べる。
- 英語を読むのが嫌でなければ[公式ドキュメント](https://api.slack.com/methods)を読んだほうがいい。


Twitterもやってるので、よければフォローお願いします。
→https://twitter.com/ObataGenta