【超解説】Notionでランダムな1件をスマホに定期通知する方法❶LINE通知
以下の記事でざっくり紹介した方法❶Google Apps Script (GAS) + LINE Notifyの方法について、詳しくご紹介したいと思います。
以前、私もNotion×GAS×LINE Notifyの記事を上げさせていただきましたが、今回はもう少しシンプルな処理になりますので、GASのコーディング内容もご説明出来たらなと思います。
わりとモリモリです。既知の箇所があれば適宜お飛ばしください🎈
まずは実現したい内容のイメージ
通知元のデータベース画面
LINE通知画面
処理の全体像
実現手順
1️⃣ 処理に必要な各種キーを取得しておく
今回は、各アカウント(Google, Notion, LINE)の登録方法は割愛しますね。
■ 【Notion】インテグレーションシークレット
1.対象データベースがあるNotionアカウントでログインしておく
2.Notionインテグレーションシークレット作成画面アクセス
🔗 https://www.notion.so/my-integrations
3.新しいインテグレーションシークレットを作成
4.インテグレーションシークレットを控えておく(メモ帳等に一旦貼付)
■ 【Notion】データベースID
1.対象のリストがあるNotionデータベースをブラウザで開く
2.ブラウザのアドレスバーから、データベースIDを抜き出して控えておく
(メモ帳などに一旦貼付)
■ 【LINE Notify】アクセストークン
1.LINE Notifyのログイン画面へアクセス
🔗 https://notify-bot.line.me/ja/
2.ログインし、マイページへ遷移する
3.「トークンを発行する」ボタンをクリック
4.トークン発行画面で、必要事項を入力・選択して発行
5.発行されるトークンを控えておく(メモ帳などに一旦貼付)
2️⃣ データベースにインテグレーションをコネクト追加
1.先ほどの手順 1️⃣ で作成したインテグレーションを、対象データベースにコネクト追加
接続先の一覧には、インテグレーション作成時に付けた名前で表示されます。表示されない場合は、ブラウザのリロードを何度か試みましょう。
3️⃣ GASにてコーディング
1.Google Apps Scriptのログイン画面へアクセス
🔗 https://www.google.com/script/
2.新しいプロジェクトを作成
3.コード.gsを開き、初期記述コードを消す
4.コード.gsに後述のサンプルコードをペースト
今回のサンプルコードは、対象のNotionデータベースから、タイトルプロパティに登録された文字(今回はプロパティ種類はタイトル、プロパティ名は「言葉」)をランダムに1件取得→LINE Notifyへ送信するという処理です。
サンプルコードについて:少し冗長的ではありますが、説明しやすいよう関数(`function~`)をかなり切り分けています。各処理内容をコメント(`/* ~ */` や `//`)で補足していますので、理解の参考になれば幸いです。
※エラーハンドリングは省略しています、悪しからず…🙃
サンプルコードを「コード.gs」にコピペして、定数定義の3項目をご自身の値に書き換えれば(値を囲むシングルクォート '' は消さない)OKです。
/**
* 定数定義(`const`宣言)
*
* - 各処理で使用する必要な各値をあらかじめ定数に定義
*/
const NOTION_API_KEY = '値をここに入れる'; // Notion APIインテグレーションシークレット
const DATABASE_ID = '値をここに入れる'; // NotionデータベースID
const LINE_NOTIFY_API_TOKEN = '値をここに入れる'; // LINE Norify APIアクセストークン
/**
* メイン処理
*
* - 後述【1】~【5】の処理を統合した実行関数
* - コーディング後に、この関数をトリガーとした定期実行の設定を行う
*/
function sendNotification() {
// 【1】Notion APIを通じ、Notionの指定データベースからデータを取得
const data = getAllData();
// 【2】取得データから欲しい情報(タイトル)のみ抽出
const words = getAllWords(data);
// 【3】【2】のリストから、ランダムに1件抽出
const randomWord = getRandomWord(words);
// 【4】通知文の設定
const message = setNotificationMessage(randomWord);
// 【5】LINE Notify APIを通じ、指定トークルームへ【4】を送信
sendLineMessage(message);
}
/**
* 【1】Notion APIを通じ、Notionの指定データベースからデータを取得
*
* - `UrlFetchApp.fetch`メソッドを使用して、指定したURL(`url`)にPOSTリクエストを送信
* - `url`内の`DATABASE_ID`は冒頭で定義した定数(データベースID)
* - リクエストの際はNotionインテグレーションシークレット(定数`NOTION_API_KEY`)で認証しデータ取得
* - `url`や`method`は、操作内容によって異なる(取得、追加、データベースかページかなど)
* - 取得データ(JSON形式)をパース(GASで使える形に変換)して返す
*/
function getAllData() {
const url = `https://api.notion.com/v1/databases/${DATABASE_ID}/query`;
const options = {
method: 'POST',
headers: {
'Authorization': `Bearer ${NOTION_API_KEY}`,
'Content-Type': 'application/json',
'Notion-Version': '2022-06-28',
},
// -- もしフィルターをかけたい場合はここに追加(☆記事にて後述)
};
const response = UrlFetchApp.fetch(url, options);
const data = JSON.parse(response.getContentText());
return data;
}
/**
* 【2】取得データから欲しい情報(タイトル)のみ抽出
*
* - 取得したデータを`map`メソッド(配列の繰り返し操作・新たに配列生成)を使って
* 各結果から「言葉」というタイトルプロパティの文字を抽出・配列へ格納して返す
* ★プロパティ名は、ご自身のデータベースに合わせて変更してください
* - プロパティの種類によって`result.properties['言葉'].`以降の記述は異なる
*/
function getAllWords(data) {
const pageTitles = data.results.map(
(result) => result.properties['言葉'].title[0].text.content
);
return pageTitles;
}
/**
* 【3】【2】のリストから、ランダムに1件抽出
*
* - 抽出したタイトルの配列から、`Math.random`メソッドを使用してランダムなインデックスを生成
* - そのインデックスに位置する1つの単語を選択して返す
*/
function getRandomWord(words) {
const index = Math.floor(Math.random() * words.length);
const randomWord = words[index];
return randomWord;
}
/**
* 【4】通知文の設定
*
* - 渡されたランダムな言葉を通知文の形式に整えて返す
* - `\n` はエスケープ文字の一種で、文字列内に挿入するとその位置で改行される
*/
function setNotificationMessage(randomWord) {
const message = `\n${randomWord}`;
return message;
}
/**
* 【5】LINE Notify APIを通じ、指定トークルームへ【4】を送信
*
* - `UrlFetchApp.fetch`メソッドを使用して、指定したURL(`url`)にPOSTリクエストを送信
* - リクエストの際はLINE Notify APIトークン(定数`LINE_NOTIFY_API_TOKEN`)で認証しデータ送信
*/
function sendLineMessage(message) {
const notifyUrl = 'https://notify-api.line.me/api/notify';
const options = {
method: 'POST',
headers: {
'Authorization': `Bearer ${LINE_NOTIFY_API_TOKEN}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
payload: {
message: message,
},
};
UrlFetchApp.fetch(notifyUrl, options);
}
🐍 補足
もしNotionデータベースからデータを取得する際、フィルターを適用したい場合は、上記サンプルコードの「 // -- もしフィルターをかけたい場合はここに追加(☆記事内にて補足)」の箇所に、以下記述を追加してください。
// -- もしフィルターをかけたい場合はここに追加(☆)
payload: JSON.stringify({
filter: {
property: '対象外', // Notionデータベースのプロパティ名
checkbox: { // プロパティの種類
equals: false // 条件(この場合は、チェックボックスに未チェックのデータのみ)
}
},
}),
フィルターしたいプロパティ種類や、複数のフィルター条件を組み合わせたい場合などによって、記述内容が異なります。今回は網羅しませんが、詳細は公式Developer向けリファレンスで確認できます🔍
5.「実行」をクリックして権限を承認(初回のみ必要)
6.権限の承認
7.改めて実行してエラーの有無・LINE通知されたか確認
🤢 よくあるエラー
エラーメッセージの内容はほとんど英語ですが、落ち着いて単語を拾っていくと原因の予測が立ちやすいです。以下にありがちエラーをまとめました。
# コード.gsで保存したときのエラーメッセージ
構文エラー: SyntaxError: Unexpected end of input 行: 115 ファイル: コード.gs
# 原因:
全角スペースが混じっていたり、閉じカッコ`}`や文末コロン`;`が抜けている、誤植など
正しい構文になっていない場合
# コードgs.で実行したとき実行ログのエラーメッセージ
Exception: Request failed for https://api.notion.com returned code 401. Truncated server response: {"object":"error","status":401,"code":"unauthorized","message":"API token is invalid.","request_id":"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"} (use muteHttpExceptions option to examine full response)
# 原因:
インテグレーションシークレット(NOTION_API_KEY)の値に誤りがある
# コードgs.で実行したとき実行ログのエラーメッセージ
Exception: Request failed for https://api.notion.com returned code 400. Truncated server response: {"object":"error","status":400,"code":"validation_error","message":"path failed validation: path.database_id should be a valid uuid, instead was `\... (use muteHttpExceptions option to examine full response)
# 原因:
データベースID(DATABASE_ID)の値に誤りがある
# コードgs.で実行したとき実行ログのエラーメッセージ
Exception: Request failed for https://notify-api.line.me returned code 401. Truncated server response: {"status":401,"message":"Invalid access token"} (use muteHttpExceptions option to examine full response)
# 原因:
LINE Notify アクセストークン(LINE_NOTIFY_API_TOKEN)の値に誤りがある
# コードgs.で実行したとき実行ログのエラーメッセージ
Exception: Request failed for https://api.notion.com returned code 404. Truncated server response: {"object":"error","status":404,"code":"object_not_found","message":"Could not find database with ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. Make sur... (use muteHttpExceptions option to examine full response)
# 原因:
コネクト追加できていない
4️⃣ GASにてトリガーの設定
1.トリガーを追加
2.トリガーで通知タイミングを設定
おわり
いかがでしたか…画像を多めにしたらかなりの量になってしまった感…。
サンプルコードはご自由にカスタムください。
もっと関数のことや、取得データのフィルター詳細も説明できたらと思ったのですが、根尽きてしまったので煩雑になりそうでしたので、今回はこのあたりで留めたいと思います。
参考になったなぁと感じていただけたら、スキ🤍を押していただけると励みになります!長文お読みいただきまして、ありがとうございました🥰
次回は Notionでランダムな1件をスマホに定期通知する3つの方法【全4回③iOSリマインダー通知】の記事をまとめたいと思います。がんばろう🏋️♀️
👇 記事UPしました! 👇