タスク管理データベースのワークスペースお引越し(7) : hkob の雑記録 (145)

はじめに

hkob の雑記録の第145回目は、タスク管理データベースのお引越しの7回目です。今日は Notion API を使った各種ユーティリティなどを新しいワークスペースに対応させていきます。

nrm_console.rb

ちょっとした時に NotionRubyMapping のテストをしたいときに実行するコンソールを修正します。こちらは token をアンバサダーワークスペースのものに変えただけです。

#!/usr/bin/env ruby

require "irb"
require "notion_ruby_mapping"
include NotionRubyMapping
NotionRubyMapping.configure { |c| c.token = ENV["AMBASSADOR_NOTION_API_KEY"] }

IRB.start

このあとで、自分の user_id が必要になるので、コンソール起動を確認するとともに取得しておきます。取得した user_id はあとで使います。後者はインテグレーショントークンの bot なので、前者の方の id を記録しておきます。

> nrm_console.rb
irb(main):001> UserObject.all.each { |u| p [u, u.name] }
[NotionRubyMapping::UserObject-fffd872b594c811b82180002b0392cd8, "hkob (private | Notion Ambassador)"]
[NotionRubyMapping::UserObject-9c1dfdfc452740459decf815c42a9efc, "Manage tasks"]
=> NotionRubyMapping::List-

icsToNotion.rb

最初は、カレンダーデータである ics から Notion タスクを作成する icsToNotion.rb の修正です。修正したのは、インテグレーショントークン、上で取得した user_id 、登録する Tasks の database_id、そして Date property の名称です。

#! /usr/bin/env ruby
require "notion_ruby_mapping"
include NotionRubyMapping
NotionRubyMapping.configure { |c| c.token = ENV["AMBASSADOR_NOTION_API_KEY"] }

# https://www.notion.so/1f70ce2a652080db9569e58b8eb84e98?v=1f70ce2a6520803898c6000cba4ffa66&pvs=4
db = Database.find "1f70ce2a652080db9569e58b8eb84e98"
user_id = "fffd872b594c811b82180002b0392cd8"

if ARGV.length == 0
  print "Usage: icsToNotion.rb ics-file"
  exit
else
  summary = nil
  start_date = nil
  end_date = nil
  previous = {}
  open(ARGV.first, "rt") do |f|
    while (line = f.gets)
      case line
      when /^BEGIN:VEVENT.*/
        start_date = nil
        end_date = nil
        summary = nil
      when /^DTSTART.*(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})/
        start_date = "#{$1}-#{$2}-#{$3}T#{$4}:#{$5}:00+0900"
      when /^DTEND.*(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})/
        end_date = "#{$1}-#{$2}-#{$3}T#{$4}:#{$5}:00+0900"
      when /^SUMMARY:(.*)/
        summary = $1
        summary_sub = summary.split("[").first
      when /^END:VEVENT/
        page = db.build_child_page
        pp = page.properties
        pp["Date"].start_date = start_date
        pp["Date"].end_date = end_date
        pp["Assignee"].people = user_id
        pp["Task name"] << summary
        blocked_by_id = previous[summary_sub]
        pp["blocked by"].relation = blocked_by_id if blocked_by_id
        page.save
        previous[summary_sub] = page.id

        print "#{summary}\t#{start_date} #{end_date}\n"
      end
    end
  end
end

実行結果は以下のとおりです。

> icsToNotion.rb データベース_授業スケジュール.ics
データベース(44)[6]   2025-05-26T08:40:00+0900 2025-05-26T10:10:00+0900
データベース(44)[7]   2025-06-02T08:40:00+0900 2025-06-02T10:10:00+0900
データベース(44)[8]   2025-06-16T08:40:00+0900 2025-06-16T10:10:00+0900
データベース(44)[9]   2025-06-23T08:40:00+0900 2025-06-23T10:10:00+0900
データベース(44)[10]  2025-06-30T08:40:00+0900 2025-06-30T10:10:00+0900
データベース(44)[11]  2025-07-07T08:40:00+0900 2025-07-07T10:10:00+0900
データベース(44)[12]  2025-07-14T08:40:00+0900 2025-07-14T10:10:00+0900
データベース(44)[13]  2025-07-21T08:40:00+0900 2025-07-21T10:10:00+0900
データベース(44)[14]  2025-07-28T08:40:00+0900 2025-07-28T10:10:00+0900
データベース(44)[15]  2025-08-04T08:40:00+0900 2025-08-04T10:10:00+0900

Tasks データベースにカレンダータスクが一括で入りました。

Tasks for lectures

この機能については、こちらで解説しています。

hkob.hatenablog.com

make_prepare_tasks.rb

次はこれらのタスクのための準備タスクを用意するスクリプトです。こちらはインテグレーショントークンだけでしたが、Assignee の設定を忘れていたので、上と同じように自分を担当者に設定することにしました。

#!/usr/bin/env ruby

require "notion_ruby_mapping"
include NotionRubyMapping

user_id = "fffd872b594c811b82180002b0392cd8"

NotionRubyMapping.configure { |c| c.token = ENV["AMBASSADOR_NOTION_API_KEY"] }

if ARGV.length != 1
  puts "Usage: make_prepare_tasks.rb <page_id>"
  exit
end
lecture_page = Page.find ARGV.first
pre_lecture_page = nil
db = lecture_page.parent

while lecture_page do
  title = lecture_page.title
  puts "Page: #{title}"
  db.create_child_page do |_, pp|
    pp["Task name"] << "#{title}のレジュメ作成"
    pp["blocking"].add_relation lecture_page.id
    pp["Assignee"].people = user_id
    pp["blocked by"].add_relation pre_lecture_page.id if pre_lecture_page
  end
  pre_lecture_page = lecture_page
  lecture_page_id = lecture_page.properties["blocking"].relation.map { |r| r["id"] }.first
  lecture_page = lecture_page_id && Page.find(lecture_page_id)
end

このスクリプトは依存関係の大元となる最初のページの page_id が必要です。NotionRubyMapping では URL でも代替できるので、最初のページのリンクを取得します。

obtain the first task of lectures

あとはスクリプトを実行するだけです。URL の場合 ? が含まれるので、クオートが必要です。

> make_prepare_tasks.rb "https://www.notion.so/44-6-1fa0ce2a65208177a599d7193acc21ea?pvs=4"
Page: データベース(44)[6]
Page: データベース(44)[7]
Page: データベース(44)[8]
Page: データベース(44)[9]
Page: データベース(44)[10]
Page: データベース(44)[11]
Page: データベース(44)[12]
Page: データベース(44)[13]
Page: データベース(44)[14]
Page: データベース(44)[15]

実行結果は以下のようになりました。

Tasks for making resumes

レジュメ作成は「いつかやる」タスクに相当しますが、後ろのカレンダータスクが依存されているので、Remain に猶予日数が表示されています。いつかやればいいタスクではありますが、期限はあるということがわかります。

Someday view

この機能については、こちらで解説しています。

hkob.hatenablog.com

Alfred の設定

Alfred の設定も同様です。Alfred の場合には、ユーザ固有の情報は Environment Variables にまとめているので、個々のスクリプトで修正する必要はありません。ただ、日付プロパティなどいくつかのプロパティ名を変更しているので、その部分は修正が必要です。

Environment Variables

すでに紹介済の Workflow については、こちらで紹介しますがまだ未紹介のものはここで修正しておき、後日解説します。

Create Task Workflow

Create Task Workflow は「いつかやる」タスクを生成するものです。紹介記事はこちらです。

hkob.hatenablog.com

こちらはスクプリトの修正は必要ありませんでした。

require "notion_ruby_mapping"
include NotionRubyMapping
NotionRubyMapping.configure { |c| c.token = ENV["NOTION_API_KEY"] }

text = ARGV[0]

sprint_db = Database.find ENV["SPRINT_DB_ID"]
ssp = sprint_db.properties["Sprint status"]
sprint = sprint_db.query_database(ssp.filter_equals "Current").first

db = Database.find ENV["TASK_DB_ID"]
page = db.create_child_page do |p, pp|
  pp["Sprint"].relation = sprint.id
  pp["Next Step"].checkbox = true
  pp["Task name"] << text
  pp["Assignee"].people = ENV["USER_ID"]
end
print page.url.gsub("^https://", "notion://")

Do it now Workflow

Do it now Workflow は今すぐやるタスクを作成するものです。概ね2分以内に実行できるタスクはこれで行います。実際にはもう少し長いタスクもこれで作成してしまうことも多いですが。紹介記事はこちらです。

hkob.hatenablog.com

こちらは Next step のプロパティ名だけでした。

require "notion_ruby_mapping"
include NotionRubyMapping
NotionRubyMapping.configure { |c| c.token = ENV["NOTION_API_KEY"] }

text = ARGV[0]

sprint_db = Database.find ENV["SPRINT_DB_ID"]
ssp = sprint_db.properties["Sprint status"]
sprint = sprint_db.query_database(ssp.filter_equals "Current").first

db = Database.find ENV["TASK_DB_ID"]
page = db.create_child_page do |p, pp|
  pp["Sprint"].relation = sprint.id
  pp["Next step"].checkbox = true
  pp["Task name"] << text
  pp["Assignee"].people = ENV["USER_ID"]
end
print page.url.gsub("^https://", "notion://")

Start the nearest task Workflow

Start the nearest task Workflow は最も近いカレンダー他タスクを開始するものです。紹介記事はこちらです。

hkob.hatenablog.com

この Workflow を実現するためにはそれぞれのタスクが現在時刻からどれだけ離れているかを計算する必要があります。今回は「Difference in minutes」というプロパティ名にしてみました。

Formula for Difference of minutes

数式は以下のようになっています。

prop("Date").dateBetween(now(), "minutes").abs()

このプロパティを使って、スクリプトは以下のように書き換えました。数式および Next step のプロパティ名を変えただけでなく、Status の Completed と Cancelled の両方に対応しています。

require "notion_ruby_mapping"
include NotionRubyMapping
NotionRubyMapping.configure { |c| c.token = ENV["NOTION_API_KEY"] }

db = Database.find ENV["TASK_DB_ID"]
dps = db.properties
sp = dps["Status"]
fp = dps["Difference in minutes"]
query = sp.filter_does_not_equal("Completed") \
          .and(sp.filter_does_not_equal("Cancelled")) \
          .ascending(fp)
query.page_size = 1
page = db.query_database(query).first
page.properties["Next step"].checkbox = true
page.save
print page.url.gsub("^https://", "notion://")

おわりに

今回は、Tasks に関する Notion API を使ったコマンドおよび Alfred の Workflow を修正しました。明日は maps のデータベースを使って、タスク一覧の定時メール送信を解説します。

hkob.notion.site