Subscribed unsubscribe Subscribe Subscribe

perl の勉強がてら、google readerのフィードの名前の更新

perlの勉強がてら google readerのフィードの登録されている名前が新しくなっていたら変更するスクリプトを書いてみました。(livedoor readerは確か自動的に反映される)

use strict;
use warnings;

use Coro;
use Coro::LWP;
use Coro::Semaphore;
use Coro::State;
use WebService::Google::Reader;
use LWP::UserAgent;
use Encode;
use Time::HiRes;
use Config::Pit;
use XML::FeedPP;
use Try::Tiny;

my $reader = WebService::Google::Reader->new(
    %{Config::Pit::get('google')}
);
my $ua = LWP::UserAgent->new;

my @coros;

my @timeouts;
my @failds;
my @targets;

my $semaphore = new Coro::Semaphore 20;

for my $feed ( $reader->feeds ) {

    my $url = $feed->id;
    $url =~ s/^feed\///;

    push @coros, async {
        my $guard = $semaphore->guard;
        my $coro = $Coro::current;

        $coro->{timeout_at} = Time::HiRes::time() + 10;
        $coro->desc( 'LWP' );

        $coro->on_destroy(
            sub {
                push @timeouts, $url if shift eq 'timeout';
            }
        );

        my $res = $ua->get( $url );
        if ( $res->is_success ) {
            try {
                my $title = encode_utf8( XML::FeedPP->new( $res->decoded_content )->title );
                my $old_title = encode_utf8( $feed->title );
                if ( $title ne $old_title ) {
                    push @targets, [$feed->id, decode_utf8( $title ) ];
                    warn $title;
                }
            }
            catch {
                push @failds, [$url, $_];
            };
        }
        else {
            push @failds, [$url, $res->status_line];
        }
    };
}

my $w = AnyEvent->timer( 
    after => 0.5, 
    interval => 1, 
    cb => sub {
        my $now = Time::HiRes::time();
        my @lwp_coro = grep { $_->{desc} and $_->{desc} eq 'LWP' } Coro::State::list;
        for my $coro (@lwp_coro) {
            if ( $now > $coro->{timeout_at} ) {
                $coro->cancel('timeout');
            }
        }
    }
);

$_->join for @coros;

@coros = ();
for my $t (@targets) {
    push @coros, async {
        my $guard = $semaphore->guard;
        $reader->rename_feed($t->[0], $t->[1]);
    };
}

$_->join for @coros;

#print "--------------------------\n";
#warn "timeout ($_)" for @timeouts;
#
#print "--------------------------\n";
#warn "faild because $_->[1] ($_->[0])" for @failds;

まぁ、色々参考にしながら、フィードの登録の量が多かったので、Coro::LWPを使いました。今回はタイトルの変更だけ反映してるけど、404だったら購読から外すとかも出来そう。