Pythonで、Slackに投稿する方法

「これをSlackのメッセージの取得の次にやれよ!」という声が聞こえてきそうですが、ゆったりあちこちに手を出します。何をどういう順でやると良いのかも、慣れているから分かる問題です。分からなくても順番にやれば(手戻りが発生して時間はかかるかもしれませんが、)できるはずです。

Q. Slackにメッセージを送信するにはどうすればいい? A. chat.postMessageを使おう

もうこのシリーズではSlackからメッセージを取得できたんだから、似たような方法でできそうだと想像します。

Web API methods | Slackでconversations.historyの他に何があるかを見てみると、conversations.repliesという返信できそうなメソッドがあります。が、よく読むとスレッドの内容を取得するメソッドのようです。というかhistoryを調べているときに出てきたやつでしたね。予想でやっちゃうと危ないので改めて「slack メッセージ 送信 api」と検索するとSlack API を使用してメッセージを投稿するが見つかります。内容を読むと、chat:writeというscope(もうあなたは能力1でscopeという単語が分かるようになっていますね)が必要なこと、HTTP POST https://slack.com/api/chat.postMessageでメッセージを送信できることが判明します。

Q. chat.postMessageはどう使う? A. chat:write scopeを持ったtokenで…(取得と似てるな?)

chat:writeをさっきと同様にSlack APIのOAuth & PermissionsのBot Token Scopesに追加します。すると画面の上からappを再起動する必要があるという注意が出るので文中のリンクを押して再起動します。さっきより権限が増えていますが、したいことも増えているので妥当ですね。緑色の許可するボタンを押してappに権限を与えます。

ちなみに権限を追加してもtokenは変わっていなさそうです……が、念のためもう一度Pythonのコードにコピペしました。

Q. chat.postMessageで他に必要なのは? A. channel ID と、例えばtextを用意しよう

chat.postMessage method | Slackを読むと、tokenとchannelに適切な値を追加する必要があること、そしてattachmentsかblocksかtextの少なくとも1つが必要なことが書いてあります。tokenとchannel(channel ID)は既に手に入れているはずです。attachmentsかblocksかtextを選ぶ必要がありますが、一番簡単そうなのでtextで”Hello World!”でも送ってみましょう。

Q. HTTP POSTってどうすればいいの? A. requests.post(url, headers=header, json=data)しよう

GETをPOSTに変えるだけ….で良いのか分からないので「requests post python」で検索してPython, RequestsでWeb APIを呼び出し(データ取得・操作) | note.nkmk.meを見つけます。

url_items = 'https://qiita.com/api/v2/items'

item_data = {
    'title': 'テスト記事',
    'body': 'テスト',
    'private': True,
    'tags': [{'name': 'test'}],
    'coediting': False,
    'gist': False,
    'tweet': False
}

r_post = requests.post(url_items, headers=headers, json=item_data)

と書いてあるので3〜11行目をchannel IDとtextに置き換え、jsonに渡します。Slackからメッセージの取得に使っていたプログラムを変えたものが以下のようなプログラムです。

import requests
url = "https://slack.com/api/chat.postMessage"
token = "xoxb-xxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxx..."# tokenを入れてください

header={
    "Authorization": "Bearer {}".format(token)
}

data  = {
    "channel" : "C0123456789",# Conversation IDを入れてください
    "text" : "Hello World!"
    }

res = requests.post(url, headers=header, json=data)

resonse_json = res.json()
print(resonse_json)

{'ok': True, 'channel': ... という出力と共に、slackにメッセージが届きました。

ちなみに、「requests.post python data」で検索して[Python] requestsモジュールを使って楽々HTTP(s)通信を行う - YoheiM .NETを見ると、14行目のpostの引数はjson=dataではなくdata=dataでも動くようです。jsonファイルじゃないのにjsonに渡しているのでdata=dataで書きたいと思いました。

Q. チャンネルに投稿じゃなく、返信できない? A. thread_tsで指定すればできる

575のメッセージにスレッドで返したいので、chat.postMessage でそんな機能を探すとthread_tsというargumentがあります。

「Slackからメッセージを取得する」で

json_channel_history = res.json()

と受け取ったjsonファイルの中には、メッセージ毎にtsという値がありました。

{
    'ok': True,
    'messages': [{'bot_id': 'XXXXXXXXXXX',
                            'type': 'message',
                            'text': 'Hello World!',
                            'user': 'YYYYYYYYYYY',
                            'ts': '1234567890.123456'...  # 架空の数字です

このtsの値を、thread_tsの値として入れてみましょう(下記12行目)。

import requests
url = "https://slack.com/api/chat.postMessage"
token = "xoxb-xxxxxxxxxxxxx-xxxxxxxxxxxxx-xxxxxxxxxx..."# tokenを入れてください

header={
    "Authorization": "Bearer {}".format(token)
}

data  = {
    "channel" : "C0123456789",# Conversation IDを入れてください
    "text" : "Hello World!",
    "thread_ts": 1234567890.123456  # リプライしたいメッセージのtsの値を入れてください
    }

res = requests.post(url, headers=header, data=data)

resonse_json = res.json()
print(resonse_json)

返信に成功しました。

Slackにメッセージを送信するには、「Slackのchat.postMessageに、書き込みたいテキストをtextに設定し、chat:write scopeが付与されたtokenとチャンネルのConversation IDを使ってHTTPのPOSTをすれば良い」なんて文が書けるようになりました。返信をするときには、「thread_tsに返信先のメッセージのunix時間を設定すれば良い」なんて文も書けるようになりました。こうして短いブログも書けるようになっていきます。

能力3. Slackにメッセージを送信するを獲得しました。

シリーズを通して進めている人は特に、似たことを一度やったことがあるので、今回はすんなり行けたのではないでしょうか。

© 2019- estie, inc.