はじめに
Notion API のパブリックベータが使えるようになりました。そしたら、以前作ったカレンダーデータのデータベースへの一括登録方法 (ics → Excel → Notion): Notion 解説(14) - hkob’s blogを改良することで、直接 ics から Notion に一括登録できます。ということで、早速作りました。
準備
Integrations の登録
Setting & Members の下の方にIntegrations が用意されています。開くとこんな画面になります。すでに私は登録しているので、「Input tasks」というのが出ています。
Integration を登録するには、下にある「Develop your own integrations」のページからアクセスできます。
リンクに飛ぶとこんな感じになっています。先ほどの Input tasks が登録されています。
登録するべき情報はタスク名、アイコンイメージとどの Notion に接続するかだけです。特に問題ないと思います。
作成するとこんな画面が表示されます。「Internal Inregration Token」の Show をクリックするとかなり長いトークンが出てくるので、これをコピーして取っておきます。
Notion の Share の設定
実際に登録したいデータベースの Share を設定します。私の場合にはタスクというテーブルなので、それを開きます。Linked Database になっている「↗︎タスク」の部分をクリックすればよいです。
先ほど作成した Input tasks の Integration を Invite します。Invite するとこんな感じで表示されます。
さらに、Database の ID を取得します。上の画面の「Copy link」をクリックして適当なエディタに貼り付けます。リンク名のうち、https://www.notion.so/
の後ろから始まり、?v
までにある16進数(0-9までの数字とa-fまでの文字で書かれた文字列)をコピーして取っておきます。
ics2notion.rb の作成
Rubist なので、ics2tsv.rb を下に ics2notion.rb というプログラムを作成します。properties の下の「タスク名」と「日付」の部分は自分のテーブルの属性名に読み替えてください。ics2tsv で print していた部分を API 呼び出しにしただけです。API は Notion API のサンプルからいただきました。少しハマったところというと、日付のところは何もしないと GMT になってしまったので、後ろに「+09:00」を足した部分くらいですね。アクセス制限は1秒あたり3アクセスくらいらしいんですが、念のため1秒に1件の登録にしています。
#! /usr/bin/env ruby require "net/http" require "uri" require "json" require "date" MY_NOTION_TOKEN="この部分にIntegration Token を書きます。" DATABASE_ID="この部分にDatabase ID を書きます" def send_notion(title, datetime) uri = URI.parse("https://api.notion.com/v1/pages") request = Net::HTTP::Post.new(uri) request.content_type = "application/json" request["Authorization"] = "Bearer #{MY_NOTION_TOKEN}" request["Notion-Version"] = "2021-05-13" request.body = JSON.dump({ "parent" => { "database_id" => "#{DATABASE_ID}" }, "properties" => { "タスク名" => { "title" => [ { "text" => { "content" => "#{title}" } } ] }, "日付" => { "type" => "date", "date" => { "start" => "#{datetime}" } } } }) # デバッグ用動いたら消す # p request.body response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http| http.request(request) end code = response.code print "#{title}\t#{datetime}...#{code}\n" unless code == "200" # エラーの時だけエラーを表示する print "Error!\n#{response.body}\n" end # API 制限のため、あまり早く実行しない(最大3access/1秒らしい) sleep 1 end if ARGV.length == 0 print "Usage: ics2notion ics-file" exit else datetime = nil summary = nil summary_hash = Hash.new 0 print "タスク名\t日付\n" open(ARGV.first, "rt") do |f| while line = f.gets case line when /^BEGIN:VEVENT.*/ start = nil summary = nil when /^DTSTART.*(\d{4})(\d{2})(\d{2})T(\d{2})(\d{2})/ datetime = "#{$1}-#{$2}-#{$3} #{$4}:#{$5}+09:00" when /^SUMMARY:(.*)/ summary = $1 summary_hash[$1] += 1 when /^END:VEVENT/ num = " #{summary_hash[summary]}" send_notion("#{summary}#{num == ' 1' ? '' : num}", datetime) end end end end
実行例
サンプルで今日の16:40 に一つイベントを作成した ics を用意しました。「デバッグ表示あり」の部分にコメントを付ける前の結果です。動いているかどうか心配だったので、request データも表示されています。ちゃんと登録されているか見るために、ics2tsv.rb と同じタブ区切り表示は残しています。また、表示の後ろにレスポンスコードを表示しています。200 となっていれば成功で何も表示しませんが、それ以外の数字の時には response.body もエラー表示するようにしています。
./ics2notion.rb a.ics タスク名 日付 "{\"parent\":{\"database_id\":\"2395e3ffb55e4a8abc1ba426243776e3\"},\"properties\":{\"タスク名\":{\"title\":[{\"text\":{\"content\":\"テストイベント\"}}]},\"日付\":{\"type\":\"date\",\"date\":{\"start\":\"2021-05-14 16:40+09:00\"}}}}" テストイベント 2021-05-14 16:40+09:00...200
Notion 見てみるとちゃんと入っています。素晴らしいですね。
おわりに
API ができるといろいろと夢が広がりますね。もう少し何ができるかを考えていきます。