Notion AI によるプロパティ一括置換(リベンジ) : hkob の雑記録 (406)

はじめに

hkob の雑記録の第406回目(通算1日目)は、先日失敗した音名の英語変換に再挑戦してみます。通算数値は今日から開始します。

前回の失敗を受けて

前回の失敗を受けて、アンダーラインの中に入っている文字を先にマーキング処理してみることにしました。

Notion AI への指示

うまくいっているようです。

アンダーラインのみ処理

やはり何度も中断するものの続きを実行しているうちに全てのページが出来上がったと連絡がありました。このスクリーンショットで完成というつもりでよくみると、別のアノテーションが付いているものがアンダーラインの - がついていませんでした。やはり中断が何度かあると最初の指示を忘れてしまうようです。

全ページ完了後

結局いつもの API に

結局、AI に頼るのではなくいつもの自分らしく API でやることにしました。データ構造を確認しましたが、アノテーションごとに TextObject が分割されるので、underline の状態で tr の引数を変えるだけですみそうです。

src.text_objects[0..1]
=>
[#<NotionRubyMapping::TextObject:0x00000001244638e8
  @options=
   {"plain_text" => "",
    "bold" => false,
    "italic" => false,
    "strikethrough" => false,
    "underline" => true,
    "code" => false,
    "color" => "default",
    "href" => nil},
  @text="",
  @type="text",
  @will_update=false>,
 #<NotionRubyMapping::TextObject:0x00000001244634d8
  @options=
   {"plain_text" => "そみふぁ そそそ",
    "bold" => false,
    "italic" => false,
    "strikethrough" => false,
    "underline" => true,
    "code" => false,
    "color" => "red",
    "href" => nil},
  @text="そみふぁ そそそ",
  @type="text",
  @will_update=false>]

とりあえず最初のページだけテストで試してみることにします。

#!/usr/bin/env ruby

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

page = Page.find "https://www.notion.so/hkob/Golden-Keyboard-a90b1cb46a394b6d98a71ae6705eb53d?v=44f2448afeda494fb67a94655202bf0c&source=copy_link"

print "#{page.title}\n"
src = page.properties["音名"]
dst = page.properties["音名2"]
trans_hash = {
  false => ["どれみふそらしー", "CDEFGAB-"],
  true => ["どれみふそらしー", "cdefgab-"]
}
dst.text_objects.rich_text_objects = src.text_objects.map do |text_object|
  text = text_object.text
  underline = text_object.options["underline"]
  pre, post = trans_hash[underline]
  new_text = text.tr(pre, post).gsub("", "").gsub(" ", " ")
  options = text_object.options.dup
  options["underline"] = false
  TextObject.new(new_text, options)
end
page.save

問題なく動いていました。

1ページのみ実行

あとは、回すだけです。途中で止まった時のために、finished のチェックも含めて追加してみました。

#!/usr/bin/env ruby

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

trans_hash = {
  false => ["どれみふそらしー", "CDEFGAB-"],
  true => ["どれみふそらしー", "cdefgab-"]
}

ds = DataSource.find "79799295-3ea8-41e8-97b5-f1d46a118d17"
query = ds.properties["finished"].filter_equals false
ds.query_data_source(query).each do |page|
  print "#{page.title}\n"
  src = page.properties["音名"]
  dst = page.properties["音名2"]
  dst.text_objects.rich_text_objects = src.text_objects.map do |text_object|
    text = text_object.text
    underline = text_object.options["underline"]
    pre, post = trans_hash[underline]
    new_text = text.tr(pre, post).gsub("", "").gsub(" ", " ")
    options = text_object.options.dup
    options["underline"] = false
    TextObject.new(new_text, options)
  end
  page.properties["finished"].checkbox = true
  page.save
end

実行してみると以下のようなエラーになりました。Notion API だと rich_text の長さに上限があるようです。

Over the Moore to Maggie
/Users/hkob/.local/share/mise/installs/ruby/4.0.0/lib/ruby/gems/4.0.0/gems/notion_ruby_mapping-3.0.5/lib/notion_ruby_mapping/blocks/base.rb:396:in 'NotionRubyMapping::Base#update_json': {"object" => "error", "status" => 400, "code" => "validation_error", "message" => "body failed validation: body.properties.音名2.rich_text.length should be ≤ `100`, instead was `127`.", "request_id" => "44e30a59-90db-416b-9ed5-7d502127e9aa"} (StandardError)

実際にデータを確認してみると Dual の 3 パートなのでちょっと長いですね。とりあえずチェックマークだけつけて残りをやってもらいましょう。ただ、この程度でダメなら他の曲でも失敗しそうです。

失敗した音名

アノテーションを回避

アノテーションが頻繁にあるとどうしても TextObject の数が超えてしまいます。ここでは、アノテーションを回避して単なるテキストに変換します。D と G だと「ど」の音が # のオンオフが変わります。色をなくす代わりに赤の「ど」だけ「C#」または「c#」に変換するようにしてみます。

#!/usr/bin/env ruby

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

trans_hash = {
  [false, false] => ["どれみふそらしー", "CDEFGAB-"],
  [true, false] => ["どれみふそらしー", "cdefgab-"],
  [false, true] => ["どれみふそらしー", "CDEFGAB-"],
  [true, true] => ["どれみふそらしー", "cdefgab-"]
}

ds = DataSource.find "79799295-3ea8-41e8-97b5-f1d46a118d17"
query = ds.properties["finished"].filter_equals false
ds.query_data_source(query).each do |page|
  print "#{page.title}\n"
  src = page.properties["音名"]
  dst = page.properties["音名2"]
  texts = src.text_objects.map do |text_object|
    text = text_object.text
    underline = text_object.options["underline"]
    red = text_object.options["color"] == "red"
    pre, post = trans_hash[[underline, red]]
    text.tr(pre, post).gsub("", "").gsub(" ", " ").gsub("", "C#").gsub("", "c#")
  end
  dst.text_objects.rich_text_objects = texts.join("")
  page.properties["finished"].checkbox = true
  page.save
end

再度実行してみました。API だと Notion AI よりも速く終わりますね。

hkob@hM1Pro tmp % time ruby kana.rb
Glass of Beer
New Copperplate
(中略)
The Kilmovee
Miss McLeod
Tattar Jack Walsh
ruby kana.rb  2.66s user 1.05s system 0% cpu 11:50.74 total

実行結果はこんな感じです。

最終的な実行結果

おわりに

結局、いろいろと Notion AI で頑張りましたが、テキストのアノテーションはかなり厳しそうでした。やはり得手不得手はありそうですね。

hkob.notion.site