9月 14

ブログの更新をTwitterへ通知するのにFriendFeedを利用しているのですが、FriendFeedのクローラ―がフィードを取得しにくるまでTwitterへは通知されず、ひどい時は1日経っても通知されないことがありました。

これを解消するために、最近Googleによって開発・公開された新しいプロトコルPubSubHubbubに対応させました。

PubSubHubbubとは

PubSubHubbubは、今までの配信者(Publishers。以下、ブログ)と購読者(Subscribers。以下、RSSリーダー)が直接やり取りをしていたその間に、ハブ(Hubs)と呼ばれる中間サーバーを配置して、そのハブを介してメッセージのやり取りをWeb Hooksの仕組みで行うものです。
Web Hooksはある決められたアクション(たとえば、「ブログの公開ボタンを押す」など)をきっかけに動作して、決められたデータを決められたURLに決められた方法で送信する仕組みです。

いままで「更新されました?」「いや、まだです。」と304の繰り返しだったフィードの世界に、「更新したしました」きっかけで、購読者に一斉に通知が行くわけですから、こんなエコな仕組みはないと思います。

WordPressで対応するには

簡単です。プラグインを入れるだけです。
現在PubSubHubbubに対応させるためのプラグインは2つ出ていて、どちらも最新の2.8.4に対応していますし、機能的には同じですので好みで導入しましょう。

ハブのURLを登録するだけの簡単な設定画面で、しかもすでに2つのハブが登録されているので特に設定することはありません。

プラグインを有効にすると、出力されたAtomに
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="http://superfeedr.com/hubbub"/>
とハブへのリンクが追加されます。

ここから以下の流れで更新の通知がされるようになります。

  1. この新しいフィードを取得したPubSubHubbubに対応したRSSリーダーがハブへのリンクを読み取って、ハブに購読の依頼を行います。
  2. ハブは本当にRSSリーダーが依頼してきたのか確認します。確認ができたら次回の更新から通知するように動作します。
  3. WordPressで新しく記事が公開されたタイミングで、プラグインがハブに対して公開の通知を送信します。
  4. ハブは本当に記事が公開されたのか確認します。確認ができたら購読の依頼があったRSSリーダーへ通知を行います。

PubSubHubbubの実力

実際に前回の投稿がどのようになったかを追ってみました。

まず投稿後、ハブからチェックがきます(apacheのログ)。

64.233.172.18 - - [12/Sep/2009:18:42:23 +0900] "GET /feed HTTP/1.1" 200 14246 "-" "AppEngine-Google; (+http://code.google.com/appengine; appid pubsubhubbub)"

ハブのデバッグツールでハブにどのように登録されているか確認してみると、

ハブのデバッグツールのキャプチャ

無事登録されているようです。(クリックで拡大)

ではFriendFeedの方はというと、

FriendFeedのキャプチャ

WordPressの投稿ボタンを押して、登録が終わってから一拍おいてすぐ画面に現れたくらいの感覚です。

さて、本題のTwitterは

Twitterのキャプチャ

素晴らしい!画面の更新タイミングに影響していますがが、ほぼリアルタイム。

その他のPubSubHubbub対応サービス

FriendFeed以外にも、Google ReaderGoogle Alertslivedoor Readerなどが対応していて、確認できるGoogle Readerとlivedoor Readerでも確認してみました。

Google Reader

PubSubHubbubへの対応という記事は共有機能からということだったので、対応していないかもしれないと思ったんですが、

Google Readerのキャプチャ

時差なしできっちり更新に上がってきました。(クリックで拡大)

livedoor Reader

こちらは更新がされず…。

ライブドアリーダーのキャプチャ

PubSubHubbub対応後にlivedoor Readerのクローラが来ていることは確認しているので、腑に落ちないところです。

(※ 最初の更新でLDRがそのブログのpubsubhubbub対応を検出し,次の更新から更新情報を受けるようになるので,二回目の更新から反映が最速になります。)
PubSubHubbub で最速に更新を通知しつつ,舌をかまないためのテスト : nabokov7; rehash – livedoor Blog

ということなので、この更新から反映されるようになるかもしれません。
今回は確認できず。

2009/9/15 追記
やはりlivedoor Readerではすぐに更新されませんでした。
時間が経ってからの更新だとクロールによる更新なのか、ハブからの通知によるものなのか判断できないので、やはり確認できず。
livedoor Readerでちゃんとリアルタイムで更新されてるというパブリッシャーはいらっしゃるんでしょうか。livedoor Blog以外で。
ざっと調べてみたところ実践している方はいらっしゃいましたが、やはりリアルタイムでの更新は確認できていないようです。

わかりにくいPubSubHubbub

読み方の話ではなく。
複数の要素が絡まっているため、仕様が明らかとは言え、ブログ側からするとハブやRSSリーダーの挙動がわからず、更新が通知されない場合に理由がわかりにくい側面があります。

例えば、ハブへ購読依頼をするRSSリーダーが、エントリーが更新されているかどうかにかかわらず、フィード内にハブへのリンクを検出したらハブへ購読依頼をする仕様なのか(FriendFeedはこちらのようです)、エントリーが更新されたタイミングで検出・通知する仕様なのか(livedoor Readerはこちらのようです)、などです。

FriendFeedは前者のようなので、PubSubHubbub対応を行った後に、1度フィードを手動で読み込ませれば次のポストから反映されるはずです。

FriendFeedでフィードの手動取得

設定→サービス 追加/編集→マイサービスのリンクをクリック→Blogを更新(クリックで拡大)

まだまだ新しい仕組みなので、確立されるまでもう少し時間がかかるかもしれませんが、多くのサービスが対応してさらに便利になることを望みます。

参考サイト

FriendFeed→Twitterの詳しい説明が載っています。

PubSubHubbubに関する参考サイト

Tagged with:
9月 07

WordPressのコメントをOpenID対応にしました。
導入目的はコメント書き込みの敷居をいかに下げるかです。

目次

2系→3系の変更点

mixi OpenIDをWordPressで利用する方法 でも紹介しましたが、「WP-OpenID」プラグインが2系から3系に上がり、名称も「OpenID」プラグインになり、コメントフォームに含めるOpenIDのフィールド名が変わりました。

WP-OpenIDプラグイン 2系
<input type="text" name="openid_url" id="openid_url" />

OpenIDプラグイン 3系
<input type="text" name="openid_identifier" id="openid_identifier" />

設定

設定は、敷居を下げる目的なので、
「Don’t require name and e-mail for comments left with verified OpenIDs」をチェックします。
OpenIDプロバイダーになるつもりはないので「OpenID Provider Options」のチェックは全てはずしておきます。

カスタマイズ

標準ではドーンとOpenID(URL)を入力するフォームを用意するだけの簡素なものなので、あらかじめ主要なOpenIDプロバイダーへのログインボタンを用意したものへとカスタマイズしました。

コメント欄キャプチャ

OpenID認証を利用した場合は、名前とメールアドレスの入力を省くことができる設定にしたので、既存のコメントフォームにOpenIDを入力するフォームだけ追加してもユーザビリティーが悪くなります。

対応策として、「通常のコメントフォーム」と「OpenID対応コメントフォーム」を用意して、デフォルトはOpenID対応、クリックによって通常とOpenID対応がtoggleする仕様にしました。

各(X)HTMLにclassとidを付けます。

  • OpenID対応のコメントフォーム(form)にid=”openid_commentform”を設定
  • OpenID対応のコメント欄(textarea)にid=”openid_comment”を設定
  • 各OpenIDプロバイダーの画像にclass=”openid_submit”、それぞれ個別にidを付ける
  • toggleのスイッチになるリンクにid=”comment_toggle”を設定

javascript(jQuery)を追加します。

jQuery(document).ready(function(){

    jQuery(".openid_submit").click(function(){
        if(jQuery('#openid_comment').val() == ''){
            alert('コメントを入力してください。');
            return false;
        }
        var openid_target= jQuery(this).attr('id');
        var openid_url = '';
        if(openid_target == 'mixi'){
                openid_url = 'https://mixi.jp/';
        }else if(openid_target == 'google'){
                openid_url = 'https://www.google.com/accounts/o8/id';
        }else if(openid_target == 'yahoo'){
                openid_url = 'http://yahoo.co.jp/';
        }else if(openid_target == 'livedoor'){
                openid_url = 'http://livedoor.com/';
        }else if(openid_target == 'hatena'){
                var hatena_id = window.prompt("はてなIDを入力して下さい。","");
                if(hatena_id == null) return false;
                openid_url = 'http://www.hatena.ne.jp/'+hatena_id+'/';
        }else if(openid_target == 'other'){
                var open_id = window.prompt("OpenID(URL)を入力して下さい。","");
                if(open_id == null) return false;
                openid_url = open_id;
        }

        if(openid_url == ''){
            alert('不正なOpenIDです。');
            return false;
        }

        jQuery('#openid_identifier').val(openid_url);
        return true;
    });
    jQuery(".openid_submit").mouseover(function(){
        jQuery(this).css('border-color','#e6db55 #dfcd2a #dfcd2a #e6db55');
    });
    jQuery(".openid_submit").mouseout(function(){
        jQuery(this).css('border-color','#CCCCCC #AAAAAA #AAAAAA #CCCCCC');
    });

    jQuery("#commentform").hide();
    jQuery("#comment_toggle").toggle(
            function(){
                jQuery("#openid_commentform").hide();
                jQuery("#commentform").show();
                jQuery('#comment_toggle').text("OpenID認証のコメント欄に切り換え");
            },
            function(){
                jQuery("#commentform").hide();
                jQuery("#openid_commentform").show();
                jQuery('#comment_toggle').text("通常のコメント欄に切り換え");
            }
    );
});

PHP5.3.0でハマった

このサーバーではWordPressをPHP5.3.0で動かしています。
OpenIDプラグインはPHP OpenID Libraryを内包していて、OpenIDにかかわる実装はこのライブラリに依存していますが、これが5.3.0に対応していないため、素のままでは動きません。

問題の解説と解決方法はこちらのブログが詳細ですので、ご覧ください。
PHP 5.3: 参照渡しの関数/メソッドを定義してた人は call_user_func_array に注意 – 肉とご飯と甘いもの @ sotarok

PHP OpenID Libraryのオフィシャルでも5.2.4までしかテストしてないよと言っているので仕方ないところです。
修正箇所が3箇所なので、パッチを作成しました。パスを変えれば、PHP OpenID Libraryのパッチとしても動くはずです。
wordpress-openid-3.2.3-cloudrop-090907.patch.tar.gz

それから、id:sotarokさんが触れられている時とドキュメントが変わってましたので、触れておきます。

下位互換性のない変更点

旧ドキュメント

引数を参照渡しする関数に値を渡した場合の振る舞いが変更されました。 以前は値渡しとして引数を受け取っていましたが、5.3.x からは warning が生成され、 全ての参照渡しのパラメーターが NULL となります。

現在のドキュメント

引数を参照渡しする関数に値を渡した場合の振る舞いが変更されました。 以前は値渡しとして引数を受け取っていましたが、今は fatal error が発生するようになりました。 参照渡しを期待している関数に定数やリテラルを渡していたコードは、 いったんその値を変数に代入してから関数に渡すよう書き換える必要があります。

Tagged with:
preload preload preload