Facebook開発者向けドキュメントの日本語訳とTips

http://developers.facebook.com/docs/ に記載されているdocumentationの和訳と、調べていて分かったノウハウを紹介します。
Life is tough, so are we.
ドキュメント全体の目次はこちら
Facebook関連情報はFacebookページで共有しています。

FQL:ユーザ名のフリガナを得る方法

ユーザの名前をローマ字と日本語両方の表記で取得したい場合、以下のような2つのリクエストを送るのが一般的です。
(余談ですが、上記2つのリクエストを、バッチリクエストという機能を使って1度のリクエストで済ますことも可能です。)

ただし、これではせっかく日本語名がとれてもフリガナが取れません。こういった場合、FQLのuserテーブルを利用することができます。FQLのuserテーブルにはsort_last_nameとsort_first_nameというカラムが用意されていて、ユーザが日本語名を登録している場合はフリガナを返してくれます。
以下のようなクエリです。

SELECT first_name, sort_first_name, last_name, sort_last_name,name FROM user WHERE uid = 44007581
この際、locale=ja_JPを指定することを忘れないでください。
https://graph.facebook.com/fql?q=SELECT+first_name%2C+sort_first_name%2C+last_name%2C+sort_last_name%2Cname+FROM+user+WHERE+uid+%3D+44007581&locale=ja_JP
以下はGraph API Explorerで実行したときのキャプチャです。FQL Queryタブだとlocaleパラメータの指定ができないので、Graph APIタブで直接入力し、実行しています。
furigana

日本語名が登録されていないユーザの場合にはsort_last_nameとsort_first_nameもローマ字のまま返されるので、その点だけチェックするようにしてください。
{
  "data": [
    {
      "first_name": "Mark",
      "sort_first_name": "Mark",
      "last_name": "Zuckerberg",
      "sort_last_name": "Zuckerberg",
      "name": "Mark Zuckerberg"
    }
  ]
}

Open Graphに触れる 2:ユーザ認証と権限の認可

前回の「Open Graphに触れる:基本」では、Open Graphが何であるか、そしてOpen Graphにアクセスする手段としてのGraph APIについて紹介しました。今回は、ユーザ認証(authenticate)と、ユーザから権限の認可(authorize)を受ける手順を紹介します。この手順を完了してアクセストークンを取得することにより、ユーザのウォールやグループに投稿したり、イベントを作成・管理したり、Facebookページを管理したりするなど、ユーザに代わってOpen Graph上のデータを読み書きできるようになります。

アプリケーションの登録

ユーザ認証したり権限の認可を受けるには、Facebook Platformでアプリケーションを登録しなくてはなりません。ここで作成されるアプリケーションIDを用いて認証・認可を行うことになります。
まず、アプリ一覧ページへ行きます。初めてアプリを作成する場合、ここは以下のキャプチャのように空になっているので、「新しいアプリを作成」をクリックします。

create_new_app
アプリの名称やネームスペースを入力するフォームがポップアップしますので、App Nameにアプリ名を入力します。App Nameは必須ですが、App Namespaceは任意ですので、とりあえずは空のまま「続行」してください。後から設定画面で変更できます。
app-input
画像認証を求められますので、表示される文字列を入力して「続行」します。読みにくい場合は「別の文字を表示」で文字列を変更します。
captcha
ここまでの過程で、まだFacebook Platform開発者登録が済んでいない場合は、電話番号やクレジットカードを用いての本人確認を求められますので、手順に従って登録します。
それが済むと、作成されたアプリの設定画面へと遷移します。

app-setting-page
このページでまず大事なのは、以下のキャプチャの通り、Sandbox Modeを「有効」にすることです。これにより、アプリの開発関係者のみがアプリを利用できる状態となりますので、開発中はずっと「有効」にしておきます。また、「Facebookでログインするウェブサイト」に、今回利用するウェブサイトのURLを入力しておきます。認証完了時にFacebook側からアプリのウェブページへリダイレクトされますが、そのリダイレクト先のドメインと、ここで入力する「サイトURL」のドメインは一致していなくてはなりません。

sandbox

ユーザ認証と権限の認可

Facebookは認証と認可の手段としてOAuth 2.0を採用していて、ドキュメント中では、完了までのフローを以下の3つのステップで紹介しています。これら3つのステップに対し、OAuth 2.0が定めるフローの各ステップ(A~E)の対応を書いておきますので、それぞれのステップの詳細についてはOAuth 2.0仕様の4.1. Authorization Code Grantや、FacebookドキュメントのAuthentication和訳を参照してください。
User Authentication(ユーザ認証)
Facebookのログイン状態をチェックし、未ログイン状態であればユーザにログインを促します。ここで、ユーザが誰であるのかが保証されます。
4.1. Authorization Code Grantの(A)
App Authorization(権限の認可)
アプリが要求する権限のうち、全部、もしくはどれを許可するのかをユーザに確認します。ここで、アプリに対してどの権限を与えるのか理解していることが保証されます。
4.1. Authorization Code Grantの(B)と(C)
App Authentication(アプリ認証)
正しいアプリに対して権限を与えていることが保証されます。
4.1. Authorization Code Grantの(D)と(E)

実装

上記ステップのうち、ユーザ認証と権限の認可についてはAuthダイアログと呼ばれるダイアログページが担ってくれます。そのため、適切なクエリパラメータを付けてダイアログページにユーザをリダイレクトすれば、最後のアプリ認証のステップ以外は完了することになります。
Authダイアログ
ユーザをリダイレクトするAuthダイアログのURLは以下のような形式になります。
https://facebook.com/dialog/oauth/?redirect_uri=CALLBACK_URL&client_id=APP_ID&state=ANTI_CSRF_STR
ここで渡すそれぞれのパラメータは以下の通りです。
redirect_uri認証完了時にユーザが遷移してくるページのURLを、URLエンコードしたもの 
client_idアプリ設定画面のApp IDの項目に出ている数値 
state(オプション)CSRF対策の為に用いられる文字列。完了時にこの値が返されるので、アプリ側でもこの値は保持しておき、同じ値が返されているかを比較します。
scope(オプション)基本データへのアクセス権限以外にも権限が必要な場合に指定するパラメータ。詳細は後述します。

サンプルは以下の通りです。
https://facebook.com/dialog/oauth/?redirect_uri=https%3A%2F%2Fsample.com%2Fauth_callback&client_id=1234567890&state=vlXgu64BQGFSQrY0ZcJBZASMvYvTHu9GQ0YM9rjPSso
上記URLへとユーザが遷移すると、Facebook未ログインであればログインを促され、ユーザが誰であるかが保証された上で以下のようなダイアログが表示されます。
auth-dialog
右にある「このアプリが受け取る情報」の項目を見ると、ユーザの基本データに関するアクセス権限を与えられることが分かります。通常はscopeパラメータで各権限を要求する必要がありますが、基本データのみはデフォルトで許可されます。ユーザが「アプリへ移動」を選択すると、ユーザは基本データへのアクセス権限を許可したこととなり、redirect_uriに指定したwebページへとリダイレクトされます。ここまでで、上記3ステップのうちユーザ認証と権限の認可までが完了しました。
アクセストークンの取得
ユーザが権限を認可し、redirect_uriに指定したURLへと遷移すると、以下のようにcodeパラメータも一緒に渡されます。
https://sample.com/auth_callback?code=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX#_=_
アクセストークンを取得するには、アプリ認証のため、このcodeの他にもapp ID(client_id)とApp secret(client_secret)が必要となります。いずれもアプリ設定画面の上部に書かれているので確かめてください。これら3つの値を使って、サーバサイドで以下のURLにアクセスします。
https://graph.facebook.com/oauth/access_token?redirect_uri=https%3A%2F%2Fsample.com%2Fauth_callback&client_secret=XXXXXXXX&client_id=1234567890&code=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
この段階で、client_id,client_secret,codeを基に、適切なアプリがアクセストークンをリクエストしていることが保証され、以下のようにaccess_tokenとexpiresが返されます。
access_token=AAAXXXXXXXXXXXXX&expires=5183951
この際、redirect_uriにはダイアログ表示の際に使ったものと同じURLを指定します。この値が違った場合、「OAuthException:Invalid redirect_uri: 指定されたURLは、アプリケーションの設定で許可されていません」というエラーが返されますので気をつけてください。
また、expiresの値はアクセストークンが切れるまでの秒数を示しています。通常であれば60日(5184000秒)に近い数値が返されるはずです。
ユーザ情報の取得
ここまでで、ユーザから権限認可を受け、アクセストークンを受け取る所までは完了しました。しかし、OAuthは認証(authenticate:誰が誰であるかの保証)の手段ではなく認可(authorization)の手段であるため、この段階ではユーザIDなどの情報は渡されず、認可された権限を行使する為のトークンのみ渡されています。こういった場合には、Open GraphオブジェクトIDの代わりに"me"というエイリアスを利用します。これはユーザのアクセストークンと組み合わせた場合に有効で、オブジェクトIDの代わりに"me"を使うことで、アクセストークンの持ち主の情報へアクセスできます。
Authダイアログの段階でFacebook側でのユーザ認証が完了し、そのユーザ用のアクセストークンが発行されているため、このアクセストークンを使ってユーザ自身の情報を取得すれば、アプリ側でもユーザの身元を保証できるというわけです。
そのため、Facebookでログインする機能を実装する場合は、上記手順の最後に以下のエンドポイントにアクセスしてユーザID等を取得するのが一般的です。
https://graph.facebook.com/me?access_token=AAAXXXXXXXXXXXXX

パーミッション

Facebookアプリを作る上で、ユーザのメールアドレスやウォール投稿内容など、基本情報以上の情報が欲しい場合があります。また、ユーザに代わってウォールに書き込みしたりイベント作成するなどの権限が欲しい場合も出てきます。そういった場合は、Authダイアログを開く際のscopeパラメータに、パーミッションと呼ばれる物を足してあげます。様々な権限にはそれに対応するパーミッションが定められていて、それをscopeパラメータでリクエストし、ユーザに許可してもらうことで様々な情報の読み書きが可能となります。
例えば、emailというパーミッションを許可されればユーザのメールアドレスにアクセスできるようになり、read_mailboxというパーミッションを許可されればユーザの受信箱の中身を見ることができるようになります。以下のURLのように、カンマ区切りにしたパーミッション一覧をscopeパラメータに指定すれば大丈夫です。
https://facebook.com/dialog/oauth/?scope=email,read_mailbox,publish_actions&redirect_uri=https%3A%2F%2Fsample.com%2Fauth_callback&client_id=1234567890&state=Foo

ベストプラクティス

パーミッションを確かめる

パーミッションを要求した上でアクセストークンを取得できたとしても、リクエストしたパーミッション全てが許可されるわけではないことに気をつけてください。認証と認可の3つのステップの中で紹介した通り、ユーザはどの権限を与え、どれを拒否するか選択することができます。(詳細は「Facebook Night vol.7 発表内容まとめ 2:認証ダイアログの構成」を参照してください。)そのため、ユーザ情報を取得する際に、どのパーミッションが許可されたのかも確認することをお勧めします。以下のエンドポイントへのリクエストで、ユーザが許可したパーミッション一覧を取得できます。
https://graph.facebook.com/me/permissions?access_token=ACCESS_TOKEN
返り値は以下の通りとなります。
{
   "data": [
      { // key: パーミッション名, value: 1
         "installed": 1, // アプリがインストール済(認証済み)
         "read_stream": 1,
         "user_birthday": 1,
         "user_religion_politics": 1,
         "user_relationships": 1,
}
]
}
リクエストしたパーミッションのうち、どれが実際に許可されたのかを確認し、与えられた権限の範囲内でGraph APIを利用することとなります。現状では、ウォールへの投稿権限を拒否した上で利用開始したアプリでも、「ウォールに投稿する」オプションがチェックボックスで表示されることがあります。が、理想としてはどのパーミッションが許可されているかを必ず確認し、ウォールへの投稿権限が与えられていないのならば「ウォールに投稿する」オプションを非表示にするなどの配慮をすべきです。詳しくは「Facebook Night vol.7 発表内容まとめ 3:Batch RequestとReal-time Update API」を参照してください。
また、パーミッションの解説や一覧に着いては、Permissions和訳をご覧ください。

必要最低限のパーミッションのみ要求する

最善の機能を提供するには、ユーザから色々なパーミッションを得る必要が出てきます。しかし、最初のログイン段階でそれらを全て要求するのは、ユーザを警戒させ、離脱させてしまう原因になり得ます。こういった場合の対応については「Facebook Night vol.7 発表内容まとめ 2:認証ダイアログの構成」で以下のように紹介している通りです。
もう一点大事なことは、必要なときに必要なパーミッションのみ要求することだと思います。アプリのインストール時には全ユーザに共通して必要となる最低限のパーミッションのみ要求し、あとは設定画面を設けておいて、On / Offの切り替え時に適宜要求するなどです。Kloutは 最初のログイン時はフィード読み込みなどのパーミッションしか要求せず、設定画面でFacebook共有をOnにするときに初めて投稿系パーミッションを 要求します。自分の影響度という繊細な部分を扱うサービスなので、最初から投稿系パーミッションを要求されると、自分の影響度が勝手に投稿されると感じて ためらうユーザもいるでしょうから、そのようなユーザの不安を避ける上でも参考になる実装例だと思います。
On / Offを切り替える際、ユーザがすでに該当するパーミッションを許可しているか否かを把握し、必要に応じてパーミッションを要求する必要がありますが、それに関しては3番目のエントリで紹介します。
(※ あとから追加でパーミッションを要求する場合は、追加で要求するパーミッションのみscopeに指定して認証ダイアログに飛ばせば大丈夫です。他のパー ミッションをscopeに指定しなかったからといって、既に許可されたパーミッションが消されてしまうことはありません。)

まとめ

ここまでで、認証・認可のステップまでを完了し、ユーザの基本情報にアクセスできるようになりました。次回は、ユーザのウォールに投稿したり画像を投稿する方法を紹介します。

Open Graphに触れる 1:基本

Facebookのソーシャルグラフ

まずOpen Graphを理解するには、Facebookがソーシャルグラフと呼ぶものを理解しなくてはなりません。ソーシャルグラフについてWikipediaを見ると、以下のように定義されています。

The social graph in the Internet context is a sociogram, a graph that depicts personal relations of internet users. It has been referred to as "the global mapping of everybody and how they're related".
和訳:インターネット上でsocial graphと呼ばれるものはソシオグラムを指していて、インターネットユーザ同士の繋がりを表現するものである。「人々の繋がりと、どのように繋がっているかを示す世界規模のマッピング」とも表現される。
また、Brad Fitzpatrick氏が自身のサイトで発表したThoughts on the Social Graphでも、人と人の関係に絞って話されています。

ただし、Facebookがソーシャルグラフと呼ぶものは、人と人の関係のみにとどまりません。ドキュメントでは、「人々や人々が周りの物事に対して持つ繋がりを指すもの」と定義されています。ドキュメント中に出てくる以下の画像を見ると分かる通り、人と人の繋がりに限らず、人と物事の繋がり(いいね!した、料理した、視聴した)なども含まれています。

attachment

Open Graphとは

ここまでで紹介したソーシャルグラフを、サードパーティの開発者向けに拡張したものがOpen Graphで、そのOpen Graphへアクセスする手段がGraph APIです。このAPIを利用することで、ユーザやユーザの友だち情報、参加しているグループやイベントの情報、投稿内容など様々な情報を取得できるだけでなく、ユーザに代わって投稿したりイベント作成するなど、Open Graphへ書き込むこともできます。また、ユーザの行動(いいね!した、視聴した、料理したなど)を書き込むことも可能で、これらの行動はOpen Graph Actionと呼ばれています。このOpen Graph Actionは開発者が独自に定義することも可能です。たとえば「走った」「一気した」などの行動を定義して、「Aさんが皇居前を走った」「Bさんがテキーラを一気した」など、人と物事の繋がりを作り出すことができます。

Open Graphにアクセスする

基本

早速、Graph APIを用いてOpen Grpah上の情報にアクセスしてみましょう。一般公開されている情報ならば、アクセストークンなしでも簡単に取得できます。ブラウザのアドレスバーに以下のURLを入力してみてください。
https://graph.facebook.com/4
Facebook創設者であるザッカーバーグ氏の情報が返されます。
{
   "id": "4",
   "name": "Mark Zuckerberg",
   "first_name": "Mark",
   "last_name": "Zuckerberg",
   "link": "https://www.facebook.com/zuck",
   "username": "zuck",
   "gender": "male",
   "locale": "en_US"
}
ユーザ、Facebookページ、アプリ、Open Graph上に存在する全てのオブジェクトには固有のIDが与えられています。先ほどの例だと、https://graph.facebook.com/の後に続く4という数値です。ここを任意のIDに置き換えることで、該当するオブジェクトの情報を取得できます。
例えば、ID: 204277149587596を指定すると、私の運営するOklahomerというFacebookページの情報が返されます。
{
   "about": "http://facebook-docs.oklahome.net/",
   "description": "Facebook\u6280\u8853\u8005\u5411\u3051\u30c9\u30ad\u30e5\u30e1\u30f3\u30c8\u306e\u548c\u8a33\u3084\u3001Facebook\u7d61\u307f\u306e\u30cb\u30e5\u30fc\u30b9\u3092\u7d39\u4ecb\u3057\u3066\u3044\u307e\u3059\u3002",
   "is_published": true,
   "release_date": "2011-02-24",
   "talking_about_count": 14,
   "username": "Oklahomer",
   "website": "http://facebook-docs.oklahome.net/",
   "were_here_count": 0,
   "category": "Reference website",
   "id": "204277149587596",
   "name": "Oklahomer",
   "link": "https://www.facebook.com/Oklahomer",
   "likes": 1039,
   "cover": {
      "cover_id": 500726406609334,
      "source": "http://sphotos-g.ak.fbcdn.net/hphotos-ak-snc6/s720x720/283711_500726406609334_431792850_n.jpg",
      "offset_y": 57
   }
}

メタデータ

IDさえ置き換えれば様々なオブジェクトの情報を取得できるというのは便利ですが、時々不便なときがあります。ただIDだけ与えられていて、それがユーザなのかFacebookページなのか、それとも他の何かなのか分からない場合です。そういった場合、metadata=1を足してあげます。すると対象オブジェクトのメタデータが返され、metadata.typeの値(user、pageなど)を見ることでオブジェクトの型を知ることができます。型だけでなく、返されるフィールドの説明や、そのオブジェクトと紐づくオブジェクト群へのアクセス方法も返されます。ここに貼付けるには情報が多すぎるので、以下のURLにアクセスして試してみてください。
https://graph.facebook.com/204277149587596?metadata=1

コネクション

graph.facebook.com/OBJECT_ID へのアクセスで任意のオブジェクトにアクセスできることは分かりました。ですが、Open Graphは人と人、または人と物事の繋がりを示すものですから、取得したオブジェクトが繋がりを持つオブジェクト群にもアクセスできなくては意味がありません。これはコネクションと呼ばれ、以下の形式で取得することができます。
https://graph.facebook.com/OBJECT_ID/CONNECTION_TYPE
たとえば、Oklahomerページに投稿された画像オブジェクト群にアクセスするには、以下のようなURLとなります。
https://graph.facebook.com/204277149587596/photos
返される情報は以下の通りです。data配列の中に、オブジェクトID(id)、投稿者情報(from)、各サイズのURL(images)が入っているのが分かります。また、pagingフィールドのpreviousとnextを見ることで、ページングを行うことができます。ページングについての詳細はGraph API, FQLのページングの罠を参照してください。
{
   "data": [
      {
         "id": "204277402920904",
         "from": {
            "category": "Reference website",
            "name": "Oklahomer",
            "id": "204277149587596"
         },
         "picture": "http://photos-d.ak.fbcdn.net/hphotos-ak-snc6/181698_204277402920904_249682_s.jpg",
         "source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-snc6/181698_204277402920904_249682_n.jpg",
         "height": 153,
         "width": 158,
         "images": [
            {
               "height": 1983,
               "width": 2048,
               "source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-snc6/s2048x2048/181698_204277402920904_249682_n.jpg"
            },
            {
               "height": 153,
               "width": 158,
               "source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-snc6/181698_204277402920904_249682_n.jpg"
            },
            {
               "height": 153,
               "width": 158,
               "source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-snc6/181698_204277402920904_249682_n.jpg"
            },
            {
               "height": 581,
               "width": 600,
               "source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-snc6/s600x600/181698_204277402920904_249682_n.jpg"
            },
            {
               "height": 464,
               "width": 480,
               "source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-snc6/s480x480/181698_204277402920904_249682_n.jpg"
            },
            {
               "height": 309,
               "width": 320,
               "source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-snc6/s320x320/181698_204277402920904_249682_n.jpg"
            },
            {
               "height": 153,
               "width": 158,
               "source": "http://photos-d.ak.fbcdn.net/hphotos-ak-snc6/181698_204277402920904_249682_a.jpg"
            },
            {
               "height": 125,
               "width": 130,
               "source": "http://photos-d.ak.fbcdn.net/hphotos-ak-snc6/181698_204277402920904_249682_s.jpg"
            },
            {
               "height": 125,
               "width": 130,
               "source": "http://photos-d.ak.fbcdn.net/hphotos-ak-snc6/s75x225/181698_204277402920904_249682_s.jpg"
            }
         ],
         "link": "https://www.facebook.com/photo.php?fbid=204277402920904&set=a.204277399587571.61963.204277149587596&type=1",
         "icon": "http://static.ak.fbcdn.net/rsrc.php/v2/yz/r/StEh3RhPvjk.gif",
         "created_time": "2011-02-23T17:00:52+0000",
         "updated_time": "2011-02-23T17:00:54+0000",
         "likes": {
            "data": [
               {
                  "id": "100002002178183",
                  "name": "Philipp Kasdorff"
               }
            ],
            "paging": {
               "next": "https://graph.facebook.com/204277402920904/likes?limit=25&offset=25&__after_id=100002002178183"
            }
         }
      }
   ],
   "paging": {
      "previous": "https://graph.facebook.com/204277149587596/photos?limit=25&since=1298480452&__previous=1",
      "next": "https://graph.facebook.com/204277149587596/photos?limit=25&until=1298480451"
   }
}
自分が扱うオブジェクトに何と言うコネクションがあるのかは、先ほど示したmetadata=1を付けてオブジェクトにアクセスしてconnectionsフィールドを見ることで分かります。詳しくは各Open Graphオブジェクトのドキュメント和訳にも書かれていますのでご覧ください。

まとめ

ここまでで、Facebookが持つソーシャルグラフをサードパーティ向けに拡張した物がOpen Graphであること、そのOpen Graphへのアクセス方法を提供するのがGraph APIであること、そしてGraph APIの基本的な使い方を紹介しました。次回は、ユーザの認証と権限の認可について紹介します。

Graph APIを多用するときに便利な機能

Facebook の中核をなすのはソーシャルグラフですが、そのソーシャルグラフへ外部開発者がアクセスする手段として、Facebook Platform は Graph API を提供しています。この Graph API が提供する機能を利用すると、ユーザやその友だちの情報を取得したり、イベントやグループを作成したり、Facebook ページを管理するなど様々なことができます。ただし、情報の読み書きをするには頻繁に API を利用する必要があるため、安易に多用するとリクエストが増えてサービスのレスポンスが悪くなってしまったりします。
Facebook Platform はそれを解消するための機能をいくつか提供しているので、今回は、最近作り始めた Facebook::OpenGraph というモジュールを例にして、それらの手段を紹介します。

通常のアクセス

便利機能とは別ですが、Open Graph オブジェクトへの通常のアクセス方法です。
curl -X GET \
https://graph.facebook.com/4
一般公開されたプロパティを取得するだけであれば、とくにアクセストークンの指定は必要ありません。
Facebook::OpenGraphの場合だと以下のようになります。
my $fb = Facebook::OpenGraph->new;
my $user = $fb->fetch(4);
# 第2引数にパラメータ指定可。$fb->fetch(4, +{locale => 'ja_JP'})

返り値

$VAR1 = {
'link' => 'http://www.facebook.com/zuck',
'name' => 'Mark Zuckerberg',
'locale' => 'en_US',
'username' => 'zuck',
'last_name' => 'Zuckerberg',
'id' => '4',
'first_name' => 'Mark',
'gender' => 'male'
};

Batch Request

Batch Requestは複数のHTTPリクエストを1つにまとめる機能で、複数オブジェクトの情報を一気に取得するだけでなく、1つ1つのリクエストのHTTPメソッドを指定して読み書きを同時に扱うことも出来ます。
curl -X POST \
-F 'batch=[{"relative_url":"4","method":"GET"},{"relative_url":"44007581","method":"GET"}]' \
-F 'access_token=1234567|fooBarBuzz' \
https://graph.facebook.com
詳しくはBatch Requestドキュメントの和訳をご覧ください。

Facebook::GraphAPIだと以下のようにして複数オブジェクトを取得できます。
my $fb = Facebook::OpenGraph->new(+{app_id => 1234567, secret => 'app_secret_key'});
$fb->set_app_token;
my $users = $fb->bulk_fetch([qw/4 44007581/]);

返り値

$VAR1 = [
{
'link' => 'http://www.facebook.com/zuck',
'name' => 'Mark Zuckerberg',
'locale' => 'en_US',
'username' => 'zuck',
'last_name' => 'Zuckerberg',
'id' => '4',
'first_name' => 'Mark',
'gender' => 'male'
},
{
'link' => 'http://www.facebook.com/go.hagiwara',
'name' => "\x{8429}\x{539f} \x{8c6a}",
'locale' => 'en_US',
'username' => 'go.hagiwara',
'id' => '44007581',
'first_name' => "\x{8c6a}",
'last_name' => "\x{8429}\x{539f}",
'gender' => 'male'
}
];
また、batchメソッドを利用して個々のリクエスト内容を詳細に指定することも可能です。
my $fb = Facebook::OpenGraph->new(+{access_token => '1234567|fooBarBuzz'});
my $responses = $fb->batch([
+{ # ユーザ自身の情報取得
 method => 'GET',
relative_url => 'me?fields=picture'
},
+{ # ユーザのウォールに書き込み
 method => 'POST',
relative_url => 'me/feed',
body => 'message=TEST&link=https://developers.facebook.com/'
},
]);

FQL

FQLを利用した情報取得は通常、以下の通りです。
curl 'https://graph.facebook.com/fql?q=SELECT+display_name%2C+icon_url+FROM+application+WHERE+app_id+%3D+127497087322461'
Facebook::OpenGraphだと以下の通りです。
my $fb = Facebook::OpenGraph->new;
my $res = $fb->fql(
'SELECT display_name, icon_url FROM application WHERE app_id = 127497087322461'
);

返り値

{
'data' => [
    {
        'icon_url' => 'http://photos-c.ak.fbcdn.net/photos-ak-snc7/v43/45/127497087322461/app_2_127497087322461_1287.gif',
            'display_name' => 'app'
        }
    ]
};

FQL Multi-query

bulk_fqlを用いると、複数のfqlクエリを一つにまとめることが出来ます。
my $datam = $fb->bulk_fql(+{
"all friends" => "SELECT uid2 FROM friend WHERE uid1=me()",
"my name" => "SELECT name FROM user WHERE uid=me()",
})->{data};

返り値

[
+{
fql_result_set => [
+{
uid2 => '100004652133279',
},
+{
uid2 => '100004657083353'
},
],
name => 'all friends',
},
+{
fql_result_set => [
+{
name => 'Linda Amdgjheicghf Laustein',
},
],
name => 'my name',
},
];
また、2つ以上のクエリの依存関係も扱うことができます。
my $datam = $fb->bulk_fql(+{
"query1" => "SELECT uid, rsvp_status FROM event_member WHERE eid=12345678",
"query2" => "SELECT name, url, pic FROM profile WHERE id IN (SELECT uid FROM #query1)"
})->{data};

Fields Expansion

Fields Expansionは、これまでのfieldsパラメータの拡張を可能にするものです。以前であれば、/me?fields=picture のように fields パラメータを指定する場合、そこに指定できるのはオブジェクトのフィールドのみでした。この機能により、fieldsパラメータにオブジェクトのコネクションや、そのコネクションを構成するオブジェクトのコネクション、そしてそのコネクションを構成するオブジェクトの。。。という具合に入れ子にすることが可能になりました。
curl -X GET \
https://graph.facebook.com/me\
?access_token=USER_ACCESS_TOKEN\
&fields=name,email,albums.fields(name,photos.fields(name,picture,tags.limit(2)).limit(3)).limit(5)
このように指定した場合、ユーザのname, emailフィールドの他に、albumsコネクションを通じてユーザが所有するアルバム5件のname、さらにそれぞれのアルバムのphotosコネクションを通じて、写真3枚のname, pictureフィールド、それから写真にタグ付けされているオブジェクト2件を返します。
以下のような書き方が出来ます。
my $fb = Facebook::GraphAPI->new(+{access_token => '1234567|fooBarBuzz'});
$fb->fetch('me', +{
fields => 'name,email,albums.fields(nam.......',
});
上記のように書いていると入れ子が分かりにくいという場合は、以下のように書くことも可能です。
$fb->fetch('me', +{
fields => [
'name',
'email',
+{
'albums' => +{
'fields' => [
'name',
+{
'photos' => +{
'fields' => [
'name',
'picture',
+{
'tags' => +{
'limit' => '2'
}
}
],
'limit' => '3'
}
}
],
'limit' => '5'
}
}
]
});
user_basic_fields.yamlなどの外部ファイルを作っておくのも良いのかもしれません。というのも、通常は全件返されていたAPIが突然25件しか返さなくなったという不具合が夏にあったためです。こうして別ファイルに書いておくと、担当者でなくても把握しやすくなり、暫定的にlimit: 5000を足そうという解決策が見つけやすくなるかもしれません。
user_basic_fields.yaml
- name
- email
- albums:
limit: 5
fields:
- name
- photos:
limit: 3
fields:
- name
- picture
- tags:
limit: 2

use YAML qw(LoadFile);

my $fb = Facebook::GraphAPI->new(+{access_token => '1234567|fooBarBuzz'});
my $fields = LoadFile('user_basic_fields.yaml');
my $user = $fb->fetch('me', +{fields => $fields});

返り値

以下の通り、fileds に指定した入れ子構造が維持された状態で返されます。

{
email => 'foo_bar_buzz@tfbnw.net',
name => 'Linda Amdgjheicghf Laustein',
id => '12345678',
albums => +{
data => [
+{
created_time => '2012-11-20T10:35:36+0000',
name => 'test album',
id => 111111111111111,
photos => +{
data => [
+{
created_time => '2012-11-20T10:35:41+0000',
name => 'abc',
id => 123456,
picture => 'http://photos-a.ak.fbcdn.net/hphotos-ak-ash4/123456_s.jpg',
tags => +{
paging => +{
next => 'https://graph.facebook.com/12345678/tags?limit=2&offset=2',
},
data => [
+{
y => '50.42735042735',
created_time => '2012-11-20T10:36:55+0000',
name => '100004657083353',
x => '74.137931034483'
},
+{
y => '33.333333333333',
created_time => '2012-11-20T10:36:37+0000',
name => '100004691462769',
x => '47.931034482759'
},
],
},
},
+{
created_time => '2012-11-20T10:35:41+0000',
name => 'def',
id => 23456,
picture => 'http://photos-h.ak.fbcdn.net/hphotos-ak-prn1/23456_s.jpg',
tags => +{
paging => +{
next => 'https://graph.facebook.com/12345678/tags?limit=2&offset=2'
},
data => [
+{
y => '37.142857142857',
created_time => '2012-11-20T10:36:50+0000',
name => '100004657083353',
x => '44.137931034483'
},
],
},
},
+{
created_time => '2012-11-20T10:35:41+0000',
id => 34567,
picture => 'http://photos-g.ak.fbcdn.net/hphotos-ak-ash3/34567_s.jpg'
},
],
},
},
],
}
};

ここでは Batch Reuqest, FQL Multi-query, Fields Expansion など、複数のリクエストをまとめて HTTP リクエスト数を減らす機能に絞って紹介しましたが、OpenGraph.pm の主要なメソッドの脇には、該当ドキュメントのURLがコメントで書かれていますので、まだ作成中ですが何かの役に立つかもしれません。

Open Graphアプリとウォール投稿が一部規制される詳細

以前書いた「Open Graphアプリの規制強化 & 友だちのウォールへの投稿禁止」で、ユーザの友だちのウォールへの書き込みが禁止されることや、Open Graphアクション投稿の一部が禁止されることを紹介しました。その内容で伝わりにくい部分があったので、今回補足してみます。

友だちのウォールへの書き込み

まず一点目の大きな規制は、友だちのウォールへの投稿禁止です。具体的な流れとしては以下のようなものが禁止の対象となります。

ステップ1. ユーザのアクセストークンを用いて、ユーザの友だち一覧を取得

curl -X GET https://graph.facebook.com/me/friends?access_token=USER_ACCESS_TOKEN
返り値:
{
  "data": [
    {
      "name": "Mark Zuckerberg",
      "id": "4"
    },
    {
      "name": "Chris Hughes",
      "id": "5"
    },
    {
      "name": "Dustin Moskovitz",
      "id": "6"
    },
  ]
}
余談ではありますが、友だち一覧を得る為だけの目的で read_friendlists パーミッションを求めるアプリがありますが、そういった目的ならば read_friendlists パーミッションは必要ありません。このパーミッションは、ユーザが作成した友だちリスト(Google+でいうサークル)を取得する為のもので、 /me/friends で友だちを取得したいだけならば、特にパーミッションを求めなくても取得することができます。

こうして友だち一覧を取得するところまでは、今後もOKです。

ステップ2. 取得した友だちのウォールに対して投稿

curl -X POST \
       -F 'access_token=USER_ACCESS_TOKEN' \
       -F 'message=abcd' \
       https://graph.facebook.com/FRIENDS_ID/feed


ここで示したように、ユーザのアクセストークンを用いて、そのユーザの友だちのウォールへ投稿を行う行為が、今後の仕様変更で禁止となります。最近のメジャーなアプリで言うと、「○○City Socialがあなたのタイムラインに投稿しました」という通知が来て、自分のタイムラインにまで投稿されて驚いた人も居るのではないでしょうか?以前は、認証時に publish_stream というパーミッションをユーザから得ると、そのユーザの友だちのウォールに対しても投稿することができましたが、今後は publish_stream パーミッションを取得していても投稿できなくなります。(「Facebook Night vol.7 発表内容まとめ 1:publish_streamとpublish_actions」で publish_stream と publish_actions の違いについて書きましたが、あえて publish_stream パーミッションを選択する利点が減ることになります。)

ただし、/me/feed でユーザ自身のウォールに対して投稿するのは引き続き可能です。

Open Graph アクションの一部禁止

去年(2011年)の流れ
去年の f8 での 新 Open Graph 発表で話題となったのは、ユーザが音楽や動画を視聴すると自動的に Facebook 上で共有される機能や、ニュース記事を読むだけでそれが共有されるソーシャルリーダ機能でした。これらは frictionless share (摩擦の無い共有:手間がかからない簡単なライフログ共有)と呼ばれ、いちいちシェアボタンを押したりフォームに入力したりすることなくライフログを共有することを可能にしました。
また、これと前後して Frictionless Request という機能も公開されました。 citiville をやったことのある方なら分かるかと思いますが、何かあるたびにリクエストを送る相手を選ばされるのは面倒です。この機能を有効にすると、毎度同じプロセスを経ずともリクエストを送信できるようになるという利点があります。
このように去年の方針としては、ユーザの介入無しにライフログやリクエストが投稿されていくという、2007年当時の Beacon に近づいていく流れがありました。おそらく、スマートフォンの流通によってチェックインや写真などのライフログ共有がメジャーになり、ライフログ共有への抵抗が減った(と判断された)のがキッカケかと思います。
ところが実際のところ、勝手にライフログが共有されるのは気持ちが悪いし、スパムまがいの使われ方が多いというわけで、少なくともユーザや Facebook 自身がコントロールできる範囲に限って frictionless share を許可する流れに現在向かっているのかと思います。
今後の流れと、規制の線引き
以上のような流れがあるので、今後はユーザの意図しない形式での Open Graph アクション投稿への規制が厳しくなります。この規制を理解する上で重要なキーワードが "content consumption" で、これは、ユーザが web ページを閲覧する行為を指します。これだけがトリガーとなって Open Grpah アクションを投稿するのが今後は規制対象となります。
ただし例外として、Facebook が提供する ビルトインアクション(listen, watch, readなど)を利用する場合は、ユーザが音楽や動画を視聴したり、ニュース記事を読んだだけで Open Graph アクションを投稿することが許されます。これが、前回のエントリで説明した以下の内容です。
ということは、ソーシャルリーダーはビルトインのreadアクションを用いるのでOKでも、グラビアのプロフィールを見ただけで「欲情した」というカスタムアクションを共有するアプリは、今日以降はアウトになるということです。
現状
ここまでが、去年の Open Graph 発表と今後の流れです。で、今はどういう状態なのかというと、90日間の移行猶予期間の最中です。すでに申請通過済みの Open Grpah アクションであれば、 content consumption に該当するものでもまだ動作しますが、新規の申請は許可されません。また、すでに申請通過済みであっても、この90日の猶予期間が終われば規制の対象となります。

ただし、content consumption に該当しない用法であれば、今後もカスタムアクションの定義は許可されます。この点が前回のエントリで一番誤解を招いてしまった部分なので、気をつけてください。単純に言ってしまうと、音楽を視聴するだけで listen アクションが共有される Spotify や、ニュース記事を読むだけで read アクションが共有されるソーシャルリーダのようなものは、 listen, read などのビルトインアクションを利用しているから許可されるけど、自前で定義するカスタムアクションに関しては、そういった実装は許可されなくなるということになります。

参考までに、どこがボーダーラインになるのか、Facebookのガイドラインにあるテーブルを共有します。
シナリオ 許可される? 理由
ユーザがアプリのページを閲覧すると、ユーザのタイムラインに「閲覧した」旨が自動的に投稿され、と友だちのニューソフィードにも流れる。
No サイト上のコンテンツを閲覧しただけで自動的に投稿される。このアクション(閲覧する)は content consumption に該当する。
ユーザがアプリ内のコンテンツを閲覧し、「閲覧した」ボタンをクリックする。ユーザのタイムラインに「閲覧した」旨が投稿され、友だちのニュースフィードにも流れる。
No content consumption に該当するカスタム Open Graph アクション(閲覧する)は、意図せず何かを共有してしまったと感じて混乱する。
ユーザがアプリ内のコンテンツを閲覧し、「欲しい」ボタンをクリックする。ユーザのタイムラインに「欲しい」旨が投稿され、友だちのニュースフィードにも流れる。
Yes 共有することに関してユーザがコントロールできている。また、カスタムアクション(want)は、content consumption には該当しない。
ユーザがゲーム中でレベル達成し、「勝った」旨がユーザのタイムラインに投稿され、友だちのニュースフィードにも流れる。
Yes ユーザ自身が、投稿のトリガーとなるアクションを行った。また、カスタムアクション(win)は content consumption に該当しない。

これを見ると、単に閲覧や視聴したことだけを示すカスタムアクションを定義したり、閲覧や視聴だけをトリガーとしてそれらのアクションを投稿するのが禁止されるのが分かります。
記事検索