LoginSignup
37
37

More than 5 years have passed since last update.

雨の日に傘を持つよう通知するLINEbotを作ってみた

Last updated at Posted at 2018-04-25

きっかけ

「あ〜、今日雨なら傘を持って来れば良かった。」と思う時、ありませんか?
私は稀によくあります。

天気予報は毎朝確認しなくとも、雨の日だけ分かれば。
ということで、雨の日には「傘を持てよ!」と通知してくれるbotを、毎朝必ずと言って良いほど確認するLINEで作ってみました。

概要

実装する機能

以下の2点を機能として実装します。

 ・傘が必要な日のみ、毎朝6:00〜7:00の間に天気予報をLINEにて通知する。
 ・予報内容は、当日9:00〜21:00までの3時間刻みの天気情報とする。

使用するサービス

今回使用するサービスは以下の3点です。

 ・LINE - Messaging API
   https://developers.line.me/ja/services/messaging-api/
 ・Google Apps Script(GAS)
   https://developers.google.com/apps-script/
 ・OpenWeatherMap - Weather API
   https://openweathermap.org

システムの全体像

スクリーンショット 2018-04-25 0.38.53.png

処理は、① → ② → ③ という流れで進みます。

①・・・毎朝6:00〜7:00の間にGASが実行され、Weather API(OpenWeatherMap)より天気予報を取得する。
②・・・Weather APIより天気予報が返ってくる。
③・・・LINE送信用にメッセージを編集し、Messaging API(LINE)に送信する。

各種サービスの事前準備

Weather APIの登録

下記のサイトでFreeプランで登録します。(「Get API key and Start」を押下)

https://openweathermap.org/price
スクリーンショット 2018-04-25 1.40.03.png

登録後、取得したAPIkeyをメモります。

GASの登録

GASはgoogleのアカウントがあれば利用可能です。
以下、利用方法の参考記事です。スクリプトファイルの新規作成まで実施してください。

LINE developersの登録

Messaging APIを利用するにあたり、LINE developersへの登録が必要になります。
以下の記事を参考に、Channelの設定まで実施してください。(プランは「Developer Trial」)

実装

コード全体

実装に移ります。以下、GASのコードの全てです。(GAS以外のコーディングは不要です。)
詳細は後ほど小分けで説明します。

//諸々の設定
var channel_access_token = 'LINEdevelopersのChannelより取得'
var user_id = 'LINEからuserIdを取得'
var line_url = 'https://api.line.me/v2/bot/message/push'
var openweathermap_url = 'http://api.openweathermap.org/data/2.5/forecast?id=1850147' //idで東京を指定
var openweathermap_appid = 'Weather APIで取得したAPIkey'
var text
var text_jp = []
var rain_info
var final_text

//毎日AM6:00〜7:00に以下のメソッドを起動
function weatherforecast() {
  //openweathermapから東京の天気予報を取得
  var weatherforecast_finalurl = openweathermap_url + '&APPID=' + openweathermap_appid
  var response = UrlFetchApp.fetch(weatherforecast_finalurl)
  var json = [JSON.parse(response.getContentText())]
  Logger.log(json[0]) //意図した場所の天気が取得できているか確認

  //天気情報を日本語に変換
  for (var i = 0; i <= 4; i++) {
    text = JSON.stringify((json[0].list[3 + i].weather[0].icon))
    Logger.log(json[0].list[3 + i]) //意図した時間の天気が取得できているか確認
    start_weatherforecast(text)
    text_jp[i] = text
  }
  //天気情報をline送信用に編集する
  text_edit()
  //lineへ送信する
  weatherforecast_to_line(channel_access_token,user_id,final_text);
}

//天気情報を日本語に変換
function start_weatherforecast(weather) {
  if (weather == '"01n"' || weather == '"01d"'){
    text = '快晴'
  }
  if (weather == '"02n"' || weather == '"02d"'){
    text = '晴れ'
  }
  if (weather == '"03n"' || weather == '"03d"'){
    text = '曇り'
  }
  if (weather == '"04n"' || weather == '"04d"'){
    text = '曇り'
  }
  if (weather == '"09n"' || weather == '"09d"'){
    text = '小雨'
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"10n"' || weather == '"10d"'){
    text = ''
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"11n"' || weather == '"11d"'){
    text = '雷雨'
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"13n"' || weather == '"13d"'){
    text = ''
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"50n"' || weather == '"50d"'){
    text = ''
  }
}

//line送信用にテキストを編集
function text_edit() {
  final_text = '天気予報です。\n' + rain_info + '\n09:00  ' + text_jp[0] + '\n12:00  ' + text_jp[1] + '\n15:00  ' + text_jp[2] + '\n18:00  '
              + text_jp[3]+ '\n21:00  ' + text_jp[4] + '\n\n今日も一日頑張りましょう!'
}

//LINEへ送信
function weatherforecast_to_line(channel_access_token,user_id,text){
  if (rain_info == '今日は傘を持ちましょう。\n') {
    //LINEに取得結果を送る
    UrlFetchApp.fetch(line_url,{
      'headers': {
          'Content-Type': 'application/json; charset=UTF-8',
          'Authorization': 'Bearer ' + channel_access_token,
      },
      'method': 'post',
      'payload': JSON.stringify({
        'to': user_id,
        'messages' : [
          {
            'type':'text',
            'text':final_text,
          }
        ]
      })
    });
  }
}

コード詳細の説明

諸々の設定

まずは諸々の設定から説明します。


//諸々の設定
var channel_access_token = 'LINEdevelopersのChannelより取得'
var user_id = 'LINEからuserIdを取得'
var line_url = 'https://api.line.me/v2/bot/message/push'
var openweathermap_url = 'http://api.openweathermap.org/data/2.5/forecast?id=1850147' //idで東京を指定
var openweathermap_appid = 'Weather APIで取得したAPIkey'
var text
var text_jp = []
var rain_info
var final_text

❶ 「channel_accsess_token」の宣言
LINE developersのChannel画面で取得します。

❷ 「user_id」の宣言
LINEからpostされたときに一緒に送信される情報で、pushメッセージを送信するときに必要になります。user_idはLINEからのメッセージに含まれているため、LINEからのメッセージに対してuser_idを返すプログラムを作成して取得しました。(もっと効率の良い取得方法があるかと思います。。)
LINEからのメッセージをおうむ返しするという以下の記事を参考に、user_idを返すプログラムを作成できます。
https://qiita.com/nogizakaJinro/items/e2a178c1cb7a0699a80f

❸ 「openweathermap_url」の宣言
3時間ごとの天気予報が取得できるurlの一部です。"id=〜"の部分を変更することで、特定の都市の天気予報を取得できます。天気予報を都市名で取得するなど、取得方法は色々ありますので、詳しくは公式サイトをご参照ください。

❹ 「openweathermap_appid」の宣言
weather API登録時にメモしたAPIkeyを設定します。openweathermap_urlに結合することで、実際に天気予報を取得することができるurlが完成します。

❺ その他変数の宣言
後ほど使用しますので、ここでは説明を割愛します。

メインメソッド

次に、毎朝起動するメインメソッドを説明します。


//毎日AM6:00〜7:00に以下のメソッドを起動
function weatherforecast() {
  //openweathermapから東京の天気予報を取得
  var weatherforecast_finalurl = openweathermap_url + '&APPID=' + openweathermap_appid
  var response = UrlFetchApp.fetch(weatherforecast_finalurl)
  var json = [JSON.parse(response.getContentText())]
  Logger.log(json[0]) //意図した場所の天気が取得できているか確認

  //天気情報を日本語に変換
  for (var i = 0; i <= 4; i++) {
    text = JSON.stringify((json[0].list[3 + i].weather[0].icon))
    Logger.log(json[0].list[3 + i]) //意図した時間の天気が取得できているか確認
    start_weatherforecast(text)
    text_jp[i] = text
  }
  //天気情報をline送信用に編集する
  text_edit()
  //lineへ送信する
  weatherforecast_to_line(channel_access_token,user_id,final_text);
}

❶ 天気予報取得用のurl作成
諸々の設定で宣言した「openweathermap_url」と「openweathermap_appid」を組み合わせて、天気予報取得用のurl「weatherforecast_finalurl」を作成します。

❷ 天気予報の取得
「UrlFetchApp.fetch」を使用し、「weatherforecast_finalurl」より取得した天気予報をjson形式に変換し、「json」に格納します。

❸取得した天気予報から必要な情報を抜き取る
欲しい情報は「6:00〜7:00の間で天気予報を取得した時の、9:00・12:00・15:00・18:00・21:00時点の天気5つ」です。以下のページで各天気のコードを確認します。
https://openweathermap.org/weather-conditions

ログを残す「Logger.log(data)」を使用して「json」の中身を確認し、天気のコードを探します。どうやら天気のコードは「json[0].list[3〜7].weather[0].icon」に格納されているようなので、for文で各時間帯の天気ごとに処理を実行します。
for文の中では取得した天気の情報を日本語に変換し、配列である「text_jp」に格納します。(日本語への変換は「start_weatherforecast(text)」で実施。中身は後ほど説明します。)

❹天気情報をLINE送信用に編集
「text_edit()」を呼び出し、LINE送信用のメッセージを作成します。(中身は後ほど説明します。)

❺LINEにメッセージを送信
「weatherforecast_to_line(channel_access_token,user_id,final_text)」を呼び出し、LINEにメッセージを送信します。(中身は後ほど説明します。)

❻メインメソッドの自動起動を設定
以下の記事を参考に、毎日AM6:00〜7:00の間に自動で起動するよう設定します。
https://tonari-it.com/gas-trigger-set/

天気コードの日本語変換

次に、メインメソッドの❸で呼び出したメソッド(start_weatherforecast(text))を説明します。

//天気情報を日本語に変換
function start_weatherforecast(weather) {
  if (weather == '"01n"' || weather == '"01d"'){
    text = '快晴'
  }
  if (weather == '"02n"' || weather == '"02d"'){
    text = '晴れ'
  }
  if (weather == '"03n"' || weather == '"03d"'){
    text = '曇り'
  }
  if (weather == '"04n"' || weather == '"04d"'){
    text = '曇り'
  }
  if (weather == '"09n"' || weather == '"09d"'){
    text = '小雨'
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"10n"' || weather == '"10d"'){
    text = ''
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"11n"' || weather == '"11d"'){
    text = '雷雨'
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"13n"' || weather == '"13d"'){
    text = ''
    rain_info = '今日は傘を持ちましょう。\n'
  }
  if (weather == '"50n"' || weather == '"50d"'){
    text = ''
  }
}

「text」に格納された天気コード("01n"など)を判断し、日本語に変換します。また、雨・雪が振る場合は"傘を持ちましょう。"という文言を「rain_info」に格納します。(理由は後ほど説明します。)

天気情報をLINE送信用に編集

次に、メインメソッドの❹で呼び出したメソッド(text_edit())の説明です。

//line送信用にテキストを編集
function text_edit() {
  final_text = '天気予報です。\n' + rain_info + '\n09:00  ' + text_jp[0] + '\n12:00  ' + text_jp[1] + '\n15:00  ' + text_jp[2] + '\n18:00  '
              + text_jp[3]+ '\n21:00  ' + text_jp[4] + '\n\n今日も一日頑張りましょう!'
}

日本語に変換した天気情報(text_jp)を使用してLINE送信用のメッセージを編集し、「final_text」に格納します。なお、”\n”は改行を意味します。

LINEにメッセージを送信

最後に、メインメソッドの❺で呼び出したメソッド(weatherforecast_to_line(channel_access_token,user_id,final_text))の説明です。

//LINEへ送信
function weatherforecast_to_line(channel_access_token,user_id,text){
  if (rain_info == '今日は傘を持ちましょう。\n') {
    //LINEに取得結果を送る
    UrlFetchApp.fetch(line_url,{
      'headers': {
          'Content-Type': 'application/json; charset=UTF-8',
          'Authorization': 'Bearer ' + channel_access_token,
      },
      'method': 'post',
      'payload': JSON.stringify({
        'to': user_id,
        'messages' : [
          {
            'type':'text',
            'text':final_text,
          }
        ]
      })
    });
  }
}

以下のMessaging APIのAPIリファレンスより、プッシュメッセージの送信に必要な情報を確認し、実装しています。
https://developers.line.me/ja/docs/messaging-api/reference/
 →「プッシュメッセージを送る」を参照

「if (rain_info == '今日は傘を持ちましょう。\n')」で傘が必要な場合だけLINEに送信するようにしていますが、このif文を外せば毎朝天気予報をLINEに送信するようになります。(雨が振る場合だけ「rain_info」に格納していたのはこのためです。)

テスト

さて、実装が完了したので、意図した通りに動くかテストします。
8:00にラインを確認すると、以下の通知がありました。

スクリーンショット 2018-04-25 22.46.08.png

なんとか無事に天気予報をpush送信することができたようです。
これにて傘通知bot、完成となります。

作り終えてみての感想

小さなシステムではありますが、プログラミング初心者、かつ、使用した3つのサービス全てが初めてであったため、作り終えるのに苦戦しました。(なんだかんだで着手から1週間ほどかかりました。)

そんな苦戦の中で以下の2点を痛感しています。

・何かしら実現したいものを考え、実現に向けて思考することで体系的な知識が身につく。
・プログラミングはワクワクの塊。

ということで、引き続き高いモチベーションをキープして学習したいと思います。
お読みいただき、ありがとうございました。

※記事にミスや改善点等ありましたら、ご指摘いただけると幸いです。

37
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
37