理系学生日記

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

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

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

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

将来的に何がしたいのか

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

LDRAPI をテストしよう

まず、未読の全 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;