読者です 読者をやめる 読者になる 読者になる

ぱらつり記

No description

Twitter Gemの画像アップロードをオンメモリでやろうとして挫折したお話

ラズパイでRubyをいじるぱらつりです。

RubyにおけるTwitterライブラリといえばTwitter Gemが有名ですね。
フォローしてたりされてたりのユーザーとか一括で扱いたいと思ったらpry立ち上げてサクッとやったりするのですが、今回はRMagickでいじった画像でプロフィール画像を更新させたかったのです。

Twitter Gemでやってみる

とりあえずドキュメントを漁れば、Twitter::REST::Users#update_profile_imageが見つかります。

このメソッドがとる引数を見てみると、

Parameters:

  • image (File) — The avatar image for the profile, base64-encoded. Must be a valid GIF, JPG, or PNG image of less than 700 kilobytes in size. Images with width larger than 500 pixels will be scaled down. Animated GIFs will be converted to a static GIF of the first frame, removing the animation.
  • options (Hash) (defaults to: {}) — A customizable set of options.

Fileですか…。いちいち書き出すの面倒だからオンメモリで渡したいんですが…。

easyramble.com

こちらの記事を読んだ限り、渡すオブジェクトに#to_ioが存在しないといけないらしい。

StringIO

RubyにおけるMemoryStreamならこれどう?というstackoverflowの投稿をみて試した。

いけると思った。

が、#to_ioが定義されておらず死亡

公式ドキュメントのObject#to_ioを見ると

このメソッドを定義する条件は、

  • IOオブジェクトが使われるすべての場面で代置可能であるような、
  • IOオブジェクトそのものとみなせるようなもの

という厳しいものになっています。

ということではずれでした。

IO.new, IO.pipe

FileっぽいIOならとか意味不明なことを考えたもののよく理解できずに死亡

結局

「もうAPI叩けばいいんじゃね?」

qiita.com

というわけで、こちらの記事を参考にしてこんな感じに。

require 'rmagick'
require 'oauth'

img = Magick::Image.read("foo.jpg").first
# img.もげもげ 
# ...

consumer = OAuth::Consumer.new("consumer_key", "consumer_secret", site: "https://api.twiter.com")
endpoint = OAuth::AccessToken.new(consumer, "access_token", "access_token_secret")

res = endpoint.post('https://api.twitter.com/1.1/account/update_profile_image.json', image: Base64.encode64(img.to_blob))
# => #<Net::HTTPOK 200 OK readbody=true>
puts response.kind_of?(Net::HTTPSuccess) ? "succeeded" : "failed"

行き当たりばったりだったり思考がクソなのが悲しい。