NotionRubyMapping のアップデート(9) : hkob の雑記録 (164)

はじめに

hkob の雑記録の第164回目は、NotionRubyMapping 1.0.0 の公開と、昨日作成した single_file_upload の実装の修正について解説します。

NotionRubyMapping 1.0.0 の公開

まだ File Upload API の更新中ですが、この開発をしているマシンで、NotionRubyMapping が動作しなくなっていました。開発のために Faraday 2.13.1 の gem が入っていたため、こちらが読み込まれてしまい、Faraday 2 系列で動作しない FaradayMiddleware が読み込まれないためでした。別のツールで Faraday 2 がインストールされてしまうこともあると思うので、早急に File Upload API が含まれない Faraday 2.13.1 対応の NotionRubyMapping 1.0.0 をリリースしました。

rubygems.org

FileUploadObject#single_file_upload の修正

また、require_relative で notion_ruby_mapping を読み出し、 FileUploadObject.new を実行してみました。すると、以下のようなエラーが出てきました。画像・動画・音声・PDF など様々なファイルがアップロードされるので、Content-Type を octet-stream にしていたのですが、Notion API 側が Content-Type でフィルタしているようです。

/Users/hkob/Library/CloudStorage/Dropbox/ruby/notion_ruby_mapping/lib/notion_ruby_mapping/objects/file_upload_object.rb:35:in 'FileUploadObject#single_file_upload': File upload failed: {object: "error", status: 400, code: "validation_error", message: "File upload has an invalid or unsupported content type of `application/octet-stream`.", request_id: "3102ade0-a5fd-4a90-9a36-448552c18a94"} (StandardError)

スクリプトでは以下のように実行していました。こちらの場合、Content-Type は curl が準備してくれていたのだと思います。

curl --request POST \
  --url 'https://api.notion.com/v1/file_uploads/20cd8e4e-98ab-81aa-973b-00b23083c115/send' \
  -H 'Authorization: Bearer '"$NOTION_API_KEY"'' \
  -H 'Notion-Version: 2022-06-28' \
  -H 'Content-Type: multipart/form-data' \
  -F "file=@ErSxuLeq.png-medium.png"

mime-types の追加

Content-Type を準備するために mime-types gem をインストールします。 notion_ruby_mapping.gemspec に mime-types を依存関係で追加しました。

  spec.add_dependency "faraday"
  spec.add_dependency "faraday-multipart"
  spec.add_dependency "mime-types"

さらに、 notion_cache.rbmime/types の読み込みを追加します。

# frozen_string_literal: true

require "singleton"
require "faraday"
require "faraday/multipart"
require "mime/types"

module NotionRubyMapping
  # singleton class of caching Notion objects
  class NotionCache
    include Singleton

NotionCache#multipart_request の修正

multipart_request で octet-stream に決め打ちしていた、content-type を MIME::Types#type_for でファイル名から取得できるようにしました。

    # @param [String] path
    # @param [Hash] json
    # @param [String] fname
    # @return [Hash] response hash
    def multipart_request(path, json, fname)
      raise "Please call `NotionRubyMapping.configure' before using other methods" unless @notion_token

      content_type = MIME::Types.type_for(fname).first.to_s

      sleep @wait
      json_part = Faraday::Multipart::ParamPart.new(json.to_json, "application/json")
      file_part = Faraday::Multipart::FilePart.new(fname, content_type, File.basename(fname))
      p multipart_client
      response = multipart_client.send(:post) do |request|
        request.headers["Authorization"] = "Bearer #{@notion_token}"
        request.headers["content-Type"] = "multipart/form-data"
        request.path = path
        request.body = {json: json_part, file: file_part}
      end
      p response.body if @debug
      response.body
    end

この修正をしたところ、無事に FileUploadObject が無事に作成できました。

おわりに

とりあえず動くことは確認できたので、再度 multipart のテストができるかを試してみます。

hkob.notion.site