Do You PHP はてブロ

Do You PHPはてなからはてブロに移動しました

mixiのAPIが増えていたので、Services_MixiAPI作ってみた

via. http://ido.nu/kuma/2007/08/01/two-more-api-found-in-mixi-station-221/

やば。。。もう1ヶ月半も前のネタなので、既出かも知れません。
とはいえ、なんか色々追加されてるみたいで面白そうなので試してみました。基本的にはWSSE認証+XMLということで、mixiのあしあとAPIを使って「あしあと一覧」を作ってみた - Do You PHP はてなでやっていることと変わりありません。

<?php
error_reporting(E_ALL);
require_once 'HTTP/Request.php';

$user = '[mixiのログインID]';
$pass = '[mixiのパスワード]';
$id = '[mixiのユーザーID]';

function execute($user, $pass, $url, $is_debug = false) {
    $nonce = pack('H*', sha1(md5(time().rand().posix_getpid())));
    $created = date('Y-m-d\TH:i:s') . 'Z';
    $digest = base64_encode(pack('H*', sha1($nonce . $created . $pass)));
    $wsse_header = sprintf('UsernameToken Username="%s", PasswordDigest="%s", Nonce="%s", Created="%s"', $user, $digest, base64_encode($nonce), $created);
    if ($is_debug) {
        var_dump($wsse_header);
    }

    $request = new HTTP_Request($url);
    $request->addHeader('X-WSSE', $wsse_header);

    if (PEAR::isError($request->sendRequest())) {
        die('request failed');
    }
    $response = $request->getResponseBody();
    if ($is_debug) {
        var_dump($response);
        echo '<hr>';
    }

    $xml = new SimpleXMLElement($response);
    return $xml;
}

/**
 * あしあと
 */
$xml = execute($user, $pass, 'http://mixi.jp/atom/tracks/r=2/member_id=' . $id);
echo '<ul>';
foreach ($xml->entry as $entry) {
    $updated_iso8601 = $entry->updated;

    $updated = date('Y/m/d H:i:s', mktime(substr($updated_iso8601, 11, 2),
                                          substr($updated_iso8601, 14, 2),
                                          substr($updated_iso8601, 17, 2),
                                          substr($updated_iso8601, 5, 2),
                                          substr($updated_iso8601, 8, 2),
                                          substr($updated_iso8601, 0, 4)
                                          ));
    printf(
        '<li><a href="%s" title="%sさん">%s</a>さん (%s)</li>',
        $entry->link['href'],
        $entry->author->name,
        $entry->author->name,
        $updated
    );
}
echo '</ul>';
echo '<hr>';

/**
 * マイミク一覧
 */
$xml = execute($user, $pass, 'http://mixi.jp/atom/friends/r=1/member_id=' . $id);


echo '<ul>';
foreach ($xml->entry as $entry) {
    printf(
        '<li><a href="%s" title="%sさん (%s)">%s</a>さん (%s)</li>',
        $entry->link[0]['href'],
        $entry->title,
        $entry->category['label'],
        $entry->title,
        $entry->category['label']
    );
}
echo '</ul>';
echo '<hr>';

/**
 * マイミク日記、コミュニティなど最新更新一覧
 */
$xml = execute($user, $pass, 'http://mixi.jp/atom/updates/r=1/member_id=' . $id);


echo '<ul>';
foreach ($xml->entry as $entry) {
    switch ($entry->category['term']) {
    case 'diary':
        printf('<li>%s</li>', $entry->content);
        break;
    case 'comment':
    case 'album':
    case 'video':
        printf(
            '<li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">%s</a>さんの%s)</li>',
            $entry->link['href'],
            $entry->title,
            $entry->title,
            $entry->author->url,
            $entry->author->name,
            $entry->author->name,
            $entry->category['label']
        );
        break;
    case 'bbs':
        printf(
            '<li><a href="%s" title="%s">%s</a> (「<a href="%s" title="%s">%s</a>」の%s)</li>',
            $entry->link['href'],
            $entry->title,
            $entry->title,
            $entry->author->uri,
            $entry->author->name,
            $entry->author->name,
            $entry->category['label']
        );
        break;
    default:
    }
}

ホントにやってることは全然変わっていません。
ついでに、データ取得の部分をPEARパッケージにしてみました。Services_Mixiはすでにいくつか存在しているので、名前はServices_MixiAPIです。

インストールは

# pear install -a http://www.doyouphp.jp/pear/Services_MixiAPI-0.0.1.tgz

な感じで。
また、PEAR::Services_FeedMeterPEAR::Services_Hatena_StarPEAR::Services_Recruit_AkasuguPEAR::Services_Recruit_Abroadと同様、HTTP_Request1.4.1以上が必要になります。なお、PHP5.2.x系のみ対応としていますが、特別な拡張やPEARパッケージを使っているわけではないので、PHP5系であれば動作すると思います(PHP5.2.4以外は動作未確認です)。
また、APIドキュメントも用意してあります。

使い方は、ざっと以下の通りです

  1. Services_MixiAPI_Factoryを使ってサービスインスタンスを取得
  2. Services_MixiAPI#execute()
  3. Services_MixiAPI#get()の戻り値(XML)を適宜変換して利用する

となります。先ほどのサンプルでServices_MixiAPIを使ってみると次のようになります。

<?php
error_reporting(E_ALL);
require_once 'Services/MixiAPI/Factory.php';

$user = '[mixiのログインID]';
$pass = '[mixiのパスワード]';
$id = '[mixiのユーザーID]';

$service = Services_MixiAPI_Factory::getInstance(
               Services_MixiAPI_Factory::API_MODE_FOOTPRINT,
               $user, $pass, $id);
$service->execute();
$xml = new SimpleXMLElement($service->get());
echo '<ul>';
foreach ($xml->entry as $entry) {
    $updated_iso8601 = $entry->updated;

    $updated = date('Y/m/d H:i:s', mktime(substr($updated_iso8601, 11, 2),
                                          substr($updated_iso8601, 14, 2),
                                          substr($updated_iso8601, 17, 2),
                                          substr($updated_iso8601, 5, 2),
                                          substr($updated_iso8601, 8, 2),
                                          substr($updated_iso8601, 0, 4)
                                          ));
    printf(
        '<li><a href="%s" title="%sさん">%s</a>さん (%s)</li>',
        $entry->link['href'],
        $entry->author->name,
        $entry->author->name,
        $updated
    );
}
echo '</ul>';
echo '<hr>';

/**
 * マイミク一覧
 */
$service = Services_MixiAPI_Factory::getInstance(
               Services_MixiAPI_Factory::API_MODE_MYMIXI,
               $user, $pass, $id);
$service->execute();
$xml = new SimpleXMLElement($service->get());
echo '<ul>';
foreach ($xml->entry as $entry) {
    printf(
        '<li><a href="%s" title="%sさん (%s)">%s</a>さん (%s)</li>',
        $entry->link[0]['href'],
        $entry->title,
        $entry->category['label'],
        $entry->title,
        $entry->category['label']
    );
}
echo '</ul>';
echo '<hr>';

/**
 * マイミク日記、コミュニティなど最新更新一覧
 */
$service = Services_MixiAPI_Factory::getInstance(
               Services_MixiAPI_Factory::API_MODE_WHATSNEW,
               $user, $pass, $id);
$service->execute();
$xml = new SimpleXMLElement($service->get());
echo '<ul>';
foreach ($xml->entry as $entry) {
    switch ($entry->category['term']) {
    case 'diary':
        $updated_iso8601 = $entry->updated;

        $updated = date('Y/m/d H:i:s', mktime(substr($updated_iso8601, 11, 2),
                                              substr($updated_iso8601, 14, 2),
                                              substr($updated_iso8601, 17, 2),
                                              substr($updated_iso8601, 5, 2),
                                              substr($updated_iso8601, 8, 2),
                                              substr($updated_iso8601, 0, 4)
                                              ));
        printf('<li>%s %s</li>', $entry->content, $updated);
        break;
    case 'comment':
    case 'album':
    case 'video':
        printf(
            '<li><a href="%s" title="%s">%s</a> (<a href="%s" title="%s">%s</a>さんの%s)</li>',
            $entry->link['href'],
            $entry->title,
            $entry->title,
            $entry->author->url,
            $entry->author->name,
            $entry->author->name,
            $entry->category['label']
        );
        break;
    case 'bbs':
        printf(
            '<li><a href="%s" title="%s">%s</a> (「<a href="%s" title="%s">%s</a>」の%s)</li>',
            $entry->link['href'],
            $entry->title,
            $entry->title,
            $entry->author->uri,
            $entry->author->name,
            $entry->author->name,
            $entry->category['label']
        );
        break;
    default:
    }
}

うー。。。どことなく、「惰性で作ってる感」満載だ(^^;

追記(2007/11/14 00:56)

id:doublenegativeさんが挙げている修正内容を反映させました。ありがとうございます。