虎の穴開発室ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

LINE BOT お天気通知くん

皆さんこんにちは、虎の穴ラボのO.Sです。

近頃は秋雨が多く、傘が必要な日が続いておりますね・・・
さて、皆さんはお出かけの際に傘を持っていくかどうか、どう判断しておりますか?

  • 天気予報を見る
  • 窓から差し込む朝日の強弱から判断する

などでしょうか・・・
天気予報を見る方は、朝バタバタしていると天気予報の確認を忘れてしまうことはありませんか?
そこで、天気予報と降水確率を取得し、傘を持っていくかどうかを通知してくれるLINE BOTを作成しました!!
ぜひ、いままで勘に頼っていた方もお天気通知BOTを作成して、雨の日に備えて下さい!

LINE BOTは以下の情報を通知します。

■ 出力情報

天気予報:対象地域
気温:最高気温/最低気温
傘予報:当日の6:00~12:00、12:00~18:00、18:00~24:00における降水確率により変動

降水確率対応表

降水確率 表示
30%未満 傘は持たなくても良いね!
30%が最高 折りたたみ傘があると安心!
40%以上 傘を持って行ったほうが良いね!

以下にLineBotの作成手順を記載しましたので、お役に立てると幸いです! 

■環境

  • Google Apps Script(GAS)
  • Line Developers

■下準備

まずはLineDeveloperに登録して各種設定を行う必要があります。
下の記事が良くまとまっておりますので、こちらを参考にオウム返しLINE BOTの作成をお願いします。
qiita.com

■お天気通知LINE BOT作成

お天気情報のメッセージ送信にはMessagingAPIを利用します。
https://developers.line.me/ja/reference/messaging-api/

■メッセージ送信先IDの取得

リクエストボディにメッセージの宛先を指定する必要があります。
これはオウム返しBOTで返される、JSONから取得出来ます。

自分のLINEアカウントを使ってオウム返しBOTに向かってメッセージを送信し
doPost実行時に受け取るJSONの中から自分のuserIdを取得します。

まずはUserIDをログ出力する為、doPostのreturn前に以下の1行を追加します。

  console.log("USER_ID:" + json.events[0].source.userId)

このままでは変更内容が反映されないので、オウム返しBOTを更新します。[公開] -> [ウェブアプリケーションとして導入]
f:id:toranoana-lab:20180927192645p:plain:w500

プロジェクト バージョンを[新規作成]にし【更新】します。
f:id:toranoana-lab:20180927192720p:plain:w300

最新URLが表示されるのでコピーし、LineDevelopersの[Webhook URL]を更新します。
f:id:toranoana-lab:20180927194703p:plain

Lineアプリから友達登録したBotに向かって適当にメッセージを送信します。
f:id:toranoana-lab:20180926181048p:plain:w300

GASのログビューアーを確認します。[表示]->[Stackdriver Logging]
f:id:toranoana-lab:20180926181735p:plain:w400

自分のuserIdが表示されると成功です!

■ライブラリ追加

お天気情報取得時のパースには公開ライブラリを利用しますので、以下を参考にparserライブラリを追加して下さい。
https://tadaken3.hatenablog.jp/entry/parser-for-gas

■お天気通知機能の実装

以下のコードを追記します。
グローバル変数のUSER_IDとCHANNEL_ACCESS_TOKEN は、 自環境のものに置き換えて下さい。

var CHANNEL_ACCESS_TOKEN = "xxxxxxxxxxxxxxx"; //オウム返しBotで利用したのものと同様
var USER_ID = "xxxxxxxxxxxxxxxxxxxxxxxx"; //ログビューアーから取得したID

// 通知機能
function push_message() {
  var today = new Date();
  var toWeekday = toWD(today);
  var msgWeatherForecast = getTemperatureForecast();
  
  var postData = {
    "to": USER_ID,
    "messages": [
      {
        "type": "text",
        "text": "今日は、" +Utilities.formatDate( today, 'Asia/Tokyo', 'yyyy年M月d日') + toWeekday + "だよ!\n"
                + msgWeatherForecast[0] + msgWeatherForecast[1] + msgWeatherForecast[2]
      }
    ]}
  
  var headers = {
    "Content-Type": "application/json",
    'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN,
  };
  
  var options = {
    "method": "post",
    "headers": headers,
    "payload": JSON.stringify(postData)
  };
  
  var response = UrlFetchApp.fetch("https://api.line.me/v2/bot/message/push", options);
  
}

// 天気予報の取得 
function getTemperatureForecast() {
  const area = "東京地方"
  var options =
      {
        "contentType" : "text/xml;charset=utf-8",
        "method" : "get",
      };
  var response = UrlFetchApp.fetch("https://www.drk7.jp/weather/xml/13.xml", options); 
  var xmlDoc = XmlService.parse(response.getContentText());
  var rootDoc = xmlDoc.getRootElement();
  var region = parser.getElementById(rootDoc,area);
  var weather = parser.getElementsByTagName(region, 'weather');
  var temperature = parser.getElementsByTagName(region, 'range');
  var rainyPercent = parser.getElementsByTagName(region, 'period');
  var weathermsg = "■天気予報:" + area + "\n" + weather[0].getValue() + "\n"
  var tempmsg ="■気温\n" + temperature[0].getValue() + "℃/" + temperature[1].getValue() + "℃\n";
  var umbrellamsg = "■傘予想\n" + getUmbrellNecessary(rainyPercent[1].getValue(),rainyPercent[2].getValue(),rainyPercent[3].getValue()) + "\n";
  var rainyTemperature = [weathermsg,tempmsg,umbrellamsg];
  return rainyTemperature
}

// 傘予想
function getUmbrellNecessary(mor,eve,nig){
  var msg = ""
  if (mor < 30 && eve < 30 && nig < 30 ) {
    msg = "傘は持たなくても良いね!";
  }
  if (mor == 30 || eve == 30 || nig == 30 ) {
    msg = "折りたたみ傘があると安心!";
  }
  if (mor > 30 || eve > 30 || nig > 30 ) {
    msg = "傘を持って行ったほうが良いね!";
  }
  return msg
}

// 曜日の日本語変換
function toWD(date){
  var myTbl = new Array("日","月","火","水","木","金","土","日"); 
  var myDay = Utilities.formatDate(date, "JST", "u");
  return "(" + myTbl[myDay] + ")";
}
■GAS実行

[ファイル]->[保存]で変更内容を保存し、
[実行]->[関数の実行]->push_message を実行して下さい。

f:id:toranoana-lab:20180927184019p:plain:w300
BOTから天気予報が届いたら成功です!

あとは以下ページ[GASのトリガー設定]を参考に設定を行っていただければ、任意の時間に天気予報を受け取れるようになります。
toranoana-lab.hatenablog.com

■あとがき

当初はLivedoor社のAPIを利用し天気情報を取得していたのですが、
2018年9月月初の数日間Livedoor天気予報の更新が停止した事がありました。

いつから天気予報が再開されるか情報が無かったので、
代わりのAPIがないか探したところ気象庁の天気予報をXML形式で
配信しているdrk様のページを見つけ現在の形に落ち着きました。

現在はLivedoorの天気予報の更新は再開されていますが、
突然更新が止まる事に備え気象庁とLivedoor天気予報の冗長構成を組めると理想的だと思います!

虎の穴ではJavascriptエンジニアをはじめとして一緒に働く仲間を絶賛募集中です!
この記事を読んで、興味を持っていただけた方はぜひ弊社の採用情報をご覧下さい。
www.toranoana.jp

また虎の穴は、技術書典5にスポンサー出展します!
新刊もありますので、ぜひブース番号「ス08」へお越しください。
techbookfest.org