忍者ブログ
MASTER →  ADMIN / NEW ENTRY / COMMENT
現代魔法(nearly equal 情報技術)を勉強中な人のメモ(チラシの裏)
/ 2024/04/26 (Fri) / 編集
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

/ 2010/07/22 (Thu) / 編集
TwitPicはTwitterのツィートに画像を使いたいときにとても役立つサービス。Twitterのアカウントでログインできる。

というのは普通にブラウザでアクセスするときの話。ボットからアクセスするにはBASIC認証かOAuth Echo認証を使わないといけない!そしてBASICは将来的になくなるかもしんない。。。

というわけで、OAuth Echo認証に挑戦するお!


参考文献:
[ふと思う--ちょっと考える (いたずら編)]TwitPic API v2で画像のアップロード
[しばそんノート]OAuthコンシューマの仕組みと実装 ~ Ruby編

OAuth Echoには「コンシューマキー等OAuthに使うもの」と「TwitPicのAPIキー」が必要です。TwitPicのAPIキーは「http://dev.twitpic.com/」で取得しませう。
今回は開発中のbot用なので、以前作成したTwitterClass.rbに追加する感じで作ります。なのでグローバルな変数が2つ使われてますが。適宜書き換えてください。

OAuthに使うヘッダを取得しよう

まず始めに、普通のOAuthに使うヘッダを作ります。このためにしばそんさんのrb-simple-oauthからsimple-oauth.rbをダウンロードしてきます。

でもって”ふと思う”さんのサイトを参考に次の関数を追加します。追加するときは「private」とある行よりも上に書くようにしましょう。
def make_auth_header(method, url, body = nil)
  method = method.to_s
  uri = URI.parse(url)
  request_body = body.is_a?(Hash) ? encode_parameters(body) : body.to_s
  return auth_header(method, uri, request_body)
end
するとこんな感じになります。

リクエストを作る準備

上のライブラリを使ってHTTPでリクエストするためのヘッダとかを作る訳ですが、そのためには以下のような機能を実装した関数が必要です。
  1. OAuth Echo用のヘッダを作る
  2. リクエストに画像ファイルを追加
  3. メッセージやAPIキーの情報を追加する
このときめんどくさくなるのが、リクエストのBodyは文字列なのはいいんだけど、改行が「\r\n」であるということです。文字列でやるといろいろとめんどくさいので今回は「配列に情報を詰め込む」→「配列の要素を\r\nで連結して一つの文字列にする」という手順で行きます。

というわけで、まずはヘッダを作る関数を作ります。
def add_oauth_echo_heder(request,realm_url,auth_provider_url)
  auth = @access_token.make_auth_header(:GET, auth_provider_url)
  request["X-Auth-Service-Provider"] = auth_provider_url
  request["X-Verify-Credentials-Authorization"] = auth + ", realm=\"#{realm_url}\""
end

次に、APIキーやmessageはヘッダではなくBodyに書くそうなので、そのための関数を作ります。
def add_form_body(body_array,boundary,key,value)
  body_array << "--#{boundary}"
  body_array << "Content-Disposition: form-data; name=\"#{key}\""
  body_array << ""
  value.split(/\n/).each{|line|
    body_array << "#{line}"
  }
end

あとは画像ファイルを追加するための関数を作ります。
#MIMEタイプを調べる
def mime_type(file)
  case 
  when file =~ /\.jpg/ then 'image/jpg'
  when file =~ /\.gif$/ then 'image/gif'
  when file =~ /\.png$/ then 'image/png'
  else 'application/octet-stream'
  end
end

#配列に画像追加用の情報を詰め込む
def add_file_body(body_array,boundary,key,file_path)
  file_name = File.basename(file_path)
  mime_type = mime_type(file_name)
  body_array << "--#{boundary}"
  body_array << "Content-Disposition: form-data; name=\"#{key}\"; filename=\"#{file_name}\""
  body_array << "Content-Type: #{mime_type}"
  body_array << ""
  #バイナリデータを押し込む
  open(file_path){|io|
    body_array << io.read
  }
end


さて、以上をつかってTwitPicに画像をアップロードする関数を作ります。
def twitpic_upload(image_file_path, message = "")
  twitpic_api_url = "http://api.twitpic.com/2/upload.json"
  realm_url = "http://api.twitter.com/"
  auth_provider_url = "https://api.twitter.com/1/account/verify_credentials.json"

  url_token = URI.parse(twitpic_api_url)
  request = Net::HTTP::Post.new(url_token.request_uri)
#
  # construct HTTP request
  #バウンダリ文字列を生成(なんでもいい)
  boundary = Time.now.strftime("%Y%m%d_%H%M%S_#{$$}")

  #OAuth Echoヘッダを追加
  add_oauth_echo_heder(request,realm_url,auth_provider_url)

  #Content-Typeヘッダでバウンダリの指定
  request["Content-Type"] = "multipart/form-data; boundary=#{boundary}"

  body_part = []
  #APIキーの情報を押し込む
  add_form_body(body_part,boundary,'key',@twitpic_api_key)
  #メセージの情報を押し込む
  add_form_body(body_part,boundary,'message',message) if(message!="")
  #画像の情報を押し込む
  add_file_body(body_part,boundary,'media',image_file_path)

  #おわり
  body_part << "--#{boundary}--"
  body_part << ""

  #区切り文字「\r\n」で配列を結合する
  request.body = body_part.join("\r\n")

  #Content-Lengthにリクエストボディのサイズを設定
  request["Content-Length"] = request.body.size

  #送りつける
  begin
    http = Net::HTTP.new(url_token.host, url_token.port).start
    response = http.request(request)

    #ちゃんと送れたか確認
    retrun_message=JSON.parse(response.body)
    return nil  if (retrun_message['text'] != message)
    return retrun_message
  rescue => err
    time = Time.now.strftime("%Y/%m/%d %H:%M:%S")
    STDERR.print "#{time}\t[Error:upload_twitpic]\t #{err}\n"
  end
end

ここで、まだ書いてないのが2つ。そう、「@twitpic_api_key」と「@access_token」です。
「@twitpic_api_key」は普通にTwitPic APIキーが入っています。「@access_token」は「SimpleOAuth」のインスタンスです。
def initialize(con_key,con_secret,ac_token,ac_token_secret,twitpic_api_key='')
  @access_token = SimpleOAuth.new(con_key,con_secret,ac_token,ac_token_secret)
  @twitpic_api_key = twitpic_api_key
end
以上をつめこんだクラスがこちらになります。
まぁ関係ない関数も書いてありますがスルーしてください。

使い方

完成した TwitterClass.rbをダウンロード用意したら、次は使い方です。

「$configなんたら」にはコンシューマキーなどが入ってると思ってください。
twitter = TwitterClass.new($config[:CONSUMER_KEY],$config[:CONSUMER_SECRET],$config[:ACCESS_TOKEN],$config[:ACCESS_TOKEN_SECRET],$config[:TWITPIC_API_KEY])
p twitter.twitpic_upload('image/test.jpg','関数に分割したい!')

拍手[1回]

PR
忍者ブログ [PR]