Slack Events APIで飛んでくるJSONの内容を確認するだけのLambdaコード

複数サービスを連携して処理するとき、Slack Events API(いわゆるWebhook)を使って、AWS LambdaやAzure Logic Apps経由でもろもろ処理させることが増えた。

ただ、Events APIで飛んでくるJSONが、公式ドキュメントを見てもわかりにくい(というか、メッセージの種類が多くて把握できていない)。

ドキュメント読むよりは、実際にWebhookを設定し、メッセージ送信してログ出力したほうが楽だなと思い、適当なLambdaを書いたのでメモ。

環境

LambdaをNode.js v20で作成。おそらくバージョンには依存していないと思う。

Lambdaの関数URLを有効にし、認証タイプは NONE でパブリックアクセス可能にしておく。

実装

チャレンジリクエスト(url_verification)には対応しているが、Verification Tokenの検証はしていない、あくまで検証用。

index.mjs に張り付ければOK。

export const handler = async event => {
  const {
    requestContext: {
      http: {
        method,
      },
    },
    body: bodyString, // stringのため、JSON.parseが必要
  } = event

  if (method !== 'POST') {
    console.error('invalid method', { method, bodyString })
    return { statusCode: 404 }
  }

  const {
    // token, // 本番ではチェックが必要だが、検証なので無視
    challenge,
    type: eventType,
    event: slackEvent,
  } = JSON.parse(bodyString)

  // チャレンジ
  if (eventType === 'url_verification') {
    return {
      statusCode: 200,
      headers: { 'Content-Type': 'text/plain' },
      body: challenge,
    }
  }

  console.log(bodyString)

  return { statusCode: 200 }
}

Slack Apps側の設定

Slack Appsの「Event Subscriptions」にて、「Enable Events」を有効化。

「Request URL」にLambdaの関数URLを設定すればいい。

イベント通知が来れば、Lambdaに紐づくCloudWatch LogsにリクエストされたJSONが出力される。

振り返り

とりあえずこのLambdaを書いておいて、必要に応じて関数URLの有効/無効を切り替えて使っている。非公開であれば課金も発生しないので、似たようなLambdaをサービスごとに用意している。

Slackのメッセージ、チャンネルがpublic/private、送信者がユーザー/ボット、チャンネル直下/スレッド内、スレッド内から「以下にも投稿する」でチャンネルにも投稿した場合、などなど種類と組み合わせが多いし、それが全部メッセージとして飛んでくる。

一度やったことを焼き直すのは簡単なんだが、別種のメッセージを処理しようと思うと結構大変。

サブタイプなどで分かれてはいるが、もう少し細かく分けてくれると嬉しいと思いつつ、大多数のユースケースではそこまで細かな分類/制御はしないだろうとも思う。

ただでさえAPI設計は大変だし、もともと小さなサービスだったのが、これほど急成長するとは中の人も思ってなかったのではなかろうか。