LoginSignup
15
13

More than 5 years have passed since last update.

API Gateway + Lambda で slack (2) ~ slash commandとinteractive message ~

Posted at

API Gateway + Lambda で slack

前回slack appを登録した続きからです。

slash commandとinteractive messageを利用して対話的にslackで処理を進めてみます。

lambdaの登録

まずは動作テストのためにapexのhelloを置いてしまいます。

apex deploy hello

で実行されるとテキストだけ出力するサンプルが配置されます。

API Gatewayの登録

/ に配置してしまいます。

  • [アクション] -> [メソッドの作成] -> POSTを選んでチェックをクリック

API_Gateway.png

  • セットアップ画面になるので、先ほど作成したlambdaを選んで[保存]

API_Gateway2.png

  • 権限許可確認画面がでるので[OK]

API_Gateway3.png

  • メソッドの実行画面で[統合リクエスト]を選択

API_Gateway4.png

  • [本文マッピングテンプレート]をクリックして詳細を出してから、[マッピングテンプレーとの追加] -> application/x-www-form-urlencoded を入力してチェックをクリック

API_Gateway5.png

  • パススルー動作の変更画面がでるので [はい、この統合を保護します]

API_Gateway6.png

  • POSTの中身をquerystringに押し込むテンプレートを記述して[保存]

前回は詳細を書きませんでしたが、これはvelocityのテンプレートです。awsで規定されている変数をvelocityのテンプレートを使ってlambdaに渡すことができるという仕組みです。

POSTのデータを展開して渡すことができるので下記を参考にしたテンプレートを配置しています。基本的に使うのは、querystring内に展開されるPOSTで渡されたパラメータです。

http://qiita.com/durosasaki/items/83af014aa85a0448770e
http://dev.classmethod.jp/cloud/aws/sugano-013-api-gateway/

API_Gateway7.png

#set($rawAPIData = $input.path('$'))
## escape any quotes
#set($rawAPIData = $rawAPIData.replace('"', '\"'))

## first we get the number of "&" in the string, this tells us if there is more than one key value pair
#set($countAmpersands = $rawAPIData.length() - $rawAPIData.replace("&", "").length())

## if there are no "&" at all then we have only one key value pair.
## we append an ampersand to the string so that we can tokenise it the same way as multiple kv pairs.
## the "empty" kv pair to the right of the ampersand will be ignored anyway.
#if ($countAmpersands == 0)
 #set($rawPostData = $rawAPIData + "&")
#end

## now we tokenise using the ampersand(s)
#set($tokenisedAmpersand = $rawAPIData.split("&"))

## we set up a variable to hold the valid key value pairs
#set($tokenisedEquals = [])

## now we set up a loop to find the valid key value pairs, which must contain only one "="
#foreach( $kvPair in $tokenisedAmpersand )
 #set($countEquals = $kvPair.length() - $kvPair.replace("=", "").length())
 #if ($countEquals == 1)
  #set($kvTokenised = $kvPair.split("="))
  #if ($kvTokenised[0].length() > 0)
   ## we found a valid key value pair. add it to the list.
   #set($devNull = $tokenisedEquals.add($kvPair))
  #end
 #end
#end

{
    "headers" : {
#foreach( $key in $input.params().header.keySet() )
       "$key" : "$input.params().header.get($key)"#if( $foreach.hasNext ),#end
#end
    },
    "querystring" : {
#foreach( $kvPair in $tokenisedEquals )
  ## finally we output the JSON for this pair and append a comma if this isn't the last pair
  #set($kvTokenised = $kvPair.split("="))
  #if($kvTokenised.size() == 2 && $kvTokenised[1].length() > 0)
    #set($kvValue = $kvTokenised[1])
  #else
    #set($kvValue = "")
  #end
  #if( $foreach.hasNext )
    #set($itemDelimiter = ",")
  #else
    #set($itemDelimiter = "")
  #end
 "$kvTokenised[0]" : "$kvValue"$itemDelimiter
#end
    },
    "stage" : "$context.stage",
    "sourceIp" : "$context.identity.sourceIp",
    "userAgent" : "$context.identity.userAgent"
}
  • デプロイしないと反映されないので[アクション] -> [APIのデプロイ] -> APIのデプロイウィンドウがでるので、ステージ名を前回作ったものを選択して[デプロイ]

API_Gateway8.png

  • URLの呼び出し:で示されるURLを取っておきます

API_Gateway9.png

slash commandを登録

slack appの画面から[slash commands]を選択して、[Create New Command]を選びます。

Slack_API__Applications___wacul_Slack.png

この時点で、API gatewayにapplication/x-www-form-urlencodedでPOSTすると、helloworldが帰ってくるはずです。

$ curl -XPOST -d "test" [API gatewayのURL]
{"hello":"world"}

slack appの設定

  • 作成したslack appの[Slash Commands]から[Create New Command]

Slack_API__Applications___wacul_Slack.png

  • コマンドを登録する

登録するコマンド名をCommandRequest URLにAPI Gatewayで控えたURL、Short Descriptionに適当な説明を入れて[Save]

Slack_API__Applications___wacul_Slack3.png

slackで/helloしたら返事が返って来れば成功です。

tokenチェックの追加

このままではcurlでテストした通り、どこからでもURLを叩けば結果を出してしまいます。
helloのように特に意味のない結果を返すだけなら問題ないですが、作ったslack appの通知だということを確認するためにtokenをチェックするようにします。

tokenは作成したslack appのclient idclient secretが記載されていた、[Basic Infomation]のVerification Tokenに記載されています。

これが、slackからPOSTされた時のパラメータ

のtokenとして送られてくるので、文字列が一致するかチェックするだけです。

他、使用するユーザやチャンネルを制限したいなら、user_idchannel_idをチェックしたりすればいいことになります。

interactive message

interactive messageとは、slackのドキュメントに乗っているものを見てもらうのが一番早いかと思います。

ボタンを表示して、押したボタンに対してさらに反応させることができるものです。
これを利用すると、jenkinsでやっていたようなデプロイの実行などをslackで完結させることが可能になります。

slack appの設定

interactive message用に別のlambdaを作ってもいいですが、ここでは同じものを使いまわします。

  • 登録したslack appの[Interactive Messages]から[Enable Interactive Messages]

Slack_API__Applications___wacul_Slack.png

  • [Request URL]にAPI Gatewayで控えたURLを入れて[Enable Interative Messages]

Slack_API__Applications___wacul_Slack2.png

lambda functionの変更

slackのドキュメント通り、返却するメッセージにactionを付け加えます。

console.log('starting function')
exports.handle = function(e, ctx, cb) {
  console.log('processing event: %j', e)
  cb(null, { text: "button", attachments: [{ "callback_id": "test", actions: [{name: "test", text: "Test", type: "button", value: "test"}] }] } )
}
apex deploy hello

でデプロイして準備完了です。

実行してみる

slackで /hello を実行すると下記のようになるはずです。

Slack_-_wacul.png

この[Test]ボタンが押せるようになっています。押すと、ボタンは消えてしまうはずです。

ボタンを押した際に、interactive messagesで登録したURLにリクエストが飛んでおり、その返答が表示されているのですが、今回はボタンを押した際にも同じcallback_idのボタンを出しているので、ボタンが表示されない結果になっています。

あとは、ボタンを押した時に渡されるパラメータ

に従って処理を進めていけば対話的にslack上で処理を組み立てることができます。

注意点として、slash commandの場合と異なり、payloadパラメータにURLエンコードされたjsonでデータが渡されるので、slash commandと同じlambdaを使う場合は、payloadパラメータの有無で処理を分けるといいでしょう。

TIPS

3秒以上かかる処理

slash commandsの最初の応答は3秒以内ではないとエラーになる仕様です。その場合、非同期で別のlambdaを呼びだしてあげたりすることで回避します。

呼び出されたlambdaでは、response_urlパラメータに記載されているURLに対して、メッセージをPOSTします。そうすればメッセージが表示されるようになります。response_urlは30分以内で5回までしか利用できません。

メッセージのの表示非表示

コマンドを実行したときに、本人にしか見えないメッセージかどうかは response_typein_channelephemeralかで決まります。デフォルトはephemeralなので本人にしか表示されません。

response_urlを使って複数回メッセージを送ると、デフォルトではメッセージを書き変えますが、メッセージを書き変えずに新しく途中からメッセージを表示するようにしたりといったことができます。

15
13
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
15
13