Changeset 430

Show
Ignore:
Timestamp:
03/31/06 21:50:24
Author:
miyagawa
Message:

Reorganized CustomFeed? API:

  • Added RSS/Atom auto-discovery in Aggregator::Simple. Fixes #20
  • Fixes CustomFeed? bugs with multiple instances. Fixes #56
  • Fixes Aggregator::Simple bug it ignores title in Config. Fixes #110.
  • Automatically loads Aggregator::Simple where no Aggregator is installed. Refs #125
  • Warns if no aggregator corresponds with the feed. Fixes #125
  • Added $context->is_loaded($plugin). Fixes #132
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/plagger/lib/Plagger.pm

    r415 r430  
    3939        subscription => Plagger::Subscription->new, 
    4040        plugins_path => {}, 
     41        plugins => [], 
    4142    }, $class; 
    4243 
     
    149150} 
    150151 
     152sub is_loaded { 
     153    my($self, $stuff) = @_; 
     154 
     155    my $sub = ref $stuff && ref $stuff eq 'Regexp' 
     156        ? sub { $_[0] =~ $stuff } 
     157        : sub { $_[0] eq $stuff }; 
     158 
     159    for my $plugin (@{ $self->{plugins} }) { 
     160        my $module = ref $plugin; 
     161           $module =~ s/^Plagger::Plugin:://; 
     162        return 1 if $sub->($module); 
     163    } 
     164 
     165    return; 
     166} 
     167 
    151168sub load_plugin { 
    152169    my($self, $config) = @_; 
     
    167184    $plugin->cache( Plagger::CacheProxy->new($plugin, $self->cache) ); 
    168185    $plugin->register($self); 
     186 
     187    push @{$self->{plugins}}, $plugin; 
    169188} 
    170189 
     
    183202 
    184203sub run_hook { 
    185     my($self, $hook, $args) = @_; 
     204    my($self, $hook, $args, $once) = @_; 
    186205    for my $action (@{ $self->{hooks}->{$hook} }) { 
    187206        my $plugin = $action->{plugin}; 
    188207        if ( $plugin->rule->dispatch($plugin, $hook, $args) ) { 
    189             $action->{callback}->($plugin, $self, $args); 
    190         } 
    191     } 
     208            my $done = $action->{callback}->($plugin, $self, $args); 
     209            return 1 if $once && $done; 
     210        } 
     211    } 
     212 
     213    # if $once is set, here means not executed = fail 
     214    return if $once; 
     215
     216 
     217sub run_hook_once { 
     218    my($self, $hook, $args) = @_; 
     219    $self->run_hook($hook, $args, 1); 
    192220} 
    193221 
     
    198226    $self->run_hook('subscription.load'); 
    199227 
    200     for my $type ($self->subscription->types) { 
    201         for my $feed ($self->subscription->feeds_by_type($type)) { 
    202             $self->run_hook("aggregator.aggregate.$type", { feed => $feed }); 
    203         } 
    204     } 
     228    unless ( $self->is_loaded(qr/^Aggregator::/) ) { 
     229        $self->load_plugin({ module => 'Aggregator::Simple' }); 
     230    } 
     231 
     232    for my $feed ($self->subscription->feeds) { 
     233        if (my $sub = $feed->aggregator) { 
     234            $sub->($self, { feed => $feed }); 
     235        } else { 
     236            my $ok = $self->run_hook_once('customfeed.handle', { feed => $feed }); 
     237            if (!$ok) { 
     238                Plagger->context->log(error => $feed->url . " is not aggregated by any aggregator"); 
     239            } 
     240        } 
     241    } 
     242 
    205243    $self->run_hook('aggregator.finalize'); 
    206244 
  • trunk/plagger/lib/Plagger/Feed.pm

    r373 r430  
    33 
    44use base qw( Plagger::Thing ); 
    5 __PACKAGE__->mk_accessors(qw( link url image description language author updated tags meta type source_xml )); 
     5__PACKAGE__->mk_accessors(qw( link url image description language author updated tags meta type source_xml aggregator )); 
    66 
    77use Digest::MD5 qw(md5_hex); 
  • trunk/plagger/lib/Plagger/Plugin/Aggregator/Simple.pm

    r399 r430  
    33use base qw( Plagger::Plugin ); 
    44 
     5use Feed::Find; 
    56use Plagger::UserAgent; 
    67use List::Util qw(first); 
     
    1617    $context->register_hook( 
    1718        $self, 
    18         'aggregator.aggregate.feed'  => \&aggregate, 
     19        'customfeed.handle'  => \&aggregate, 
    1920    ); 
    2021} 
     
    2425 
    2526    my $url = $args->{feed}->url; 
     27    my $res = $self->fetch_content($url); 
     28 
     29    if ( $Feed::Find::IsFeed{$res->http_response->content_type} ) { 
     30        $self->handle_feed($url, \$res->content); 
     31    } else { 
     32        my @feeds = Feed::Find->find_in_html(\$res->content, $url); 
     33        if (@feeds) { 
     34            $url = $feeds[0]; 
     35            $res = $self->fetch_content($url); 
     36            $self->handle_feed($url, \$res->content); 
     37        } else { 
     38            return; 
     39        } 
     40    } 
     41 
     42    return 1; 
     43} 
     44 
     45sub fetch_content { 
     46    my($self, $url) = @_; 
     47 
     48    my $context = Plagger->context; 
    2649    $context->log(info => "Fetch $url"); 
    2750 
     
    3962    $context->log(debug => $response->status . ": $url"); 
    4063 
    41     $self->handle_feed($url, \$response->content)
     64    $response
    4265} 
    4366 
  • trunk/plagger/lib/Plagger/Plugin/Aggregator/Xango.pm

    r323 r430  
    2929    $context->register_hook( 
    3030        $self, 
    31         'aggregator.aggregate.feed' => \&aggregate, 
    32         'aggregator.finalize'       => \&finalize, 
     31        'customfeed.handle'  => \&aggregate, 
     32        'aggregator.finalize' => \&finalize, 
    3333    ); 
    3434} 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/AmazonAssociateReportJP.pm

    r377 r430  
    1111        $self, 
    1212        'subscription.load' => \&load, 
    13         'aggregator.aggregate.amazonassociate' => \&aggregate, 
    1413    ); 
    1514} 
     
    1817    my ($self, $context) = @_; 
    1918    my $feed = Plagger::Feed->new; 
    20     $feed->type('amazonassociate'); 
     19    $feed->aggregator(sub { $self->aggregate(@_) }); 
    2120    $context->subscription->add($feed); 
    2221} 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/Debug.pm

    r390 r430  
    1111        $self, 
    1212        'subscription.load' => \&load, 
    13         'aggregator.aggregate.debug' => \&aggregate, 
    1413    ); 
    1514} 
     
    1817    my ($self, $context) = @_; 
    1918    my $feed = Plagger::Feed->new; 
    20     $feed->type('debug'); 
     19    $feed->aggregator(sub { $self->aggregate(@_) }); 
    2120    $context->subscription->add($feed); 
    2221} 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/FlickrSearch.pm

    r360 r430  
    1313        $self, 
    1414        'subscription.load' => \&load, 
    15         'aggregator.aggregate.flickr.search' => \&aggregate, 
    1615    ); 
    1716} 
     
    2120 
    2221    my $feed = Plagger::Feed->new; 
    23     $feed->type('flickr.search'); 
     22    $feed->aggregator(sub { $self->aggregate(@_) }); 
    2423    $feed->id('flickr:search'); 
    2524    $context->subscription->add($feed); 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/Frepa.pm

    r403 r430  
    1212        $self, 
    1313        'subscription.load' => \&load, 
    14         'aggregator.aggregate.frepa' => \&aggregate, 
    1514    ); 
    1615} 
     
    2120 
    2221    my $feed = Plagger::Feed->new; 
    23     $feed->type('frepa'); 
     22    $feed->aggregator(sub { $self->aggregate(@_) }); 
    2423    $context->subscription->add($feed); 
    2524} 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/Mailman.pm

    r189 r430  
    1212    $context->register_hook( 
    1313        $self, 
    14         'subscription.load' => \&load, 
    15         'aggregator.aggregate.mailman' => \&aggregate, 
     14        'customfeed.handle' => \&handle, 
    1615    ); 
    1716} 
    1817 
    19 sub load
    20     my($self, $context) = @_; 
     18sub handle
     19    my($self, $context, $args) = @_; 
    2120 
    22     my $url = $self->conf->{url} 
    23         or $context->error("pipermail url not set"); 
     21    if ($args->{feed}->url =~ m!/pipermail/[^/]+/$!) { 
     22        $self->aggregate($context, $args); 
     23        return 1; 
     24    } 
    2425 
    25     my $feed = Plagger::Feed->new; 
    26        $feed->type('mailman'); 
    27        $feed->url($url); 
    28     $context->subscription->add($feed); 
     26    return; 
    2927} 
    3028 
     
    3634 
    3735    my $now = Plagger::Date->now; 
    38     $now->set_locale('en_us'); 
     36       $now->set_locale('en_us'); 
    3937 
    4038    my $base_url = $url . $now->year . '-' . $now->month_name . '/'; 
     
    109107=head1 SYNOPSIS 
    110108 
    111   - module: CustomFeed::Mailman 
     109  - module: Subscription::Config 
    112110    config: 
    113       url: http://lists.rawmode.org/pipermail/catalyst/ 
     111      feed: 
     112        - http://lists.rawmode.org/pipermail/catalyst/ 
    114113 
    115114=head1 DESCRIPTION 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/Mixi.pm

    r286 r430  
    1313        $self, 
    1414        'subscription.load' => \&load, 
    15         'aggregator.aggregate.mixi' => \&aggregate, 
    1615    ); 
    1716} 
     
    2322 
    2423    my $feed = Plagger::Feed->new; 
    25        $feed->type('mixi')
     24       $feed->aggregator( sub { $self->aggregate(@_) }
    2625    $context->subscription->add($feed); 
    2726} 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/POP3.pm

    r275 r430  
    1313        $self, 
    1414        'subscription.load' => \&load, 
    15         'aggregator.aggregate.pop3' => \&aggregate, 
    1615    ); 
    1716} 
     
    2120 
    2221    my $feed = Plagger::Feed->new; 
    23        $feed->type('pop3'); 
     22       $feed->aggregator(sub { $self->aggregate(@_) }); 
    2423    $context->subscription->add($feed); 
    2524} 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/SVNLog.pm

    r405 r430  
    2020        $self, 
    2121        'subscription.load' => \&load, 
    22         'aggregator.aggregate.svnlog' => \&aggregate, 
    2322    ); 
    2423} 
    2524 
    2625sub load { 
    27        my($self, $context) = @_; 
    28          
    29        $self->{svnlog} = SVN::Client->new(); 
    30          
    31        my $feed = Plagger::Feed->new; 
    32        $feed->type('svnlog'); 
    33        $context->subscription->add($feed); 
     26    my($self, $context) = @_; 
     27 
     28    $self->{svnlog} = SVN::Client->new(); 
     29 
     30    my $feed = Plagger::Feed->new; 
     31    $feed->aggregator(sub { $self->aggregate(@_) }); 
     32    $context->subscription->add($feed); 
    3433} 
    3534 
    3635sub aggregate { 
    37         my($self, $context, $args) = @_; 
    38          
    39         $error_msg = ''; 
    40         @data = (); 
    41         $current_target = ''; 
    42          
    43         if (ref($self->conf->{target}) ne 'ARRAY') { 
    44                 $self->conf->{target} = [$self->conf->{target}]; 
    45         } 
    46          
    47         my $feed = Plagger::Feed->new; 
    48         $feed->type('svnlog'); 
    49         $feed->title($self->conf->{title} or 'SVN Log'); 
    50         $feed->link($self->conf->{target}->[0]); 
    51          
    52         my $revision_from = $self->conf->{revision_from} || 1; 
    53         my $revision_to   = $self->conf->{revision_to}   || 'HEAD'; 
    54          
    55         for my $target (@{ $self->conf->{target} }) { 
    56                 $context->log(debug => 'Connecting repository ' . $target); 
    57                  
    58                 $current_target = $target; 
    59                  
    60                 $self->{svnlog}->log( 
    61                         $target, 
    62                         $revision_from, 
    63                         $revision_to, 
    64                         1, 
    65                         1, 
    66                         \&log_receiver 
    67                 ); 
    68                  
    69                 if ($error_msg) { 
    70                         $context->log(error => $error_msg); 
    71                         exit; 
    72                 } 
    73         } 
    74          
    75         my $format = DateTime::Format::Strptime->new(pattern => '%Y-%m-%dT%H:%M:%S.%6NZ'); 
    76          
    77         if ($self->conf->{reverse}) { 
    78                 @data = sort { $b->{revision} <=> $a->{revision} } @data; 
    79         } 
    80         else { 
    81                 @data = sort { $a->{revision} <=> $b->{revision} } @data; 
    82         } 
    83          
    84         my $items_count = 0; 
    85         for my $data (@data) { 
    86                 last if $items_count++ >= $self->conf->{fetch_items}; 
    87                  
    88                 my $entry = Plagger::Entry->new; 
    89                  
    90                 $entry->title('revision ' . $data->{revision}); 
    91                 $entry->link($data->{target}); 
    92                 $entry->author($data->{author}); 
    93                 $entry->date( Plagger::Date->parse($format, $data->{date}) ); 
    94                 $entry->body($data->{message}); 
    95                  
    96                 $feed->add_entry($entry); 
    97         } 
    98          
    99         $context->update->add($feed); 
     36    my($self, $context, $args) = @_; 
     37 
     38    $error_msg = ''; 
     39    @data = (); 
     40    $current_target = ''; 
     41 
     42    if (ref($self->conf->{target}) ne 'ARRAY') { 
     43        $self->conf->{target} = [$self->conf->{target}]; 
     44    } 
     45 
     46    my $feed = Plagger::Feed->new; 
     47    $feed->type('svnlog'); 
     48    $feed->title($self->conf->{title} or 'SVN Log'); 
     49    $feed->link($self->conf->{target}->[0]); 
     50 
     51    my $revision_from = $self->conf->{revision_from} || 1; 
     52    my $revision_to   = $self->conf->{revision_to}   || 'HEAD'; 
     53 
     54    for my $target (@{ $self->conf->{target} }) { 
     55        $context->log(debug => 'Connecting repository ' . $target); 
     56 
     57        $current_target = $target; 
     58        $self->{svnlog}->log( 
     59            $target, 
     60            $revision_from, 
     61            $revision_to, 
     62            1, 
     63            1, 
     64            \&log_receiver 
     65        ); 
     66 
     67        if ($error_msg) { 
     68            $context->log(error => $error_msg); 
     69            exit; 
     70        } 
     71    } 
     72 
     73    my $format = DateTime::Format::Strptime->new(pattern => '%Y-%m-%dT%H:%M:%S.%6NZ'); 
     74 
     75    if ($self->conf->{reverse}) { 
     76        @data = sort { $b->{revision} <=> $a->{revision} } @data; 
     77    } 
     78    else { 
     79        @data = sort { $a->{revision} <=> $b->{revision} } @data; 
     80    } 
     81 
     82    my $items_count = 0; 
     83    for my $data (@data) { 
     84        last if $items_count++ >= $self->conf->{fetch_items}; 
     85 
     86        my $entry = Plagger::Entry->new; 
     87        $entry->title('revision ' . $data->{revision}); 
     88        $entry->link($data->{target}); 
     89        $entry->author($data->{author}); 
     90        $entry->date( Plagger::Date->parse($format, $data->{date}) ); 
     91        $entry->body($data->{message}); 
     92 
     93        $feed->add_entry($entry); 
     94    } 
     95    $context->update->add($feed); 
    10096} 
    10197 
    10298sub log_receiver { 
    103         my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; 
    104          
    105         $message =~ s/\x0D\x0A|\x0D|\x0A/<br>/g; 
    106          
    107         push(@data, 
    108                 { 
    109                         target => $current_target, 
    110                         changed_paths => [sort keys %$changed_paths], 
    111                         revision => $revision, 
    112                         author => $author, 
    113                         date => $date, 
    114                         message => $message, 
    115                 } 
    116         ); 
     99    my ($changed_paths, $revision, $author, $date, $message, $pool) = @_; 
     100 
     101    $message =~ s/\x0D\x0A|\x0D|\x0A/<br>/g; 
     102    push(@data, { 
     103        target => $current_target, 
     104        changed_paths => [sort keys %$changed_paths], 
     105        revision => $revision, 
     106        author => $author, 
     107        date => $date, 
     108        message => $message, 
     109    }); 
    117110} 
    118111 
    119112sub error_handler { 
    120        if (ref($_[0]) and UNIVERSAL::isa($_[0], '_p_svn_error_t')) { 
    121                $error_msg = $_[0]->message; 
    122        
     113    if (ref($_[0]) and UNIVERSAL::isa($_[0], '_p_svn_error_t')) { 
     114        $error_msg = $_[0]->message; 
     115   
    123116} 
    124  
    125117 
    1261181; 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/Yahoo360JP.pm

    r263 r430  
    1313        $self, 
    1414        'subscription.load' => \&load, 
    15         'aggregator.aggregate.yahoo360jp' => \&aggregate, 
    1615    ); 
    1716} 
     
    2120 
    2221    my $feed = Plagger::Feed->new; 
    23        $feed->type('yahoo360jp'); 
     22       $feed->aggregator(sub { $self->aggregate(@_) }); 
    2423    $context->subscription->add($feed); 
    2524} 
  • trunk/plagger/lib/Plagger/Plugin/CustomFeed/iTunesRecentPlay.pm

    r369 r430  
    1414        $self, 
    1515        'subscription.load' => \&load, 
    16         'aggregator.aggregate.itunesrecentplay' => \&aggregate, 
    1716    ); 
    1817} 
     
    2221 
    2322    my $feed = Plagger::Feed->new; 
    24     $feed->type('itunesrecentplay'); 
     23    $feed->aggregator(sub { $self->aggregate(@_) }); 
    2524    $context->subscription->add($feed); 
    2625} 
  • trunk/plagger/lib/Plagger/Plugin/Subscription/Bloglines.pm

    r398 r430  
    2020            $self, 
    2121            'subscription.load' => \&notifier, 
    22             'aggregator.aggregate.bloglines' => \&sync, 
    2322        ); 
    2423    } 
     
    6665    if ($count) { 
    6766        my $feed = Plagger::Feed->new; 
    68         $feed->type('bloglines'); 
     67        $feed->aggregator(sub { $self->sync(@_) }); 
    6968        $context->subscription->add($feed); 
    7069 
  • trunk/plagger/lib/Plagger/Plugin/Subscription/Config.pm

    r285 r430  
    1010    $context->register_hook( 
    1111        $self, 
    12         'subscription.load' => \&load
     12        'subscription.load' => $self->can('load')
    1313    ); 
    1414}