Slackの雨通知botを爆速で作る【メッ●●】

ZOZOテクノロジーズのむーさん[@murs313](https://twitter.com/murs313)です。

ZOZOテクノロジーズでは8月にフルリモート・フルフレックスが始まり、各チームで相談しながら利用しています。
うちのチームも気軽に利用できる雰囲気なのですが、しばしばこんなことが…。

～平日の夜の自宅にて～
むー「あーーー、明日雨じゃん」
むー「明日リモートにしよ……」
むー「……**PC持って帰ってきてないじゃん！！！**無理じゃん！！！」

というわけで、翌日が雨予報だったらSlack通知をしてくれるbotをつくりました。**もちろんメッ●●でね。**

# できたもの
翌日が雨予報だったら、17時に通知してPCを持って帰ることを促してくれます。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/7f755740-3e51-1aa7-012e-50c73232c15d.png">

# 使うもの
**天気予報の公開API**
こちらからlivedoorを選びました。
[[2019] 公開されているAPI一覧まとめ](https://matome.naver.jp/odai/2144230147636045901?page=2)

**SlackのIncoming WebHook**
SlackのApp。チャンネルに設定すると`Webhook URL`が発行されて、このURLにPOSTすると該当チャンネルに投稿できます。
https://slack.com/intl/ja-jp/help/articles/115005265063

**Google Apps Script**
通称GAS。JavaScriptが動きます。「トリガー」という機能で定期実行できます。（知らなかった！）

# 手順
### 1. Incoming WebHooksの設定
Slack左上のメニューから「Slackをカスタマイズ」を選択
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/352d0740-0684-13bb-c0f3-01758a6de54e.png">
ブラウザが開いたら、サイドメニューから「App管理」を選択
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/a9bb0f57-14f9-2238-9ae6-4c8ec918c2e4.png">
「Appディレクトリを検索…」の検索窓で検索して「Incoming WebHook」を選択
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/3d52d666-93c3-122a-98b5-a797c6c396e1.png">
「Slackに追加」をクリック
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/85c022d7-571e-9587-d059-3da7e5d396d3.png">
投稿したいチャンネルを選択して、「Incoming WebHookインテグレーションの追加」をクリック
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/1fd0da0e-1148-b19f-9fa4-0e58ca9d54fb.png">
これで`Webhook URL`が発行されました。あとで使います。このURLにPOSTすると該当チャンネルに投稿できてしまうので、むやみに公開しないように注意してください。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/c2222dba-46f5-4cd7-1a5f-5e707b35b5e0.png">
「セットアップの手順」にリンクの付け方やペイロードの説明が書かれているので読んでおくと良いでしょう。
「インテグレーションの設定」でアイコンの名前や画像を設定できるので、**メッ●●にしておきましょう。**こんなふうにね。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/ce16c743-1f8e-1792-1ef1-274776cb8804.png">

### 2. GASの設定
#### 2-1. スクリプトを書く
[Googleドライブ](https://drive.google.com)の「新規」から、「Google Apps Script」を選択
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/463b0d12-fa4d-640e-574a-78f7b743d64f.png">

下記のコードから、2箇所書き換える必要があります。

- `webhookUrl`  
手順1で取得したもの。
- `cityId`  
livedoorのcityId。下記参照。  
http://weather.livedoor.com/weather_hacks/webservice

```js
function main() {
  const today = new Date();
  var tomorrow = new Date();
  tomorrow.setDate(today.getDate() + 1);

  if (isHoliday(today)) return; // 今日が休日なら処理しない
  if (isHoliday(tomorrow)) return; // 明日が休日なら処理しない
  
  const cityId = 120010; // http://weather.livedoor.com/forecast/rss/primary_area.xml

  const forecast = getForecast(cityId);
  if (forecast.indexOf('雨') !== -1) { // 雨のときだけSlack通知する
    sendToSlack(forecast);
  }
}

function getForecast(cityId) {
  const response = UrlFetchApp.fetch('http://weather.livedoor.com/forecast/webservice/json/v1?city=' + cityId);
  const obj = JSON.parse(response.getContentText()); 
  
  const forecast = '明日の' + obj['location']['city'] + 'は' + obj['forecasts'][1]['telop'] + 'です。';
  return forecast;
}

function sendToSlack(message) {
  const webhookUrl = '取得したWebhook URL';
  const jsonData = {
    'text' : message
  };
  const payload = JSON.stringify(jsonData);
  const options = {
    'method' : 'post',
    'contentType' : 'application/json',
    'payload' : payload
  };
  UrlFetchApp.fetch(webhookUrl, options);
}

function isHoliday(date) {
  // 土日ならtrue
  const weekInt = date.getDay();
  if(weekInt == 0 || weekInt == 6) return true;

  // 国民の祝日に該当していたらtrue
  const holidays = CalendarApp.getCalendarsByName('日本の祝日');
  const todayholidays = holidays[0].getEventsForDay(date).length;
  if(todayholidays.length > 0) return true;

  return false;
}
```
#### 2-2. 動作確認
一度正しく動作するか確認します。ヘッダーの「▶︎」で実行できます。
このままのコードでは、翌日が祝日だったり雨じゃなかったりするとメッセージが届かないので、都合が悪ければコメントアウトしましょう。メッ●●からメッセージが来ればOKです。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/39a2e835-4e88-475a-f7d0-6e22f71e6f37.png">

#### 2-3. トリガーの設定
ヘッダーの時計マークをクリックすると、トリガー設定画面に遷移するので、「トリガーを追加」をクリック。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/441242f7-5220-1023-cc3d-7de17d19c884.png">
実行する関数を`main`にして、好みの設定にすれば完成です！
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309128/efddee74-3f83-6dc2-d598-7d2427e0516a.png">


#### 2-4. (オマケ)複数チャンネルに召喚したいとき
「うちにもメッ●●置いてよ！」と言われて、「何度も`Webhook URL`を発行しなきゃいけないのか…」と絶望しますが、そんな必要はありません。
ペイロードにチャンネル名を記述して、メッセージの宛先を変更することができます。
パブリックチャンネルは`‘channel’: ‘#channel-name’`、ダイレクトメッセージは`‘channel’: ‘@username’`で指定できます。

sendToSlackで送りたいチャンネルも引数として受け取ってペイロードで指定すればOKです。
こんな感じでmainとsendToSlackを書き換えましょう。

```js
function main() {
  const today = new Date();
  var tomorrow = new Date();
  tomorrow.setDate(today.getDate() + 1);

  if (isHoliday(today)) return; // 今日が休日なら処理しない
  if (isHoliday(tomorrow)) return; // 明日が休日なら処理しない

  const firstChannelName = '#first-channel'
  const secondChannelName = '#second-channel'
  const thirdChannelName = '@hanako.yamada'
  const cityId = 120010; // http://weather.livedoor.com/forecast/rss/primary_area.xml

  const forecast = getForecast(cityId);
  if (forecast.indexOf('雨') !== -1) { // 雨のときだけSlack通知する
    sendToSlack(firstChannelName, forecast);
    sendToSlack(secondChannelName, forecast);
    sendToSlack(thirdChannelName, forecast);
  }
}

function sendToSlack(channelName, message) {
  const webhookUrl = '取得したWebhook URL';
  const jsonData = {
    'channel': channelName,
    'text' : message
  };
  const payload = JSON.stringify(jsonData);
  const options = {
    'method' : 'post',
    'contentType' : 'application/json',
    'payload' : payload
  };
  UrlFetchApp.fetch(webhookUrl, options);
}
```

# 感想
雑実装ですが、一瞬でできました！GAS便利！
これでもうPC忘れない…！

リモートでWEARの開発をしたい方はJOIN US!!!
https://tech.zozo.com/recruit/mid-career/detail59/

# スペシャルサンクス
- GASでコードの定期実行できるよって教えてくれた田島（https://twitter.com/kaz_tch）  
「slackbotだ！！！」と言いながらbotkitを使い、定期実行で困っていた私には天啓でした。ありがとう！！
- メッ●●の鳴き声が分からず聞いたら、めちゃめちゃ調べて音声ファイルまで送ってくれたポ●モン女子まゆちゃん

# 参考リンク
- [【初心者向け】GASを使ってSlackへ自動通知](https://qiita.com/chihiro/items/c7b11abc78f5d806c3a8)  
- [Google Apps Scriptで外部のREST APIを呼び出す](https://journal.lampetty.net/entry/call-external-api-in-gas)
- [GASで日本の休日・祝日を判定する方法（Google Apps Script)](https://qiita.com/Panda_Program/items/31f331fd4c2f3cfab333)