iTunesから再生中の曲のタイトルをFacebookへポストする

3週間くらい前から,何となくFacebookが楽しい気がしていたのですが,そう感じていた人が結構周りに多くて一気に活性化してきた感があります.
Facebookに何かポストすると,ゆーすけべーとかid:amachangとかid:higeponさんとか宴やんとかが0.5秒で「いいねd」してくれるので,寂しがり屋にぴったりです.


で,今朝,iTunesで聴いている音楽をポストしたいなーと思ったのですが,いい方法が見つかりませんでした.
now playingというアプリを使えば実現できそうなのですが,無職なので小銭でもけちりたいところです.
また,iPhoneからなら簡単にできるみたいですが,自宅警備が忙しくiTunesからポストできると助かるなーと思いました.
そこで色々調べてみると,割と簡単に実現できそうなので簡単なコードを書いてみました.

構成

f:id:k_kinukawa:20101012150625j:image
こんな感じです.
環境は MacOS 10.6.4です.

AppleScript

AppleScriptを使うと,iTunesで再生している曲の情報を得ることができます.
シェルもたたけるので,面倒なところはそっち任せにします.
今回は,iTunesから再生中の曲名とアーティスト名を取得し,pythonのプログラムに渡します.
スクリプトはこんな感じです.
postmusic.scpt

on replaceText(myText, serchStr, replaceStr)
	set theDelim to AppleScript's text item delimiters
	set AppleScript's text item delimiters to serchStr
	set theList to every text item of myText
	set AppleScript's text item delimiters to replaceStr
	set myText to theList as string
	set AppleScript's text item delimiters to theDelim
	return myText
end replaceText

tell application "iTunes"
	set artist_name to artist of current track
	set track_name to name of current track
end tell

set artist_name to replaceText(artist_name, "\"", " ")
set track_name to replaceText(track_name, "\"", " ")
do shell script "python ~/postmusic.py \"" & artist_name & "\" \"" & track_name & "\""

正直,AppleScriptはほとんど触ったことがなかったので,色々なページを切り貼りです.
文字列の置換はこちらのページを,iTunesの操作はこちらのページを参考にしました.
置換は何をしているのかというと,トラック名やアーティスト名にダブルクォーテーションが入っていると嫌な気がしたので入れただけです.
無くても動きそうな気がします.
AppleScriptは色々面白く,Macで動いているアプリケーションを外側から突っつくことができます.
今回は曲名とかを取得するだけでしたが,iTunesなら再生したり止めたりすることもできます.
さらに,~/Library/iTunes/Scriptsに作ったAppleScriptを置くと,iTunesのメニューバーに項目が現れます.
f:id:k_kinukawa:20101012150626p:image
iTunesは「あいちゅーんず」と「ず」まで発音する派です.

python script

pythonの方では,渡された曲名とアーティスト名を軽く整形してからFacebookに投げます.
ただのHTTP POSTです.
postmusic.py

# -*- coding: UTF-8 -*-
import sys
import urllib

user_name = "k.kinukawa"
access_token="your access token"

argvs = sys.argv
for argv in argvs:
    print argv

message = "I'm playing "+ argvs[1] + " : " + argvs[2] + " on iTunes"
url = "https://graph.facebook.com/" + user_name + "/feed"
params = urllib.urlencode({'access_token':access_token, 'message':message})
f = urllib.urlopen(url, params)
print f.read()

簡単ですね.
ポイントは,access_tokenです.
こいつを取得さえすれば,何とかなります.

Facebook

一番ハマったのは,Facebookでoauthのアクセストークンを取得するところでした.
おれおれアプリでwebで運用しなくても,まずはFacebookアプリを登録し,自分がそのアプリを利用するという形になります.
参考にしたのは
公式ページ
こちらのページ
です.


まず,Facebookの開発者ページで新規アプリケーションを作成します.
色々登録すると,アプリケーションIDとシークレットキーが手に入ります.
ここからが手間がかかるのですが,こちらのページのAuthorizationの項目を見ながらがんばってアクセストークンを取得します.
自分は,公式にもあるPythonのGoogle App Engine環境で取得しました
App EngineのコードにアプリケーションIDとシークレットキーを書く部分があるので,そこを修正.
ローカルhttp://localhost:8088/で起動し,このURIをサイトURLとして使います.
途中,なんど試しても

{"error":{"type":"OAuthException","message":"Invalid OAuth access token."}

が返ってきてしまいやめようかと思ったのですが,Facebookアプリの設定でサイトのURLを設定していなかったのが原因でした.
サイトURLの設定にも,上記の場合のhttp://localhost:8088/にあたるURLを設定しておきます.
そしてあとはこちらのページとにらめっこしながら何とかアクセストークンを取得できました.
※追記にも書きましたが,authorizeの時にはscope=user_photos,user_videos,publish_streamを指定しないと自分のアカウントにアクセスできません.

けっか

こんな感じのおれおれアプリができたので,クールな曲を聴いているときにはみんなにアピールできます.
f:id:k_kinukawa:20101012150627j:image
oauth周りが人力すぎるので,誰でも使ってくださいーとは言い難いですが,使いたい人は自由に使ってください.
半日くらいでこういうのができるっぽいので,これから和製アプリがもっと増えれば楽しいだろうなー.
10月15日にはid:amachang首謀の同時多発ログイン会があるみたいなので,また一気にアクティブユーザーが増える予感がする.
私はこちらです k.kinukawaのfacebook

追記

このエントリー書いて少ししたら,
{"error":{"type":"OAuthException","message":"Error validating access token."}}
というエラーが出るようになった.
Facebookログアウトしたから?Google App Engineのローカルサーバ落としたから?と思い,色々試してみたけど変化無しで,結局はアクセストークン取り直したら動くようになった.
oauthの仕様的に,自分なにかやらかしているのかな.
原因がわかりしだい追記します.

追記2

OAuthのキーを取り直しているうちにいくつか気がついたことがあるのでメモ.
まず,手順を整理.

ローカルでGAEのサーバを起動しておく

PythonのGAEサーバをローカルで立ち上げておく.
このサーバのURLがリダイレクトURLになる.

何処かにURLを書き出しておく

authorizeするときに2回ほどURLを打ち込むので何処かに書き出しておくと楽.
自分の場合は,

https://graph.facebook.com/oauth/authorize?client_id=アプリケーションID&redirect_uri=自分の場合はhttp://localhost:8088/&scope=user_photos,user_videos,publish_stream

https://graph.facebook.com/oauth/access_token?client_id=アプリケーションID&redirect_uri=上記と同じhttp://localhost:8088/&client_secret=シークレットキー&code=

を用意した.

一つ目のURLにアクセス

ローカルサーバが動いている状態で上記最初のアドレスにアクセスすると,ログイン画面みたいなのが表示されている.
このときに,URLを見るとcode=の部分にコードが表示されているので,コピーして上記下側のURLのcode=にドッキングしておく.

二つ目のURLにアクセス

先ほどcodeをドッキングさせたURLにアクセスすると,ブラウザ画面に
access_token=peroperopero-pero
みたいにアクセストークンが表示される.
authorizeの時に,scope=offline_accessを指定していないと,expiresも指定されるので注意.
先のアクセストークンが使えなくなったのは,ここが原因かもしれない.

追記3

やっぱり、scope=offline_accessを指定したら
{"error":{"type":"OAuthException","message":"Error validating access token."}}
はでなくなった。
もうしばらく様子を見る。