blog/content/post/1970-01-01-00000004.md

22 KiB
Raw Blame History

title author date url wordtwit_post_info categories
GaucheでMixi Voiceに投稿する kazu634 1969-12-31 /1970/01/01/_4/
O:8:"stdClass":13:{s:6:"manual";b:0;s:11:"tweet_times";i:1;s:5:"delay";i:0;s:7:"enabled";i:1;s:10:"separation";s:2:"60";s:7:"version";s:3:"3.7";s:14:"tweet_template";b:0;s:6:"status";i:2;s:6:"result";a:0:{}s:13:"tweet_counter";i:2;s:13:"tweet_log_ids";a:1:{i:0;i:5433;}s:9:"hash_tags";a:0:{}s:8:"accounts";a:1:{i:0;s:7:"kazu634";}}
gauche

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 のページにリダイレクトします:

http://mixi.jp/connect_authorize_success.html?code=<英数字>

上の「<英数字>」の部分が 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")

実行結果はこんな感じです:

f:id:sirocco634:20110619114337j:image

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 のデータを取得するだけですね。