理系学生日記

おまえはいつまで学生気分なのか

LDR の API を使って、未読の全 URL を取り出してみる

Livedoor Reader には非公開の API があるそうです。

なので、取り急ぎ Perl から使ってみようということになりました。

将来的に何がしたいのか

http://readitlaterlist.com/ を使うと、オフライン状態(地下鉄の中など)でも iPhone でフィードを読めるようになるんですけど、Read It Later にエントリの URL をイチイチ登録するのはなかなかメンドい。
Read It Later には API があることが分かったので、LDR からエントリの URL を自動的に Read It Later に送るようにしたいのです。

LDR の API をテストしよう

まず、未読の全 URL を取り出してみます。
ちょっとスクリプトが汚くなりそうだったので、WebService::LivedoorReader ってモジュールをでっちあげました。まだインタフェースっていうか、メソッド名とかも全然洗練されていませんが、とりあえず動作確認するって位置付けです。もうちょっと洗練させていきたいですね。

スクリプトはこんな感じ。

#!/opt/local/bin/perl
use strict;
use warnings;
use WebService::LivedoorReader;

my @links;
my $ldr = WebService::LivedoorReader->new( { user => 'user_id', pass => 'password' } );

my $subscriptions = $ldr->subs_json( { unread => 1 } );
my @sids  = map { $_->{subscribe_id} } @$subscriptions;
for my $sid (@sids) {
    my @entries = $ldr->unread_entries( $sid );
    push @links, map { $_->{link} } @entries;
}

print join "\n" => @links;

いまのところ、モジュールは以下の通りです。たぶんこれからガンガン変わっていくはず。

package WebService::LivedoorReader;

use strict;
use warnings;
use WWW::Mechanize;
use JSON;
our $VERSION = '0.01';

my $url = {
    login  =>  'http://reader.livedoor.com/reader/',
    subs   =>  'http://reader.livedoor.com/api/subs',
    unread =>  'http://reader.livedoor.com/api/unread',
};

sub new {
    my ($class, $param) = @_;
    my $self = bless {
        mech => WWW::Mechanize->new,
        user => $param->{user},
        pass => $param->{pass},
    }, $class;
    $self;
}

sub apikey {
    my $self = shift;
    $self->{apikey} and return $self->{apikey};

    $self->{mech}->get( $url->{login} );
    $self->{mech}->submit_form(
        form_name => 'loginForm',
        fields => {
            livedoor_id => $self->{user},
            password    => $self->{pass},
        }
    );
    $self->{mech}->cookie_jar->scan(
        sub {
            my ($key, $val) = @_[1, 2];
            $key eq 'reader_sid' or return;

            $self->{apikey} = $val;
        }
    );
    $self->{apikey};
}

sub subs_json {
    my ($self, $param) = shift;
    my $unread = $param? $param->{unread} : 0;
    my $res = $self->{mech}->post(
        $url->{subs}, { 
            ApiKey => $self->apikey, unread => $unread 
        }
    );
    from_json( $res->decoded_content );
};

sub unread_entries {
    my ($self, $sid) = @_;
    my $res = $self->{mech}->post(
        $url->{unread}, {
            ApiKey => $self->apikey, subscribe_id => $sid
        }
    );
    my $e = from_json( $res->decoded_content )->{items};
    wantarray? @$e : $e;
}

1;