Web上の画像を付けてツイート(1つ・複数)

以下の記事はTwitter gemバージョン6.1.0までの内容です。

画像の URL を img_url に入れておきます。ツイート本文は text に。

require 'twitter'
require 'open-uri'

client = Twitter::REST::Client.new(KEY_SECRET_HASH)
img_url = "http://…"
open(img_url) do |img|
  media_id = client.upload(img)
  client.update(text, {media_ids: media_id})
end

以下でもいけると思ったのだが、しばしば「Tempfile が保存出来ない」とのエラーが出たのでやめた。

img = open(img_url)
media_id = client.upload(img)
client.update(text, {media_ids: media_id})

Twitter::REST::Tweets#update_with_media が楽だと思ったのだが、 API 側が deprecated になったので NG 。

実用編

のメソッドを使います。

require 'twitter'
require 'open-uri'

client = Twitter::REST::Client.new(KEY_SECRET_HASH)

def tweet_attached_image_by_url(text, image_url = "")
  twitter_rescue do 
    if url_exist?(image_url)
      open(image_url) do |img|
        media_id = client.upload(img)
        client.update(text, {media_ids: media_id})
      end
    else
      client.update(text)
    end
  end 
end

img_url = "http://…"
tweet_attached_image_by_url(text, img_url)

複数画像(4枚まで)

(2017/3/29追加)

def tweet_attached_images_by_url(text, image_urls = [])
  twitter_rescue do
    if image_urls.empty?
      client.update(text)
    else
      media_ids = image_urls[0, 4].map { |image_url|
        if url_exist?(image_url)
          Thread.new(image_url) do |i_url|
            media_id = nil
            open(i_url) do |img|
              media_id = client.upload(img)
            end
            media_id
          end
        else
          nil
        end
      }.map(&:value).compact
      client.update(text, {media_ids: media_ids.join(",")})
    end
  end 
end

img_urls = ["http://…", "http://…", "http://…", "http://…"]
tweet_attached_images_by_url(text, img_urls)

この複数画像ツイートメソッドを書くための参考にしたサイト2つ

スレッド self が終了するまで待ち(Thread#join と同じ)、 そのスレッドのブロックが返した値を返します。スレッド実行中に例外が 発生した場合には、その例外を再発生させます。