GaucheでOAuthを使ってTwitterに投稿する
自分がGaucheでOAuthを使うために試行錯誤していたら、
id:SaitoAtsushiさんがGaucheでOAuthを使うコードを書いてくれていたようなので(http://d.hatena.ne.jp/SaitoAtsushi/20100429/1272545442)、
そのコードを元に、Twitterでつぶやくコードを作ってみました。
;APIのURLをapi.twitter.comにしてみた ;uri-encode-stringを日本語に対応させてみた (use rfc.http) (use rfc.sha) (use rfc.hmac) (use rfc.base64) (use www.cgi) (use math.mt-random) (use gauche.uvector) (define consumer-key "Consumer Key") (define consumer-secret "Consumer Secret") (define message "GaucheでOAuthを使ってつぶやいてみる") (define (uri-encode-string str) (call-with-string-io str (lambda(in out) (while (read-byte in) (compose not eof-object?) => ch (if (char-set-contains? #[a-zA-Z0-9.~_-] (integer->char ch)) (write-char (integer->char ch) out) (format out "%~2,'0X" (char->integer (integer->char ch)))))))) (define (time-stamp) (number->string (sys-time))) (define (random-string) (let ((random-source (make <mersenne-twister> :seed (sys-time))) (v (make-u32vector 10))) (mt-random-fill-u32vector! random-source v) (digest-hexify (sha1-digest-string (x->string v))))) (define (query-compose query) (string-join (map (cut string-join <> "=") query) "&")) (define (signature method uri info :optional (token-secret "")) (let* ((query-string (query-compose info)) (signature-basic-string (string-append method "&" (uri-encode-string uri) "&" (uri-encode-string query-string)))) (uri-encode-string (base64-encode-string (hmac-digest-string signature-basic-string :key #`",|consumer-secret|&,|token-secret|" :hasher <sha1>))))) ; Request Tokenの取得 (define query `(("oauth_consumer_key" ,consumer-key) ("oauth_nonce" ,(random-string)) ("oauth_signature_method" "HMAC-SHA1") ("oauth_timestamp" ,(time-stamp)) ("oauth_version" "1.0"))) (define s (signature "POST" "http://api.twitter.com/oauth/request_token" query)) (define token (receive (status header body) (http-post "api.twitter.com" "/oauth/request_token" (query-compose `(,@query ("oauth_signature" ,s)))) (cgi-parse-parameters :query-string body))) (define request-token (cadr (assoc "oauth_token" token))) (define request-token-secret (cadr (assoc "oauth_token_secret" token))) ; OAuth Verifierの取得 (display "open this url.") (newline) (format #t "https://api.twitter.com/oauth/authorize?oauth_token=~A" request-token) (newline) (newline) (display "input pin: ") (flush) ;これが無いと、「input pin: 」と表示されるのがread-lineの後になってしまう。 (define oauth-verifier (read-line)) ; Access Tokenの取得 (define query `(("oauth_consumer_key" ,consumer-key) ("oauth_nonce" ,(random-string)) ("oauth_signature_method" "HMAC-SHA1") ("oauth_timestamp" ,(time-stamp)) ("oauth_token" ,request-token) ("oauth_verifier" ,oauth-verifier))) (define s (signature "GET" "http://api.twitter.com/oauth/access_token" query request-token-secret)) (define token (receive (status header body) (http-post "api.twitter.com" "/oauth/access_token" (query-compose `(,@query ("oauth_signature" ,s)))) (cgi-parse-parameters :query-string body))) (define access-token (cadr (assoc "oauth_token" token))) (define access-token-secret (cadr (assoc "oauth_token_secret" token))) ; つぶやく (define query `(("oauth_consumer_key" ,consumer-key) ("oauth_nonce" ,(random-string)) ("oauth_signature_method" "HMAC-SHA1") ("oauth_timestamp" ,(time-stamp)) ("oauth_token" ,access-token))) (define s (signature "POST" "http://api.twitter.com/statuses/update.json" `(,@query ,`("status" ,(uri-encode-string message))) access-token-secret)) (http-post "api.twitter.com" "/statuses/update.json" (format "status=~A" (uri-encode-string message)) :Authorization (format "OAuth ~A" (string-join (map (cut string-join <> "=") `(,@query ("oauth_signature" ,s))) ", ")))
こんなコードです。
変更点
元のコードはRequest Tokenを取得するところまでなので、OAuth Verifier、Access Token、Twitter投稿の部分を書きました。
OAuthは、URLエンコードの結果の十六進数は、アルファベットを大文字にする必要があるので、
uri-encode-stringはSaitoAtushiさんが作ったものを使っていますが、元のコードでは日本語に対応していないので、
「一文字ずつ読み込む」ところを「一バイトずつ読み込む」ようにして日本語に対応しました。
実行する方法
「Consumer Key」「Consumer Secret」は、自分の使うものに変更してください。
「"GaucheでOAuthを使ってつぶやいてみる"」の部分は、Twitterに投稿したい文字列に変更してください。
コードをファイル(ここでは「oauth.scm」という名前)に保存して、
gosh oauth.scm
のようにすれば実行できます。
実行してしばらくすると、「open this url.」の後にURLが出るので、そのURLにアクセスして、「許可する」を押して、
出てくる数字を、「input pin:」と出てきたところに入力してエンターを押してください。
しばらく待つと、Twitterにメッセージが投稿されます。