LoginSignup
3
2

More than 3 years have passed since last update.

slack interactive messageをaws api Gatewayで受け取り、Lambdaでパースする。

Last updated at Posted at 2019-07-26

はじめに

インターンで作成した受付アプリの中でSlackのinteractive messageを利用した際に少し躓いたため、共有します。

  • Slackにメッセージ送信(Webhook)->ボタン押下(Slack)->メッセージ書き換え
  • 機能自体はawsおよびSlackについて無知な状態から6日間ほどで作成

API Gateway作成

一般的なやり方でAPI Gatewayを作成し、POSTメソッドを定義します。
スクリーンショット 2019-07-26 11.42.46.png
普通です。

正直試行錯誤していた時の記憶が曖昧なのでもしかしたら設定を変えている部分があるかもしれません。

なかなかLambdaでうまく受け取れなかったためこの辺りを参照しましたが、結局Lambdaでデコードおよびパースしたため効いていないように思います。
https://qiita.com/durosasaki/items/83af014aa85a0448770e

デプロイしてエンドポイントを発行します。
発行したエンドポイントのURLをSlack AppのInteractive ComponentsのRequest URLの部分に書き込みます。

スクリーンショット 2019-07-26 11.40.37.png

これで一先ずはSlackからAPI Gateway+Lambdaへの流れができたことになります。

ログを見ることの大切さ

私が躓いたのはここです。デバッグをするにあたってSlackからそもそもリクエストが飛んできていないのか、などと疑ってしまいました。ログを見れば良かったんだと気づくまでに超絶時間がかかり、時間を溶かしてしまったのは内緒で。

さて肝心のどうやってログを見るのかということですが、Lambdaに紐づいているロールにAmazon CloudWatchAmazon CloudWatch Logsを含めます。Amazon CloudWatchのみで十分だと思っていましたがログが書き込まれなかったためおそらく両方必要です。
スクリーンショット 2019-07-26 11.48.32.png

さらに、関数コード内に以下を記入します。

import subprocess
import logging

# ログ設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# イベントハンドラ
def lambda_handler(event, context):
    logging.info(json.dumps(event))
    # 以下略

これでAmazon CloudWatchのリソース内のログ部分から、どんなリクエストが飛んできたのかを見ることが可能です。jsonでdumpしてあげると見やすいので強くお勧めします。
スクリーンショット 2019-07-26 11.53.33.png

ここで確認すると、Slackからのリクエストはしっかりと届いていました。どうやら自分のパースがうまく出来ていなかったせいでSlack上でボタンを押しても次のアクションに繋がらなかったようです。

Slackからのリクエストのパース

{
    "headers": {
        "Accept": "application/json,*/*",
        "Accept-Encoding": "gzip,deflate",
        "CloudFront-Forwarded-Proto": "https",
        "CloudFront-Is-Desktop-Viewer": "true",
        "CloudFront-Is-Mobile-Viewer": "false",
        "CloudFront-Is-SmartTV-Viewer": "false",
        "CloudFront-Is-Tablet-Viewer": "false",
        "CloudFront-Viewer-Country": "US",
        "Content-Type": "application/x-www-form-urlencoded",
...
    },
    "querystring": {
        "payload": "{slackからのメッセージ本文がx-www-form-urlencodedされたもの}"},
...
}

Slackからのリクエストの中身を見てみると"Content-Type": "application/x-www-form-urlencoded"で取得できていることがわかりました。つまり、Lambdaではevent["querystring"]["payload"]をデコードしてあげればjsonでパース可能な形になるわけです。(これに気づくまでに地球が3周しました。)

というわけで以下Lambda上のパース部分のみ取り出して載せておきます。

def lambda_handler(event, context):
    logging.info(json.dumps(event))
    # print(event) #デバッグ用
    #urlencodedされているためデコードする
    response = json.loads(unquote(event['querystring']['payload']))
    print(json.dumps(response))
    print(response['response_url'])
    # 返信用URL
    response_url = response['response_url']

まとめ

  • PaaSでログ見る方法ってシンプルに思えて結構入り組んでいるように感じました。慣れればどこ見ればいいかすぐに分かるはずですが初心者にはキツかった(涙)
  • API Gateway側でjsonにdumpしてLambdaに渡す処理の記事読んだけど全く理解できずに断念したので、LambdaのPythonでdecodeできてよかったです。これができなかったら存続の危機だった。
  • SlackのAPIの仕様が新しくなって過去の文献があまり役に立たなかったりするのでお気をつけください。
  • Slack clientのZipをアップロードをして実装している記事もありましたが面倒なのでお勧めしません。今動くのか?
3
2
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
3
2