Google Books API との格闘 (失敗談) : Notion 解説 (58)

1. はじめに

昨晩、熊倉さんから以下のダイレクトメッセージを受け取りました。

小林さん突然すみません!こちら原因わからなくて困っているようなのですが、もし理由すぐ分かるようでしたら教えていただけるとめちゃ助かります・・ 個人的には、画像URLでカバー設定してもたまに引っ張ってこれない(.htaccess周りとかの設定?)ケースがあるのでそれに引っ掛かってるのかなーとかありますが、api特有の動きってあったりします・・?

熊倉さんが受けた質問主は Google Books API のイメージを API 経由で Notion に埋め込みたいが失敗するという話でした。結局、検証の結果、API から画像ブロックは埋め込めないことを結論づけました。夜中にふと、プロパティならいけるのではと思い再検証してみました。以下その再検証記録です。最終的には再検証も失敗したのですが、失敗談も記録ではあるので、ここに残しておきます。

2. 再検証準備

テストするためのページが必要なので、まずは検証ページを作ります。検証自体もタスクなので、ショートカットで作成します。タスク開始するショートカットの説明はこちらです。私の場合は、Cmd-Option-]で起動し、「A new task」でタイトルを入れるだけです。hkob.hatenablog.com

検証ページが出来ました。

ショートカットでタスク作成

Google Books API は知らなかったので、検索したところここに解説がありました。

labo.kon-ruri.co.jp

ちなみにサムネールの URL はこんな感じになるそうです。画像ファイルではなく単なる API 呼び出しなのですね。

https://books.google.com/books/content?id=Bdh_RQAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api"

検証には NotionRubyMapping を使います。irb を立ち上げ、以下のコマンドを実行し、上で作ったページを取得しておきます。また、上記のリンクを url という変数に格納しておきます。

require "notion_ruby_mapping"
include NotionRubyMapping

token = ENV["NOTION_API_KEY"]
NotionCache.instance.create_client token

page = Page.find "ce85304228264674b8ba99694def2d4d"
url = "https://books.google.com/books/content?id=Bdh_RQAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api"

3. 昨晩の再現

3.1 Notion からの貼り付けたものを検証

まずは質問主ができるという Notion 上での貼り付けをやってみます。以下のような画面が出てきます。URL なので Create embed が候補に出ていました。

URL を Notion で貼り付け

貼り付けられたサムネール画像

まず、このブロックを検証してみます。このためブロックの link を取得します。

ブロックの URL を取得

URL はこうなっています。Page ID の後に # があり、その後が Block ID になります。Block ID は 44368f420e0c44ddb5082a797843a48b ということがわかりました。

https://www.notion.so/hkob/Google-Books-API-ce85304228264674b8ba99694def2d4d#44368f420e0c44ddb5082a797843a48b

このブロックを Block.find で取得してみます。embed で作成したのですが、内部では ImageBlock になっています。

b0 = Block.find "44368f420e0c44ddb5082a797843a48b"
# => NotionRubyMapping::ImageBlock-44368f420e0c44ddb5082a797843a48b

中身を見てみましょう。確かに ImageBlock であり、URL は上記のリンクがそのままついています。

b0.block_json
# => 
# {"type"=>"image", 
#  "object"=>"block", 
#  "image"=> 
#   {"type"=>"external", 
#    "external"=> 
#     {"url"=>"https://books.google.com/books/content? id=Bdh_RQAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api"},
#   "caption"=>[]}}

3.2 ImageBlock の作成 (失敗)

質問主が失敗するという ImageBlock を作成してみます。Invalid image url というエラーで失敗しました。

b1 = page.append_block_children ImageBlock.new(url)
/Users/hkob/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/notion_ruby_mapping-0.5.2/lib/notion_ruby_mapping/blocks/base.rb:97:in `append_block_children': {"object"=>"error", "status"=>400, "code"=>"validation_error", "message"=>"Content creation Failed. Fix the following: \nInvalid image url."} (StandardError)                         
        from (irb):12:in `<main>'                                                      
        from /Users/hkob/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/irb-1.4.1/exe/irb:11:in `<top (required)>'
        from /Users/hkob/.rbenv/versions/3.1.2/bin/irb:25:in `load'
        from /Users/hkob/.rbenv/versions/3.1.2/bin/irb:25:in `<main>'

URL が画像のファイルと判断されていないためですね。API reference の Block object によると、URL は以下のものでなければならないようです。

Includes supported image urls (i.e. ending in .png, .jpg, .jpeg, .gif, .tif, .tiff, .bmp, .svg, or .heic)

3.3 EmbedBlock の作成 (失敗)

ImageBlock がダメなら EmbedBlock にしたらどうなるのかということでやってみました。作成自体は成功しています。

b1 = page.append_block_children EmbedBlock.new(url)
# => NotionRubyMapping::EmbedBlock-ced41ce10eb8444aafac53f5ea2b4577

確かに EmbedBlock は作成されているのですが、これは画像としては認識されていません。

作成された EmbedBlock
ちなみに、b1 の内容を確認してみると以下のようになりました。type が image であればよいのですが、残念ながら API からブロックタイプを変換することはできません。

b1.block_json
=> 
{"type"=>"embed",                                   
 "object"=>"block",                                 
 "embed"=>                                          
  {"caption"=>[],                                   
   "url"=>"https://books.google.com/books/content?id=Bdh_RQAACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api"}}

3.3 力技での対応 (失敗)

画像と認識されればいいのではということで、文字列に .jpg が入っていればいいのではという話になり、オプションでdummy=a.jpgのようなものをつけてみました。しかし、オプションは画像かどうかの判断には使われていないようで失敗しました。

b2 = page.append_block_children ImageBlock.new("#{url}?dummy=a.jpg")
/Users/hkob/.rbenv/versions/3.1.2/lib/ruby/gems/3.1.0/gems/notion_ruby_mapping-0.5.2/lib/notion_ruby_mapping/blocks/base.rb:97:in `append_block_children': {"object"=>"error", "status"=>400, "code"=>"validation_error", "message"=>"Content creation Failed. Fix the following: \nInvalid image url."} (StandardError)       

ファイル名に相当する部分ということで、途中の content に jpg 拡張子をつけてみました。

b2 = page.append_block_children ImageBlock.new(url.gsub "content", "content.jpg")
# => NotionRubyMapping::ImageBlock-581e98f8b8bb4e62a0c8aaa851391dab

作成には成功しましたが、画像 URL がおかしいとエラーになりました。当たり前ですね。

画像URLの異常

3.4 FileBlock として貼り付け (失敗)

URL を貼り付けられるものとして他には FileBlock があります。こちらでは確かに貼り付けられました。

b3 = page.append_block_children FileBlock.new(url)
=> NotionRubyMapping::FileBlock-029a1f7ee19d4c6bb1a377837856b2ea

確かに貼り付けはできましたが、これは期待するものではないですね。

貼り付けられたファイル

3.5 検証時の結論

結局、熊倉さんとは「とりあえず適当な画像を使って ImageBlock を作成し、URL を近くに書いておく」という結論に達しました。一番簡単なのは caption かと思うので、以下のようにしてみました。

b4 = page.append_block_children ImageBlock.new("https://cdn.worldvectorlogo.com/logos/notion-logo-1.svg", ca
ption: url)
# => NotionRubyMapping::ImageBlock-460b7356cd054c29a89ebd503109911f

作成されたものはこちらです。

別の画像を貼り、キャプションに URL

ここで、キャプションの内容をコピーし、メニューから Replace をクリックします。

メニューから Replace

Embed link でコピーした URL を貼り付けます。

Embed link

画像に変換されました。キャプションは適当なものに変換するか消せばよいです。

画像に変換

4 再検証 (結局失敗)

昨晩は早く寝てしまったので、早朝に目が覚めてしまいました。この件を朝に記事にしようと考えていたところ、File & Image プロパティなら画像ファイルとして制約を受けないのではと思いつきました。ということで、再検証スタートです。タイミングがいいことに昨日、インラインデータベースが作成できるようになりましたので、早速使ってみます。

db = page.create_child_database "Google Books",
                                TitleProperty, "Title",
                                FilesProperty, "Thumbnail" do |d, dp|
  d.is_inline = true
end

インラインデータベースが作成できるようになったのはいいですね。あとはビューも作れるといいのですが。

作成されたインラインデータベース

仕方ないので、ビューは手動でギャラリービューに変換しました。

ギャラリービューに変更

早速、データベースの下にページを作成してみました。URL が長すぎて、name の文字数制限に引っかかるようになってしまったので、file_names を別途設定できるように NotionRubyMapping を v0.5.5 にアップデートしました。

p0 = db.create_child_page do |p, pp|
  pp["Title"].text_objects << "我輩は猫である"
  pp["Thumbnail"].files = url
  pp["Thumbnail"].file_names = "thumbnail"
end

作成はできましたが、画像は表示されませんでした。

作成されたページ

ページを確認してみたところ、Thumbnail とだけ書かれています。ページにつけた時と同様に単なるファイルリンクと認識されているだけのようです。

ファイルプロパティ

View original とするとちゃんと画像は表示されます。

View original

URL を取得し、上の「Add a file or image」に貼り付けてみます。 もっと悪い結果になり、URL だけが見えた状態になりました。クリックすると画像は開くのですが、思った結果ではありませんでした。

URL だけが見える状況

5. おわりに

FileProperty なら行けるのではと考えたのですが、やはり無理でした。せめて URL が画像だとわかる形になっていればよかったのですが、Google Books API ではうまくいかないようです。何にせよ、こんな感じの検証には NotionRubyMapping は便利だなというのを再認識しました。作ってよかったです。


www.notion.so