Plagger使ってTwitterのFavやふぁぼったーをTumblrに流すプラグイン作ったよ

前回,わざわざログインして Fav を取るやつ を書きましたが,あんなことしなくても 普通に Fav のフィード取れることが分かったので,さくっと作り直しました. これを使えば,Twitter, Favotter→Tumblr に流すことができます.てか,実は Tumblr にはフィードを食う機能があるのですが,整形できないのと調子が悪くて すぐに死ぬので自分で API 使ってあげた方が早いです.

ちなみに,ソースはすべて github にあげているので使い方分かる人はそっちから 取った方がいいかも.

Plagger::Plugin::Plugin::Tumblr

まずはメインの Tumblr にポストするプラグイン.別にたいそうなことは していなくて,WWW::Tumblr という CPAN モジュールをラップしただけ. しかも,めんどくさいから Text と Quote と Link しか作ってない.

- module: Publish::Tumblr
  config:
  username: your-email
  password: your-password
  type: post type(text, quote, or link)
  interval: 2

type の部分を変更するとこんな感じで Post してくれます.

  • text

    • title
    • body(added link to the url at the end)
  • quote

    • quote(body)
    • source(title linked to the url)
  • link

    • name(title)
    • url
    • description(body)

lib/Plagger/Plugin/Publish/Tumblr.pm

package Plagger::Plugin::Publish::Tumblr;
use strict;
use base qw( Plagger::Plugin );

use Encode;
use Time::HiRes qw(sleep);
use WWW::Tumblr;

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

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

    $self->{tumblr} = WWW::Tumblr->new;
    $self->{tumblr}->email($self->conf->{username});
    $self->{tumblr}->password($self->conf->{password});
}

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

    my $title = $args->{entry}->{title};
    $title = encode_utf8($title);
    my $body = $args->{entry}->{body};
    $body = encode_utf8($body);
    my $link = $args->{entry}->{link};

    my $type = $self->conf->{type} || 'regular';

    $context->log(info => "Tumblr($type) posting '$title'");
    if($type eq 'text'){
        my $post = $body . "<div><a href=\"" . $link . "\">" . $title . "</a></div>";
        $self->{tumblr}->write(
            type => 'regular',
            title => $title,
            body => $post,
            );
    }
    elsif($type eq 'quote'){
        my $source = "<a href=\"" . $link . "\">" . $title . "</a>";
        $self->{tumblr}->write(
            type => 'quote',
            quote => $body,
            source => $source,
            );
    }
    elsif($type eq 'link'){
        $self->{tumblr}->write(
            type => 'link',
            name => $title,
            url => $link,
            description => $body,
            );
    }

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

1;

Plagger::Plugin::Filter::TwitterQuote

続いて,Twitter のフィードを Tumblr の Quote 形式にあわせて整形する Filter プラグイン. 参考にしてるのは Tombloo のやつね.あれが気に入ってるんでそれにしてます. 他の形にしたい人はお好きに変更して下さい.Publish::Tumblr のポスト方法は 上を参考にして下さい.

使い方は以下を YAML に挟むだけ.

  - module: Filter::TwitterQuote

lib/Plagger/Plugin/Filter/TwitterQuote.pm

package Plagger::Plugin::Filter::TwitterQuote;
use strict;
use base qw( Plagger::Plugin );

use Encode;

sub register {
    my ($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.entry.fixup' => \&filter,
    );
}

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

    my $body = $args->{entry}->{body};
    $body =~ /^(.+?): (.+)/o;
    my $id = $1;
    my $quote = encode_utf8($2);
    my $title = "Twitter / " . $id;

    $args->{entry}->title($title);
    $args->{entry}->body($quote);
}

1;

Plagger::Plugin::Filter::FavotterQuote

ふぁぼったーから流すやつも作りました.Link 先は Favotter のままです.

lib/Plagger/Plugin/Filter/FavotterQuote.pm

package Plagger::Plugin::Filter::FavotterQuote;
use strict;
use base qw( Plagger::Plugin );

use Encode;

sub register {
    my ($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.entry.fixup' => \&filter,
    );
}

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

    my $body = $args->{entry}->{body};
    $body =~ /^.+?<\/img>(.+?)<\/a> (.+?)<br \/>/o;
    my $id = $1;
    my $quote = $2;
    my $title = "Twitter / " . $id;

    $args->{entry}->title($title);
    $args->{entry}->body($quote);
}

1;

Plagger::Plugin::Filter::Reverse

それから,Twitter とかのフィードは最新の方から処理されてしまうので, そのまま Plagger で Tumblr に流すと一番古い奴が一番上にくるので,それを 逆転させておく.これは id:inirvash さんの書かれた奴をコピーしただけです. id:nirvash++

lib/Plagger/Plugin/Filter/Reverse.pm

package Plagger::Plugin::Filter::Reverse;
use strict;
use base qw( Plagger::Plugin );

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.feed.fixup' => \&feed
  );
}

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

    $context->log(debug => "reverse");
    my @entries = $args->{feed}->entries;
    @entries = reverse(@entries);
    $args->{feed}->{entries} = \@entries;
}

1;

レシピの YAML ファイル

こいつらを自分の Plagger が入ってるマシンの適当な所に放り込みます. おすすめは自分用のプラグインフォルダを作っておいて,それを YAML で読み込むことです.僕の場合,github から Pull したものを そのまま読み込んでいます.

前回も書いた様に,僕はプラグインの場所とかを設定した base.yaml を include させています.一応そちらも載せておきます.

base.yaml

global:
  plugin_path:
    - /home/user/plagger/lib/Plagger/Plugin
    - /home/user/github/plagger/lib/Plagger/Plugin
  assets_path: /home/user/plagger/assets
  timezone:     Asia/Tokyo
  log:
    level: debug
#    level: info
  cache:
    base: /home/user/cache

define_recipes:

で,以下がメインの YAML.Filter::Rule を使っているのは,以前に 送信したものを送信しないようにするためです.Tumblr はそういうチェックを してくれないので,テストする段階で何度もやると,同じものを大量に 送信してしまいますので,こいつを使いましょう w 指定したファイルが DB となって,同じものは送らないようにしてくれます.

twitterfav2tumblr.yaml

include:
  - /home/user/yaml/base.yaml

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://twitter.com/favorites/riywo.atom

  - module: Filter::Rule
    rule:
      module: Deduped
      path: /home/user/cache/plagger-twitterfav2tumblr.db

  - module: Filter::TwitterQuote
  - module: Filter::Reverse

  - module: Publish::Tumblr
    config:
      username: email address
      password: *****
      type: quote
      interval: 3

こちらは,Favotter 用.

favotter2tumblr.yaml

include:
  - /home/user/yaml/base.yaml

plugins:
  - module: Subscription::Config
    config:
      feed:
        - http://favotter.matope.com/userrss.php?user=riywo&mode=new

  - module: Filter::Rule
    rule:
      module: Deduped
      path: /home/user/cache/plagger-favotter2tumblr.db

  - module: Filter::FavotterQuote
  - module: Filter::Reverse

  - module: Publish::Tumblr
    config:
      username: email address
      password: ******
      type: quote
      interval: 3

使用方法

あとは,こいつらを指定して Plagger を起動すれば OK です.

$ plagger -c /home/user/yaml/twitterfav2tumblr.yaml
$ plagger -c /home/user/yaml/favotter2tumblr.yaml

うまくいった様でしたら,cron に設定しちゃって下さい.以下の設定なら 10 分毎に実行してくれます.

*/10 * * * * plagger -c /home/user/yaml/twitterfav2tumblr.yaml
*/10 * * * * plagger -c /home/user/yaml/favotter2tumblr.yaml

注意すべきキャッシュの存在

さて,Plagger の使用にあたって最も注意すべきこと,それは**「キャッシュ」**の 存在です.Plagger はフィードを取りに行く前にローカルのキャッシュを見ます. もしキャッシュがあれば(かつそれほど古くなければ?)フィードを見に行きません. そのため,あまり短い時間感覚で cron でまわしても新しいフィードを取りに行って くれないのです.

ですので,僕はキャッシュフォルダを削除する cron を 1 分毎にまわすという,アホなことを やっています.しかも厄介なのが,base.yaml で指定したキャッシュフォルダの 他に/home/user/.plagger 辺りに別のキャッシュを勝手に作っていました.なので, 指定したものの他にこいつも消さないといけません.これに気づかなくてしばらく キレてたのは秘密です.

というわけで,現在は base.yaml で/home/user/.plagger を指定して,ここのキャッシュを 削除する cron を回しています.

*/1 * * * * rm -rf /home/user/.plagger/cache