🤝

NotionAPIとGoogle Apps Scriptを使って、Notionのページを自動的にSlack通知する方法

2023/02/07に公開

こんにちは!
電話自動応答サービスIVRyのQAエンジニアの関です。
IVRyでは、QAの設計からテストまで担当しています。
https://twitter.com/IvryQa

https://note.com/ryomaseki/n/nd6debe0590f0

QA時の不具合報告フローを改善する際に、NotionAPIとGoogle Apps Scriptを活用することで、簡単に自動化できたので記事にまとめてみました。
元々、IVRyではテスト中に発見した不具合をSlackにてエンジニアチームへ報告し、その後notionのデータベースに不具合ページを作成し、不具合ページのリンクをスレッド内で共有するという冗長なフローを行っていました。
それらを改善するために、NotionAPIとGoogle Apps Scriptを使って、不具合ページが作成されたタイミングで、自動的にSlackへ通知されるようにしてみました。

処理のながれ


[Google Apps Scriptの] の処理のながれは、以下になります。

  1. [Notion] からデータを取得する。(NotionAPI を使い、特定の条件を満たすデータを取得します。)

  2. 「手順1」から取得したNotionページのデータを、 [Spreadsheet] 内に保存されているデータと比較することで、自動的にNotionページが過去に投稿されたものと重複していないか確認します。(Spreadsheet内では、過去に投稿されたページのIDが管理されています)

  3. [Slack] に、不具合ページを投稿する。

  4. [Spreadsheet] に、 [Notion] のページIDを書き込む。

仕様について

  • Notionのページ作成後、5分以内にSlackへ通知される
  • Notionのページが重複して通知されない
  • フィルター
    • ページプロパティの「Category」に"QA結果"が含まれる
    • ページプロパティの「最終更新日」が"過去1週間以内"
      • 日付フィルター条件については、こちらを参照ください
    • ページプロパティの「Publish」が"true"になっている
      • 作成中のページが通知されないために、フラグを設定しています

やること

  1. Slackにて、通知先のchannelを作成し、Webhookを取得する。

  2. Notionにて、データベースを作成し、NotionAPIの作成・設定を行う。

  3. 重複チェック用のSpreadsheetを作成する。

  4. Google Apps Scriptにコードを書き込み、トリガーを設定する。

💡 注意ポイント
NotionAPIを作成するには、admin権限が必要になります。

それでは、詳しく解説していきます!

1. Slackにて、通知先のchannelを作成し、Webhookを取得する

(1) まずは、Slackを開き、通知先のチャンネルを作成します。
(2) 「Incoming WebHooks」を設定します。
・ チーム名をクリックし、設定と管理 > アプリを管理するを選択します。
・ 検索窓に「Incoming」と入力し、「Incoming Webhooks」を選択します。
・ そこから、「Slackに追加」→「チャンネルを選択」→「インテグレーションの追加」の順番でクリックします。
・ 作成完了後、Webhook URLの項目に表示されているURLをコピーします。

設定は、以上です。

2. Notionにて、データベースを作成し、NotionAPIの作成・設定を行う

(1) Notion Developerを開きます。
(2) 「New integration」 をクリックします。
(3) 各項目を入力します。
「Name」 を入力します。
・ Capabilities > Content Capabilitiesは、 「Read Content」 のみチェックします。
・ User Capabilities > は、「Read user information without email addresses」 にチェックします。

3. Spreadsheetを作成する

(1) Spreadsheetを開きます。
(2) シート名を 「list」 に変更します。

4. Google Apps Scriptのエディタにコードを反映し、トリガーを設定する

(1) 先ほどのSpreadSheetのメニューバー > 機能拡張から 「Apps Script」 をクリックします。
(2) 以下のコードを 「スクリプトエディタ」 にコピペします。

const spreadsheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('list');
const props  = PropertiesService.getScriptProperties();
const slack_webhook = props.getProperty('SLACK_WEBHOOK');
const database_id = props.getProperty('NOTION_DATABASE_ID');
const token = props.getProperty('NOTION_TOKEN');
const messageCategory = '不具合ページ';
const messageIcon = 'ticket';

// スプレッドシートから以前に取得したデータを取得し、Notionからデータを取得する。その後、取得したデータをスプレッドシートに保存し、Slackに通知する
function main() {
  //スプレッドシートから以前に取得したデータを取得
  const pastData = getPastDataFromSpreadSheet();
  //Notionからデータを取得
  getNotionData().then(data => {
    data.results.forEach(record => {
      //以前に取得したデータに重複していないかチェック
      if (!pastData.includes(record.id)) {
        const title = record.properties.Name.title[0].plain_text;
        const url = record.url;
        const user = record.properties['Created by'].created_by.name;
        const image = record.properties['Created by'].created_by.avatar_url;
        const jsonData = {
          'username' : `Notion by ${user}`,
          'icon_url': image,
          'text' : `*[${messageCategory}]* \n <${url}|${title}> を作成しました。 \n 不具合内容のご確認お願いします。`
        };
        postToSlack(jsonData);
        setSpreadSheet(record.id);
      }
    });
  });
}

// スプレッドシートから過去に取得したデータを取得し、配列に格納する
function getPastDataFromSpreadSheet() {
    // スプレッドシートから過去に取得したデータを取得する
    const sheet = SpreadsheetApp.getActiveSheet();
    const data = sheet.getDataRange().getValues();

    // 過去に取得したデータのIDのみを配列に格納する
    const pastData = data.map(row => row[0]);
    return pastData;
}

// NotionAPIを使用して、特定の条件を満たすデータを取得し、それらのデータを返す
async function getNotionData() {
  const url = `https://api.notion.com/v1/databases/${database_id}/query`;
  const headers = {
    'content-type': 'application/json; charset=UTF-8',
    Authorization: `Bearer ${token}`,
    'Notion-Version': '2021-08-16',
  };

  const filter = {
    filter: {
      and: [
        {
          property: 'Publish',
          checkbox: {
            equals: true,
          },
        },
        {
          property: 'LastEditedTime',
          last_edited_time: {
            past_week: {},
          },
        },
        {
          property: 'Category',
          multi_select: {
            contains: 'QA結果',
          },
        },
      ],
    },
  };
  const options = {
    method: 'post',
    headers,
    payload: JSON.stringify(filter),
  };

  const data = await UrlFetchApp.fetch(url, options);
  const parsedData = JSON.parse(data);
  return parsedData;
}

// Slackに投稿する関数
function postToSlack(jsonData) {
  const options = {
    'method' : 'post',
    'payload' : JSON.stringify(jsonData)
  };
  UrlFetchApp.fetch(postUrl, options);
}

// Spreadsheetに取得したデータのIDを追加する関数(NotionのページID)
function setSpreadSheet(id) {
  spreadsheet.appendRow([id]);
}

(2) 次に、「スクリプトプロパティ」 を設定します。
プロジェクトの設定から「スクリプトプロパティ」に、NOTION_DATABASE_IDNOTION_TOKENSLACK_WEBHOOKを設定します。

(3) 最後に、5分おきに実行されるように 「トリガー」 を設定します。

まとめ

NotionAPIとGoogle Apps Scriptを組み合わせることで、Notionで作成したページが自動的にSlackへ通知されるようになり、不具合発見時のエンジニアチームへの報告フローが改善されました。
フィルターやトリガーをうまく活用することで、さまざまなシーンで利用することも可能です。

IVRyでは、プロダクト開発だけではなく、積極的に運用改善なども行っています。
https://zenn.dev/ivry/articles/a05c5cd64e76d6

最後に、IVRyでは一緒にプロダクト開発を行うメンバーを募集しています!
ご興味を持った方は、ぜひお申し込みください。
https://meety.net/matches/rlyTkXmkXQCm

https://ivry-jp.notion.site/IVRy-e1d47e4a79ba4f9d8a891fc938e02271

IVRyテックブログ

Discussion