タスク作成時にカレンダーにも同時設定 : Notion 解説(33)

(後日追加) ここで説明している Notion workflow はこちらで配布しています。 github.com

1. はじめに

一つ前の記事でカレンダーと Notion タスクを同期する記事を書きました。 hkob.hatenablog.com

ただ、Alfred から「ac」コマンドでカレンダー登録した時に、Notion タスクが二重化してしまう問題がまれに発生してしまいました。また、「ac」コマンドでは「an」コマンドと異なり、プロジェクトをつけることができません。そこで、「anc」という Notion タスクとカレンダーを同時に設定するコマンドを追加しました。この時、カレンダーの description に id を設定することで、カレンダーと Notion タスクが同期できるようになります。内容は前回の記事とあまり変わらないので、変更点だけ説明しようと思います。すでに Workflow のバージョンは 1.3 にあげているので、すでにインストール済の方のものは自動的にバージョンアップしていると思います。

2. workflow の外観

今回作成する anc は an の処理後にカレンダーも登録する形にしています。内容がほぼ一緒なので、Run Script などはすべて共通化し、Arg and Vars で処理を切り分けることにしました。

f:id:hkob:20210717140206p:plain
anc を追加した workflow

途中の 4 つの Arg and Vars は以下のようなパラメータ設定になっています。

属性 an の上 an の下 anc の上 anc の下
calendar false false true true
input {query} {query} {query} {query}
reload true なし なし true

また、この Arg and Vars で query を input 変数に入れているので、ac からの query も input に入れるように変更しました。

属性 ac
calendar true
input {query}

3. Run Script の修正

3.1 Add Notion 側

もともと an は終了時間を設定していなかったのですが、カレンダーと同じ処理になるように終了時間も設定できるように変更しました。また、最後に id を次の処理に渡すようにしました。

require './notion.rb'

project_id = ARGV[0]

date = nil
end_time = nil
start_time = nil
words = ENV["input"].split " "

end_time = (words.pop + MY_TZ) if words[-1] =~ /\d+:\d+/
if end_time
  start_time = (words.pop + MY_TZ) if words[-1] =~ /\d+:\d+/
  unless start_time
    start_time = end_time
    end_time = nil
  end
end

begin
  date = Date.parse words[-1]
  # If the above Date.parse was success, the last parameter will remove.
  words.pop
rescue
end
date ||= Date.today

datetime = {start: [date, start_time].compact.join(" ")}
datetime[:end] = [date, end_time].join(" ") if end_time
summary = words.join " "
result = create_task(summary, datetime, project_id)
print result["id"]

3.2 Add Calendar 側

「an」コマンドの場合にはcalendarが false になっているので、カレンダーは登録しないようにしています。true の場合にはこれまで通り、カレンダー登録をおこないます。ただし、キーワードの入力を input からに変更しています。また、「anc」から実行している場合には、前の処理で「id」を受け渡されているので、この id をカレンダーの description に記録します。これにより前の記事の Notion タスクとの同期を実現しています。

ObjC.import("stdlib");

function run(argv) {
  if ($.getenv("calendar") == "true") {
    createCalendar(argv)
  }
}

function createCalendar(task_id) {
  let query = $.getenv("input")
  let Calendar = Application("Calendar")
  let cal = $.getenv("NOTION_CALENDAR")
  console.log(cal)

  let notionCal = Calendar.calendars["Notion"]
  var endTimeStr = null
  var startTimeStr = null

  // query を分割
  let words = query.split(" ")
  // 最後のパラメータが時間かどうか
  var timeStr = words.slice(-1)[0]
  if (timeStr && timeStr.match("[0-9]+:[0-9]+")) {
    endTimeStr = words.pop()
  }
  // 時間が設定されていたら開始時間もあるかどうか調べる
  if (endTimeStr) {
    timeStr = words.slice(-1)[0]
    if (timeStr && timeStr.match("[0-9]+:[0-9]+")) {
      startTimeStr = words.pop()
    } else {
      startTimeStr = endTimeStr
      endTimeStr = null
    }
  }
  var dateStr = words.slice(-1)[0]
  // 日付が設定されていなければ今日にする
  if (dateStr.match("^[0-9]+/[0-9]+$")) {
    dateStr = new Date().getFullYear() + "/" + words.pop()
  } else if (dateStr.match("^[0-9]+/[0-9]+/[0-9]+/$")) {
    dateStr = words.pop()
  } else {
    let timeNow = new Date()
    dateStr = timeNow.getFullYear() + "/" + (timeNow.getMonth() + 1) + "/" + timeNow.getDate()
  }
  // 日付・時間を除いた文字列から summary を作成
  event = {summary: words.join(" ")}
  if (task_id != "") {
    event["description"] = "id:" + task_id
  }
  if (startTimeStr) {
    // 開始時間が設定されていたら時間を含めた日付を設定
    let startTime = new Date(dateStr + " " + startTimeStr)
    var endTime
    if (endTimeStr) {
      // 終了時間が設定されていたら時間を含めた日付を設定
      endTime = new Date(dateStr + " " + endTimeStr)
    } else {
      // 終了時間が設定されていなかったら開始時間の1時間後を設定
      endTime = new Date(dateStr + " " + startTimeStr)
      endTime.setHours(endTime.getHours()+1)
    }
    event["startDate"] = startTime
    event["endDate"] = endTime
    let newEvent = Calendar.Event(event)
    notionCal.events.push(newEvent)
  } else {
    let date = new Date(dateStr)
    event["startDate"] = date
    event["endDate"] = date
    event["alldayEvent"] = true
    let newEvent = Calendar.Event(event)
    notionCal.events.push(newEvent)
  }
}

終わりに

anc コマンドではすでに Notion タスクが作成済みなため、GAS 側でカレンダートリガーがかかっても、Notion タスクが重複することはなくなりました。内容の更新処理は動きますが、同じ内容なので見た目は何も変わりません。これで、カレンダー作成時に Notion タスクが重複する問題を解決することができました。また、an コマンドと同じでプロジェクトも自動的に設定できて一石二鳥になりました。


はてなブログに書いた Notion 記事一覧