この暑さを何とかしてくれるBotを作る！！！

この記事は[リンク情報システム](https://www.lis.co.jp/)（Facebookは[こちら](https://www.facebook.com/lis.co.jp/)）が主催する真夏のアドベントカレンダー「[2019 Tech Connect Summer](https://qiita.com/dgkz/items/2862d5e6b77203a126b3)」のリレー記事です。engineer.hanzomon のグループメンバによってリレーされます。

ついに「2019 Tech Connect Summer」も最終日！！
:bear:クマさんチームの最終日は、@r-kanai が担当致します:bear:



## 最近暑いですね～
な～んてのんきなことを言ってられないくらい、
毎日が暑すぎる:sun_with_face::dizzy_face::sun_with_face:

通勤とお昼休みしか外に出ないけど、
滝のように汗をかく日々:sweat_drops::sweat_drops::sweat_drops:

**『お願いだから、この暑さなんとかして！！』**

と(心の中で)何度も叫んでいるけれど、誰も助けてくれないので、
自分で**暑さを何とかしてくれるBot**でも作ってみようかしら。（唐突）

## 暑さを何とかしてくれる「涼しくなるBot」
できることは2つ。

**1. 今居るところの気温と体感温度がわかる。**
  
　今どんだけ暑いかを知りたいので、
　気象情報を取得できるAPIを利用して、現在地の気温と体感温度を表示する。


**2. 涼しくなる方法を提案してくれる。**

　涼しくなる方法なんて山ほどあるので、今回は「体感温度」を下げるものに絞る。
　今回は提案する方法は、
　『涼しい画像を見る』
　『涼しい音を聞く』
　の２つにします。
　（画像を見たり、聞いたりするだけでも人間って体感温度が下がるらしい。）

## どうやって作る？
- Bot　→　 LINEMessagingAPI(LINEBot) （[公式](https://developers.line.biz/ja/docs/messaging-api/)）
- サーバー　→　googleAppsScript （[公式](https://developers.google.com/apps-script/)）
- 気象情報の取得　→　DarkSky （[公式](https://darksky.net/dev)）


**★処理の概要は以下の通り**

1. ユーザーが位置情報を送信

1. 位置情報をセットしてDarkSkyAPIを実行

1. DarkSkyAPIの戻り値から体感温度(currently.apparentTemperature)と気温(currently.temperature)を取得し、botに表示

1. LINEのFlexMessageを利用し、涼しくなる方法をボタンで表示

1. 選択されたボタンによってそれぞれのコンテンツを表示
   - 『涼しい画像を見る』を選択　→　GoogleDriveに保存してある画像を表示する。
   - 『涼しい音を聞く』を選択　→　予め探しておいたYoutubeの動画URLを表示する。
 
## 準備

- LINEDevelopers と GoogleAppsScript（GAS）の登録
（参考にした記事は[こちら](https://qiita.com/hakshu/items/55c2584cf82718f47464)）


- Dark Sky の登録
（参考にした記事は[こちら](https://qiita.com/masuraoProg/items/41d57671bc1ba89489bb)）

## 実装
```javascript:cool.gs

/** LINE関連情報 */
var LINE_ACCESS_TOKEN = '**LINEBotのアクセストークン**';
var LINE_REPLY_URL = 'https://api.line.me/v2/bot/message/reply';

/** DarkSky関連情報 */
var DARK_SKY_URL = 'https://api.darksky.net/forecast/**DarkSkyのsercretKey**/';

/**
 * ユーザーがBotに対してアクションした時の処理
 * @param {object} e 
 */
function doPost(e) {
  var events = JSON.parse(e.postData.contents).events;
  events.forEach(function(event) {
    if(event.type === 'message') {
      // メッセージの返信
      replyMessage(event);
    } else if (event.type === 'postback') {
      var data = JSON.parse(event.postback.data);
      if (data.action === 'next') {
        if (data.res === 'img') {
          // 涼しい画像の返信
          replyCoolImg(event);
        } else if (data.res === 'sound') {
          // 涼しい音の返信
          replyCoolSound(event);
        }
      }
    }
  });
};

/**
 * メッセージの返信
 * @param {object} e 
 */
var replyMessage = function (e) {
  var replyToken = e.replyToken;
  var lat = e.message.latitude;
  var lon = e.message.longitude;

  // DarkSkyAPIの実行
  var weatherURL = DARK_SKY_URL + lat + ',' + lon + '?lang=ja';
  var json = UrlFetchApp.fetch(weatherURL).getContentText();
  var jsonData = JSON.parse(json);

  // 気温情報の取得・変換
  var AppTemp = changeTemp(jsonData.currently.apparentTemperature);
  var AirTemp = changeTemp(jsonData.currently.temperature);
  
  // 体感気温と気温表示の設定
  var tempMsg = {
    type: 'text',
    text: '体感温度は' + AppTemp + "℃だよ。\n気温は" + AirTemp + "℃だよ。"
  }

  // 「涼しくなる方法」の提案表示の設定
  var coolMsg = {
    type: "flex",
    altText: "This is cool msg.",
    contents: {
      "type": "bubble",
      "styles": {
        "body": {
          "backgroundColor": "#000080"
        }
      },
      "header": {
        "type": "box",
        "layout": "vertical",
        "contents": [
          {
            "type": "text",
            "text": "どうやって涼しくなる？"
          }
        ]
      },
      "body": {
        "type": "box",
        "layout": "vertical",
        "spacing": "md",
        "contents": [
          {
            "type": "button",
            "style": "primary",
            "color": "#66ccff",
            "action": {
              "type": "postback",
              "label": "涼しい画像を見る",
              "data": "{\"action\":\"next\", \"res\":\"img\"}"
            }
          },
          {
            "type": "button",
            "style": "primary",
            "color": "#66ccff",
            "action": {
              "type": "postback",
              "label": "涼しい音を聞く",
              "data": "{\"action\":\"next\", \"res\":\"sound\"}"
            }
          }
        ]
      }
    }
  };
  
  // ユーザに返信
  UrlFetchApp.fetch(url, {
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
      Authorization: 'Bearer ' + ACCESS_TOKEN
    },
    method: 'post',
    payload: JSON.stringify({
      replyToken: replyToken,
      messages: [
        {tempMsg},
        {coolMsg}
      ]
    })
  });  
};

/**
 * 華氏温度から摂氏温度変換
 * @param {number} fTemp 華氏温度
 * @return {number} 摂氏に変換した温度
 */
var changeTemp = function(fTemp) {
  var cTemp = (5/9) * (fTemp - 32);
  var fixedCTemp = cTemp.toFixed(1);
  return fixedCTemp;
}

/**
 * 涼しい画像の返信
 * @param {object} e 
 */
var replyCoolImg = function(e) {
  var replyToken = e.replyToken;
  var imageURL = 'https://drive.google.com/uc?id=**googleDrive内の画像ID**';
  var imagePreURL = 'https://drive.google.com/uc?id=**googleDrive内の画像ID**';
  
  UrlFetchApp.fetch(url, {
    headers: {
      'Content-Type': 'application/json; charset=UTF-8',
      Authorization: 'Bearer ' + ACCESS_TOKEN
    },
    method: 'post',
    payload: JSON.stringify({
      replyToken: replyToken,
      messages: [
        {
          type: 'image',
          originalContentUrl: imageURL,
          previewImageUrl: imagePreURL
        }
      ]
    })
  }); 
};

/**
 * 涼しい音の返信
 * @param {object} e 
 */
var replyCoolSound = function(e) {
  var replyToken = e.replyToken;
  var soundURL = 'https://youtu.be/ZJVSjhYwQpE';
  
  UrlFetchApp.fetch(url, {
      headers: {
          'Content-Type': 'application/json; charset=UTF-8',
          Authorization: 'Bearer ' + ACCESS_TOKEN
      },
      method: 'post',
      payload: JSON.stringify({
          replyToken: replyToken,
          messages: [
            {
              type: 'text',
              text: soundURL
            }
          ]
      })
    }); 
};

```

## 完成した「涼しくなるBot」

(![bot1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311809/45784d61-db1f-5846-6c1e-af7d8304f4d7.png)

位置情報を送るとすぐに体感温度と気温を教えてくれる。
（体感温度がほぼ40℃は暑すぎる:joy:）

そして、涼しくなる方法を提案。

『涼しい画像を見る』をクリックすると、
![bot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311809/41badef5-605a-fc29-85b8-bc5f7a440b02.png)
涼しげなかき氷の画像が表示:shaved_ice:

『涼しい音を聞く』をクリックすると、
![図4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311809/67f22dad-5376-a133-ab70-f4c9b200f2d7.png)
風鈴の音が聞けるYoutubeのURLを表示:wind_chime:

## このBotをもっと良くする為に

今回は体感的に涼しくなる方法のみ提案するBotを作ってみたけど、
結局のところ、物理的に涼しくならないとダメ！！

実用性を考えると選択肢としてこういうものも追加したい。
「涼しい場所に避難する」→　近くの涼しい場所（図書館・美術館）を表示してくれる。
「冷たい食べ物を食べる」→　近くのアイスクリーム・かき氷屋さんを表示してくれる。
...etc

アイディアが膨らむ:balloon:

## 作ってみて

GASを使って、LineBotを作るのはとても簡単！！
（オウム返しのBotを作るのに準備含めて30分もかからなかった。）

LINEBotだと作ったBotを他の人に手軽に見せることができるのがいいなぁと感じます。
（自分が作ったものは自慢したいタイプ:stuck_out_tongue:）

改善の余地がたくさんあるので、少しずつ改修していきます:fist_tone1:


## 最後に
[前回](https://qiita.com/r-kanai/items/ed5ed1361728431b9a59)に引き続き、アドベントカレンダー2回目の参加でした。

業務以外でプログラミングをしようしようと思っても、
なかなか~~しない~~できない私にとって、こういう機会はとてもありがたいです:grinning:

同じ会社の人でも中々技術について話すことは少ないので、
**「この人こういうことできるんだ！」**とか、
**「この人こういうことに興味だあるんだ！！」**とか、
アドカレを通じて知ることができるのはいいなぁと思いました:sunglasses:

**何より毎日更新される記事を読むのが楽しかったです！！**