このブログ(MT)ともう一つのブログ(WP)で更新pingのリストを共通化したかったので、練習&リハビリがてら簡単なpingのproxy的なCGIを作ってみました。更新pingを受けてリストになっている送信先に送るだけという単純なものです。ping-o-maticやpingooの超ミニチュアみたいな感じですね。
WordPressは更新時にキューイングしてからpingするのでさほど遅くはありませんが、MovableT ypeの場合、更新すると全部にpingを撃つまで終わらないので更新完了に時間がかかってしまうのが少し気になっていました。別なCGIにして高速化できないかという考えです。
ping送信時の挙動はMovableTypeとWordPressで異なっているようです。
- MTは単純に新規の記事の投稿時にのみ、その場で送信。その時点で失敗したらもう送れない仕様のようです。送るのははpingのみ。
- WPは修正だけであっても、とにかく更新毎にpingを撃ちます。また送信のタイミングは記事の保存時ではなくバックグラウンドで走るスクリプトが少し後で送ってきます。またextendedPingとpingの両方を撃つようです。
スクリプトはとりあえずXMLRPCのweblogUpdate.pingとextendedPingを受け付けるようにしておき、pingはなにもしない、extendedPingは失敗したらpingにfallbackするようにしました。
実行にはXMLRPC::Liteを使っているのでUbuntuではlibsoap-lite-perl、CentOSではperl-SOAP-Liteが必要です。
MTで動かないので、いったんスクリプトは差戻しで。。。お恥ずかしい。
use XMLRPC::Transport::HTTP;
use XMLRPC::Lite;
my $logfile = "<MyLogFile>";
my @pingservers = (
'http://rpc.weblogs.com/RPC2',
'http://ping.feedburner.com',
'http://rpc.pingomatic.com',
#...
'http://www.bloglines.com/ping',
);
my $server = XMLRPC::Transport::HTTP::CGI
->dispatch_to('weblogUpdates')
->handle;
package weblogUpdates;
use POSIX qw(strftime);
# @0:weblogUpdates, @1:blogname,@2:URL
sub ping {
my $blogname = @_[1];
open(FD, ">>$logfile");
flock(FD, LOCK_EX);
$now_string = strftime "%a %b %e %H:%M:%S %Y", localtime;
print FD $now_string, " ping from $blogname ignored\n";
close FD;
return {'message' => "Thanks for the ping", 'flerror' => 0};
}
# @0:weblogUpdates, @1:blogname,@2:URL,@3:Permalink:@4:RSS
sub extendedPing {
shift(@_);
my $blogname = @_[0];
open(FD, ">>$logfile");
flock(FD, LOCK_EX);
print FD $now_string, " ex-ping from $blogname start\n";
my $succ = 0;
my $total = 0;
$now_string = strftime "%a %b %e %H:%M:%S %Y", localtime;
foreach $p (@pingservers) {
my $result = XMLRPC::Lite
-> proxy($p)
-> call('weblogUpdates.extendedPing', @_)
-> result;
print FD $now_string, " ext: ",$p," res=",qq/$result->{message}($result->{flerror})\n/;
if (!$result || $result->{flerror} != 0) {
my $result = XMLRPC::Lite
-> proxy($p)
-> call('weblogUpdates.ping', ($_[0], $_[1]))
-> result;
print FD $now_string, " fallback: ",$p," res=",qq/$result->{message}($result->{flerror})\n/;
}
$succ++ if ($result && $result->{flerror} == 0);
$total++;
}
close FD;
return {'message' => "Thanks for the ping($succ/$total)", 'flerror' => 0};
エラー処理がいまいちで、どこかで接続に失敗したら中断してしまったりします。on_faultコールバックを使えばいいのかな?