Google Apps ScriptでDark Skyから取得したお天気情報をkintoneに登録するまで

## 概要
Google Apps Scriptを利用してお天気情報を自動で取得、kintoneに投げるスクリプトを書いたので備忘録をまとめます。
GAS初心者では有りましたが、先人の知恵やライブラリを借りつつ無事に動かせるところまで出来ました。
今回はkintoneへの登録が目的でしたが、SlackBotのような各種Botを作る際にも使えそうです。

### やったこと:
Google Apps Scriptでお天気情報サイトDark SkyのAPIを呼び出し、お天気情報をとってくる。
取ってきた情報をkintoneのAPI使って新規レコードとしてお天気情報アプリに登録。
Google Apps Scriptのトリガー機能で上記の完全自動化。

[こちらの記事のライブラリ](https://qiita.com/Arahabica/items/063877b0da439020d2c2#create)を使わせてもらいました。
このライブラリを使って実際にPOSTしてみた記事が[Cyboze Developers Network](https://developer.cybozu.io/hc/ja/articles/115003856483-Google-%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E3%81%A8kintone%E3%82%92%E9%80%A3%E6%90%BA%E3%81%97%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86-)上にもあったため目的を果たせそうだと思ったためです。


### 目的：
全自動でDark Skyから指定した地域のお天気情報を取得、その後kintoneへ情報を登録すること。

### 使うもの
* Google Apps Script
    * Dark Sky APIから情報を取得、変換してからkintoneへ投げる。…というコードを定期的に自動実行する。
    * 動かすためには[上記記事のライブラリ]((https://qiita.com/Arahabica/items/063877b0da439020d2c2#create))が必要
* kintone(スタンダードプラン)
    * 最終的な受け皿。アプリとフォームは事前に作っておき、いい感じのフィールドコードを振るのと、書き込み権限のあるトークンを発行しておくことが必要。
* Dark Sky 
    * 情報元。1000回/Day無料で呼び出し可能なAPIをGAS経由で呼ぶ。かなり詳細な情報も呼べるが、ここではほんの一部しか使わない。

### やっていること：
* 緯度経度を指定した地点における呼び出し時点でのお天気情報(取れるものはドキュメント参照)をDark Skyより取得
* 取得した値の天気を日本語に変換する(Clear-dayなら晴れなど)
* json化してkintoneへレコードとして登録する

### ソースコード：
```
function Darksky2kintone() {
  'use strict';
  var subdomain = "subdomain.cybozu.com";//kintoneサブドメイン名
  var apps = {
    YOUR_APPLICATION1: { appid: xx, name: "xxxxx", token: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
  }; //お天気情報を登録したいkintoneアプリのid, 名前及びトークンの記載
  var manager = new KintoneManager.KintoneManager(subdomain, apps);// ライブラリーの初期化
  var forecast = {};
  forecast["hoge"] = UrlFetchApp.fetch("https://api.darksky.net/forecast/[key]/[latitude],[longitude]?units=si");
  forecast["huga"] = UrlFetchApp.fetch("https://api.darksky.net/forecast/[key]/[latitude],[longitude]?units=si");
  var json = {};
  var forecast_summary ={}; //天気は「晴れ」か「雨」か「曇」かを入れる
  Object.keys(forecast).forEach(function(key){ //連想配列forecast[]のkeyの数だけループ
    json[key]=JSON.parse(forecast[key].getContentText()); //受け取ったJSONデータを解析して配列jsonに格納
    switch(json[key]["currently"]["icon"]){
      case "clear-day":
        forecast_summary[key] = "晴れ";
        break;
      case "clear-night":
        forecast_summary[key] = "晴れ";
        break;
      case "rain": 
        forecast_summary[key] = "雨";
        break;
      case "snow":
        forecast_summary[key] = "雪";
        break; 
      case "sleet":
        forecast_summary[key] = "雪";
        break;
      case "wind": //天気が強風の場合はCloud Cover(雲量)の数値で晴れか曇かを判定する。雲量0.8以下は晴れ。
        if(json[key]["currently"]["cloudCover"] <= 0.8 )forecast_summary[key] = "晴れ";
        else if(json[key]["currently"]["cloudCover"] > 0.8 )forecast_summary[key] = "曇り";
        break;
      case "fog":
        forecast_summary[key] = "霧";
        break;
      case "cloudy":
        forecast_summary[key] = "曇り";
        break;
      case "partly-cloudy-day":
        forecast_summary[key] = "曇り";
        break;  
      case "partly-cloudy-night":
        forecast_summary[key] = "曇り";
        break;
      case "hail":
        forecast_summary[key] = "雹";
        break;
      case "thunderstorm":
        forecast_summary[key] = "雷雨";
        break;
      case "tornado":
        forecast_summary[key] = "竜巻";
        break;
    }
  });
  
  //Dark SkyのtimeはUnix時間/1000な値なので人にわかりやすい値に変換
  var posix = 0;
  posix  = new Date(json["hoge"]["currently"]["time"] *1000);
  var day = posix.getFullYear()+("-")+(posix.getMonth()+1)+("-")+posix.getDate();
  var time = posix.getHours()+(":") + posix.getMinutes();
  
  //kintoneへ登録する情報をつくる。"漢字"のところがフィールドコード。
  //指定されたフィールドコードの"value"として各変数の値が登録される。
  var body = {};  
  Object.keys(forecast).forEach(function(key){
    body[key] = [{ 
      "日付": { 
        "value": day
      },
      "時刻":{
        "value": time
      },
      "天気":{
        "value": forecast_summary[key]
      },
      "概要":{
        "value": json[key]["currently"]["summary"]
      },
      "最高気温":{
        "value": json[key]["daily"]["data"][0]["temperatureHigh"]
      },
      "最低気温":{
        "value": json[key]["daily"]["data"][0]["temperatureLow"]
      },
      "湿度":{
        "value": json[key]["daily"]["data"][0]["humidity"] * 100
      },
      "降水確率":{
        "value": json[key]["currently"]["precipProbability"] * 100
      },
      "降水量":{
        "value": json[key]["currently"]["precipIntensity"]
      },
      "風速":{
        "value": json[key]["currently"]["windSpeed"]
      },
    }];
    var response = manager.create("YOUR_APPLICATION1", body[key]); //kintoneにデータを登録
    var code = response.getResponseCode();
    Logger.log('Response code is "%s\n"', code); //200が成功
  });
}
```

### 実行
Response Codeが200となり、kintone上のアプリにお天気情報が新規登録されれば成功です。
後はGASのトリガーの設定で自動起動させると幸福度が上がります。

#### メモ:DarkSkyのURLの構造

`https://api.darksky.net/forecast/[key]/[latitude],[longitude]?units=si`

* keyにはDark Sky APIのSecret Key、Latitude, Longitudeには緯度経度がそれぞれ入ります
* URLの末尾に ?units=si を追記すると摂氏温度で表示されます

##### ハマったところ

* Unix時間周り
    * GetMonth()で変換したらちょうど1ヶ月ずれる
        * Javascriptの仕様とは知らず。
        * GetMonth()+1で解決。
    
* kintoneへのPOST周り
    * Responseが400で帰ってくる
        * Jsonの構造がおかしい
        * 公式ドキュメントを見ながら修正
    * Responseで200が帰ってくるけれど登録されてない
        * フィールドコードの設定がされてなかった

特にkintoneへのPOSTは[ドキュメント](https://developer.cybozu.io/hc/ja/articles/202166160-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E7%99%BB%E9%8C%B2-POST-)見ながら何度もトライしました。


無料のサービスを組み合わせて全自動で動くシステム組めるのはとても良いですね。
作れるものは多そうですが、技術とネタを思いつく脳みそが足りないので精進します。