はじまり
あ〜!
濡れた濡れた・・・
お、お帰りさん、
ズブ濡れだねえ
今日、夕方から雨が降るなんて
聞いてないよお・・・
じゃあ、今回はその日に雨が降るかどうかを
Discordで通知してくれるツールを作ってみよう
おおっ。
ツールの概要
今回は、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[![OpenWeatherMap](${urlImage})](${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で表示されたテキストのとおりに喋り始めます。
画像の場合だと、「今日は雨が降るみたいだよ。ぜろじぜろぜろふんぜろぜろびょう・・・」といった具合になります。
使いどころですね・・・
おしまい
うわ、通知されてきた!
DiscordのWebhookを使ったツールは、
通知するだけなら比較的簡単に作れます。
ぜひ試してみて下さい。
他にも何か作れないかなあ
以上になります!
コメント