<目次>
(1) Slackで自動返信の投稿をするボットをPythonで作る手順(ngrokでローカルPCをサーバーに見立てて)
(1-1) STEP1:Slackアプリの新規作成&権限付与
(1-2) STEP2:Python⇒Slackへのメッセージ投稿の疎通
(1-3) STEP3:「ngrok」のインストール
(1-4) STEP4:Python環境にflaskをインストール
(1-5) STEP5:Slackでイベント発行&受取りの準備
(1-6) STEP6:Pythonコードの作成(最終版)
(1-7) STEP7:疎通テスト
(1) Slackで自動返信の投稿をするボットをPythonで作る手順(ngrokでローカルPCをサーバーに見立てて)

(1-1) STEP1:Slackアプリの新規作成&権限付与
(1-2) STEP2:Python⇒Slackへのメッセージ投稿の疎通
(1-3) STEP3:「ngrok」のインストール


↓
(1-4) STEP4:Python環境にflaskをインストール
> pip install flask

from flask import Flask app = Flask(__name__) @app.route('/', methods=['GET', 'POST']) def helloworld(): return "Hello World!" if __name__ == "__main__": app.run(debug=True)


(参考)Flaskについてもう少し知りたい方は下記もご参照ください
(1-5) STEP5:Slackでイベント発行&受取りの準備
> pip install slackeventsapi > pip install slackclient


・②ご自身のSlackアプリ画面で左メニューから「Signing Secret」のキーの値を取得します。


・③取得したSigning Secretの値を使い、Python側でイベントを処理するためのSlackEventAdapterインスタンスを生成するコード等を追加。
import slack from flask import Flask from slackeventsapi import SlackEventAdapter SLACK_SIGNING_SECRET = 'XXXXX' SLACK_BOT_TOKEN = 'xoxb-XXXXXX' post_channel = '[投稿先チャンネル]' post_text = "[投稿メッセージ]" app = Flask(__name__) ####【イベント受付 追記START】#### # Slackから来たイベントを受け付けるためのインスタンスを生成 slack_event_adapter = SlackEventAdapter( SLACK_SIGNING_SECRET,'/slack/events',app) ####【イベント受付 追記END】#### @app.route('/', methods=['GET', 'POST']) def respond_message(): # トークンを指定してWebClientのインスタンスを生成 client = slack.WebClient(token=SLACK_BOT_TOKEN) # chat_postMessageメソッドでメッセージ投稿 client.chat_postMessage(channel=post_channel, text=post_text) return post_channel+'チャンネルにメッセージ:'+post_text+'を投稿しました' if __name__ == "__main__": app.run(debug=True)
(図130④)

> ngrok http [ポート番号]

↓
Session Status online Session Expires 1 hour, 56 minutes Version 2.3.40 Region United States (us) Web Interface http://127.0.0.1:4040 Forwarding http://d112-49-106-215-201.ngrok.io -> http://localhost:5000 Forwarding https://d112-49-106-215-201.ngrok.io -> http://localhost:5000 Connections ttl opn rt1 rt5 p50 p90 0 0 0.00 0.00 0.00 0.00
(図130⑧)

(補足)「Event Subscription」設定について
・チャンネル上で起きるイベント(例:誰かが投稿した、メンションしたなど)を検知するための仕組みが「Event Subscription」設定。
・その中でも「Request URL」という設定があります。これは、検知対象のイベントが発生した時に、指定したURLに対してHTTPプロトコルの「POST」リクエストを送ります。
・このURLを、ご自身でPython等から作成したAPIに指定する事で、イベント発生時にご自身でプログラミングした処理を実行させる事ができます。
※あくまでValidationチェックを通過する目的であり、最終形のコードではありません
from flask import Flask, request, jsonify app = Flask(__name__) @app.route('/slack/events', methods=['GET', 'POST']) def respond_message(): # Slackから送られてくるPOSTリクエストのBodyの内容を取得 json = request.json print(json) # レスポンス用のJSONデータを作成 # 受け取ったchallengeのKey/Valueをそのまま返却する d = {'challenge' : json["challenge"]} # レスポンスとしてJSON化して返却 return jsonify(d) if __name__ == "__main__": app.run(debug=True)

⇒「先程のグローバルアドレス」に「/slack/events」を追記したURL

(図131③)

(図131④)

(図132①)

(1-6) STEP6:Pythonコードの作成(最終版)
import slack from flask import Flask from slackeventsapi import SlackEventAdapter SLACK_SIGNING_SECRET = 'a045c2b352f561e746d7dc162aa40f21' SLACK_BOT_TOKEN = 'xoxb-2928218983906-3134145028820-OhTdoMy2EB9WjqvyqKNq7ZQ0' app = Flask(__name__) # トークンを指定してWebClientのインスタンスを生成 client = slack.WebClient(token=SLACK_BOT_TOKEN) # ボットのユーザーIDを取得 BOT_USER_ID = client.api_call("auth.test")['user_id'] # Slackから来たイベントを受け付けるためのインスタンスを生成 # 第1引数:Singing Secretキーを指定 # 第2引数:イベントの送り先(ルートURL以降の部分) # 第3引数:イベントの送り先のWebサーバ(今回はFlaskのインスタンス) slack_event_adapter = SlackEventAdapter( SLACK_SIGNING_SECRET,'/slack/events',app) # メッセージが投稿された事を検知してイベントを発行 @slack_event_adapter.on('message') # 誰かの投稿に対してオウム返しする関数 # payloadはSlack APIが送ってくるデータで、投稿に関する情報を保持している def respond_message(payload): # payloadの中の'event'に関する情報を取得し、もし空なら空のディクショナリ{}をあてがう event = payload.get('event', {}) # 投稿のチャンネルID、ユーザーID、投稿内容を取得 channel_id = event.get('channel') user_id = event.get('user') text = event.get('text') # もしボット以外の人からの投稿だった場合 if BOT_USER_ID != user_id: # chat_postMessageメソッドでオウム返しを実行 client.chat_postMessage(channel=channel_id, text=text) if __name__ == "__main__": app.run(debug=True)
(1-7) STEP7:疎通テスト
