見出し画像

TaskChute for Notion に Google カレンダーからタスクを追加する方法

前回は、TaskChute for Notion の一般リリースを記念して、というか、便乗しまして、個人的な TCN との関わりについて、書かせてもらいましたが、

最後に予告した通り、今回は、TCN を使っている/使おうとしている人に向けて、Notion API や GAS の使い方を、紹介してみたいと思います。

まぁ、タイトル通りなのですが、Google カレンダーとの連携?については、結構、需要もあるのではないでしょうか?

と言っても、Google カレンダーから「今日の予定」を取得し、「今日のタスク」として Notion のデータベースへ追加する方法については、
すでに、以前、書いたことがあるので、今回の内容は、単に、これの「TCN 版」といった感じですね。

一応、上の記事を書いてから、割と時間も経っていますし、改めて、手順を振り返っておくとしましょう。

もちろん、TCN 特有の工程が、ちょっと増えているところもあります。

そこそこ難易度は高いと思うので、まずは、一通り全体を眺めてみてから、真似してやってみるかどうか、判断した方がいいかもしれません。

それでは、少し長いですが、興味があれば、お付き合いください。


Google カレンダーから今日の予定を取得する

まずは、Google カレンダーから「今日の予定」を取得する方法ですが、

Google の Apps Script(GAS)自体については、細かいことを説明しているとキリがないので、慣れてもらうしかないといったスタンスでいきます。

色々とできることは多いのですが、とりあえず、今、必要な部分だけ、なんとなく使えるようになれば、それで十分だと考えましょう。

JavaScript についても、同様です。

Google Calendar API サービスを使ってみる

ともかく、Google にログインして、https://script.google.com/home にアクセスし、「新しいプロジェクト」を作成してください。

そして、左のサイドバーにある「サービス」の「+」ボタンから、「Google Calendar API」を追加して、

「Google Calendar API」を追加する

例えば、以下のような JavaScript のコードを書くと、

function myFunction() {
  const calendarId = 'primary';
  const now = new Date();
  const max = new Date(new Date().setHours(23, 59, 0, 0));
  const events = Calendar.Events.list(calendarId, {
    timeMin: now.toISOString(),
    timeMax: max.toISOString(),
    singleEvents: true,
    orderBy: 'startTime'
  });
  if (!events.items || events.items.length === 0) {
    console.log('No events found.');
    return;
  }
  for (const event of events.items) {
    if (event.start.date) {
      const start = new Date(event.start.date);
      console.log('%s (%s)', event.summary, start.toLocaleDateString());
      continue;
    }
    const start = new Date(event.start.dateTime);
    console.log('%s (%s)', event.summary, start.toLocaleString());
  }
}

ログインしている Google アカウントの、自分の(デフォルトの)カレンダーから、「今日の予定」だけを、取得できるはずです。

取得する予定を、どのような条件で絞り込むかは、当然、自分のタスクシュートの運用方針に合わせて、変えてもらっても構いませんが、
ここでは、「timeMax」に「今日の23時59分」を指定しておきました。

それにより、プログラムを実行した時の「現在時刻」から「23時59分」までの「今日の予定」が、取得できるというわけですね。

ちなみに、上のコードは、次のページのサンプルを元にしています。

仮に、以下のような予定が、カレンダーに入っているとすると、

Google カレンダーに予定を入れる

上部のメニューバーにある「実行」ボタンを押せば、以下のような「実行ログ」が、出力されますでしょうか?

「実行ログ」を確認する

ひとまず、これで、Google カレンダーから、思った通りに「今日の予定」を取得できているかどうか、確認できるようになったのは、確かです。

少なくとも、上のコードの「events」変数の中に、必要なデータが入っているんだな、ということさえ、覚えておいてもらえれば、
下の方の「console.log()」を使った「実行ログ」の出力に関わる部分については、よく分かっていなくても、特に、問題ありません。

コードを編集したら、「実行」ボタンの左にある「プロジェクトを保存」ボタンか、「Command + S」などのショートカットを使って、
こまめに上書き保存しておくのも、お忘れなく。

アクセス権を承認する

ところで、「実行」ボタンを押すと、特定の関数、ここでは「myFunction()」に書かれた処理が、実行されるわけですが、

初めて動かす際には、次のように「承認」が求められると思います。

「権限を確認」する

基本的には、普通に進めていってもらえばいいのですが、途中、ちょっと分かりにくい部分があるので、補足しておくと、
次のような画面では、左下の「詳細」という部分をクリックし、

左下の「詳細」を開く

詳細が表示されたら、その一番下にあるリンクに移動することで、

「無題のプロジェクト(安全ではないページ)に移動」する

この「無題のプロジェクト」に対し、自分の Google アカウントの情報にアクセスすることを、許可してあげてください。

つまり、今回で言えば、Google カレンダーの情報へのアクセス権に関して、ちゃんと自分で書いたスクリプトで使うなら、承認してもいいのですが、
信頼できないプログラムに情報を取得されたりすると困るため、基本的にはセキュリティがかかっている感じですね。

管理ページ(https://myaccount.google.com/connections)から、アクセス権を削除することもできるので、念の為、覚えておきましょう。

Notion に今日のタスクを追加する

上では、Apps Script のページに、ログを出力しただけでしたが、
実際にやりたいのは、「今日の予定」を「今日のタスク」として、Notion のデータベースに追加してしまうことです。

そこで、次は、Notion API を使って、TCN のデータベースにページを追加する手順を、確認してみましょう。

内部インテグレーションを追加する

まず、https://www.notion.so/profile/integrations にアクセスして、「新しいインテグレーション」を追加してください。

「新しいインテグレーション」を追加する

例えば、インテグレーションの名前は、適当に「API」とし、
種類は「内部」で、もちろん、「関連ワークスペース」には、TCN が存在するワークスペースを選択しておく必要があります。

さらに、これは、オプションなのですが、一応、分かりやすいように、Notion のロゴも設定しておきました。

インテグレーション設定の画面へ移動したら、「内部インテグレーションシークレット」を表示して、コピーできることも確認しておきましょう。

「内部インテグレーションシークレット」を表示してコピーする

あとは、TCN のページを開いて、右上の「…」メニューの下の方にある「接続先」に、上で作成した「API」を追加しておけば、

「接続先」に「API」を追加する

ともかく、Notion API の利用設定は、完了です。

タスクデータベースの ID を調べる

また、API からデータベースにアクセスするためには、そのデータベースを識別する ID も必要なので、ついでに、調べておきましょう。

と言っても、TCN 右上の「データベース」のトグルリスト内にある「タスクDB」ページを開くなどして、
その URL から、該当する文字列を取得するだけですね。

ページの URL は、次のような形式になっているはずなので、

https://www.notion.so/{workspace_name}/{database_id}?v={view_id}

Working with databases - Adding pages to a database

ここから、{database_id} の部分を抜き出しておいてください。

ここまでで、Notion API を利用するための「内部インテグレーションシークレット」と、「タスクDB の ID」が、確保できました!

それでは、いよいよ、API を使って、Apps Script から「タスクDB」にタスクを追加してみましょう。

Notion API を使ってタスクを追加してみる

とりあえず、上で書いたコードを、例えば、以下のように、編集します。

function myFunction() {
  const calendarId = 'primary';
  const now = new Date();
  const max = new Date(new Date().setHours(23, 59, 0, 0));
  const events = Calendar.Events.list(calendarId, {
    timeMin: now.toISOString(),
    timeMax: max.toISOString(),
    singleEvents: true,
    orderBy: 'startTime'
  });
  if (!events.items || events.items.length === 0) {
    return;
  }
  for (const event of events.items) {
    const title = event.summary;
    const date = { "time_zone": null };
    if (event.start.date) {
      const start = new Date(event.start.date);
      date["start"] = start.toISOString().split('T')[0];
    } else {
      const start = new Date(new Date(event.start.dateTime).getTime() + (9 * 60 * 60 * 1000));
      const end = new Date(new Date(event.end.dateTime).getTime() + (9 * 60 * 60 * 1000));
      date["start"] = start.toISOString().replace('Z', '') + '+09:00';
      date["end"] = end.toISOString().replace('Z', '') + '+09:00';
    }
    const data = {
      "parent": { "type": "database_id", "database_id": "xxxxxxxxxx" },
      "properties": {
        "タスク名": { "type": "title", "title": [{ "type": "text", "text": { "content": title } }] },
        "日付": { "type": "date", "date": date },
        "集計DB": {
          "type": "relation",
          "relation": [
            { "id": "1214fdbd-c7b9-81dd-b4f0-d15ae72af79a" }
          ]
        },
        "カレンダー": { "type": "checkbox", "checkbox": true },
        "セクションデータベース": {
          "type": "relation",
          "relation": [
            { "id": "1214fdbd-c7b9-81b3-9a19-f97a71de31ca" },
            { "id": "1214fdbd-c7b9-81b2-a719-eba5847a5438" },
            { "id": "1214fdbd-c7b9-8170-84df-c20a4c8591f1" },
            { "id": "1214fdbd-c7b9-8115-b441-c3d9b853c53f" },
            { "id": "1214fdbd-c7b9-81f5-846f-e70d0f7ee913" },
            { "id": "1214fdbd-c7b9-8141-9857-db3f73b645bd" },
            { "id": "1214fdbd-c7b9-81b2-9438-fb7914b9d2f6" },
            { "id": "1214fdbd-c7b9-8133-b530-cadc64a95e55" }
          ]
        }
      }
    };
    const options = {
      'method': 'post',
      'headers': {
        'Authorization': 'Bearer ntn_XXXXXXXXXX',
        'Content-Type': 'application/json',
        'Notion-Version': '2022-06-28'
      },
      'payload': JSON.stringify(data)
    };
    UrlFetchApp.fetch('https://api.notion.com/v1/pages', options);
  }
}

書いてみると、思った以上に、大変なコードになってしまいましたが、これから少しずつ、説明していきますね。

とは言え、基本的には、「data」変数の内容さえ、理解できたなら、
それを「options」変数の「payload」に含め、「UrlFetchApp.fetch()」関数に渡して、Notion API を実行しているだけです。

コード中の「xxxxxxxxxx」と「ntn_XXXXXXXXXX」という文字列は、
上で確認した「タスクDB の ID」と「内部インテグレーションシークレット」に、それぞれ、置き換えておいてください。

ちなみに、通常、Notion API は、次のように実行する必要があるので、参考までに。

では、そろそろ、「data」変数の中の「properties」で指定する必要がある項目について、具体的に見ていきましょう。

いちばん分かりやすいのは「タスク名」で、「title」変数には、Google カレンダーから取得した予定のタイトルが入っています。

"タスク名": { "type": "title", "title": [{ "type": "text", "text": { "content": title } }] },

つまり、新しいタスクを追加する際には、このようにして、設定しておきたいプロパティの値を含んだ、適切な(JSON)形式のデータを作成し、
API を使って、Notion に POST(送信)する必要があるのです。

同様に、「日付」プロパティに渡すための「date」変数も、上の方で作成しているのですが、ここは、ちょっと難しいかもしれませんね。

const date = { "time_zone": null };
if (event.start.date) {
  const start = new Date(event.start.date);
  date["start"] = start.toISOString().split('T')[0];
} else {
  const start = new Date(new Date(event.start.dateTime).getTime() + (9 * 60 * 60 * 1000));
  const end = new Date(new Date(event.end.dateTime).getTime() + (9 * 60 * 60 * 1000));
  date["start"] = start.toISOString().replace('Z', '') + '+09:00';
  date["end"] = end.toISOString().replace('Z', '') + '+09:00';
}

まぁ、結局のところ、何をやっているのかと言えば、主に、日時の「フォーマット」を整えているだけで、
Google カレンダーから取得した予定が、「終日」の予定なら、「date」変数の中身は、例えば、次のようになり、

{
  "start": "2024-10-17",
  "time_zone": null
}

10時から12時までの予定なら、以下のようになるのですが、

{
  "start": "2024-10-17T10:00:00.000+09:00",
  "end": "2024-10-17T12:00:00.000+09:00",
  "time_zone": null
}

要するに、「日付」プロパティには、このような形式でデータを渡す必要があるから、頑張って整形している、というわけです。

簡単に補足するなら、日本時間に「toISOString()」を適用すると、
作ろうとしている表記には、かなり近づく代わりに、「9時間」巻き戻ってしまうので、あらかじめ「9時間」進めていたりするのですが、

細かいことは置いておいて、次の「集計DB」と「セクションデータベース」の話に移りましょうか。

厄介度合いで言えば、あるいは、こちらの方が、厄介かもしれません。

上の「data」変数の中でも、一際、目をひくデータとなっていますが、これらは、他のデータベースと関連する「リレーション」プロパティであり、
しかも、TCN で、普通にタスクを新規作成した際にも、特定の値が、デフォルトで入るようになっているため、
おそらくですが、Notion API からタスクを追加する際にも、ちゃんと値を入れておかないと、不具合が生じそうです。

例えば、Notion カレンダーからタスクを追加し、全プロパティを表示して確認してみると、次のようになっていました。

Notion カレンダーからタスクを追加して確認してみる

そこで、どうするのかと言うと、このタスクを API で取得し、中身を出力してみれば、どのようなデータになっているのか、具体的に分かりますよね。

試しに、上の「myFunction()」関数とは、別の関数「test()」を、以下のように作成し、実行してみるとしましょう。

function test() {
  const data = { "filter": { "property": "日付", "date": { "on_or_after": "2024-10-17" } } };
  const options = {
    'method': 'post',
    'headers': {
      'Authorization': 'Bearer ntn_XXXXXXXXXX',
      'Content-Type': 'application/json',
      'Notion-Version': '2022-06-28'
    },
    'payload': JSON.stringify(data)
  };
  const response = UrlFetchApp.fetch('https://api.notion.com/v1/databases/xxxxxxxxxx/query', options);
  const contents = JSON.parse(response.getContentText());
  console.log(JSON.stringify(contents.results[0].properties, null , "  "));
}

もちろん、関数の中の最初の行の日付「2024-10-17」は、少なくとも、なんらかのタスクが取得できる、適切なものに変更し、
コード中の「ntn_XXXXXXXXXX」や「xxxxxxxxxx」という文字列も、以前と同じように、置き換えてください。

ちなみに、「日付」による絞り込みについては、こちらに書かれています。

ともかく、この「test()」関数のいちばん下の行では、API で取得したデータの中から、
適当に、一つのタスクの内容(properties)だけを、ピックアップしてみているのですが、以下のように、出力されましたでしょうか?

「test()」関数を追加して実行してみる

メニューバーの「実行」ボタンを押す前に、その少し右にあるドロップダウンメニューで、「test」の方を選択しておくのも、お忘れなく。

また、初めて Notion API を使う際には、新たに外部サービスへ接続することになるので、再度、アクセス権の承認を求められるかもしれませんが、
Google カレンダーの時と同じように、許可しておいてください。

さて、ともあれ、これで、「実行ログ」の中をスクロールして確認すれば、
どのようなデータを「集計DB」や「セクションデータベース」プロパティに設定しておくと良いかも、分かると思うので、
それぞれ、以下のように、「data」変数内へ記入しておきましょう。

"集計DB": {
  "type": "relation",
  "relation": [
    { "id": "1214fdbd-c7b9-81dd-b4f0-d15ae72af79a" }
  ]
},
"セクションデータベース": {
  "type": "relation",
  "relation": [
    { "id": "1214fdbd-c7b9-81b3-9a19-f97a71de31ca" },
    { "id": "1214fdbd-c7b9-81b2-a719-eba5847a5438" },
    { "id": "1214fdbd-c7b9-8170-84df-c20a4c8591f1" },
    { "id": "1214fdbd-c7b9-8115-b441-c3d9b853c53f" },
    { "id": "1214fdbd-c7b9-81f5-846f-e70d0f7ee913" },
    { "id": "1214fdbd-c7b9-8141-9857-db3f73b645bd" },
    { "id": "1214fdbd-c7b9-81b2-9438-fb7914b9d2f6" },
    { "id": "1214fdbd-c7b9-8133-b530-cadc64a95e55" }
  ]
}

ただ、注意点として、この部分については、本記事のコードをコピペするのではなく、上で実行した、自分の「実行ログ」から、コピペしてください。

というのも、おそらく、これらの「id」の値は、TCN のテンプレートを複製した時点でランダムに決まるのか、人によって違うと思うんですよね。

最後に、「カレンダー」プロパティについては、必須ではないのですが、
一応、カレンダーから取得した予定なので、Notion 上のカレンダービューなどにも、表示させておきたいところかもしれません。

その場合には、次の行も必要となります。

"カレンダー": { "type": "checkbox", "checkbox": true },

それでは、ようやくですが、実際に「myFunction()」関数を実行して、TCN にタスクを追加してみましょう!

まず、Google カレンダーに、確認のための「終日の予定」と、
上で Notion カレンダーから追加したのとは別に、今日は、もう一つ「ミーティング」があると仮定し、予定を追加しておきます。

Google カレンダーに予定を追加する

果たして、この状態で「myFunction()」関数を実行すると、以下のように、タスクが追加されましたでしょうか?

Notion API で追加したタスクを確認する

アイコンのついていないタスクが、今、新たに追加されたタスクですね。

どうやら、終日の予定は、「セクションなし」ではなく、「0:00」からという扱いになってしまうようなので、そこは、ご注意ください。

また、Notion カレンダー上には、そもそも Google カレンダーの予定も表示しておくことが可能なので、
その場合は、次のようになっているかもしれません。

Notion カレンダー上でも確認する

青が Google カレンダーの予定で、オレンジの方が、TCN に存在するタスクの表示です。

ところで、実は、「data」変数の中に、次のような「icon」に関する行も追記しておけば、
API を使った場合でも、Notion や Notion カレンダー上からタスクを追加した時と同じようなアイコンを、タスクにつけておくことができます。

const data = {
  "parent": { "type": "database_id", "database_id": "xxxxxxxxxx" },
  "icon": { "type": "external", "external": { "url": "https://www.notion.so/icons/clipping_gray.svg" } },
  "properties": {
    ...
  }
}
アイコン付きのタスクも追加してみる

トリガーを追加して自動実行させる

ここまでで、Google カレンダーから取得したデータを Notion API を使って、「今日のタスク」として追加することができるようになったので、
最後に、このプログラムが、毎日、自動的に実行されるように、設定しておきましょう。

まず、ページの左端の、アイコンが並んでいるバーにカーソルを合わせ、その中から「トリガー」を選択して、
今まで開いていた「エディタ」画面から、移動してください。

そこで、右下にある「トリガーを追加」ボタンから、例えば、以下のような設定で、トリガーを作成しておくだけで、

「トリガーを追加」する

毎日、上で作った「myFunction()」関数を「午前0時〜1時」の間に自動実行し、その日の予定を Google カレンダーから取得して、
Notion に「今日のタスク」として、追加しておいてくれるというわけです。

普通、このような自動実行の仕組みを作るのは大変なのですが、これなら非常に簡単であり、これだけでも、GAS を使う価値があるかもしれません。

ただ、その代わり、用意されている選択肢の中から選ぶ必要はあるので、
実際に、どのような時刻設定で実行させるかは、ご自身の運用方針に合わせて、色々と検討してみてくださいね。

Google カレンダーのデータと「同期する」わけではなく、あくまでも、ある時刻に TCN へタスクを「追加する」という点にも、改めて、要注意です。

まとめ

さて、今回の記事は、今までにないくらい長くなってしまったので、ごく簡単にまとめさせてもらいますが、
結論として、やる気のある人は、是非、頑張ってください。笑

まぁ、あとは、今時、ChatGPT などに訊けば、なんでも答えてくれるし、
とりあえず、そもそも、どういった方法があるのかを知る上で、この記事が少しでも参考になったなら、幸いです。

ではまた。

いいなと思ったら応援しよう!