2008/01/31


Plaggerで、はてなハイクにポストするPublish::HatenaHaiku書いた。
コードはこんな感じ
package Plagger::Plugin::Publish::HatenaHaiku;
use strict;
use base qw( Plagger::Plugin );

use Encode;
use Time::HiRes qw(sleep);
use URI;
use Plagger::Mechanize;

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

sub initialize {
    my $self = shift;
    unless ($self->{mech}) {
        my $mech = Plagger::Mechanize->new;
        $mech->agent_alias('Windows IE 6');
        $mech->quiet(1);
        $self->{mech} = $mech;
    }
    $self->login_hatena_haiku;
}

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

    unless ($self->conf->{default_keyword}) {
        Plagger->context->log(error => 'set default_keyword.');
    }
    my $summary = encode('utf-8', $args->{entry}->title)
        . "\n" . encode('utf-8', $args->{entry}->link);
    my $keyword = $self->conf->{default_keyword};

    my $keyword_behaviour = $self->conf->{keyword_behaviour};
    if ('default' ne $keyword_behaviour) {
        if ('tag' eq $keyword_behaviour) {
            my @tags = @{$args->{entry}->tags};
            $keyword = $tags[0] if ($tags[0]);
        }
        if ('title' eq $keyword_behaviour) {
            if ($summary =~ /^\[([^\]]+)\]/) {
                $keyword = $1;
            }
        }
    }

    my $res = eval { $self->{mech}->get('http://h.hatena.ne.jp/') };
    if ($res && $res->is_success) {
        eval {
            $self->{mech}->submit_form(
                form_number => 1,
                fields => {
                    word       => encode('utf-8', $keyword),
                    body       => $summary,
                },
            )
        };
        if ($@) {
            $context->log(info => "can't submit: " . $@);
        } else {
            $context->log(info => "Post entry success.");
        }
    } else {
       $context->log(error => "fail to post HTTP Status: " . $res->code);
    }
 
    my $sleeping_time = $self->conf->{interval} || 3;
    $context->log(info => "sleep $sleeping_time.");
    sleep( $sleeping_time );
}

sub login_hatena_haiku {
    my $self = shift;
    unless ($self->conf->{username} && $self->conf->{password}) {
        Plagger->context->log(error => 'set your username and password before login.');
    }
    my $res = $self->{mech}->get('https://www.hatena.ne.jp/login?location=http://h.hatena.ne.jp/');
    $self->{mech}->submit_form(
        form_number => 1,
        fields => {
            name  => $self->conf->{username},
            password => $self->conf->{password},
        },
    );
    if ($self->{mech}->content !~ 'http-equiv="Refresh"') {
        Plagger->context->log(error => "failed to login to hatena haiku.");
    }
}

1;

__END__

=head1 NAME

Plagger::Plugin::Publish::HatenaHaiku - Post to hatena haiku automatically

=head1 SYNOPSIS

  - module: Publish::HatenaHaiku
    config:
      username: your-username
      password: your-password
      default_keyword: id:mattn
      #keyword_behaviour: title
      #keyword_behaviour: tag
      #interval: 2

=head1 DESCRIPTION

This plugin automatically posts feed updates to hatena haiku
L<http://h.hatena.ne.jp/>. It supports automatic tagging(keyword) as well.
It might be handy for synchronizing your blog feeds into hatena haiku.

=head1 CONFIG

=over 4

=item username, password

username and password for Hatena Haiku. Required.

=item default_keyword

default keyword string. Required.

=item keyword_behaviour

Optional. if set 'title', it should accept 'plagger' in '[plagger]title'.
if set 'tag', it should accept a first of tags in feed.

=item interval

Optional.

=item timeout

Optional.

=back

=head1 AUTHOR

Yasuhiro Matsumoto

=head1 SEE ALSO

L<Plagger>, L<Plagger::Mechanize>

=cut

default_keywordは必須項目として、keyword_behaviourでキーワードの動作が変えられます。
keyword_behaviourに何も設定しなければ(もしくは'default')、default_keywordが使われ、'title'を設定すれば"[書評]ほにゃらら"の"書評"がキーワードに、'tag'を設定すればフィードタグの先頭を使う様になっています。
ただ、やっぱりフィードの転載なのではてなハイクのトップページに掲載する/掲載しないのオプションが欲しいなぁ...=>はてな事務局さん

なお、コードはCodeReposに置いてあります。
lang/perl/plagger/lib/Plagger/Plugin/Publish/HatenaHaiku.pm

ところで、dankogai氏それっぽい事(書評とか)やってるように見えるんだけど、もしかして手動だろうか?
Posted at by




なんにつかうねん!www
/lang/perl/Acme-Jyogakusei/trunk/ - CodeRepos::Share - Trac
こうか!? #!/usr/bin/perl

use strict;
use warnings;
use utf8;
use Acme::Jyogakusei;

my $jyogakusei = '女子高生';
my $re = Acme::Jyogakusei::regexp;
print "Jyogakusei\n" if $jyogakusei =~ /$re/;
あと #!/usr/bin/perl

use strict;
use warnings;
use utf8;
use Acme::Jyogakusei;

my $jyogakusei = 'なんちゃって女子高生';
my $re = Acme::Jyogakusei::regexp;
$jyogakusei =~ s/(なんちゃって$re)/おばちゃん/g;
print $jyogakusei;
こんなんもありか...
Posted at by




いいなぁiPod touch欲しいなぁ。

Plaggerでニコニコ動画を一括ダウンロード&変換 Podcast を生成して iPod touch で見る - 2007年11月最新版
うちでは臨時予算案は可決されそうにありません。宝くじが当たるま携帯で我慢したいと思います。

今日は、ゆーすけべさんの所に置いてあるYAMLをちょこっと弄って、携帯向け変換をやろうかと思います。ちょっとだけオリジナリティを出そうとニコニコではなく、YouTubeから...
まず、こんなYAMLを用意します。

youtube_hatena_tagged.yaml
global:
  assets_path: /home/user/plagger/assets/
  timezone: Asia/Tokyo
  log:
    evel: info

plugins:

  - module: Subscription::Config
    config:
      feed:
          - url: http://b.hatena.ne.jp/t/youtube?mode=rss&amp;sort=hot&amp;threshold=3
          
  - module: Filter::FindEnclosures
  - module: Filter::FetchEnclosure
    config:
      dir: /home/user/plagger/out
  - module: Filter::FLVInfo
  
  - module: Filter::FFmpeg
    config:
      command: /usr/bin/ffmpeg
      ext: 3gp
      dir: /home/user/plagger/out
      encoding: utf-8
      options:
        video_codec:         mpeg4
        audio_codec:         libamr_nb
        audio_sampling_rate: 8000
        audio_bit_rate:      12.2k
        frame_size:          176x144
      extra_options: -ac 1 -f 3gp

  - module: Publish::Feed
    config:
      format: RSS
      dir: /home/user/plagger/out
      filename: youtube_hatena_tagged.xml
はてなで「youtube」タグが付いているフィードを取ってきて、Enclosureをフェッチ&解析。最後にFFmpegで変換というフェーズになります。Feed作成は意味なさそうですが、この後役に立ちます。
私の携帯SB810T向けには、映像コーデックにmpeg4、音声コーデックにamr-nb(libamr_nb)を指定します。メーカーの仕様によると、AACでも行けそうな事が書いてありますが、どうやら動画でない音声ファイルの場合のみAACが再生出来るようです。
また、サンプルレート8000はamr-nbの標準値で、オーディオチャネル(ac)は1にしないといけない様です。 もちろん
  • lib/Plagger/Plugin/Filter/FFmpeg.pm
  • lib/Plagger/Plugin/Filter/FLVInfo.pm
はCodeReposから取得して下さい。
殆んどyusukebeさん(yousukebeさんではありません。ここ大事)のと同じです。大概はffmpegのオプションでなんとか出来るかと思います。ただ現状Plaggerのtrunkに入ってるFind-Enclosuresのyoutube.plでは、jp.youtube.comドメインのリソースが対象外になっていますので、以下のパッチを当てます。
Index: assets/plugins/Filter-FindEnclosures/youtube.pl
===================================================================
--- assets/plugins/Filter-FindEnclosures/youtube.pl (revision 1988)
+++ assets/plugins/Filter-FindEnclosures/youtube.pl (working copy)
@@ -3,7 +3,7 @@
 
 sub handle {
     my ($self, $url) = @_;
-    $url =~ qr!http://(?:www.)?youtube.com/(?:watch(?:\.php)?)?\?v=.+!;
+    $url =~ qr!http://(?:www.|jp.)?youtube.com/(?:watch(?:\.php)?)?\?v=.+!;
 }
 
 sub find {
※パッチが当たった物はCodeReposに入れてあります。チンして食べてください。ただGData APIでないのでカッコよくはありませんが。
あとは # plagger -c youtube_hatena_tagged.yaml を実行すると、上のYAMLで指定している「out」フォルダにゴッチョリと3gpファイルが出来上がっている筈です。
携帯の場合はPodcast出来ませんし、動画のサイズが大きくなるとメールで送ったりHTTPでダウンロードする事も出来ません。結局はメモリ転送になりますが、Feed.pmにちょっとだけ手を加えて...
Index: lib/Plagger/Plugin/Publish/Feed.pm
===================================================================
--- lib/Plagger/Plugin/Publish/Feed.pm  (revision 1988)
+++ lib/Plagger/Plugin/Publish/Feed.pm  (working copy)
@@ -122,6 +122,15 @@
     open my $output, ">:utf8", $filepath or $context->error("$filepath: $!");
     print $output $xml;
     close $output;
+
+    if ($self->conf->{command_after}) {
+        my $command = $self->conf->{command_after};
+        my $dir = $self->conf->{dir};
+        $filepath =~ s!\\!/!g;
+        $command =~ s!\$\(filename\)!$filepath!g;
+        $command =~ s!\$\(dir\)!$dir!g;
+        system($command);
+    }
 }
 
 sub make_author {
こんなパッチを当てると、フィード出力時に「command_after」が実行されますので   - module: Publish::Feed
    config:
      format: RSS
      dir: /home/user/plagger/out
      filename: youtube_hatena_tagged.xml
      command_after: find $(dir) -name "*.3gp" -exec cp \{\} /media/usbdisk/private/myfolder/My Items/Video
こんなYAMLにしておけば、出来上がった3GPがUSB越しに携帯のmicroSDカードにズコーーーーンと転送されるって仕組です。
microSD-card
ズゴーーーーン
まぁ、Podcastと違って出来上がるまで、良い子ちゃんで待ってなきゃいけないですが...

追記
plagger流儀で言えば、Notify::Commandを使うべきですね。
Posted at by