22 KiB
title | author | date | url | wordtwit_post_info | categories | ||
---|---|---|---|---|---|---|---|
GaucheでMixi Voiceに投稿する | kazu634 | 1969-12-31 | /1970/01/01/_4/ |
|
|
Gauche で Mixi Voice に投稿できるところまで書きました。まだモジュールにはしていないのですが、とりあえずここにひっそりと書いておきます。
はじめに
Twitter から任意のキーワードにマッチするものだけを Mixi Voice に投稿したい、という希望がありました。Mixi には大学の時のサークル関係の方が多くいて、その人達向けに Runkeeper のつぶやきを見せたかったのです。
Mixi Voice の OAuth の取得などに関しては、次のページが詳しかったので、まずはこのページをご覧ください:
ソース
つぎのソースを適当な名前で保存してください:
(use rfc.http) (use rfc.json) ;;; class definition (define-class <mixi-token> () ((consumer-key :init-keyword :consumer-key :init-value #f :accessor consumer-key-of) (consumer-secret :init-keyword :consumer-secret :init-value #f :accessor consumer-secret-of) (authorization-code :init-keyword :authorization-code :init-value #f :accessor authorization-code-of) (refresh-token :init-keyword :refresh-token :init-value #f :accessor refresh-token-of) (access-token :init-keyword :access-token :init-value #f :accessor access-token-of))) ;; /* _\|/_ ;; (o o) ;; +----oOO-{_}-OOo--------------+ ;; |Wrapper macro for HTTP access| ;; +----------------------------*/ (define-macro (wrap-http http-method proc) (let ((g!status (gensym)) (g!header (gensym)) (g!body (gensym))) `(receive (,g!status ,g!header ,g!body) ,http-method (cond ((equal? "200" ,g!status) (,proc ,g!body)) (else (print ,g!status ,g!header ,g!body)))))) (define-macro (wrap-http/debug http-method proc debug-flag) (let ((g!status (gensym)) (g!header (gensym)) (g!body (gensym))) `(receive (,g!status ,g!header ,g!body) ,http-method (cond ((equal? "200" ,g!status) (,proc ,g!body)) (else ,(if debug-flag `(else (print ,g!status ,g!header ,g!body)) #f)))))) ;;; <mixi-token>インスタンスから、 ;;; アクセストークンを取得するためのクエリーを生成 (define-method compose-access-token-query ((token <mixi-token>)) `(("grant_type" "authorization_code") ("client_id" ,(consumer-key-of token)) ("client_secret" ,(consumer-secret-of token)) ("code" ,(authorization-code-of token)) ("redirect_uri" "http://mixi.jp/connect_authorize_success.html"))) ;;; アクセストークン取得のための手続き (define-method acquire-access-token! ((token <mixi-token>)) (wrap-http/debug (http-post "secure.mixi-platform.com" "/2/token" (compose-access-token-query token) :secure #t) (lambda (response) (update-token! response token)) #f)) ;;; <mixi-token>を更新するための手続き (define-method update-token! ((response <string>) (mixi-instance <mixi-token>)) (define (refresh-token response) (if (equal? #f response) response (cdr (assoc "refresh_token" (parse-json-string response))))) (define (access-token response) (if (equal? #f response) response (cdr (assoc "access_token" (parse-json-string response))))) (set! (access-token-of mixi-instance) (access-token response)) (set! (refresh-token-of mixi-instance) (refresh-token response)) mixi-instance) ;;; mixi voiceに投稿するための手続き (define-method post-voice ((mixi-instance <mixi-token>) (voice <string>)) (define (post-id response) (cdr (assoc "id" (parse-json-string response)))) (let ((post-status (http-compose-query #f `((status ,voice)))) (authorization-key (string-append "OAuth " (access-token-of mixi-instance)))) (wrap-http/debug (http-post "api.mixi-platform.com" "/2/voice/statuses/update" post-status :content-type "application/x-www-form-urlencoded" :Authorization authorization-key) post-id #f))) ;;; OAuth tokenの更新 (define-method update-access-token! ((mixi-instance <mixi-token>)) (define (token-update! response) (update-token! response mixi-instance)) (wrap-http/debug (http-post "secure.mixi-platform.com" "/2/token" `(("grant_type" "refresh_token") ("client_id" ,(consumer-key-of mixi-instance)) ("client_secret" ,(consumer-secret-of mixi-instance)) ("refresh_token" ,(refresh-token-of mixi-instance))) :secure #t) token-update! #f)) ;;; 投稿の削除 (define-method delete-voice ((mixi-instance <mixi-token>) (id <string>)) (let ((authorization-key (string-append "OAuth " (access-token-of mixi-instance))) (uri (string-append "/2/voice/statuses/" id))) (wrap-http/debug (http-delete "api.mixi-platform.com" uri :Authorization authorization-key) (lambda (response) #t) #f))) ;;; Voice一覧の取得 (define-method friend-voices ((mixi-instance <mixi-token>)) (wrap-http/debug (http-get "api.mixi-platform.com" `("/2/voice/statuses/friends_timeline/" (oauth_token ,(access-token-of mixi-instance)) (trim_user "1") (attach_photo "1"))) (lambda (response) (parse-json-string response)) #f))
使い方
ソースコードを適当な名前で保存します (たとえば「foo.scm」とか)。その後、loadしてください:
gosh> (load "foo")
Consumer key, Consumer secret の取得
参考ページを参考にしてください。
Authorization Code の取得
参考ページを参考にして、次の URL にアクセスしてください:
https://mixi.jp/connect_authorize.pl?client_id=<コンシューマキー>&response_type=code&scope=r_voice%20w_voice&display=pc
[同意する]ボタンをクリックすると、次の URL のページにリダイレクトします:
上の「<英数字>」の部分が Authorization Code です。
アクセストークンの取得
次のようにしてコードを実行してください:
gosh> (define *mixi-obj* (make <mixi-token> :consumer-key "コンシューマーキー" :consumer-secret "コンシューマーシークレット" :authorization-code "authorization code")) *mixi-obj* gosh> (acquire-access-token! *mixi-obj*) #<<mixi-token> x1011521e0>
acquire-access-token! 手続きは、リフレッシュトークン・アクセストークンを取得し、 *mixi-obj* を上書きします。
Voice の投稿
アクセストークンを取得してから、次のようにして投稿してください:
gosh> (post-voice *mixi-obj* "今日はゆっくりと、だらだら過ごすのだ!") "4ncdm68fwm56j-20110619113448"
post-voice 手続きは成功すると、投稿したボイスの ID を戻り値としてます。
なお、 取得したアクセストークンの有効期限は 15 分と短いため、期限が切れた場合にはアクセストークンを再取得する必要があります。その場合には、update-access-token!手続きを使えば再取得してくれます:
gosh> (define (wrapper-post-voice mixi-instance voice) (let1 result (post-voice mixi-instance voice) (if result result (post-voice (update-access-token! mixi-instance) voice)))) wrapper-post-voice gosh> (wrapper-post-voice *mixi-obj* "test")
実行結果はこんな感じです:
Voice の削除
次のようにすると、 Voice を削除できます。 Voice の ID が必要です。
gosh> (delete-voice *mixi-obj* "4ncdm68fwm56j-20110619114011") #t
成功すると、#tが戻って来ます。失敗すると#fが戻って来ます。#fが戻ってくるときは、「(update-access-token! *mixi-obj*)」をしてください。
友人の Voice 一覧の取得
次のようにすると、自分と友人を含めた Voice の一覧を取得します。
gosh> (friend-voices *mixi-obj*)
勝手に公開するのもどうかと思うので、実行結果は省略します。成功すると、#tが戻って来ます。失敗すると#fが戻って来ます。#fが戻ってくるときは、「(update-access-token! *mixi-obj*)」をしてください。
後は
Twitter から Runkeeper のデータを取得するだけですね。