見出し画像

Notion投稿をいい感じにSlackへ通知するGoogle Apps Scriptを公開しました

こんにちは、マーティン(@mrtn)です。みなさんNotion使っていますか?
副業で広報を担当している株式会社トクイテンではコミュニケーションツールはSlack、ドキュメントツールはNotionを日々使っています。

今回、Notion投稿をいい感じにSlackへ通知するGoogle Apps Scriptを作ってソースを公開しました。ぜひ使ってください!

NotionのSlack通知機能は体験があまりよくない

私にとってNotionは、手によく馴染み、書き心地のいいドキュメントツールです。ひとつだけ不満をあげるとすれば「Slackへの通知機能」です。

公式が用意してくれていて、ノーコードで簡単に設定できるのはとても良いですが、通知のタイミングや頻度、そして内容についてはもう少しなんとかならないものかと思っています。
この画像はNotionのSlack通知を設定しているチャンネルです。

ページを作成したタイミングで通知されてしまう(正確には数分程度ラグはある)ため、書いている途中に他の人が読みに来てしまう。書くたびに通知されるためチャンネルが通知だらけになってしまう。など、体験があまりよくないです。

Notion投稿をいい感じにSlackへ通知するGoogle Apps Scriptを作りました

先日、トクイテンの社内コミュニケーションを活発にするためNoitonで社内ブログを始めました。
Notionで書いたブログは #general に通知されるようにしたい。書き終わったタイミングに自動で、かつ、誰が書いたかわかるような書式で通知する仕組みが欲しい。

無いものは作るしかないのでNotion APIとGoogle Apps Scriptを使ってつくりました。ちなみに私は広報です。

使い方と使用イメージ

Notionを書き終わったらプロパティ「Publish」に☑をすると、5分以内に予め設定したSlackチャンネルに通知されます。

※通知のデザインはクッ社のGroupad to Slack投稿をトレスしています。

通知内容は、Notionから投稿者名とアイコン画像を所得して反映してます。
人感があって良いですね。

仕様

  • 任意のNotionデータベースの投稿を、任意のSlackチャンネルへ通知する

    1. Notionデータベースから、Property:Publishにチェックがついているかつ、Property:LastEditedTimeが過去1週間以内のページを取得する

    2. スプレッドシートから過去に通知されたnotion_idを取得して重複チェックする

    3. 重複してなかったらSlackへ通知する

      • Slack通知はnotionに登録された投稿者名、アイコン画像、タイトルを反映させる

    4. 投稿したnotion_idをスプレッドシートへ書き込む

  • Google Apps Scriptのタイマートリガーで5分ごとに実行する

ざっくりこんな仕様になります。

準備するもの

  1. Notion

  2. Slack

  3. スプレッドシート

  4. Google Apps Script

1.Notion

①投稿元のNotionデータベースに必要なプロパティを作成する
プロパティ:LastEditedTime(プロパティタイプ:Last Edited Time)
プロパティ:Publish(プロパティタイプ:Checkbox)

②integration を作成してNotion APIのトークンを取得する
My integrations から新しいintegrationを作成(Notionの管理者権限が必要です)してください。設定はこちらを参考に👇

作成するとトークンが発行されます。

③投稿元のNotionデータベースに作成したintegrationをinviteする
左上のShareをタップしてinviteから作成したintegrationを選んでください。

↑ここです

2.Slack

①通知するSlackチャンネルのWebhook URLを取得する

以下を参考にしてください

3.スプレッドシート

過去に通知したnotion_idを記録しておき、重複通知を避けるためのスプレッドシートを用意してください。シート名は「list」にします。

4.Google Apps Script

最後にGoogle Apps Scriptを用意します。以下のソースコードをコピペしつつ、最初の11行に自分の情報を設定したら準備は完了です。テストで実行してちゃんと動いたらタイマートリガー5分を設定して実際に稼働させてみてください。
(テスト実行の際は、通知チャンネルを自分のDMしておくと良いです。)

// 重複idチェック用のスプレッドシートのIDとシート名を入力
const spreadsheet = SpreadsheetApp.openById(“スプレッドシートのid).getSheetByName(“list”);
// 通知するSlackチャンネルのWebhook URLを入力
const postUrl = "Webhook URL";
// 投稿元のNotionデータベースIDとトークンを入力
const database_id = “データベースID”;
const token = “トークン”;
// Slack通知メッセージの[Blog]とアイコンを変更する場合は以下を変更してください
const messageCategory = "Blog";
const messageIcon = "green_book";

function main(){
  var data = getNotionData();
  var past_data = getSpreadSheet();

  for (i=0; i<data.results.length; i++){
    var record = data.results[i];
  
    //投稿の重複チェック
    var duplicate = 0;    
    for(j=0; j<past_data.length; j++){
      if(record.id == past_data[j]){
        duplicate = duplicate+1;
        continue;
      }
    }

    //重複してなければSlackへ投稿
    if(duplicate == 0){
      var title = record.properties.Name.title[0].plain_text;
      var url = record.url;
      var user = record.properties["Created by"].created_by.name;
      var image = record.properties["Created by"].created_by.avatar_url;
      var notion_id = [record.id]
      var jsonData = {
        "username" : "Notion by " + user,
        "icon_url": image,
        "text" : "*[" + messageCategory + "]*:" + messageIcon + ":<" + url + "|" + title + ">"
      }
      postToSlack(jsonData);
      setSpreadSheet(record.id);
    }

  }
}

function getSpreadSheet(){
  var last_row = spreadsheet.getLastRow();
  if(last_row > 0) {
    var value = spreadsheet.getRange(1, 1, last_row, 1).getValues();
  } else {
    var value = "[[dummy_id]]";
  }
  return value;
}


//Notionデータを読み込む
function getNotionData() {
  const url = "https://api.notion.com/v1/databases/" + database_id + "/query";
  let headers = {
    "content-type" : "application/json; charset=UTF-8",
    "Authorization": "Bearer " + token,
    "Notion-Version": "2021-08-16",
  }

  //PublishがチェックされているかつLastEditedTimeが過去1週間以内の投稿を取得
  let filter = {
    "filter" : {
      "and" : [
        {
          "property" : "Publish",
          "checkbox" : {
            "equals" : true
          }
        },
        {
          "property" : "LastEditedTime",
          "last_edited_time" : {
            "past_week" : {}
          }
        },
      ]
    }
  }
  let options ={
    method : "post",
    headers : headers,
    payload : JSON.stringify(filter)
  }
  let data = UrlFetchApp.fetch(url, options);
  data = JSON.parse(data);
 return data;
}

//Slackへ通知する
function postToSlack(jsonData) {
  var payload = JSON.stringify(jsonData);
  var options = {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : payload
  };
  UrlFetchApp.fetch(postUrl, options);
}

//投稿したnotion_idをスプレッドシートへ書き込む
function setSpreadSheet(notion_id){
  var last_row = spreadsheet.getLastRow();
  spreadsheet.getRange(last_row+1,1).setValue(notion_id);
}

今後の改善について

現在は、1つのNotionデータベース、1つのSlackチャンネルしか対応していません。社内ブログだけでなく日報などもSlack通知したいという要望があるため、マルチデータベース、マルチチャンネルに対応するのはそのうちやりたいです。やったらまたお知らせします。

この記事が気に入ったらサポートをしてみませんか?