【超解説】Notionでランダムな1件をスマホに定期通知する方法❶LINE通知
以下の記事でざっくり紹介した方法❶Google Apps Script (GAS) + LINE Notifyの方法について、詳しくご紹介したいと思います。
以前、私もNotion×GAS×LINE Notifyの記事を上げさせていただきましたが、今回はもう少しシンプルな処理になりますので、GASのコーディング内容もご説明出来たらなと思います。 わりとモリモリです。既知の箇所があれば適宜お飛ばしください🎈
まずは実現したい内容のイメージ
通知元のデータベース画面
LINE通知画面
処理の全体
実現手順
1️⃣ 処理に必要な各種キーを取得しておく
💼 必要なもの
今回は、各アカウント(Google, Notion, LINE)の登録方法は割愛しますね。
【Notion】インテグレーションシークレット
❶ 対象データベースがあるNotionアカウントでログインしておく
❷ Notionインテグレーションシークレット作成画面アクセス
🔗 https://www.notion.so/my-integrations
❸ 新しいインテグレーションシークレットを作成
❹ インテグレーションシークレットを控えておく(メモ帳等に一旦貼付)
【Notion】データベースID
❶ 対象のリストがあるNotionデータベースをブラウザで開く
❷ ブラウザのアドレスバーから、データベースIDを抜き出して控えておく(メモ帳などに一旦貼付)
https://www.notion.so/{workspace_name}/{database_id}?v={view_id}
【LINE Notify】アクセストークン
❶ LINE Notifyのログイン画面へアクセス
🔗 https://notify-bot.line.me/ja
❷ ログインし、マイページへ遷移する
❸ 「トークンを発行する」ボタンをクリック
❹ トークン発行画面で、必要事項を入力・選択して発行
❺ 発行されるトークンを控えておく(メモ帳などに一旦貼付)
2️⃣ データベースにインテグレーションをコネクト追加
❶ 先ほどの手順 1️⃣ で作成したインテグレーションを、対象データベースにコネクト追加
接続先の一覧には、インテグレーション作成時に付けた名前で表示されます。表示されない場合は、ブラウザのリロードを何度か試みましょう
3️⃣ GASにてコーディング
❶ Google Apps Scriptのログイン画面へアクセス
🔗 https://www.google.com/script/
❷ 新しいプロジェクトを作成
❸ コード.gsを開き、初期記述コードを消す
❹ コード.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向けリファレンスで確認できます🔍
❺ 「実行」をクリックして権限を承認(初回のみ必要)
❻ 権限の承認
❼ 改めて実行してエラーの有無・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にてトリガーの設定
❶ トリガーを追加
❷ トリガーで通知タイミングを設定
おわり
いかがでしたか…画像を多めにしたらかなりの量になってしまった感…。
サンプルコードはご自由にカスタムください。もっと関数のことや、取得データのフィルター詳細も説明できたらと思ったのですが、根尽きてしまったので煩雑になりそうでしたので、今回はこのあたりで留めたいと思います。
参考になったなぁと感じていただけたら、スター🌟やフォローいただけると励みになります!
長文お読みいただきまして、ありがとうございました🥰
次回は Notionでランダムな1件をスマホに定期通知する3つの方法【全4回③iOSリマインダー通知】の記事をまとめたいと思います。がんばろう🏋️♀️
👇 記事UPしました! 👇