LoginSignup
9
9

More than 1 year has passed since last update.

pythonのFlaskを使ってslack messageのOutgoing Webhookを設定する

Last updated at Posted at 2019-05-16

やること

  • slackのメッセージ投稿をフックしてweb apiで利用できるようにする

環境

  • python3.6
  • Flask==1.0.2
  • slackeventsapi==2.1.0

対象

  • slackの投稿に対して何か処理をしたい人

前提

やりたいことそのまんまの名前をしているslackのmessage Outgoing Webhookは既に廃止😭
slack api Outgoing Webhooks

代わりにevent apiを用いることでメッセージをフックする。

手順

  • Flaskをインストールする
  • python-slack-events-apiをインストールする
  • slack apiコンソールからslackアプリを作成する
  • Flaskでslack-events-apiを用いて、フックを受けるメソッドを定義する
  • Event Subscriptionsにフック先のURLを登録する

Flaskをインストールする

  • 今回はFlaskの説明は割愛
  • 知らない方はネットに説明がたくさんあるので、そちらを参考してください

というわけで、とりあえず

pip install flask

python-slack-events-apiをインストールする

  • slack event apiには便利なクライアントライブラリが用意されている
  • 別にクライアントライブラリを使わなくても実装はできるが、後述する理由により、ライブラリを使う方が圧倒的に楽。

使うのはこれ→event api ライブラリ

こちらも

pip install slackeventsapi

公式でも導入方法が説明されている。英語に抵抗なければこちらも参考に

slack apiコンソールからslackアプリを作成する

スクリーンショット 2019-05-17 0.49.19.png

  • 導入先のワークスペースを選ぶ。アプリの名前は後からでも変えられるから適当に決める
    スクリーンショット 2019-05-17 0.50.01.png

  • Event Subscriptionsを開いて、Enable EventsをONにする。
    スクリーンショット 2019-05-17 0.55.00.png

Flaskでslack-events-apiを用いて、フックを受けるメソッドを定義する

  • 適当な名前のpythonファイルを作成して、以下を書き込む
slackHook.py
from flask import abort, Flask, jsonify, request
from slackeventsapi import SlackEventAdapter

app = Flask(__name__)

slack_events_adapter = SlackEventAdapter("SIGINING_SECRET", "/slack/events", app)
@slack_events_adapter.on("message")
def hookSlackEvents(event_data):
    app.logger.debug(event_data)
  • この際のSIGINING_SECRETには、先ほど作成したslackアプリのBasic Informationに書いてある、SIGINING SECRETを入れる。
    ※図の中ではミスによりClients Secretにオレンジ枠がかかっているが、正しくはSigning Secretなので注意
    スクリーンショット 2019-05-17 1.04.47.png

  • Flaskサーバを起動する

  • Flaskサーバをローカルで立ち上げた場合は、ngrok等を利用して、外部からアクセスできるようにする

Event Subscriptionsにフック先のURLを登録する

  • 先ほど作成したslackアプリのEvent Subscriptionsを開いて、Request Eventsにさっき立ち上げたサーバのエンドポイントを登録する
  • baseURL + /slack/eventsというように、Flaskのslack_events_adapteに登録したリソースと同じように入力する

スクリーンショット 2019-05-17 1.10.03.png

  • エンドポイントを入力してしばらくすると、Verifiedとでるので、こうなればフックが完了したこととなる
  • 同じ画面の中間あたりのSubscribe to Workspace Eventsで、フックしたいイベントを選択する。今回はmessage.channels
    スクリーンショット 2019-05-17 1.51.59.png

  • 画面を離れる前に画面下部のsave changeを押すのを忘れないように

  • ちなみに、クライアントライブラリを使わなかった場合、エンドポントが生きているかの認証処理を自分で実装しなければならないのでめんどくさい(自分はうまくできなかった・・・)

確認

  • どのチャンネルでもいいので、なにかしたメッセージを投稿すれば、コンソールにログがでるはず。

うまく行かないとき

  • apiを使うときにはいくつかの権限を付与する必要があるため、もし自分のslackアカウントがアプリに権限を与える権限を持っていない場合はうまく行かないかも

ちょっと解説

わかる人か見れば明白なのだけど、一応この部分で何やってるかの解説

slackHook.py
slack_events_adapter = SlackEventAdapter("SIGINING_SECRET", "/slack/events", app)
@slack_events_adapter.on("message")
def hookSlackEvents(event_data):
    app.logger.debug(event_data)
  • 一行目ではただクライアントのインスタンスを作成しているだけ
  • @から始まる二行目は、通常のFlaskアプリのルーティングの代わりの役目を果たす
  • 三行目が、そのローティングに対して実行したいメソッド
  • event_dataにイベントの内容がJsonで受け取れる
  • 今回はメッセージの投稿をフックしたかったため、"message"を指定したが、別のイベントもフックすることができる。
  • "message"の変わりに、使いたいイベントを@slack_events_adapter.on("event")に書いて、Subscribe to Workspace Eventsからフックしたいイベントを追加すればOK

あとがき

  • 多分slack上のほぼ全てのイベントをフックできるから、使いこなせばワークスペースの神になれる
    • 新しいメンバーがジョインしたら自動で資料を送信する
    • ファイルがアップロードされたらそれをGoogle driveにアップ
    • 嫌いな奴が投稿するたび、その投稿を削除する
  • slack web apiを使うためのpython-slackclientと、今回のpython-slack-events-apiは別ライブラリなので注意
  • slack web apiでもRTM apiを使えば、同じようにイベントのフックが可能っぽい
    参考↓
rtm.py
import os
    import slack

    @slack.RTMClient.run_on(event='message')
    def say_hello(**payload):
        data = payload['data']
        web_client = payload['web_client']
        rtm_client = payload['rtm_client']
        if 'Hello' in data['text']:
            channel_id = data['channel']
            thread_ts = data['ts']
            user = data['user']

            web_client.chat_postMessage(
                channel=channel_id,
                text=f"Hi <@{user}>!",
                thread_ts=thread_ts
            )

    slack_token = os.environ["SLACK_API_TOKEN"]
    rtm_client = slack.RTMClient(token=slack_token)
    rtm_client.start()
  • 自分はFlaskをzappaをつかって、lambdaにデプロイしたが、ワークスペースの全ての投稿のたびに呼びだされるから、さすがのlambdaも無料枠突破するのでは? とちょっと心配
    • zappaでデプロイするとデフォルトで512MBになるから、無料枠は800,000秒
    • 一回の処理に多くみつもって1秒かかるとしても800,000投稿/月までは大丈夫。1日26,666投稿までは大丈夫と考えると全然余裕だった。

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

9
9
2

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
9
9