【Google Apps Script】DiscordのWebhookを使って毎朝天気を通知する(Discord Bot改良:第1回)
はじまり





ツールの概要
今回は、DiscordのWebhookを使って、OpenWeatherMapというサイトから気象情報を取得します。

ツールを作る言語は、Google Apps Scriptを使用します。
APIをタダで作れるため、個人利用の範囲内であれば、とてもコスパが良いです。
ツールの概要はこんな感じ。

機能
Discordに通知するまでの機能の紹介です。
実際に時間トリガーでWebhookが作動するとこのように通知されます。

気温と雨の時間帯を通知するために、以下の情報を取得する必要がありますね。
- その日の天気(その日の8つの時間帯における天気を集計して最多の天気を取得する)
- 最高気温
- 最低気温
- 任意の時間における天気
気象情報を取得する
まずは、Google Apps Scriptから、OpenWeatherMapのWeather APIにGETでリクエストを送ります。 大体3、4日分くらいを3時間おきでブツ切りされた気象情報がレスポンスで返ってきます。
[ { dt: 1676224800, main: { temp: 282.88, feels_like: 281.08, temp_min: 282.88, temp_max: 283.2, pressure: 1014, sea_level: 1014, grnd_level: 1009, humidity: 68, temp_kf: -0.32 }, weather: [ [Object] ], clouds: { all: 75 }, wind: { speed: 3.47, deg: 2, gust: 5.47 }, visibility: 10000, pop: 0.42, rain: { '3h': 0.43 }, sys: { pod: 'n' }, dt_txt: '2023-02-12 18:00:00' }, { dt: 1676235600, main: { temp: 282.84, feels_like: 281.32, temp_min: 282.75, temp_max: 282.84, pressure: 1014, sea_level: 1014, grnd_level: 1008, humidity: 66, temp_kf: 0.09 }, weather: [ [Object] ], clouds: { all: 83 }, wind: { speed: 2.95, deg: 7, gust: 4.8 }, visibility: 10000, pop: 0.3, sys: { pod: 'n' }, dt_txt: '2023-02-12 21:00:00' },...]まずは、その日の天気を決めます。 天気の決め方は、その日の8つの時間帯(0:00、3:00、6:00、9:00、12:00、15:00、18:00、21:00)における天気を集計して、その中で最も多かった天気をその日の天気とします。 天気の種類は、以下のリファレンスに載っています。天気のステータスコードが5xxだと雨になります。 5xxや8xxなどの状態をグループごとに集計して天気を決めました。
おそらく、main属性のオブジェクトにあるtemp_minとtemp_maxで、その時間帯の気温を取ってこれます。その気温を1日ごとに集計して、その日の最高気温と最低気温を割り出しました。
最後に、雨の状態になっている時間帯をオブジェクトにメモっておきました。 これで、僕が欲しかった情報は手に入りました。
WebhookでDiscordに通知する
天気の情報を整理してオブジェクト形式に出来たら、それをJSON形式でDiscordのWebhookに送ります。
以下のように送ることで、Discordでメッセージを送信できるかと思います。
muteHttpExceptionsはどちらでも良いような気がします。
ログの見え方が変わるらしいですが、ぶっちゃけ、trueでもfalseでもログの見え方は大して変わると思っていません。
function getReqHeaders(type="json"){ let contentType = ""; switch(type){ case "json": contentType = "application/json" } const requestHeaders = { "Content-Type": contentType } return requestHeaders;}
const webhookUrl = "WEBHOOKのURL";let options = { method: "POST" , payload: JSON.stringify(payload) , headers: getReqHeaders("json") , muteHttpExceptions : true}let res = UrlFetchApp.fetch(webhookUrl, options);通知内容を凝りたい
通知するところまでは出来たので、通知するときのデザインを確認します。
先程貼った通知の内容にするためには、こんな感じのコードになります。単なる一部抜粋になります。
infoに整理したオブジェクトがあって、それをmapでどーのこーのしています。
最高気温Maxと最低気温Minを並べて表示したかったので、"embeds"属性の"fields"属性を使って並べました。

let embedsArray = keys.map(location => { let items = info[location]; if(items[keyRO]["weather"].length === 0){ content = "今日は雨が降らないみたいだよ!"; }else{ content = "今日は雨が降るみたいだよ!"; for(let i = 0; i < items[keyRO]["weather"].length; i++){ console.log(items[keyRO]["time"][i]); r = `${items[keyRO]["time"][i]["hour"]}:${items[keyRO]["time"][i]["minute"]}:${items[keyRO]["time"][i]["second"]} - ${items[keyRO]["weather"][i]}`; content = `${content}\r${r}`; } }
let embeds = []; for(let i = 0; i < items[keyTF].length; i++){ imageFileUrl = getImageFileUrl(items[keyWF][i]["weather"], imageFolderUrl); author = getDateDesignation(i); iconUrl = "https://openweathermap.org/themes/openweathermap/assets/vendor/owm/img/icons/favicon.ico"; embeds.push({ "title": items[keyTF][i]["date"] , "color": "15494471" , "author": { "name": author , "url": "https://openweathermap.org/city/?q=Tokyo" , "icon_url": iconUrl } , "footer": { "text": "OpenWeatherMap" , "icon_url": iconUrl } , "fields": [ { "name" : "Max" , "value" : `${items[keyTF][i]["temp_max"]}` , "inline": true } , { "name" : "Min" , "value" : `${items[keyTF][i]["temp_min"]}` , "inline": true } ] , "thumbnail": { "url" : imageFileUrl } }) } return embeds;})画像にリンクを埋め込むやつを本文中で使えるかどうかを試してみましたが、それは出来ないようです。
let urlSite = "https://openweathermap.org/city/?q=Tokyo";let urlImage = "https://openweathermap.org/themes/openweathermap/assets/img/logo_white_cropped.png";ontent = `${content}\r[](${urlSite})`;
const payload = { "username": "お天気あゆ" , "content": content , "embeds": returnEmbeds // , "tts": true}少し詰まったところ
以下、少し詰まったところです。
ICO形式のファイルは表示できない
また、Discord上では.ico拡張子のファイルは表示できないみたいでした。
2つ上に貼ったコード内のiconUrlが該当箇所です。
後ほど、自分で.png形式に変えて別の場所から公開したものをリンクに付けると、ちゃんとファビコンがDiscord上で表示されました。

Number型のままでは、リクエスト時にエラーになる
これは、Discord Webhookとか関係ないかと思いますが、最高気温と最低気温をNumber型のまま、オブジェクトをJSONにしたら、Discordへのリクエストを正常にできませんでした。 そのため、NumberをStringにして、JSON.stringifyしています。
ちなみに、しゃべらせることができる
ちなみに、1つ上に貼ったコード内の”tts”: trueですが、これをリクエストにちゃんと載せると、Discordで表示されたテキストのとおりに喋り始めます。 画像の場合だと、「今日は雨が降るみたいだよ。ぜろじぜろぜろふんぜろぜろびょう・・・」といった具合になります。 使いどころですね・・・
おしまい



以上になります!
記事を共有
この記事が役に立ったなら、ぜひ他の人と共有してください!