anz blog

Cloud FunctionsつかってSlack Bot作ってみた話

ざっくりまとめ。

  • Firebase の Cloud Functions をつかって Slack Bot つくった!
  • リクエストの検証でハマった
  • エンコードの仕様が違うので通らない
  • URLSearchParams を使うといい

です。

追記(2019.02.04)

こっちの記事で実は取れたっていうのを書いた

環境

  • firebase-tools v6.3.0
  • node v6.16.0

やりたいこと

Cloud Functions をつかって何か遊びたいな〜と思ったので、
Slack Bot をつくってみることにしました。
とりあえず、色を指定したらその情報とかを返すやつ。

成果物

さきに完成したものを。

Color Code - Slack Bot

ハマったこと

Verifying requests from Slack というので詳しく書かれているので、ありがたく参考にしつつ実装しようとしたのですが、
どうも一致しないっていうことでハマりました。
(公開はしてないんで、別にやらなくてもいいのですけど。。)

request の body をとりたい

Cloud Functions でリクエストをうけると、
Request っていうものを通してもろもろの情報をアクセスすることになるのですけれど、
これで body をそのまま受け取るためにはどうしたら。。?🤔

というのも、検証の手順のなかで、
'v0:' + timestamp + ':' + request_body と文字列を作る必要があって、
このrequest_bodyが必要なのです。

request.body というので body にはアクセスできるけど、これはすでに Object に変換されているものなので使えない。
request.rawBody みたいなものがあればいいのですけれど、どうもなさげ。。
request_raHeadersはあるけれど。。。)

どうしたのか

結局 request.body から文字列を再構築することにしました😇

const params = new URLSearchParam()
Object.keys(request.body).forEach(key => {
  params.append(key, request.body[key])
})
const baseString = params.toString()

これで、欲しかった文字列を再構築することができました。

ダメだった方法

const baseString = Object.keys(request.body).map(key => {
  return key + '=' + encodeURIComponent(request.body[key])
}).join('&')

これでもできるのだけれど、一部文字列だとだめなのです。

/cc aaaaaa はできても /cc rgb(12,12,12) は通らないみたいな。
どうやら ( と ) のエンコードが違うみたいです。

encodedURIComponent では - _ . ! ~ * ' ( ) の記号が対象外みたいだけど、
多分 Slack 側でつかっているエンコードは対象外ではないんだろうな。。と
(どの規格でやってるんだろ。。。)

encodedURIComponentドキュメントをみると、
RFC 3986 に対応するためには〜〜というサンプルがあって、
そちらと同じようにやってもダメだったんですよね。。

ほとほと困っているところで、
encodedURIComponent は最新のエンコード規格状況においきれてないので URLSearchParams を使うと良いっていうのを見て
最初に紹介した成功例の通りやったら検証が通るようになりました💪


これで Slack Bot 生活が捗りそうです!
次は annict のなにか作ってみようかな〜

参考