32
22

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 3 years have passed since last update.

Slack Python SDK でチャンネルにメッセージを投稿しよう

Last updated at Posted at 2021-05-26

slack-sdk を使おう

Python で Slack API や Webhook を扱うなら公式 SDK(slack-sdk/slack-bolt)を使おう」シリーズの記事です。公式 SDK についての概要、他にも記事がリンクされていますので、こちらのエントリーページにもアクセスしてみてください。

チャンネルにメッセージを投稿する

この記事では slack-sdk PyPI パッケージを使って Slack のチャンネル、DM にメッセージを投稿するコーディングについて解説します。以下の内容を説明していきます。

  • chat.postMessage API でメッセージを投稿
    • とりあえず投稿してみる
    • ユーザーに成り代わって投稿
    • text / attachments / blocks の違い
  • Incoming Webhooks でメッセージを投稿
  • メッセージを更新・削除
  • エフェメラルメッセージを投稿
  • ユーザーインタラクションに対して返信

盛りだくさんになっていますが、いきなりすべてを理解する必要はありませんので、必要になったときにこの記事を読み返してみてください。

chat.postMessage API でメッセージを投稿

それでは早速 chat.postMessage API の使い方から始めていきましょう。まずこの API を使うためには chat:write という OAuth スコープが必要となります。この権限を持つアプリの設定は以下のようになります。早速、こちらのリンクから作成してみてください。

_metadata:
  major_version: 1
  minor_version: 1
display_information:
  name: chat.postMessage App
features:
  app_home:
    messages_tab_enabled: true
    messages_tab_read_only_enabled: false
  bot_user:
    display_name: chat.postMessage Bot
oauth_config:
  scopes:
    bot:
      - chat:write
      # この記事では詳細を解説しませんが、この権限があれば bot user は public チャンネルに限り、チャンネルに参加せずにメッセージを投稿できるようになります
      - chat:write.public
      # この記事では詳細を解説しませんが、アプリからの投稿ではありますが username / icon_emoji / icon_url を変更して見た目を変えることができるようになります
      - chat:write.customize

作成できたら「Install to Workspace」ボタンから Slack ワークスペースにインストールすると Settings > Install App のページ内の「Bot User OAuth Token」という名前で xoxb- で始まるトークンが発行されているかと思います。これを SLACK_BOT_TOKEN という名前で環境変数に設定しておいてください。

export SLACK_BOT_TOKEN=xoxb-111-222-xxxx

以上で、この記事のサンプルを動かすための Slack アプリの設定は完了です。Python プロジェクトを設定してコードを実行していきましょう。

この記事のコードは全て Python 3.6 以上で動作します。python3 --version でバージョンを確認してください。この記事では Poetry を使って説明していきます。インストールしていない人はこちらを参考にしてください。

それではプロジェクトを作っていきましょう。

# 新しいプロジェクトを作成
poetry new chat_postMessage_app
cd chat_postMessage_app/

# 必要に応じて poetry env use 3.9 など

# virtualenv を有効化
poetry shell

# slack-sdk を追加
poetry add slack-sdk

これでひとまず完了です。

とりあえず投稿してみる

まずはボットユーザーとしてメッセージを投稿してみましょう。以下のソースコードを bot.py として保存してください。

import logging, os

# デバッグレベルのログを出力します
logging.basicConfig(level=logging.DEBUG)

# Web API クライアントを初期化します
from slack_sdk import WebClient
client = WebClient(os.environ["SLACK_BOT_TOKEN"])

# chat.postMessage API を呼び出します
response = client.chat_postMessage(
    channel="#random",
    text=":wave: こんにちは!",
)

実行が成功すると以下のような出力になるはずです。

(.venv) bash-3.2$ export SLACK_BOT_TOKEN=xoxb-111-222-xxx

(.venv) bash-3.2$ python bot.py
DEBUG:slack_sdk.web.base_client:Sending a request - url: https://www.slack.com/api/chat.postMessage, query_params: {}, body_params: {}, files: {}, json_body: {'text': ':wave: こんにちは!', 'channel': '#random'}, headers: {'Content-Type': 'application/json;charset=utf-8', 'Authorization': '(redacted)', 'User-Agent': 'Python/3.9.1 slackclient/3.5.1 Darwin/20.4.0'}
DEBUG:slack_sdk.web.slack_response:Received the following response - status: 200, headers: { ... }, body: {'ok': True, 'channel': 'C111', 'ts': '1622017093.007700', 'message': {'bot_id': 'B111', 'type': 'message', 'text': ':wave: こんにちは!', 'user': 'U111', 'ts': '1622017093.007700', 'team': 'T111', 'bot_profile': {'id': 'B111', 'deleted': False, 'name': 'chat.postMessage App', 'updated': 1622016343, 'app_id': 'A111', 'icons': {'image_36': 'https://a.slack-edge.com/111/img/plugins/app/bot_36.png', 'image_48': 'https://a.slack-edge.com/111/img/plugins/app/bot_48.png', 'image_72': 'https://a.slack-edge.com/111/img/plugins/app/service_72.png'}, 'team_id': 'T111'}}}

そして Slack ワークスペースの #random チャンネルに以下のようなメッセージが投稿されているはずです!

うまくいきましたか?おめでとうございます :tada:

ユーザーに成り代わって投稿する

次は、このアプリをインストールしてくれたユーザーに成り代わってメッセージを投稿してみましょう。これをするには先ほどの OAuth スコープだけでは不十分です。Features > OAuth & Permissions のページへ移動して User Token Scopechat:write を追加してください。これは先程と名前は同じですが、ユーザーに成り代わるためのものです。

新しい権限が追加されたので、黄色いバーが上部に表示されています。リンクをクリックするか「Reinstall to Workspace」ボタンから再度インストールしてください。

なお、これによって App Manifest の当該部分は以下のように変わっています。

oauth_config:
  scopes:
    user:
      - chat:write
    bot:
      - chat:write
      - chat:write.public
      - chat:write.customize

インストールが終わると、Settings > Install App のページ内では、これまでの「Bot User OAuth Token」に加えて「User OAuth Token」が追加されているかと思います。値は xoxp- から始まります。ここではこちらのトークンを使います。SLACK_USER_TOKEN という名前で環境変数に設定しましょう。

export SLACK_USER_TOKEN=xoxp-111-222-333-xxx

そして、以下のコードを user.py として保存しましょう。

import logging, os

# デバッグレベルのログを出力します
logging.basicConfig(level=logging.DEBUG)

# Web API クライアントを初期化します
from slack_sdk import WebClient
client = WebClient(os.environ["SLACK_USER_TOKEN"])

# chat.postMessage API を呼び出します
response = client.chat_postMessage(
    channel="#random",
    text=":wave: こんにちは!",
)

同じように実行してみます。

export SLACK_USER_TOKEN=xoxp-111-222-333-xxx
python user.py

今回はユーザーとして投稿されているはずです!

なお、トークンはメソッド呼び出し単位で上書き・指定することができます。

# デフォルトはボットトークン
client = WebClient(os.environ["SLACK_BOT_TOKEN"])

response = client.chat_postMessage(
    # ここだけはユーザートークンを使う
    token=os.environ["SLACK_USER_TOKEN"],
    channel="#random",
    text=":wave: こんにちは!",
)

また、WebClient をインスタンス化するときにトークンは未指定でも構いません。この場合は必ずメソッド呼び出し時に token パラメーターを渡すようにしてください。

client = WebClient()

# トークンを指定しないと {'ok': False, 'error': 'not_authed'} になる
client.auth_test()

text / blocks / attachments の違い

ここまでの例では text でメッセージを指定してきました。ここからはもっとリッチなメッセージを投稿してみましょう。

プロパティ名 説明
text こちらのテキストフォーマットルールを使用できるテキストフォーマット。blocksattachments がある場合には指定しなくてもメッセージを投稿できますが、モバイル通知にはこちらのテキストが使われたり、Slack の検索インデックスへの登録などで使用されますので、設定することが推奨されています。また、Bolt のメッセージのリスニングのコード例は、この text が適切に設定されていることが前提となっています(ユーザーからの投稿は必ず text が設定されています)。
blocks ブロックキットと呼ばれるよりリッチなインターフェースを JSON 形式で簡単に定義するための仕様に則った「ブロック」の配列です。ブロックキットビルダーを使えば、簡単に表示のプロトタイピングができ、完成した blocks はそのまま chat.postMessage や Incoming Webhooks に渡すことができます。また、blocks は多くの場合、チャットのメッセージだけでなく、ホームタブモーダルの中にそのまま組み込むことができます。
attachments 旧来のリッチインターフェースで、現在は blocks の利用を推奨しています。多くのことはブロックキットの方が柔軟にできますが、カラーバーを使用するためにこちらを使用しているアプリを見かけることはあります。また、若干トリッキーですが、実は attachments の中にブロックキットを含めることもできたりします。ブロックキットビルダーに加えて、元々存在するメッセージビルダーを使ってプレビューすることもできます。

ここでは textblocks を両方指定したメッセージを投稿してみましょう。私の以前の記事でホームタブやモーダルの日本語のメッセージテンプレートを紹介していましたが、今回も日本語で実際にありそうなメッセージを作ってみました。

import logging, os

logging.basicConfig(level=logging.DEBUG)
from slack_sdk import WebClient

client = WebClient(os.environ["SLACK_BOT_TOKEN"])
response = client.chat_postMessage(
    channel="#random",
    text="はじめまして、田中さん :wave: このアプリは、Slack を離れることなく、ミーティング、イベントの予定を管理することをお手伝いします。このアプリを使えば以下のことが簡単>にできるようになります。\n• ミーティングを設定する\n • 参加者を管理する\n • ミーティングの変更通知を受け取る\nこれらの機能を利用するためには、まずあなたのカレンダーサービスとこのアプリを接続する必要があります。以下のボタンから設定を行ってください :bow:",
    blocks=[
        {"type": "section", "text": {"type": "mrkdwn", "text": "はじめまして、田中さん :wave:"}},
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "このアプリは、Slack を離れることなく、ミーティング、イベントの予定を管理することをお手伝いします。このアプリを使えば以下のことが簡単にできるようになります。",
            },
        },
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "• ミーティングを設定する\n • 参加者を管理する\n • ミーティングの変更通知を受け取る",
            },
        },
        {
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "これらの機能を利用するためには、まずあなたのカレンダーサービスとこのアプリを接続する必要があります。以下のボタンから設定を行ってください :bow:",
            },
        },
        {
            "type": "actions",
            "block_id": "actions-block",
            "elements": [
                {
                    "type": "button",
                    "action_id": "connect_with_calendar",
                    "text": {"type": "plain_text", "text": "カレンダーアプリと連携する"},
                    "style": "primary",
                    "value": "configure",
                }
            ],
        },
    ],
)

以下のようなメッセージが無事投稿されたでしょうか?

「カレンダーアプリと連携する」ボタンは今のままだと動作しません。動作させたい場合は、こちらの Bolt のドキュメントを参考にリスナーを実装してみてください。上記の例そのままであれば @app.action("connect_with_calendar") というデコレーターのついたメソッドを実装すればイベントを受信できるでしょう。

Incoming Webhooks でメッセージを投稿

こちらの記事を参考にしてください。

メッセージを更新・削除

それでは API を使ってメッセージの更新・削除もやってみましょう。

import logging, os, time

logging.basicConfig(level=logging.DEBUG)
from slack_sdk import WebClient

client = WebClient(os.environ["SLACK_BOT_TOKEN"])

# 新しいメッセージを投稿
new_message = client.chat_postMessage(
    channel="#random",
    text=":wave: こんにちは!",
)

# わかりやすくするために sleep
time.sleep(2)

# 自分が投稿したメッセージを更新
client.chat_update(
    channel=new_message["channel"],
    ts=new_message["ts"],
    text=":wave: こんばんは!",
)

# わかりやすくするために sleep
time.sleep(2)

# 自分が投稿したメッセージを削除
client.chat_delete(
    channel=new_message["channel"],
    ts=new_message["ts"],
)

Slack チャンネル内での動作は以下のようになります。

エフェメラルメッセージを投稿

「エフェメラルメッセージ」とは、チャンネル内に投稿されていても特定のユーザーにだけ見えているメッセージです。Slack の画面上で「あなただけに表示されています(英語だと Only visible to you)」と表示されているメッセージを見たことがあるかもしれません。このメッセージは例えばスラッシュコマンドを実行したユーザーだけに「受け付けました!」のようなメッセージを表示したいときなどに便利です。では、このメッセージを API を使って送信してみましょう。

import logging, os

logging.basicConfig(level=logging.DEBUG)
from slack_sdk import WebClient

client = WebClient(os.environ["SLACK_BOT_TOKEN"])

# 先程発行したユーザートークンを使ってあなたのユーザー ID を取得します
user_auth = client.auth_test(token=os.environ["SLACK_USER_TOKEN"])
user_id = user_auth["user_id"]

# 場所として channel を指定、誰に対して表示するかで user を指定します
response = client.chat_postEphemeral(
    channel="#random",
    user=user_id,
    text=":wave: あなただけにお知らせです!",
)

以下のようなメッセージが表示されたでしょうか?

割愛しますが、もちろん blocks も問題なく使えます。

ユーザーインタラクションに対して返信

スラッシュコマンド、ショートカットなどへの応答でメッセージを返信したいという方は、ぜひこちらの response_url に関する詳細な記事を参考にしてみてください。

まとめ

この記事では Slack API を使ってチャットにメッセージを投稿する方法について公式 Python SDK のコード例とともに網羅的に紹介しました。

今回扱わなかった API に予約投稿のための chat.scheduleMessage API というものもあります。ぜひ API 一覧chat. から始まる API を色々と試してみてください。

それでは :wave:

export SLACK_BOT_TOKEN=___; pip install slack-sdk; python -c 'import os; from slack_sdk import WebClient; WebClient(os.environ["SLACK_BOT_TOKEN"]).chat_postMessage(channel="#random", text="それでは :wave:")'
32
22
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
32
22

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?