Skip to content


FriendConnect向けあしあとガジェット公開とコード解説

FriendIntroducerはFriendConnectを試すことに主眼を置いて作ったガジェットだったため、それほど実用的なものではありませんでした。そこで、本格的に使えるガジェットとして、MyBlogLogやgooあしあと、Yahooログール的ガジェットとしてFootprintsを作りました。

Footprintsとは?

Footprintsは、サイトメンバーの訪問を記録するガジェットです。百聞は一見にしかず、このブログの左ペイン一番下にあるガジェットをご覧ください。もしこのサイトのFriendConnectに登録していなければ、Joinしてみてください。ログインしていない場合はしてください。 Footprints1 ご想像通り、ログインした状態でブログを訪問すると、あしあととして訪問記録が残ります。ほかの人が見ると、どのくらい前に訪問したかが分かります。また、最近流行の(?)あしあとを消す機能も実装済みです。 ガジェットXMLはhttp://devlab.agektmr.com/OpenSocial/FriendConnect/Footprints.xmlになりますので、欲しい方はご自由にお持ちください。貼り方はこちらを参考にしてください。

コードと動作の解説

FriendConnectとはいえ、中身はただのOpenSocialガジェットです。OpenSocial本も発売間近、mixigooホームのOpenSocial対応も近いということで、今回はサンプルコード付きでガジェットの内容を解説してみたいと思います。

基本的な動作

まず、あしあとの記録方式ですが、FriendConnectは残念ながらmakeRequest未対応のため、外部サーバーのDBに保存、なんてことはできません。AppData(Persistent API)を使って保存しています。AppDataはガジェット+ユーザーの組み合わせごとに存在するのですが、残念ながらOWNERであるブログ自体のAppDataには保存できないことが判明しました。この辺りはPermissionが絡んでくるのですが、一般的なOpenSocialとは事情が異なるため、特殊な権限の割り振りになっていると思われます。 この問題を解決するために考えたのが、VIEWERごとに自分のAppData領域にデータを保存する、という技。OWNERの友達のAppDataをまとめて取得すれば、似たような状況が作れるはずです。今回はこの方式でうまく実現することができました。 つまり、1つのデータ領域に配列であしあとを記録して行くのではなく、メンバーごとに最終アクセス日時をあしあととして記録し、Persistent APIのnewFetchPeopleAppDataでメンバー全員分をまとめて取得しています。

コード解説

        init:function() {
          // データリクエストオブジェクトを生成
          var req = opensocial.newDataRequest();
          // 閲覧者(viewer)の情報を取得
          var params = {};
          params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = [opensocial.Person.Field.PROFILE_URL];
          req.add(req.newFetchPersonRequest(opensocial.IdSpec.PersonId.VIEWER, params), 'viewer');
          // メンバー(OWNERの友達)のAppDataをまとめて取得
          var idspec = opensocial.newIdSpec({'userId':opensocial.IdSpec.PersonId.OWNER,
                                             'groupId':opensocial.IdSpec.GroupId.FRIENDS});
          req.add(req.newFetchPersonAppDataRequest(idspec, 'footprint'), 'footprint');

          // 上記2つの取得リクエストをまとめて投げ、callback関数で受け取ります
          req.send(function(response) {
            if (!response.get('viewer').hadError()) {
              fp.viewer = response.get('viewer').getData();
            }
            if (response.get('footprint').hadError()) {
              fp.footprints = [];
            } else {
              var footprints = response.get('footprint').getData();
              var exist = false;
              // AppDataはユーザーごとに返ってきますので、ループで回します
              $.each(footprints, function(footprint) {
                // AppDataは文字列しか受け付けませんので、取得時にJSONオブジェクトに戻してやります
                var json = gadgets.util.unescapeString(this.footprint);
                var foot = gadgets.json.parse(json);
                if (fp.viewer !== null) {
                  // 閲覧者と一致した場合は上書き
                  if (foot.id == fp.viewer.getId()) {
                    exist = true;
                    foot.id = fp.viewer.getId();
                    foot.name = fp.viewer.getDisplayName(),
                    foot.thumbnail = fp.viewer.getField(opensocial.Person.Field.THUMBNAIL_URL),
                    foot.profile = fp.viewer.getField(opensocial.Person.Field.PROFILE_URL),
                    foot.timestamp = (new Date()).getTime();
                    // 新しいあしあとをAppDataに記録
                    fp.setFootprint(foot);
                  }
                }
                fp.footprints.unshift(foot);
              });
              if (!exist && fp.viewer !== null) {
                // 今まで一度もあしあとを記録したことがない人の場合、追加します
                var foot = {'id':         fp.viewer.getId(),
                            'name':       fp.viewer.getDisplayName(),
                            'thumbnail':  fp.viewer.getField(opensocial.Person.Field.THUMBNAIL_URL),
                            'profile':    fp.viewer.getField(opensocial.Person.Field.PROFILE_URL),
                            'timestamp':  (new Date()).getTime()};
                fp.footprints.unshift(foot);
                fp.setFootprint(foot);
              }
              // 時系列でソート
              fp.footprints.sort(function(a, b) {
                return b.timestamp - a.timestamp;
              });
              // レンダリングします
              fp.showFootprints();
            }
          });
        },

ユーザーごとにAppDataを保存する部分は下記のコードです。

        setFootprint:function(foot) {
          // あしあとのデータオブジェクトを文字列に変換
          var str = gadgets.json.stringify(foot);
          var req = opensocial.newDataRequest();
          // 閲覧者のAppDataに記録
          req.add(req.newUpdatePersonAppDataRequest(opensocial.IdSpec.PersonId.VIEWER, 'footprint', str));
          req.send();
        },

OpenSocial的に役立ちそうな部分のみ抜粋していますが、上記コードで基本的な動作を行っています。ソースコード全体を読みたい方はこちらから。

まとめ

FrienConnectの特殊な環境としては、前述のPermission問題。それからmakeRequestの問題が分かってきました。いずれもプライバシーの重要性に配慮した結果と思われます。 Permissionについては、一般的なSNS上のOpenSocialでは、VIEWER自身がガジェットをインストールしているかどうかで挙動が変わりますが、FriendConnectではOWNERが常に仮想人格であることから、そもそもその前提がなりたたないため、特殊な動きをしているようです。 makeRequestについては、技術的な問題は既に解決済みのはずですので、特殊なPermission下で取得されたプライバシーに関わるデータを外部サーバーに安易に保存されることを避ける狙いがあるのではないでしょうか? 何はともあれ、このガジェットを使うと、「ああ、ブログをコミュニティに変えるってこういうことなのか」と、(少しだけ)感じることができます。ぜひお試しください。

Posted in FriendConnect, Google, Mac, OAuth, OpenSocial, SocialWeb, Widget.

Tagged with , , .

  • Hi Eiji, thanks so much for sharing your Footprint gadget. It's a great tool. I downloaded it and installed on my blog but what did I do wrong? It's not appearing correctly. Help! I'm at http://studio618.blogspot.com, and the gadget is on the right sidebar at the bottom. Sorry to bother you!
    Theresa
  • Hi Theresa.
    I'm not quite sure what you did on your blog. Also, I'm not familiar with Blogspot's functionality. But it seems like you just pasted my footprint gadget's source code onto somewhat kind of form on blogspot. Am I right?

    If so, it won't work. Try following page. There should be official link to my gadget.
    http://www.google.com/friendconnect/admin/site/start?hl=en
blog comments powered by Disqus