Tender Surrender

今日から、OpenSocial機能提供に向け、iGoogleでsandboxの利用が可能になりました。これは明白に、Google自身がソーシャルネットワークを基盤とした仕組みになっていくことを意味しています。以前Maka-Makaと呼ばれるプロジェクトが存在し、Google独自のSNSサービスが始まるという話題がありましたが、それがOpenSocialというオープンな形を取り、予想していたとはいえ、iGoogleという形で現実のものにされると、さすが、としか言いようがありません。

で、早速試してみました。

まずはサインアップ。こちらからできます。(言語設定は英語にしておかないと、サインアップしてもsandboxが利用できないようです。)

http://code.google.com/apis/igoogle/docs/anatomy.html

これが新しいiGoogleの画面。

画面左にあるのがインストールしたアプリケーション/ガジェット。これをクリックするとキャンバスビューが開きます。

画面右側にはUpdateとしてアクティビティストリーム(行動履歴)が表示されるとのことですが、まだ確認できていません。SNSですから、友達リストがあってもおかしくないのですが、sandboxでは友達なしの状態からスタートし、sandboxに登録しているユーザー同士でなければ友達になれないとのこと。どうやって友達になれるかは、まだ不明。実際のサービス時はGoogle Talk/Gmailのアドレス帳からスタートすることは容易に想像できます。

また他にも、ガジェットごとの設定項目の表示方法が変更されているようです。

で、せっかくのsandboxですから、早速以前作ったFriendIntroducerを試してみました。OpenSocialとはいえ、コンテナごとにビュー名は若干違うよね、ということで、ガジェットXMLにhomeビューを追記し、Developerガジェットから追加。

んー。友達がいないので、当然こういう表示になってしまいますが、動いていることは確認できました。やはりそこはOpenSocial。

まとめ

あくまで基盤とはいえ、Googleは本当に恐ろしい存在です。すべてのウェブサービスを飲み込めるくらい、地を這ってる。auやlivedoorのGmailしかり、Google App Engineしかり。何でもかんでもGoogleに乗っけてしまえってくらい。

そしてGoogleにはAndroidもあります。そう、携帯電話のアドレス帳もこの友達リストに接続できるようになるでしょう。そうすると、友達のブログ更新をメールで受け取ったり、そのままケータイで閲覧したりといったことがユーザーに何のストレスも与えずに可能になります。

あと足りないのはプロフィールビューでしょうか。Google MapやGoogle Groupsで部分的に実現されてはいますが、これがどういう形で結実していくか、見物です。

Read on...

MySpaceで公開されているMDP(MySpace Developer Platform)には、OpenSocialだけでなく独自のRESTful APIも含まれており、これを使うことでサーバーサイドにアプリケーションを作ることもできるようになっています。今回は、MDPのRESTful APIのOAuth認証にフォーカスを当ててみます。

OpenSocial/MDPのOAuthについて

OAuthとは、ユーザーとユーザーが利用したいサービス(以後サービスプロバイダ)を仲介するOpenSocial等のコンテナ(以後コンシューマ)が、サービスプロバイダの認証情報を知ることなくAPIを操ることを可能にする、認可のためのプロトコルです。

例えばユーザーがコンシューマ上でサービスプロバイダのアプリを利用しようとすると、サービスプロバイダのドメイン上にある認証画面にリダイレクトされ、ユーザーが許可をし、そこではじめて、コンシューマがサービスプロバイダのAPIを利用可能になる、という使い方が想定されています。

しかし、現在のところOpenSocialで規定されているOAuthはフルスペックではありません。ユーザーがサービスプロバイダの認証画面にリダイレクトされたり、コンシューマとサービスプロバイダがトークンを交換したりといった仕様は想定されていないのです。

これはOpenSocialガジェットがJavaScriptで動作しているためトークンを管理できない、等の理由があるようですが、MySpace独自のRESTful APIでも条件は同じようで、コンシューマキーとコンシューマシークレットがあれば、トークンなしでOAuth認証を行うことができます。

※OAuthの詳しい仕様に関してはこの辺りを参考にしてください。

アプリケーションプロフィールを作る

まずはMySpaceでアプリケーションを作る準備をします。

MySpaceでアプリケーションを作るためには、ユーザーアカウントとアプリケーションのプロフィールアカウントが必要です。下記のサイトにスクリーンショット付きで解説がありますので、参考にしてください。

MySpaceアプリケーションを作ろう – ラーニング人生。

OAuth認証の準備

アプリケーションプロフィールが作れたら、XMLやJavaScriptのコードは不要です。今回の目的はRESTful APIの認証を試すところにありますので、画面左のMy Appsをクリックし、作成したアプリケーションプロフィールのEdit Detailsをクリックしてください。

画面下部にOAuth Consumer KeyとOAuth Consumer Secretという部分があります。RESTful APIにアクセスするには、これらが必要になりますので、メモ帳などにコピペしておいてください。OAuth Consumer Keyは任意に変更できますので、変更してもよいかもしれません(保存は忘れずに)。 

OAuth Toolで認証してみる

OAuthではコンシューマキーとNonce、Timestampなどから署名(Signature)を作って認証を行います。署名の作り方は複雑なので、今回はMDPで提供されているOAuth Toolを使って試してみます。

画面右にある項目を埋めていきます。

  • Server: サーバーURL。RFC3986で言うschemeとauthorityに当たります。ここではhttp://api.myspace.comとします。
  • ResourceURL: サーバーURL以降のパス。RFC3986で言うpathに当たります。queryとfragmentは含みません。ここは/users/{user_id}/friendsとして、user_idにはあなたのユーザーIDを入力してください。他の利用可能なエンドポイントはここに記載されています。
  • Request Method: HTTPメソッド。GETとします。
  • Consumer Key: OAuthのコンシューマキー。先程メモったConsumer Keyを入力してください。
  • Consumer Secret: OAuthのコンシューマシークレット。先程メモったConsumer Keyを入力してください。
  • OAuth Token: トークン。正式なOAuthではサービスプロバイダに許可を受けてアクセストークンと交換し、初めて認可されます。今回は空の状態にしてください。
  • OAuth Token Secret: トークンシークレット。正式なOAuthでトークンの交換に必要になります。今回は空の状態にしてください。
  • OAuth TimeStamp: TimeStamp。UNIXタイムで現在時刻を入力します。今回は空の状態にしてください。
  • OAuth Nonce: Nonce。何でもよいですが、毎回必ず違う値を送る必要があります。今回は空の状態にしてください。
  • Signature Method: 署名方式。HMAC-SHA1を選択。
  • Version: OAuthのバージョン。1.0とします。
  • OAuth Mode: OAuthモード。Authorization Headerとしてください。
  • Query options: OAuth Toolの使い方。Generate URI and Submitとしてください。

これでOK。executeをクリックします。

Response Bodyにどんな表示が返ってきたでしょうか。自分の友達リストが返ってきていれば成功です。Resource URLの最後に”.json”を付け加えると、結果をJSON形式にすることもできます。

まとめ

実はこのやり方のOAuthは、外部サーバーからコンテナであるMySpaceに対してリクエストを投げる場合だけでなく、OpenSocialのmakeRequestで、コンテナのプロキシを介して外部サーバーに送られるリクエストでも同じやり方が利用されます。その際は当然、自分で用意するサーバーの受け口がOAuthをサポートしている必要があります。

気になるのは、やはりトークンの交換や、サービスプロバイダ側に認証を行わせる部分が省かれていること。OpenSocialとOAuthは非常に相性が良いと思っていたのですが、認証が出来ないとなると、サービスプロバイダが持つUserIDとコンテナのUserIDを紐付けたりといったことができないことになります。僕が仕様を勘違いしているだけなのか、今後OAuthにもちゃんと対応して行くのか。

makeRequestを使った外部サーバーとのデータ交換については、また別の機会に解説します。

※API(OAuth Tool?)が不安定なようで、お昼はうまくいったのにこの記事を書いている時点では、なぜかNot Foundが返ってきてしまいました・・・

Read on...

OpenSocialアプリケーションを作る(1)では、ガジェットの仕組みと、Orkutでアカウントを取得するところまで書きました。今回は、前回紹介したアプリケーションのコードを解説します。

このアプリケーション(FriendIntroducer)は、自分が見た場合は友達の紹介文を書くことができ、他人が見た場合はその人に向けて書かれた紹介文を読むことができる、というmixiなどにもよくある簡単なアプリケーションです。JavaScriptやjQuery的にはもっと賢い実装方法があると思いますが、今回はOpenSocialのコードにフォーカスしますので、アホなコードは大目に見てください。

ガジェットXML

< ?xml version="1.0" encoding="UTF-8" ?>
<module>
<moduleprefs title="Friend Introducer" title_url="" description="Introduce your friend!" height="100">
  <require feature="opensocial-0.7" />
  <require feature="views" />
  <require feature="dynamic-height" />
 </moduleprefs>
<content type="html" view="canvas">
  < ![CDATA[
  <link href="http://devlab.agektmr.com/OpenSocial/css/FriendIntroducer.css" rel="stylesheet" type="text/css">
  <script type="text/javascript" src="http://devlab.agektmr.com/OpenSocial/js/jquery.js"></script>
  <script type="text/javascript" src="http://devlab.agektmr.com/OpenSocial/js/FriendIntroducer.js">< /script>
  </script><script type="text/javascript">
    gadgets.util.registerOnLoadHandler(FriendIntroducer.init);
  </script>
  <div id="title"></div>
  <div id="friends"></div>
  <div id="message"></div>
  ]]>
 </content>
</module>

ここでは

  • ガジェットの設定
  • 外部のCSSやJavaScriptを読み込み
  • 初期化スクリプトの呼び出し
  • 表示用DIV指定

を行っています。

<content type="html" view="profile">

Contentはhtmlタイプ、profileビューと指定しました。typeにはhtmlとurlが選択可能ですが、htmlとして内容をContentタグで囲まれた部分に記述しています。viewはOpenSocialの仕様上profile、canvasが想定されていますが、コンテナによってhomeやpreviewが存在するようです。ここでは例としてcanvasを使用しています。

また、viewを指定しない場合はdefaultビューとして扱われます。コンテナは表示場面(コンテキスト)によってビューを切り替えますが、Content内でviewを取り出してJavaScriptで処理を分ける方法もあります。

Contentの内容

Contentの内容は、基本的に通常のウェブページと同じように扱うことができ、HTMLで書くことができますが、

  <script type="text/javascript">
    gadgets.util.registerOnLoadHandler(FriendIntroducer.init);
  </script>

このようにgadgets.util.registerOnLoadHandlerを使って初期化処理を入れることができます。

このアプリケーションでは、表示テンプレートとして空のdivタグを3つ用意しています。

JavaScriptのコード

JavaScriptのソースコードはここにありますが、抜粋して紹介します。

$('#friends').html('Requesting friends...');
    var req = opensocial.newDataRequest();
    req.add(req.newFetchPersonRequest('VIEWER'), 'viewer');
    req.add(req.newFetchPeopleRequest('VIEWER_FRIENDS'), 'friends');
    req.add(req.newFetchPersonAppDataRequest('VIEWER', 'Introduction'), 'intro');
    req.send(FriendIntroducer.onLoadViewerFriends);

最も基本的な処理となる、閲覧者、閲覧者の友達、保存したデータを取り出す処理です。

opensocial.newDataRequest()でデータリクエストオブジェクトを作り、addで3種類のリクエストを追加、最後にsendでコールバック関数を指定した上、データリクエストを送信しています。3種類のリクエストにはそれぞれ後で区別するためviewer, friends, introという名前(キー)を付けています。

var viewer    = response.get('viewer').getData();
   var friends   = response.get('friends').getData();
   var intro     = response.get('intro').getData();

コールバック関数では、引数(response)を使って、response.get(キー名).getData()でリクエストしていたデータを取り出すことができます。

var viewer_id = viewer.getId();
    var json = null;
    if (intro[viewer_id]) {
      if (intro[viewer_id].Introduction) {
        var json_str = gadgets.util.unescapeString(intro[viewer_id].Introduction);
        var json = eval(json_str)[0];
      }
    }

introは、このアプリケーションを使ってコンテナのデータ保存領域に予め保存しておいた内容、つまり「以前保存した友達の紹介文」です。

$('#title').html('<p>Friends of '+viewer.getDisplayName()+':</p>');
    var html = '';
    if (friends.size() == 0) {
      $('#message').html("<p>You don't have any friends yet!</p>");
    }

友達が誰もいない場合を考慮して、メッセージを表示しています。

friends.each(function(person) {
      var t = FriendIntroducer.template.friend_list_canvas;
      t = t.replace('##thumbnail_url##', person.getField(opensocial.Person.Field.THUMBNAIL_URL));
      t = t.replace('##profile_url##',   person.getField(opensocial.Person.Field.PROFILE_URL));
      t = t.replace('##display_name##',  person.getDisplayName());
      t = t.replace('##input_id##',      'input_'+person.getId());
      if (json) {
        t = t.replace('##intro_text##',  json[person.getId()] ? json[person.getId()] : '');
      } else {
        t = t.replace('##intro_text##', '');
      }
      html += t;
    });
    $('#friends').html('<ul>'+html+'</ul>');

OpenSocialでは配列をなめる、いわゆるiterationも仕様に含まれていて、eachを使うことができます。ここでは、友達のリストをループして、友達の名前やサムネイル画像、保存されていた紹介文をHTMLテンプレートに埋め込んでいきます。

ここまでで、友達の紹介文を書き込むことができるcanvasページの表示することができました。次に、友達の紹介文をユーザーが書き込んだものと想定し、投稿して保存するところまでを解説します。

データの保存

OpenSocialはコンテナにデータ保存領域を持っており、アプリケーションがデータを保存することができます。これはパーシステントデータ(Persistant data)や、アプリケーションデータ(AppData)と呼ばれています。アプリケーションデータはバージョン0.7ではエスケープした文字列のみサポートしています(次のバージョンではJSONそのものの保存も可能になるようです)。

var list = $('#friends ul li');
    var intro = "{result:[{";
    for (var i=0; i < list.length; i++) {
      var textarea = list[i].lastChild.lastChild;
      var uid = textarea.id.substring(6);
      var intro_text = textarea.value.replace("'", "\\'");;
      intro += "'"+uid+"':'"+intro_text+"'";
      intro += (list.length-1)==i ? "" : ",";
    };
    intro += '}]};';
    var req = opensocial.newDataRequest();
    intro = gadgets.util.escapeString(intro);

この処理は、ユーザーが友達の紹介文を書き終わって「投稿ボタン」を押すことでトリガーされるものです。DOMを辿って各友達のユーザーIDと紹介文の内容を取得する、普通のJavaScriptです。取得した内容はJSONの文字列になるよう連結し、エスケープすることで、アプリケーションデータとして保存が可能になります。

req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'Introduction', intro));
    req.send(function() {
      $('#message').html('<p>Your introduction has been submitted.');
    });

最後に、JSON形式になった文字列をデータリクエストオブジェクトに追加して送信して、完了です。

まとめ

解説というよりはソースコード並べただけみたいな記事になってしまいましたが、OpenSocialアプリケーションのほとんどがJavaScriptでできてしまうということは、分かったかと思います。次回は外部サーバーとの連携を行うmakeRequestに触れたいと思います。</content>

Read on...

百式の中の人がやっているIDEAxIDEAというブログで募集があった「OpenSocialとかどうよ?的な勉強会」に行ってきました。場所は汐留のMySpaceジャパンオフィス。本国からエンジニアが来日しているとのことで、聞きたいことリストを用意しての参加です。

MDPとOpenSocialの関係

MDPとはMySpace Development Platformの略。MDPはOpenSocialより広い範囲のAPIです。言い換えると、OpenSocialはMDP上に作られている、とのこと。

OpenSocialではJavaScriptが先行して仕様決定されていっていますが、コンテナプロバイダはAjaxを受け付けるREST APIを作らないとRequestに対して応答を返すことが出来ません。そこでMySpaceの開発した仕様がMySpace REST APIでした。(当然、Orkutやhi5にもこれに類するものがありますが、仕様は未公開です。hi5はあったかな?)

MySpaceにはOpenSocialとは別にMyOpenSpaceという拡張があり、opensocialreference.jsとMyOpenSpace.jsとして区別されています。位置付けとしてはMyOpenSpaceがまずあり、それをラッピングする形でOpenSocialが存在する、と言った方が正確でしょう。OpenSocialは様々なSNSの持つAPIの最大公約数を取る形でデザインされているため、独自のAPIをラッピングすれば十分な訳です。確かにこれなら、他社SNSからアプリを持ってきたとしても、OpenSocialに対応したJavaScriptでさえあれば、互換性が保てますね。

また、RESTful APIについてはOpenSocial版が登場したときにどうするつもりか?という質問をしてみたのですが、「APIを増やすだけだよ」という回答。なるほど。そりゃそうだ。現行バージョンでアプリを開発した人向けに、古いバージョン用のAPIも残していくようです。

これで、以前から気になっていたMySpaceはまだ仕様が固まっていないはずのOpenSocial RESTful APIをどうやって実装したのか?という疑問が解決しました。

OpenSocialの拡張に当たる部分とは?

  • フォトアルバム
  • ヒーロー
  • 好みの映画

等々が既に存在する独自拡張で、最も利用されているのがフォトアルバム。確かにフォトアルバムはSNSによってあったりなかったりしつつも、使われそうな機能ですね。

また、個別送信可能なメッセージ機能は?と聞いたところ、今まさに開発中だそうです。(今見たら、OpenSocialにもうあるような、、、)他にも、音楽やコメディなど、様々な分野のAPIを作っていきたいとのことでした。

アプリケーションの登録について

アプリ開発者はSandboxのアカウントを取得すればすぐに開発を始めることが出来ますが、実際にアプリを公開するためには審査を通る必要があります。審査はコードのレビューやリーガルチェック(著作権侵害等)を経て、だいたい24時間〜48時間で公開されますが、権利関係が微妙な場合はもっとかかることもあるとのこと。

聞きそびれてしまいましたが、アプリをXMLでリモートサーバーに置いた場合でも、一度アプリが審査を通過してしまうと、GoogleGadgetのようにそれ以降のサーバー上のXMLの変更は反映されないと思われます。

メモ

  • Install Callback URL、Uninstall Callback URLはそれぞれ、ユーザーがアプリをインストール、アンインストールした直後にリダイレクトされるページのURLを指定できる。デフォルトはアプリのキャンバスページ。
  • OAuthの認可用にキーとシークレットが発行される。

マネタイズ

当然メインは広告収入になると思われますが、Facebookのようにある種のレコメンド広告で収益を得る方法もありえます。他にも、アプリ開発者に対して課金することで表示位置を優遇したり、といったことも考えられます。

今のところアプリ開発者は、自社サービスの会員獲得を目的としてアプリを提供するケースが多いようですが、キャンバスビューで全画面を使うことができますので、ここに好きなように広告を入れて収益を上げてよいとのこと。将来的にはアプリを使って物販や課金する方法の提供も検討しているとのことで、夢が広がります。

アプリケーションの互換性

以前から疑問だったOpenSocialアプリケーションのSNS間の互換性について。実は自分の中では答えが出てたのですが一応聞いてみました。

まず、MySpace独自拡張の部分を利用しなければ、当然他のSNSに持って行っても使うことが出来ます。まあ、そりゃそうですよね。でも、viewやcssはサイトごとに切り替える必要があるはず。例えばOrkutではcanvas、profileという2つのviewしかありませんが、MySpaceにはhome,canvas,profile.left,profile.rightの4つが、hi5にはhomepage,canvas,profileという3つがあります。この時点で、うーん、ですね。

ただ、やり方として、コンテナのメソッドにアプリが動いているコンテナの名前を取得するAPIがあるので、それによって動作を切り替える方法もあるよ、と教えてもらいました。なるほど。

リモートサーバーにアプリを実装できるか?

RESTful APIを使えば当然外部サイトでもアプリを使えるのですが、ここではGoogleGadgetのContent type=’html’をtype=’url’にできるか?という話です。

答えは、イエス。

当然、同じドメイン配下にプロキシを作って、OAuthでMySpaceのAPIを叩く仕組みを作らなければならない訳ですが、サーバー用ライブラリも用意(準備中?)されているそうです

アプリケーションディレクトリ公開後の伸び

Facebookはアプリケーション機能公開後に急激な伸びを示した訳ですが、MySpaceについてはどうか?聞いてみたところ、今のところ目立って急激な伸びは見られないとのこと。サイト上にもあまり誘導を貼っていないことから、まだその段階に達していないとの判断と伺えます。今後APIがもっとしっかりしたものになってから、色々やるんでしょうね。メッセージ機能等による口コミにも期待しているそうです。

escapeStringとunescapeStringについて

パーシステントAPIを使う際、文字列情報しか保存できないため、JSON形式でやりとりされます。その際文字列をエスケープしてから投げたり、受け取った際はアンエスケープする必要があるのですが、Orkutやhi5で使えたgadgets.util.escapeString()とgadgets.util.unescapeString()がMySpaceで使えなかったため質問してみました。

答えはescapeStringとunescapeStringはもう使われていないはずで、今はencodeURIComponentが推奨のはずだよ、とのこと。今OpenSocialの仕様を見てみたところ、まだgadgets.util.scapeString()もgadgets.util.unescapeString()も有効のようですが、、、。

MySpace用のサンプルアプリ

以前作った友達紹介アプリのMySpaceバージョンを公開します。

http://devlab.agektmr.com/OpenSocial/MySpace/FriendIntroducer.xml

別の人がこのアプリを自分のSandboxアカウントに入れることができたか分かりませんが、参考になれば。MySpaceに2つアカウント作って試すところまではまだやっていないため、物好きな方はMySpaceの僕のアカウントに友達申請してください。

感想

  • MySpaceのエンジニアの方はAptanaを使う人が多いみたい。Javaアプリはもっさりしてて嫌いなので基本的に使わないのですが、もう一回チャレンジしてみようかな・・・。
  • 何が驚いたって、参加者10人中パソコン出した人が4人。その全員がMacBook Airユーザーだったこと!
    みんなリッチだなあ。 
  • Ozzieと写真撮ってもらった!
参加者の皆様、お疲れ様でした。

※追記(4/12)

「escapeStringとunescapeStringがもう使われていない」というのは間違いではないか?の件について、当日教えてくれたTerrenceにメールで確認しました。

どうやら「escape」と言ったのを、一般的なJavaScriptのescapeと勘違いしたらしく、彼が言っていた「escapeはもう使われていない」というのは、そちらを指していたとのこと。確かに、今はescapeよりもencodeURIComponentを使うように推奨されてますね。

で、本題のgadgets.util.escpeStringとgadgets.util.unescapeStringについては、確かに、MySpaceでは実装されていないそうです。自分で解決するしかないみたい。

Read on...