MovableTypeプラグイン「Hatena Bookmarker」でブクマ出来たり出来なかったり。 - nplll: Mutter

これの続き。

新規投稿したエントリをHatena Bookmarkerを使って投稿したとき、タイトルが抜け落ちてしまうことがあるのだけど、「タイトルの編集が出来ていない」ということを考えるとすんなり理解できた。
ブックマークの流れはこんな感じになってる。

  1. MovableTypeでエントリを投稿
  2. エントリをはてなブックマークにPOST(Hatena Boomarker)
  3. タイトルを自動的に取得する(はてなブックマークのクローラー)
  4. タイトルの設定が完了
  5. GET EditURIで登録済みのタイトルを取得(Hatena Boomarker)
  6. 登録済みタイトルがエントリタイトルと違っていたらPUT EditURIで編集(Hatena Boomarker)
  7. ブックマーク完了

MobavleType経由の場合、再構築処理のタイミングの関係で、3のクローラーが来るタイミングではまだエントリページが作成されていないことがある。その場合、ブックマークはとりあえずURLをタイトルとして登録される。

仮にURLがタイトルとなってしまっても、Hatena Boomarkerがそれを正常に戻してくれる。Hatena Boomarkerでタイトルを編集できない場合、タイトルはURLのまま。

再構築処理が軽い場合は、エントリ作成がはてなのクローラーに間に合うので何の問題もないのだけど、重い場合はHatena Boomarkerの編集動作が必要。

で、正常にブックマークできないことがある。


考えてみれば当たり前の話だったなぁ。
状況からすれば全て正しい動きですね。

うーむ、そうか。




オマケ

PEAR::HTTP_Clientを使ってメソッドの動作をチェックしてみたらこうなった。


POST PostURI

リクエスト

require_once('HTTP/Client.php');

$username = 'konaze';
$password = 'pass';
$wsse = getWSSE($username, $password);

$title    = 'http://www.yahoo.co.jp/';

$rowPostData = <<<EOF
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://purl.org/atom/ns#">
<title>dummy</title>
  <link rel="related" type="text/html" href="{$title}" />
  <summary type="text/plain"></summary>
</entry>
EOF;

$client = new HTTP_Client();

$client->post(
  'http://b.hatena.ne.jp/atom/post',
  $rowPostData,
  true,
  array(),
  array(
    'Accept' => 'application/x.atom+xml, application/xml, text/xml, */*',
    'Authorization' => 'WSSE profile="UsernameToken"',
    'X-WSSE' => $wsse,
    'Content-Type', 'application/x.atom+xml'
  )
);
var_dump($client->currentResponse());


function getWSSE($username, $password) {
  $nowtime = date('Y-m-d\TH:i:s\Z');
  $nonce = pack('H*', sha1(md5(time())));
  $digest = base64_encode(pack('H*', sha1($nonce . $nowtime . $password)));
  return 'UsernameToken Username="' . $username.'", PasswordDigest="'. $digest .'", Nonce="'. base64_encode($nonce) .', Created="'.$nowtime.'"';
}

レスポンス

array
  'url' => string 'http://b.hatena.ne.jp/atom/post' (length=31)
  'code' => int 201
  'headers' => 
    array
      'date' => string 'Fri, 12 Mar 2010 04:40:11 GMT' (length=29)
      'server' => string 'Apache/2.2.3 (CentOS)' (length=21)
      'location' => string 'atom/edit/18' (length=12)
      'x-framework' => string 'Ridge/0.05' (length=10)
      'x-runtime' => string '23688ms' (length=7)
      'content-type' => string 'application/x.atom+xml; charset=utf-8' (length=37)
      'vary' => string 'Accept-Encoding' (length=15)
      'content-encoding' => string 'gzip' (length=4)
      'content-length' => string '347' (length=3)
      'connection' => string 'close' (length=5)
  'body' => string '

<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://purl.org/atom/ns#">
  <title>Yahoo! JAPAN</title>
  <link rel="related" type="text/html" href="http://www.yahoo.co.jp/" />
  <link rel="alternate" type="text/html" href="konaze/#18" />
  <link rel="service.edit" type="application/x.atom+xml" href="atom/edit/18" title="Yahoo! JAPAN" />
  <author>
    <name>konaze</name>
  </author>
  <generator url="" version="0.1">Hatena::Bookmark</generator>
  <issued></issued>
  <id>tag:hatena.ne.jp,2005:bookma'... (length=579)



GET EditURI

リクエスト

require_once('HTTP/Client.php');

$username = 'user';
$password = 'pass';
$wsse = getWSSE($username, $password);

$client = new HTTP_Client();

$client->get(
  'http://b.hatena.ne.jp/atom/edit/18',
  '',
  true,
  array(
    'Accept' => 'application/x.atom+xml, application/xml, text/xml, */*',
    'Authorization' => 'WSSE profile="UsernameToken"',
    'X-WSSE' => $wsse,
    'Content-Type', 'application/x.atom+xml'
  )
);
var_dump($client->currentResponse());

function getWSSE($username, $password) {
  $nowtime = date('Y-m-d\TH:i:s\Z');
  $nonce = pack('H*', sha1(md5(time())));
  $digest = base64_encode(pack('H*', sha1($nonce . $nowtime . $password)));
  return 'UsernameToken Username="' . $username.'", PasswordDigest="'. $digest .'", Nonce="'. base64_encode($nonce) .', Created="'.$nowtime.'"';
}

レスポンス

array
  'url' => string 'http://b.hatena.ne.jp/atom/edit/18' (length=34)
  'code' => int 200
  'headers' => 
    array
      'date' => string 'Fri, 12 Mar 2010 05:08:27 GMT' (length=29)
      'server' => string 'Apache/2.2.3 (CentOS)' (length=21)
      'x-framework' => string 'Ridge/0.05' (length=10)
      'x-runtime' => string '23ms' (length=4)
      'content-type' => string 'application/x.atom+xml; charset=utf-8' (length=37)
      'vary' => string 'Accept-Encoding' (length=15)
      'content-encoding' => string 'gzip' (length=4)
      'content-length' => string '389' (length=3)
      'connection' => string 'close' (length=5)
  'body' => string '
<?xml version="1.0" encoding="utf-8"?>
<entry xmlns="http://purl.org/atom/ns#"  xmlns:dc="http://purl.org/dc/elements/1.1/">
  <title>Yahoo! JAPAN</title>
  <link rel="related" type="text/html" href="http://www.yahoo.co.jp/" />
  <link rel="alternate" type="text/html" href="konaze/20100312#18" />
  <link rel="service.edit" type="application/x.atom+xml" href="atom/edit/18" title="Yahoo! JAPAN" />
  <author>
    <name>konaze</name>
  </author>
  <generator url="" version="0.1">Hatena::Bookmark</generator>
  '... (length=650)



POST PostURIのレスポンスを見る限り、XML::Atom::Client->createEntry()は正しく、EditURIを返しているように見える。
ということは...?

何らかの事情で、XML::Atom::Client->getEntry()がEditURIを解決できていないということなんだろうなぁ。
って、これはあれじゃん、前言ってた話題と同じじゃんね。

Ogawa::Buzz: はてなブックマークAtomAPIのPostURIのレスポンスがおかしい

XML::Atomのソースも見てみたけど別になにも難しいことはしていなくて、createEntry()では単純に返ってきたAtomの中のLocationをEditURIとして返しているだけ、getEntry()では与えられたURIにGETリクエストしてるだけだし、やっぱ結局はてなのせいか。



ただ今回違うのは...単純に追加しようとすると怒られるんだよね。なんだこれ。



Operation "ne": no method found, left argument in overloaded package XML::LibXML::Error, right argument has no overloaded magic 

オブジェクトに文字列を無理に追加してもダメってことなのか。そりゃそうだろうけども、どうしたらいいかまでは解らない。



あーもうなんか他の方法探るしかないかなー...