GASでwebhook使ってnotionのページ更新を知らせるツール作った
GAS(google app script)でnotionのページ更新をdiscordで通知してくれる機能を作ったので覚書として投稿します
作ったもの
毎日0:00に、24時間以内に指定のnotionページで新規ページ作成があったかどうかをdiscordで通知してくれます
notion側↓
discord側↓
使ったもの
- GAS(google app script)→javascript言語
- notion及びnotion API
- discord webhook
今回のポイント
実行が1日に1回なので、GASの無料版でも問題なく使える
discordでのメッセージ送信にwebhookという機能を使ったので、botよりも比較的簡単な(短い)コードで実装できた。
notionの返答データ(JSON)のobject構造が複雑なため、それを可視化できるツールが欲しいと感じた。
仕組み
説明が言葉では難しいので図を用意します
このようにnotion APIから取得したデータを加工し、条件に合わせて出力をdiscordに行います。
説明は省略しますが、notionのAPIを使うにはnotion側で手続きが必要です。
webhookとは?
discordなど多くのアプリケーションに存在する機能。webアプリケーションでイベントが発生したときにメッセージを送信できる。今回ではGASのスクリプトからdiscordへのメッセージ送信で利用する。
webhookはいわゆる”ツール”のようなものではなく、例えばdiscordではhttps://discord.com/api/webhooks/xxxx
のようにURLが用意されていて、このURLをメッセージ内容と合わせて送信をすることで実現される。このwebhookURLはチャンネルごとに別のものを使う。
- APIとの違い
webhookはAPIとは違い、一方向のみの操作であることが特徴。APIは要求・応答のセットだが、webhookはスクリプトから対象アプリへの送信のみである。
機能の流れ
①GAS→notionへデータを要求
➁notion→GASにデータを返答
③GAS上でデータ処理・条件に応じたメッセージを作成
④作成したメッセージをwebhookを用いてdiscordに送信
①GAS→notionへデータを要求
➁notion→GASにデータを返答
こちらの記事 を参考にnotionからデータをjson方式で取得します。
function fetchNotionDatabase() {
const props = PropertiesService.getScriptProperties();
const NOTION_API_KEY = props.getProperty('NOTION_API_KEY');
const DATABASE_ID = props.getProperty('NOTION_DATABASE_ID');
const url = `https://api.notion.com/v1/databases/${DATABASE_ID}/query`;
const options = {
method: 'post', // Notion API の `query` は POST リクエスト
headers: {
'Authorization': `Bearer ${NOTION_API_KEY}`,
'Notion-Version': '2022-06-28',
'Content-Type': 'application/json'
}
};
// リクエスト、結果
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
//Logger.log(data);
return data;
}
③GAS上でデータ処理・条件に応じたメッセージを作成
// 24時間以内のページを取得
let msgcontent = [];
for (let i= 0; i < data.results.length; i++){
const timestamp = data.results[i].last_edited_time;
if(isWithinLast24hrs(timestamp)){
msgcontent.push(getTitle(data.results[i]));
}
}
今回、24時間以内の編集があった記事を取得したいので、更新または新規作成のあった記事のタイトルを取得します。
④作成したメッセージをwebhookを用いてdiscordに送信
// 出力メッセージ部
let date = new Date();
date.setDate(date.getDate() - 1); //00:00更新なので前日の日付
const datestring = formatDate(date);
if (msgcontent.length === 0){
Logger.log(datestring +"\n本日の更新はありません");
msgsend(datestring +"\n本日の更新はありません");
}else{
Logger.log(datestring +"\n本日の更新タイトル:"+ msgcontent);
msgsend(datestring +"\n本日の更新タイトル:"+ msgcontent);
}
③の msgcontent
を基に送信メッセージを決定します。
msgsend()
関数
function msgsend(msgcontent) {
const props = PropertiesService.getScriptProperties();
const DISCORD_WEBHOOK_ID = props.getProperty('DISCORD_WEBHOOK_ID')
const WEBHOOK_URL = `https://discord.com/api/webhooks/${DISCORD_WEBHOOK_ID}`;
let payload =
{
"content": msgcontent
};
let options =
{
"method": "post",
"payload": payload
};
UrlFetchApp.fetch(WEBHOOK_URL, options);
}
これで新規・更新のあったページ情報をdiscordで送信できます。
機能を毎日決まった時間に実行する
GASのトリガーという機能を使って、毎日0:00に実行するよう指定します。
こちらの記事 から、スクリプト内でトリガーを操作する方法が載っているので参考にしました。任意の関数内でトリガーを登録して、次回の実行日時を指定します。今回では次の日の0:00に再度実行してほしいため、new Date()
で日付取得したデータを適切に加工します。
//新しいトリガー作成
let targettime = new Date();
targettime.setDate(targettime.getDate() + 1); //翌日00:00
//時刻
targettime.setHours(00);
targettime.setMinutes(00);
targettime.setSeconds(00);
//newTriggerメソッドでmain関数実行を特定日時でトリガー登録
Logger.log("targettime:"+targettime);
ScriptApp.newTrigger('main').timeBased().at(targettime).create();
実行した時点での日時を取得し、翌日の00:00:00に加工します。その後、GASのメソッドを呼び出して、「main関数を時間実行するトリガー」を作ります。
まとめ
今回はnotionのAPIとDiscordのWebhookという機能を使いました。今回は一方向の機能ですが、今後はDiscord側でBotを用いて双方向な機能も作りたいです。例えば、ランダムなページを紹介してくれるツールなどが作る候補になると考えています。Webhookは簡単にメッセージを送ることができる機能なのでぜひ使ってみてください。