slackのOutgoing Webhooksから受信する

Proxy統合ではなく、Lambda側のインタフェースを決めてしまう

 

/raspberrypi/{proxy+} を作成し、POSTのみ作成

/raspberrypi/speak で呼び出し、speakの場合、音声再生要求を投げる

Lambda関数を作成

実装はシンプル

https://github.com/nilesflow/Slack2RaspberryPi

下記等参考に

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html

query paramaterのtokenの値の検証のみ

tokenの値はコンソール上の環境変数に設定

Lambdaを登録しておく。

 

フォーマットは下記の形式

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-output-format

 

Lambdaオーソライザー

ロールはLambda実行権限含むものを作成しておく

 

クエリパラメータにtokenを設定して認証させたいので、認証でLambdaリクエストオーソライザーを設定。

~検証とURLクエリ文字列パラメータを設定。

リクエストパスのproxyを入力しておく

・作成したLambdaを指定

・プロキシ統合は使わずに、呼び出し側ロジックはAPI Gateway側で吸収

・リクエストパラメータのproxyをマッピング

 

・Content-Type=application/x-www-form-urlencoded で送信される

・それ以外は厳しめに通過禁止に設定しておく

 

・マッピングテンプレートは次の通り

## slackのOutgoing Webhooksから下記の形式で送信される
## token=viK8ruCmEfBjd9u84MOEeTWo
## team_id=T0001
## team_domain=例
## channel_id=C2147483705
## channel_name=テスト
## timestamp=1355517523.000005
## user_id=U2147483697
## user_name=スティーブ
## text=googlebot: 身軽なツバメの対気速度はどのくらい?
## trigger_word=googlebot:

## POSTパラメータの分割(A=x&B=y)
#set($aParams = $input.body.split(“&”))

## path変数の分割
#set($aPaths = $input.params(‘proxy’).split(“/”))

## 出力されるJSONデータの生成
{
##pathの次階層をactionとする
“action” : “$aPaths[0]”,

## 必要なPOSTパラメータのみをマッピング
#foreach( $param in $aParams)
#set($hParam = $param.split(“=”))
#if( $hParam[0] == “text”)
“text” : “$util.urlDecode($hParam[1])”,
#end
#if( $hParam[0] == “user_name”)
“user” : “$util.urlDecode($hParam[1])”,
#end
#end

## カンマ制御のためのダミー
“dummy” : null
}

 

Lambda側で定義される次の変数をマッピングしている

action

text

user

 

・統合レスポンスは200のみ設定

slackへ応答を返すには、200でレスポンスパラメータを返す必要があるため

マッピングテンプレートは次の通り

## for slack Outgoing Webhooks
## 全て200の単一フォーマットで返却
#set ($inputRoot = $input.path(‘$’))

## Lambdaで正常に処理された場合
#if ($input.path(‘$.statusCode’) > 0)

## 200の場合のフォーマット
#if ($input.path(‘$.statusCode’) == 200)
#set ($body = $util.parseJson($input.path(‘$.body’)))
{
“text” : “$body.message”
}

## それ以外の場合のフォーマット
#else ## 200
#set ($body = $util.parseJson($input.path(‘$.body’)))
{
“text” : “$body.error: $body.error_description”
}
#end ## not 200

## 例外等
#else ## statusCode
{
“text” : “$input.path(‘$.errorMessage’)”
}
#end ## not statusCode

Lambdaの応答の次のケース全てを200として返却する

・ステータスコード200:正常

・ステータスコード200以外:異常(Lambda実装コード中で認識したエラー)

・例外等それ以外:異常(Lambda実装コード中以外のエラーも含む)

 

・ゲートウェイのレスポンスで、API Gatewayで検出したエラーのレスポンスフォーマットを定義する

これも、SlackのOutgoing Webhooksのフォーマットに合わせておく。

400, 500も200で返すようにしておく。

 

メソッドレスポンスモデルは不要なのか。

https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/api-gateway-method-settings-method-response.html

統合レスポンス、ゲートウェイのレスポンスでまかなえているようだった。

slack → RaspberryPiを実現するため

python3.6で実装

下記を参考に

【AWS Lambdaの基本コードその4】 AWS IoTにメッセージをPublish

事前に作っておいたエンドポイント raspberrypi/speak へ送信

RaspberryPi側でsubscribeできることを確認しておく

 

Lambda応答

return {
‘isBase64Encoded’: False,
‘statusCode’: statusCode,
‘body’: json.dumps(dict),
‘headers’: {
‘Content-Type’: ‘application/json’,
},
}

 

Lambdaの注意点

API Gateway側でプロキシ統合を選んだ場合は、Lambda側で実装しなくてはならない

API Gateway側で吸収するなら、決まった形式で返す必要がある

こことか参考にさせてもらった

https://qiita.com/taknuki/items/dd47d1c6d4190b52df9a#%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B9

 

テスト送信しておく