Slackにメッセージを送信するPythonスクリプト(2021.7.4)

Summary

Slackに自動で定期的にレポートを送信したい。
機械学習が完了または異常終了したらメッセージで知らせてほしい。
実験コード中にメッセージフックを書いておけば送信できるようにしたい

2018年にSlack APIの仕様が変わったらしく、webの情報が古いものがある。

手順

  1. ボットを設置したいSlack Workspaceとそのchannelを作成する
  2. https://api.slack.com/にWorkspaceのアカウントでログイン
  3. https://api.slack.com/appsで「Create New App」
  4. tokenの生成(メモしておく)やmanifestoの設定(users.readも設定)をしておく
  5. Slack Workspaceを指定してAppをインストール
  6. users.list TesterでWorkspaceの登録ユーザ一覧をjson形式で取得
  7. chat.postMessage Testerでメッセージ送信の確認(mentionには<@ユーザid>を使う
  8. tokenの再発行や設定の追加は「OAuth & Permissions」の「scopes」などから行う
  9. pythonからメッセージを送る

Slack Workspaceを指定してbotを作成・登録

Basic app setupを参照

Create App

詳細はこちら

Create App
Create App
Create App
Create App
Create App
Create App
Create App
Create App

manifestについてはCreate and configure apps with manifestsに記載あり

Your Appsからappの詳細を選択すると、横のLINKリストのSettingsの中に「App Manifest」がある。ここから「Copy to Clipboard」や「Export」ができるので、次回のApp作成時にはmanifestとして貼り付ければ良い。
manifest.yml

Manifestの例はこちら
_metadata:
  major_version: 1
  minor_version: 1
display_information:
  name: HelloBot2000
  description: An example app
  background_color: "#da3a79"
  long_description: An example app that can display actionable notifications in
    Slack. App contains all the necessary scopes to find a channel for
    publishing, and to publish a message. Enables Interactivity features to
    handle use of the interactive elements of the notification. Used with
    tutorials on api.slack.com/tutorials.
features:
  app_home:
    home_tab_enabled: false
    messages_tab_enabled: true
    messages_tab_read_only_enabled: true
  bot_user:
    display_name: HelloBot2000
    always_online: true
oauth_config:
  redirect_urls:
    - https://example.com/slack/auth
  scopes:
    bot:
      - channels:read
      - chat:write
      - chat:write.customize
      - users:read
settings:
  interactivity:
    is_enabled: true
    request_url: https://example.com/slack/message_action
  org_deploy_enabled: false
  socket_mode_enabled: false

メッセージ送信テスト

users.listの取得

users.list TesterでWorkspaceの登録ユーザ一覧をjson形式で取得できる。
(ただし、tokenに対してmanifestでusers.readを許可しておく必要がある)

tokenを設定してTest methodボタンを押すとjson形式の情報がAPI responseの欄に表示される。
その中に
“id” : “xxxxxxx”,
“team_id”: “xxxxxx”,
“name”: “username”,
などの項目があるので、このidの値を<@userid>と大小記号で括ることでmentionできる

表示される情報の詳細はこちら
{
    "ok": true,
    "members": [
        {
            "id": "USLACKBOT",
            "team_id": "T012XXXXXXX",
            "name": "slackbot",
            "deleted": false,
            "color": "757575",
            "real_name": "Slackbot",
            "tz": "America/Los_Angeles",
            "tz_label": "Pacific Daylight Time",
            "tz_offset": -25200,
            "profile": {
                "title": "",
                "phone": "",
                "skype": "",
                "real_name": "Slackbot",
                "real_name_normalized": "Slackbot",
                "display_name": "Slackbot",
                "display_name_normalized": "Slackbot",
                "fields": null,
                "status_text": "",
                "status_emoji": "",
                "status_expiration": 0,
                "avatar_hash": "xxxxxxxxxxx",
                "always_active": true,
                "first_name": "slackbot",
                "last_name": "",
                "image_24": "https://a.slack-edge.com/88888/img/slackbot_24.png",
                "image_32": "https://a.slack-edge.com/88888/img/slackbot_32.png",
                "image_48": "https://a.slack-edge.com/88888/img/slackbot_48.png",
                "image_72": "https://a.slack-edge.com/88888/img/slackbot_72.png",
                "image_192": "https://a.slack-edge.com/88888/marketing/img/avatars/slackbot/avatar-slackbot.png",
                "image_512": "https://a.slack-edge.com/88888/img/slackbot_512.png",
                "status_text_canonical": "",
                "team": "T012XXXXXXX"
            },
            "is_admin": false,
            "is_owner": false,
            "is_primary_owner": false,
            "is_restricted": false,
            "is_ultra_restricted": false,
            "is_bot": false,
            "is_app_user": false,
            "updated": 0,
            "is_email_confirmed": false
        },
        {
            "id": "U0123XXXXXX",
            "team_id": "T012XXXXXXX",
            "name": "noboru",
            "deleted": false,
            "color": "9f69e7",
            "real_name": "noboru",
            "tz": "Asia/Tokyo",
            "tz_label": "Japan Standard Time",
            "tz_offset": 32400,
            "profile": {
                "title": "",
                "phone": "",
                "skype": "",
                "real_name": "noboru",
                "real_name_normalized": "noboru",
                "display_name": "",
                "display_name_normalized": "",
                "fields": null,
                "status_text": "",
                "status_emoji": "",
                "status_expiration": 0,
                "avatar_hash": "xxxxxxxxxxxx",
                "image_24": "https://secure.gravatar.com/avatar/.jpg?0023-24.png",
                "image_32": "https://secure.gravatar.com/avatar/.jpg?0023-32.png",
                "image_48": "https://secure.gravatar.com/avatar/.jpg?0023-48.png",
                "image_72": "https://secure.gravatar.com/avatar/.jpg?0023-72.png",
                "image_192": "https://secure.gravatar.com/avatar/.jpg?0023-192.png",
                "image_512": "https://secure.gravatar.com/avatar/.jpg?0023-512.png",
                "status_text_canonical": "",
                "team": "T012XXXXXXX"
            },
            "is_admin": true,
            "is_owner": true,
            "is_primary_owner": true,
            "is_restricted": false,
            "is_ultra_restricted": false,
            "is_bot": false,
            "is_app_user": false,
            "updated": 1234567890,
            "is_email_confirmed": true
        },
        {
            "id": "U0123XXXXXX",
            "team_id": "T012XXXXXXX",
            "name": "hellobot2000",
            "deleted": false,
            "color": "4bbe2e",
            "real_name": "HelloBot2000",
            "tz": "America/Los_Angeles",
            "tz_label": "Pacific Daylight Time",
            "tz_offset": -25200,
            "profile": {
                "title": "",
                "phone": "",
                "skype": "",
                "real_name": "HelloBot2000",
                "real_name_normalized": "HelloBot2000",
                "display_name": "",
                "display_name_normalized": "",
                "fields": null,
                "status_text": "",
                "status_emoji": "",
                "status_expiration": 0,
                "avatar_hash": "g1054991f15d",
                "api_app_id": "A026UHDP562",
                "always_active": true,
                "bot_id": "B026Y9AK6UV",
                "image_24": "https://secure.gravatar.com/avatar/.jpg?0026-24.png",
                "image_32": "https://secure.gravatar.com/avatar/.jpg?0026-32.png",
                "image_48": "https://secure.gravatar.com/avatar/.jpg?0026-48.png",
                "image_72": "https://secure.gravatar.com/avatar/.jpg?0026-72.png",
                "image_192": "https://secure.gravatar.com/avatar/.jpg?0026-192.png",
                "image_512": "https://secure.gravatar.com/avatar/.jpg?0026-512.png",
                "status_text_canonical": "",
                "team": "T012XXXXXXX"
            },
            "is_admin": false,
            "is_owner": false,
            "is_primary_owner": false,
            "is_restricted": false,
            "is_ultra_restricted": false,
            "is_bot": true,
            "is_app_user": false,
            "updated": 1234567890,
            "is_email_confirmed": false
        }
    ],
    "cache_ts": 1234567890,
    "response_metadata": {
        "next_cursor": ""
    }
}

users.list Tester
Test method

chat.postMessageでメッセージ送信

chat.postMessage Testerからメッセージ送信の確認ができる。

chat.postMessage Tester

tokenとchannelの情報は必須と書かれているが、他に何も書かないとAPI responseに以下のように表示されて、messageは送信されないようだ。

{
    "ok": false,
    "error": "no_text"
}

attachmentもしくはblocksに入力する必要がある。

blocksにはjson形式の文字列を入力する必要がある。typeのdefaultはmrkdwnと書かれているので、“mrkdown”指定する。mentionは’<>‘で括る必要があるが、typeを“plain_text”とすると’&lt;&gt;’にエスケープされてしまい、mentionが機能しない。
Mrkdwnのエスケープの詳細はFormatting text for app surfacesを参照。

[{
    "type": "section", 
    "text": {
        "type": "mrkdwn", 
        "text": "<@U0123XXXXXX> Hello World"
    }
}]

attachmentには“pretext”と“text”を指定できるらしい。typeは指定しなくても良いようだ。

[{
    "pretext": "<@U0123XXXXXX> pre-hello",
    "text": "<@U0123XXXXXX> text-world"
}]

blocksのsectionを二つ並べると、2段落に別れる。

[{
    "type": "section", 
    "text": {
        "type": "mrkdwn", 
        "text": "<@U0123XXXXXX> Hello World"
    }
},
{
    "type": "section", 
    "text": {
        "type": "mrkdwn", 
        "text": "<@U0123XXXXXX> Hello World"
    }
}]

上の3つの例を順に実行した時のメッセージはこんな感じ。
最後の2つの例はpythonから送ったもの。改行は文字列中に\nと書く。

chat.postMessage Tester

pythonからの送信

slack API 入門 (1) - Pythonによるメッセージ送信を参考にさせていただきました。

必要に応じてpip install requestsを実行しておく。

TOKENの設定

Your Appsから自分のAppのリンクに入って、左のメニューのFeaturesにある「OAth & Permissions」をクリックすると、「Bot User OAuth Token」が表示されるので、ボタンでコピーしてTOKEN = ''に設定

Bot User OAuth Token

USER_IDの設定

USERIDはusers.list TesterにTokenを指定してTest methodボタンで表示されるリストに情報がある。(Token以外の部分は空欄で良い)

動作確認できたスクリプトはこちら snd2slack_test.py


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# =======================================================
#  chat.postMessage APIでpythonからslackにメッセージを送信
#
#  snd2slack_test.py
#  coded by Noboru Harada (noboru@ieee.org)
#
#  Changes:
#  2021/07/04: First version
# =======================================================

import requests

# parameter settings
TOKEN = '' # set your token (e.g., 'xoxb-xxxx...')
CHANNEL = 'test' # set your channel (e.g., 'test')
USER_ID = '' # set user_id to be mentioned (e.g., 'U0123XXXXX')


# define snd2slack()
def snd2slack(channel, text):
   url = "https://slack.com/api/chat.postMessage"
   headers = {"Authorization": "Bearer "+TOKEN}
   data  = {
      'channel': channel,
      'text': text
   }
   return requests.post(url, headers=headers, data=data)


text = '<@'+USER_ID+'> 改行のテスト\n Pythonからの送信テストです。'
r = snd2slack(CHANNEL, text)
print("return ", r.json())

参考

chat.postMessage

Back to Index