見出し画像

Notionの繰り返しタスクをGASで自動追加する

今年に入ってNotionを使い始めたのですが、同じタスクを毎週手動で登録するのが面倒に感じてきました。

そんなわけで自動化していきます。

ボタン配置すればいいじゃんとの意見もあるかと思いますが、なまけものな私はボタン押すのも面倒なのです。


準備するもの

今回利用するのはNotionAPIとGoogle Apps Script(GAS)です。

まずは必要なものを準備しましていきましょう。

  • NotionAPIインテグレーショントークン

  • 追加するタスクの元となるタスク情報データベースのID *以後「タスク取得元DB」

  • タスクを追加するデータベースのID *以後「タスク追加先DB」

  • Googleアカウント

この4つが必要になります。


NotionAPI

NotionAPIインテグレーショントークンについてはこちら


データベースID

データベースIDは対象のデータベースをフルページで開いたときのURLから確認できます。
「ドメイン名/」 と 「?v=」の間にある文字列がデータベースIDです。

例: https://www.notion.so/domain/kokono32ketagadatabeseIDninaruyo?v=konohenhaViewIDninaruyo

上記の例では「kokono32ketagadatabeseIDninaruyo」がデータベースIDです。


Googleアカウント

Googleアカウントについては、、、みんな持ってるでしょうし省きます。


自動化作業

タスクを自動追加する流れ

  • タスク元DBからタスク情報を取得する

  • タスク情報の「曜日」を元に、実行された日付から1週間以内の登録する日付を決める

  • タスク追加先DBに1週間分のタスクを追加する

  • 1週間おきに実行する

こんな感じで行きます。


データベースの設定

タスク取得元DBはプロパティに
・タイトル「名前」
・セレクト「曜日」
・テキスト「時間」
・マルチセレクト「タグ」
を持ちます。セレクト「曜日」にはあらかじめ月曜日~金曜日まで作成しておきます。

タスク追加先DBはプロパティに
・タイトル「名前」
・チェックボックス「完了」
・マルチセレクト「タグ」
・日付「日付」
を持ちます。

データベースとNotionAPIインテグレーショントークンを接続します。
Notionから対象のデータベースをフルページで開き、「・・・」→「コネクト:接続先」→ 用意したNotionAPIインテグレーショントークンを選択しましょう。
これを両方のデータベースへ行います。

自身で作成したNotionAPIインテグレーショントークンを選択する

「はい」を選択すれば接続は完了です。


GAS(Google Apps Script)の設定

それでは、Google Apps Script で実際に作成していきます。以下のURLから「新しいプロジェクト」を選択します。

プロジェクトの名前を「無題のプロジェクト」から好きな名前に変更しましょう。

「プロジェクトの設定」を開きます。
スクリプトプロパティから「スクリプトプロパティの追加」を選択します。

プロパティ名とプロパティ値をそれぞれ設定していきます。
プロパティ名は自分がわかりやすいもので大丈夫です。コードをコピーして使いたい場合は、それぞれ
NOTION_API_KEY
TASK_GET_DB_ID
TASK_SET_DB_ID
としておくと楽です。
(画像内の「NOTION_API_EKY」は誤りです。EKYではなくKEYです。スペルミスです。許してください。)

入力したら「スクリプトプロパティを保存」を押して保存してください。


コードと実行

エディタを開き、コードを書いていきます。

コードはこちらです。
今回の機能そのものとは全く関係ない話ですが、ChatGPTすごいですね。
適当にブロック単位で機能を出力させて、組み立てたら大体できてしまいました。
NotionAPIの使い方も全然しらず、リファレンスも見てないのにChatGPTに「〇〇するサンプルコード出して」聞けばそれっぽいのが出てきます。エラーが出てもエラーログを丸投げすれば、なんでエラーになっているのか、どうすれば解決するのかを教えてくれます。なまけものの味方です。
注意点も聞けば教えてくれますしね。
おかげで自分の頭はほとんど使ってません。なのでエラー処理だのなんだのは全然やってません。

// NotionAPIキー
const NOTION_API = PropertiesService.getScriptProperties().getProperty("NOTION_API_KEY");
// NotionDBのID
const TASK_GET_DB = PropertiesService.getScriptProperties().getProperty("TASK_GET_DB_ID");
const TASK_SET_DB = PropertiesService.getScriptProperties().getProperty("TASK_SET_DB_ID");

function myFunction() {

  // 現在の日付を取得
  var nowDate = new Date();

  // タスク元DBからレコードを取得
  var results = getTaskByDB();

  if(results.length > 0){
    
    results.forEach(function(page) {
      var name = page.properties["名前"]?.title[0]?.plain_text || "未設定";
      var day = page.properties["曜日"]?.select?.name || "未設定";
      var time = page.properties["時間"]?.rich_text[0]?.plain_text || "未設定";
      var tags = (page.properties["タグ"]?.multi_select || []).map(function(tag) {
        return tag.name;
      }).join(",");

      // 名前、曜日どちらかが未設定なら何もしない
      if (name === "未設定" || day === "未設定") {
        // なにもしない
      }else{ 
        // タスク追加先DBへ登録
        addTask(name,day,time,tags,nowDate);
      }

    });

  } else {
    // タスク元DBの内容がなければ何もせず終了する 
    return;
  }
  
}

function addTask(name,day,time,tags, nowDate){

  // 日付
  var addDate = null;

  // 1週間先までの間で、該当する曜日の日付を取得する
  var days = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"];
  for (var i = 0; i <= 6; i++) {
    // 現在の日付にi日を加える
    var checkDate = new Date(nowDate.getTime());
    checkDate.setDate(nowDate.getDate() + i);

    // 曜日を取得
    var dayOfWeek = days[checkDate.getDay()];

    // 指定された曜日と一致する場合
    if (day === dayOfWeek) {
      addDate = checkDate;
      break;
    }
  }

  // timeに時刻データがある場合には日付に追加する
  if(isTimeFormat(time)){
    var parts = time.split(":");
    var hours = parseInt(parts[0], 10);
    var minutes = parseInt(parts[1], 10);
    addDate.setHours(hours, minutes, 0, 0); // 秒とミリ秒は0にセット
    // ISO 8601形式でJST(日本標準時)を表現
    addDate = Utilities.formatDate(addDate, "Asia/Tokyo", "yyyy-MM-dd'T'HH:mm:ssXXX");
  }else{
    addDate = Utilities.formatDate(addDate,"Asia/Tokyo", "yyyy-MM-dd");
  }


  // DBへ登録用のデータ作成
  var url = "https://api.notion.com/v1/pages";
  var headers = {
    "Authorization": "Bearer " + NOTION_API,
    "Content-Type": "application/json",
    "Notion-Version": "2022-06-28"
  };

  var properties = {
    "名前": { 
      "title": [
        { "text": { "content": name } }
      ]
    },
    "日付": {
      "date": {
        "start": addDate
      }
    }
  };
  
  // タグリストが空でない場合のみ、タグプロパティを追加
  if (tags.length > 0) {
    properties["タグ"] = { "multi_select": tags.split(",").map(tag => ({ "name": tag })) };
  }

  var payload = {
    "parent": { "database_id": TASK_SET_DB },
    "properties": properties
  };

  var options = {
    "method" : "post",
    "headers": headers,
    "payload": JSON.stringify(payload)
  };

  // DBへ登録
  var response = UrlFetchApp.fetch(url, options);
  var json = JSON.parse(response.getContentText());

  //Logger.log(json);

}

// タスク元DBからレコードを取得
function getTaskByDB(){

  var url = "https://api.notion.com/v1/databases/" + TASK_GET_DB + "/query";
  var headers = {
    "Authorization": "Bearer " + NOTION_API,
    "Notion-Version": "2022-06-28"
  };
  var options = {
    "method" : "post",
    "headers": headers
  };

  var response = UrlFetchApp.fetch(url, options);
  var json = JSON.parse(response.getContentText());
  
  return json.results;
}

// 文字列が時刻のフォーマットになっているかを判定する
function isTimeFormat(str) {
  // 文字列の形式がh:mmまたはhh:mmであるかチェック
  var timePattern = /^\d{1,2}:\d{2}$/;

  // 形式に一致するかどうかをチェック
  if (timePattern.test(str)) {
    // 時間と分を分離
    var parts = str.split(":");
    var hours = parseInt(parts[0], 10);
    var minutes = parseInt(parts[1], 10);

    // 時間が00〜23、分が00〜59の範囲内であるかチェック
    if (hours >= 0 && hours <= 23 && minutes >= 0 && minutes <= 59) {
      return true;
    }
  }
  return false;
}

コードを貼り付けたら「Ctrl + S」で保存しましょう。
保存したら「▷実行」を押します。最初は承認を求められますので、下の画像のように押していきましょう。

アカウントを選択します。

許可をしたらプログラムが実行されます。

エラーが出る場合はNotionインテグレーショントークンの値や、データベースIDをもう一度確認してください。

エラー時に見るべきところ

1.コード

// NotionAPIキー
const NOTION_API = PropertiesService.getScriptProperties().getProperty("NOTION_API_KEY");
// NotionDBのID
const TASK_GET_DB = PropertiesService.getScriptProperties().getProperty("TASK_GET_DB_ID");
const TASK_SET_DB = PropertiesService.getScriptProperties().getProperty("TASK_SET_DB_ID");

最初の5行の部分
getPropertyのカッコの中は「スクリプトプロパティ」で設定した値になっているか  *スペルミスとかよくあるよ!

2.NotionのデータベースページからNotionインテグレーショントークンの接続はしたか
3.データベースIDに誤りはないか
4.Notionインテグレーショントークンに誤りはないか
5.データベース内のプロパティの名前や型(テキストやセレクトなど)は、この記事内「データベースの設定」で提示した内容と一致しているか

問題なく実行できていればタスク追加先DBにタスク取得元DBの内容が反映されているはずです。

タスク取得元DBの内容が以下の画像のようになっていれば

タスク追加テストDBにこんな感じに登録されます。

このプログラムは、実行された日から1週間分の固定タスクを登録します。
画像の場合は2024/04/09に実行したため、2024/04/15までの1週間分のタスクが登録されました。
時間が設定されているタスクは時間まで指定されているのがわかるかと思います。


定期実行の設定

さて、ここまで出来たらあとは1週間ごとに定期実行されるように設定するだけです。
Google Apps Scriptへ戻り「トリガー」へ移動します。

右下に「+ トリガーを追加」があるはずなので押します。

「時間ベースのタイマー」を「週ベースのタイマー」に変更します。
「曜日を選択」でお好きな曜日を設定します。時刻もお好きにどうぞ。
設定できたら「保存」を押します。設定した時間になると起動するようになりました。
おすすめは「日曜日」「0~1時」です。
土曜日夜寝て、日曜の朝起きたら固定タスクが出来上がってることでしょう。

これで完了です。
お疲れさまでした。

最後に

いまさらですが、使い方は以下の通りです。
・[タスク取得元テスト.db]に毎週の固定タスクを曜日ごとに登録する。
・GASが起動した日から一週間分が[タスク取得元テスト.db]から[タスク追加テスト.db]に登録される。
・名前、曜日が未入力のものは登録されない。
・時間は半角で「hh:mm」または「h:mm」の形式で入れる。形式を無視している場合は時刻は登録されない。「23:59」「6:15」などはOK。「午前10時」「PM9:00」などはNG。
・タグはそのまま登録される。追加先でのタグ色は指定してないので色まで一緒にしたいなら手動でどうぞ。

いちいち手動で登録する手間から解放されて、充実したなまけものライフを!!

作成してから気が付いたのですが、データベーステンプレートから繰り返し機能がありましたね。ナマケモノなのにうまく怠けられませんでした。

一応このプログラムにもメリットとして「なんの繰り返しタスクが登録されるのか一目でわかる」があるので、「無駄ではなかった」と思うことにします。

*このプログラムは個人的に使うためにてきとーに組んだプログラムです。テストも細かくはしていません。利用する際には自己責任でお願いします。このプログラムを利用することによって不利益を被ったとしても責任は取りません。


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