低気圧で頭痛がひどいのでslackで頭痛ーるを表示するappをlambdaで作った
仕上がり
最終的にはこんなのが出来上がります。
slackで頭痛ーるを表示する
低気圧で頭痛がひどい。今日も低気圧で体調を持っていかれてしまいました。
ありがたいことに頭痛ピープル向けに「頭痛ーる」というツールが公開されています。
株式会社ポッケさんありがとう...
とはいえ、頭痛ーるのサイトを毎度観に行くのが面倒。
ということでslackで表示できるようにしました。
構成は以下。シンプルです
コードはここに置いてあります。
詳細の実装は省いて
- 頭痛ーるAPIの使い方
- aws lambdaへのデプロイ
- slack appでの連携
について書き、真似できるように大枠の作り方を書いていきます。
頭痛ーるAPIの使い方
頭痛ーるのサイトでdeveloper toolを開くと数字のpathに対するリクエストを送っているxhrがあります。
これが天気、気圧情報を取ってくるリクエストです。
場所
例えば東京都調布市の場合は以下。
https://zutool.jp/api/getweatherstatus/13208
{place_name: "東京都調布市", place_id: "208", prefectures_id: "13", dateTime: "2020-11-13 22",…}
どうやら
prefectures_id + place_id
でurlが設計されてるようですね。
試しに 13209にすると 東京都町田市
になります。
こんな感じで大体連番になってるので、curlで問合せして今回は都内のidを割り出します。
対応させるとこんな感じです。
"千代田": 13101
"中央": 13102
"港": 13103
"新宿": 13104
...
都内対応表: https://github.com/ShuzoN/zut/blob/master/locations.js
昨日、今日、明日、明後日
町田市を例に見てみます。
1リクエストで昨日、今日、明日、明後日の天気と気圧が取れます。
ここでは端折っていますが、0-23時の間で1時間おきの情報を取得できます。
$ curl https://zutool.jp/api/getweatherstatus/13209 | jq
{
"place_name": "東京都町田市",
"place_id": "209",
"prefectures_id": "13",
"dateTime": "2020-11-13 22",
"yesterday": [
{
"time": "0",
"weather": "100",
"temp": "7.1",
"pressure": "1033.4",
"pressure_level": "0"
},
...
{
"time": "23",
"weather": "200",
"temp": "10.8",
"pressure": "1030.1",
"pressure_level": "4"
}
],
"today": [
...
],
"tommorow": [
...
],
"dayaftertomorrow": [
...
]
}
天気と気圧レベル
先ほどのリクエストでは1時間ごとに以下の情報を取得できます。
- 天気
- 温度
- 気圧
- 気圧レベル
天気と気圧レベルは頭痛ーる特有のマジックナンバーが当たっています。
これ関してはslack絵文字を対応させることで処理します。
{
"time": "0",
"weather": "100",
"temp": "7.1",
"pressure": "1033.4",
"pressure_level": "0"
}
天気(weather)は以下のような対応になっています。 https://github.com/ShuzoN/zut/blob/master/weather.js
exports.get = function (weatherType) {
if (weatherType === "100") { // 晴
return ":sunny:";
}
if (weatherType === "200") { // 曇り
return ":cloud:";
}
if (weatherType === "300") { // 雨
return ":umbrella:";
}
return ":innocent:"; // 例外
};
気圧レベル(pressure_level) は以下のような対応になっています。
(1は本家頭痛ーるでもokになっているため合わせています)
exports.get = function (pressureLevelType) {
if (pressureLevelType === "0") { // 🆗
return ":ok:";
}
if (pressureLevelType === "1") { // 🆗
return ":ok:";
}
if (pressureLevelType === "2") { // ⤵︎
return ":arrow_heading_down:";
}
if (pressureLevelType === "3") { // ⚠️
return ":warning:";
}
if (pressureLevelType === "4") { // 💣
return ":bomb:";
}
return ":innocent:"; // 例外 😇
};
整形してresponseを返す
あとは 頭痛ーるから情報の取得 -> 整形すればok
コード: https://github.com/ShuzoN/zut/blob/master/zutool.js
今回は業務時間に合わせて 実行当日の8-20時の天気、気圧情報を整形します。
exports.formatter = function (json) {
return json.today
.filter((h) => h.time > 7 && h.time < 21)
.map((h) => {
return `${h.time}時 ${weather.get(h.weather)} ${h.temp}℃ ${
h.pressure
}hPa ${pressureLevel.get(h.pressure_level)}`;
});
}
aws lambdaへのデプロイ
ファイル zip
実行環境としてlambdaを利用します。
今回はjsで実装しています。 1scriptだと可読性が低かったためファイル分割を行っております。
複数ファイルをデプロイするためにはzip化する必要があるため、
プロジェクトルートで以下のコマンドを実行します。
zut
というプロジェクト名で作っていますが、なんでもいいです。
$ zip -r zut.zip .
aws lambdaで関数作成
こんな感じでnode12が動くlamdbaを作ります。
zipファイルのアップロードをします。
今回はデプロイフローなどは組まず手動で済ませます。
aws api gatewayでエンドポイントの作成
lambdaのデプロイだけではapiとして動作しません。
トリガーをクリックし、api gatewayを追加します。
apiを作ったら /zut2
パスへ post メソッドの追加を行います
これでpostリクエストに対応できるようになりました。
ゴールは slack からのpost requestです。
SlackのOutgoing WebHooksは application/x-www-form-urlencoded
で送られるため、これに対応します。
統合リクエストに飛んで
マッピングテンプレートを以下のように設定します。
これはhttp content typeを見てlambdaに送信する情報を指定したテンプレートに合わせて書き換えてくれる機能です。
application/x-www-form-urlencoded
## See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
## This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
#set($allParams = $input.params())
{
"body-json" : {"body" :$input.json('$')},
"params" : {
#foreach($type in $allParams.keySet())
#set($params = $allParams.get($type))
"$type" : {
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
},
"stage-variables" : {
#foreach($key in $stageVariables.keySet())
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
#if($foreach.hasNext),#end
#end
},
"context" : {
"account-id" : "$context.identity.accountId",
"api-id" : "$context.apiId",
"api-key" : "$context.identity.apiKey",
"authorizer-principal-id" : "$context.authorizer.principalId",
"caller" : "$context.identity.caller",
"cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
"cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
"cognito-identity-id" : "$context.identity.cognitoIdentityId",
"cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
"http-method" : "$context.httpMethod",
"stage" : "$context.stage",
"source-ip" : "$context.identity.sourceIp",
"user" : "$context.identity.user",
"user-agent" : "$context.identity.userAgent",
"user-arn" : "$context.identity.userArn",
"request-id" : "$context.requestId",
"resource-id" : "$context.resourceId",
"resource-path" : "$context.resourcePath"
}
}
はい、というわけで以下のパスでpost bodyが入ってくるようにマッピングしておきます。
{"body-json" : {"body" :$input.json('$')}}
APIへのデプロイを忘れると反映されないので気をつけてくださいね。
$ curl https://<your>.execute-api.ap-northeast-1.amazonaws.com/default/zut2 -d '{"text": "渋谷"}'
{"response_type":"in_channel","blocks":[{"type":"section","text":{"type":"mrkdwn","text":"8時 :sunny: 15.7℃ 1026hPa :ok:\n9時 :sunny: 16.8℃ 1026.4hPa :ok:\n10時 :sunny: 17.8℃ 1026.3hPa :ok:\n11時 :sunny: 18.6℃ 1026hPa :ok:\n12時 :sunny: 19.3℃ 1025.4hPa :ok:\n13時 :sunny: 19.7℃ 1025hPa :ok:\n14時 :sunny: 19.9℃ 1025.1hPa :ok:\n15時 :sunny: 19.5℃ 1025.5hPa :ok:\n16時 :sunny: 18.6℃ 1026.2hPa :ok:\n17時 :sunny: 17.2℃ 1027.1hPa :ok:\n18時 :sunny: 15.7℃ 1028hPa :ok:\n19時 :sunny: 14.2℃ 1028.9hPa :ok:\n20時 :sunny: 12.8℃ 1029.6hPa :ok:"}}]}%
これで curl - aws apigateway + lambda - 頭痛ーる
の連携は終わりましたね。
slackとaws lambdaを紐づける
slack appを作成します。 zut
とでも名付けましょう。
Slash Commands -> create new command
と進みます。
request urlは先ほど作成した aws api gatewayのurlを入力します。
これで作成できました。次はworkspaceへの登録です。
install app -> install app to workspace
とすすみ、追加したいworkspaceにアプリを入れます。
対象のworkspaceで /zut
と入力すると対応する市区の名前が出てきます。
あとは /zut 渋谷
のように打てば利用できます。
めでたしめでたし。ということで今回は以上です。
皆さんも使ってみてくださいね
Discussion