2008/01/31


Publish::Twitterコピって、Publish::Wassrをでっちあげた。
一応動いてる。TwitterからWassrへポストした結果
※テストでは1件だけポストした。

twitter2wassr.yaml
global:
  assets_path: /home/user/plagger/assets
  timezone: Asia/Tokyo
  log:
    level: info

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://twitter.com/statuses/user_timeline/[twitter user].rss

  - module: Filter::BreakEntriesToFeeds
    config:
      use_entry_title: 1

  - module: Publish::Wassr
    config:
      username: [user name]
      password: [pass word]

Plagger/Plugin/Publish/Wassr.pm
package Plagger::Plugin::Publish::Wassr;
use strict;
use base qw( Plagger::Plugin );

use Encode;
use Net::Wassr;
use Time::HiRes qw(sleep);

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'publish.entry' => \&publish_entry,
        'plugin.init'   => \&initialize,
    );
}

sub initialize {
    my($self, $context) = @_;
    my %opt = (
        user => $self->conf->{username},
        passwd => $self->conf->{password},
    );
    for my $key (qw/ apihost apiurl apirealm/) {
        $opt{$key} = $self->conf->{$key} if $self->conf->{$key};
    }
    $self->{wassr} = Net::Wassr->new(%opt);
}

sub publish_entry {
    my($self, $context, $args) = @_;

    my $body = $self->templatize('wassr.tt', $args);
    # TODO: FIX when Summary configurable.
    if ( length($body) > 159 ) {
        $body = substr($body, 0, 159);
    }
    $context->log(info => "Updating Wassr status to '$body'");
    $self->{wassr}->update( {status => encode_utf8($body)} ) or $context->error("Can't update wassr status");

    my $sleeping_time = $self->conf->{interval} || 15;
    $context->log(info => "sleep $sleeping_time.");
    sleep( $sleeping_time );
}

1;
__END__

=head1 NAME

Plagger::Plugin::Publish::Wassr - Update your status with feeds

=head1 SYNOPSIS

  - module: Publish::Wassr
    config:
      username: wassr-id
      password: wassr-password

=head1 DESCRIPTION

This plugin sends feed entries summary to your Wassr account status.

=head1 CONFIG

=over 4

=item username

Wassr username. Required.

=item password

Wassr password. Required.

=item interval

Optional.

=item apiurl

OPTIONAL. The URL of the API for wassr.jp. This defaults to "http://wassr.jp/user/xxx/statuses" if not set.

=item apihost

=item apirealm

Optional.
If you do point to a different URL, you will also need to set "apihost" and "apirealm" so that the internal LWP can authenticate.

    "apihost" defaults to "api.wassr.jp:80".
    "apirealm" defaults to "API Authentication".

=back

=head1 AUTHOR

Yasuhiro Matsumoto

=head1 SEE ALSO

L<Plagger>, L<Net::Wassr>

=cut
assets/plugins/Publish-Wassr/wassr.tt
[% IF entry.body %][% entry.body_text %][% ELSE %][% entry.title_text %][% END %] [% entry.permalink %]
deps/Publish-Wassr.yaml
name: Publish::Wassr
author: Yasuhiro Matsumoto
depends:
  Net::Wassr: 0

Net::Wassrは[Perl]Net::Wassr - Hatena::Diary::Neko::kak 500 Internal Server Errorを使用。
Posted at by




こういう使い方もあるね。
で、どうする...って訳でもないけど
※そういうの、「使い道ない」っていうんだよね。そうだよね。
#!/usr/bin/perl

use strict;
use warnings;

use Web::Scraper;
use URI;
use YAML;

my $airlines_accident_scraper = scraper {
  process '//div[@class="entry-content"]//table/tr',
    'airlines[]' => scraper {
      process '//td[1]', title => 'TEXT';
      process '//td[2]', last_accident => 'TEXT';
      process '//td[3]', flight_count => 'TEXT';
      process '//td[4]', death_accident => 'TEXT';
      process '//td[5]', death_rate => 'TEXT';
      process '//td[6]', accident_incidence => 'TEXT';
      process '//td[7]', total_rank => 'TEXT';
    };
  result 'airlines';
};

my $list = $airlines_accident_scraper->scrape(URI->new('http://www.manji.com/jp/2007/08/post_22.html'));
use YAML;
warn Dump $list;
リストは、マスコミが報じない危険な航空会社リストから拝借。

余談ですが...
Web::Scraper 0.16あたりから、@参照するとstringでなく、URIか返ってくるようになってるので、「認証付きのページで@srcを拾い上げて、認証無しでは参照出来ない画像を落とす」なんて事に使えるようになったみたいです。
Posted at by




これでFilterも作りやすくなるのかな...
例えば、はてなブックマークのフィードからShibuya.pmタグが付いてる物のOPMLを作るとか?(自身無さげ)
でもこれ、MIMEパターンをconfig.yamlに上手くめり込ませる方法ってないのかな...
指定する場合、「このURLに対しては変則的なxxxなMIMEで取りたい」って使いたいんだよね。

Index: lib/Plagger/Plugin/Subscription/Feed.pm
===================================================================
--- lib/Plagger/Plugin/Subscription/Feed.pm (revision 1959)
+++ lib/Plagger/Plugin/Subscription/Feed.pm (working copy)
@@ -17,7 +17,6 @@
 sub load {
     my ( $self, $context ) = @_;
 
-    # TODO: Auto-Discovery, XML::Liberal
     my $uri = URI->new( $self->conf->{url} )
       or $context->error("config 'url' is missing");
 
@@ -30,6 +29,20 @@
     my $content = Plagger::Util::load_uri($uri);
     my $feed = eval { Plagger::FeedParser->parse(\$content) };
 
+    if unless($feed) {
+        use HTML::TokeParser;
+        my $parser = HTML::TokeParser->new(\$content);
+        while (my $token = $parser->get_tag("link")) {
+            my $attr = $token->[1];
+            if ($attr->{rel} eq 'alternate'
+                    && ($attr->{type} eq 'application/rss+xml'
+                     or $attr->{type} eq 'application/atom+xml') {
+                $uri = $attr->{href};
+                $feed = eval { Plagger::FeedParser->parse(\$content) };
+                last;
+            }
+        }
+    }
     unless ($feed) {
         $context->log( error => "Error loading feed $uri: $@" );
         return;
Posted at by