見出し画像

GASとChatGPTで実現するスマートなLINEBOT開発③〜Open Weather Map APIを用いて天気予報の情報を取得しよう〜

今回はOpen Weather MapのAPIを用いて、天気予報の情報の提供をしてくれる機能をLINEBOTに追加してみようと思います。

前回までに、基本的な会話とゴミ出しを通知してくれるLINEBOTの開発を記事にしてみました。

第一弾はこちら↓

LINEBOTに天気予報の機能を導入しようと思ったきっかけは、最近国内外各地を旅行しているため、天気予報の情報を素早く取得したかったからでした。

ニュースを見ればいいのでは?と思われるかもしれませんが、僕の家にはテレビがなく、ネットで見ようにも毎回開くのもめんどくさい…。

1、2回なら良いかもしれませんが、ニュースを見るために毎回開いてたら、ちりつもで時間の無駄です。

一方で、LINEBOTが毎日通知してくれれば、LINEを開くついでに面倒かけずにすぐに分かるのでは…?と思いつきました。実装できればこんなに便利なことはありません。

そして、実装してみた結果がこちら

天気予報の情報は毎朝自動で通知してくれるし、現在の天気も知りたい時に教えてくれます。良いですね…!

今回はOpen Weather MapのAPIを用いて、天気予報の情報の提供をしてくれる機能をLINEBOTについてまとめました。

LINE BOTで実現したいこと(再掲)
・普通に会話ができる(済)
・家計簿を管理、スプレッドシートにまとめてくれる
・日々のゴミ出しを定期的に知らせてくれる(済)
・天気予報を定期的に知らせてくれる←(今回)
・買い物リストをメモしてくれる
・タスクの管理
・スケジュールの管理
・画像解析
・その他(思いついたら羅列していく)

これまでの僕の実績(再掲)


・Pythonによるデータ分析、及び自動化の実現
・友人と数多のアプリを共同開発
・GASを使った画期的なLINE BOT開発←今ここ


Open Weather Map APIについて

APIについては第一回で説明しました。今回もChatGPT同様、外部で使用するためにAPIを使います。

今回はOpen Weather MapのAPIを選択。

天気予報のAPIについては予想より数多くの会社が提供しており、どれにしようかと悩みましたが、無料かつシンプルなOpen Weather MapのAPIに注目しました。

APIを発行し、後述するコードにコピペしました。

コード詳細

だんだんコードが長くなってきましたが、前回から追加したコードを記載しておきます。

まずは下記コードにスプレッドシートIDとOpen Weather MapのAPIキーを入れます。

const spreadsheetId = "XXXXXXXXXXXXX"; // スプレッドシートのID、追加
var OPENWEATHERMAP_APIKEY = 'XXXXXXXXXXXXXXXXXXXXXXXXX'; //追加

スプレッドシートIDは、スプレッドシートのURL「/d/」と「/edit#gid=0」の間にあります。例えば、URL:https://docs.google.com/spreadsheets/d/dakdoaudfoahihadfa/edit#gid=0
↑このURLのスプレッドシートIDは、"dakdoaudfoahihadfa"となります。

スプレッドシートは自身のGoogleドライブに新規作成し、タブを「天気予報」に変更します。

そして、「天気予報」タブのセルC1、D1、E1にそれぞれ「最高気温」「最低気温」「湿度」を入力します。

さらに、前回のコードでswitch構文を入れており、そのコードに天気予報を入力した場合を追加します。

そして、追加したswich文全体がこちら。

switch (user_msgarray[0]) {
    case "ゴミ出し":
    case "ゴミの日":
      TakingOutTheTrash()
      break;
      //今回導入部分
    case "現在の天気":
      let cityList = ['Tokyo,JP', 'Kagawa,JP',"Galapagos"];
      let cityname = ['東京', '香川',"ガラパゴス"];
      var weatherInfo = [];
      for (let i = 0; i < cityList.length; i++) {
        var url = `https://api.openweathermap.org/data/2.5/weather?q=${cityList[i]}&appid=${OPENWEATHERMAP_APIKEY}&lang=ja`;
        var responseforecast = UrlFetchApp.fetch(url);
        var forecast = JSON.parse(responseforecast.getContentText());
        var weather = translateWeatherToJapanese(forecast.weather[0].main); // 天気を日本語に変換
        var temp_max = (forecast['main']['temp_max'] - 273.15).toFixed(1); // 最高気温を摂氏に変換して小数点第1位で丸める
        var temp_min = (forecast['main']['temp_min'] - 273.15).toFixed(1); // 最低気温を摂氏に変換して小数点第1位で丸める
        weatherInfo.push(`現在の${cityname[i]}の天気は${weather}、最高気温は${temp_max}℃、最低気温は${temp_min}℃です。`);
      }
      message = weatherInfo.join("\n")
      lineReply(json, message)
      break;
    case "天気予報":
      getForecast()
      const spreadsheetforecast = `https://docs.google.com/spreadsheets/d/${spreadsheetId}`;
      message = `天気予報の情報をスプレッドシートに記載しました。スプレッドシートのURLはこちらです: ${spreadsheetforecast}`
      lineReply(json, message)
      break;
    default:
      // LINEのメッセージをChatGPTにメッセージ
      const messages = [{ "role": "user", "content": user_msgarray[0] }]
      const headers = {
        'Authorization': 'Bearer ' + OPENAI_APIKEY,
        'Content-type': 'application/json',
      };
      const options = {
        'method': 'POST',
        'headers': headers,
        'payload': JSON.stringify({
          'model': MODEL_NAME,        // 使用するGPTモデル
          'max_tokens': MAX_TOKENS,   // 最大トークン
          'temperature': MODEL_TEMP,  // ランダム性
          'messages': messages
        })
      };
      //ChatGPTのAPIを呼び出す
      const res = JSON.parse(UrlFetchApp.fetch(GPT_ENDPOINT, options).getContentText());
      //ChatGPTから返却されたメッセージをLINEに
      lineReply(json, res.choices[0].message.content.trimStart());
 }
}

また、function文も追加します。

function weathernews() {
  getForecast()
  const spreadsheetforecast = `https://docs.google.com/spreadsheets/d/${spreadsheetId}`;
  message = `天気予報の情報をスプレッドシートに記載しました。スプレッドシートのURLはこちらです: ${spreadsheetforecast}`
  if (!message) return; 
  const payload = {
    to: USER_ID, //ユーザーID
    messages: [
      { type: 'text', text: message }
    ]
  };
  const params = {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: 'Bearer ' + LINE_ACCESS_TOKEN
    },
    payload: JSON.stringify(payload)
  };
  UrlFetchApp.fetch(LINE_ENDPOINT_PUSH, params);
}

function getForecast() {
  var apiUrl = 'https://api.openweathermap.org/data/2.5/forecast?q='; 
  var cities = ['Tokyo,JP',"Kagawa,JP", "Galapagos"]; 
  var weatherData = []; 
  for (var i = 0; i < cities.length; i++) { 
    var city = cities[i]; 
    var requestUrl = apiUrl + city + '&appid=' + OPENWEATHERMAP_APIKEY + '&lang=ja&units=metric'; 
    var response = UrlFetchApp.fetch(requestUrl).getContentText(); 
    var json = JSON.parse(response); 
    var weatherInfo = []; 
    for (var j = 0; j < json['list'].length; j++) { 
      weatherInfo[j] = []; 
      weatherInfo[j][0] = json['list'][j]['dt_txt']; 
      weatherInfo[j][1] = translateWeatherToJapanese(json['list'][j]['weather'][0]['description']); 
      weatherInfo[j][2] = json['list'][j]['main']['temp_min']; 
      weatherInfo[j][3] = json['list'][j]['main']['temp_max']; 
      weatherInfo[j][4] = json['list'][j]['main']['humidity']; 
    } 
    weatherData.push({ city: city, data: weatherInfo }); 
  } 
  var sheetName = '天気予報'; 
  var sheet = SpreadsheetApp.openById(spreadsheetId).getSheetByName(sheetName); 
  // 既存のデータの下に新しいデータを追加
  var lastRow = sheet.getLastRow();
  for (var i = 0; i < weatherData.length; i++) { 
    var city = weatherData[i].city; 
    var weatherInfo = weatherData[i].data; 
    // 都市名を書き込む
    sheet.getRange(lastRow + 1 + i * (weatherInfo.length + 2), 1).setValue(city); 
    // 天気情報を書き込む
    sheet.getRange(lastRow + 2 + i * (weatherInfo.length + 2), 1, weatherInfo.length, weatherInfo[0].length).setValues(weatherInfo); 
  } 
}

function translateWeatherToJapanese(weather) {
  switch (weather) {
    case "Clear":
      return "晴れ";
    case "Clouds":
      return "曇り";
    case "Rain":
      return "雨";
    default:
      return weather;
  }

ここまで記載できたら、あとはデプロイするだけです。

デプロイ後、LINEBOTに「天気予報」と入力してみました。

無事返事をしてくれました!
そして、そのURLを押してみると…

指定のスプレッドシートに天気予報の情報を書き込んでくれます。スプレッドシートと簡単に連携できるのがGASの強みですね!

また、「現在の天気」と入力すると現在の天気を教えてくれるようにしました。

うん、分かりやすくて素晴らしい。

地名については、香川やガラパゴス諸島に旅行で行ったので、その地点の天気を知らせてくれるようにしています。

もし他の地点を通知して欲しい場合、コード内の地名を変えてみましょう。

var cities = ['Tokyo,JP',"Kagawa,JP", "Galapagos"];
↑もし日本の地名ならJPを入れましょう。詳細はOpen Weather Mapの公式サイト見ていただければ…!

天気予報を通知してくれることが分かったので、あとはトリガーを追加しましょう。

これで毎日天気を自動で知らせてくれます。これは便利!!

今回はここまでとさせていただきます。

だんだんと便利になってきましたね・・・!
次回は家計簿について記事にしていこうかと思います。

この記事と並行してLINEBOTの欠点、及び画期的なLINEBOT開発について記事にしています。ぜひご覧ください。

それでは!!

※本記事は許可なく第三者へ公開すること、または本記事の内容を転載することは禁止しております。場合によっては法的措置をとらせていただきますのでご注意ください。

この記事が参加している募集

AIとやってみた

QOLあげてみた

この記事が気に入ったらサポートをしてみませんか?