PlaggerでTwitterからTumblrへFavを流す

書き直しました!

わざわざログインしなくても Fav のフィードは取れるので書き直しました!

ずっとやりたかったことをやってしまいました.僕は Twitter を見ているときに「これは秀逸www」という ポストがあったらちょくちょく Fav しています.できれば多くの人にこれらの優れたポストを見て欲しいのですが うまいやり方がなくて,それだったら Tumblr に流してしまえばいいじゃないかと思った次第です. 実際,Tumblr には Tombloo 経由で流れてくるポストが結構あります.まさか自分で Fav したポストを 開いて Tombloo するとかはありえないので,ここは Plagger といきましょう.

Twitter の自分の Fav したものを RSS で取得する

まず自分の Fav を取得する方法ですが,以下のサイトを参考に,「UserAgent::AuthenRequest」と 「Subscription::Config」を組み合わせて取得します.Twitter へのログインが必要なのでこういう 工夫が必要になりますね.

Twitter のログを Plagger でごにょごにょ – dnsystem の日記 – dnsystem グループ

- module: UserAgent::AuthenRequest
  config:
    host: twitter.com:80
    auth: basic
    realm: Twitter API
    username: =Twitter ID=
    password: =Twitter password=

- module: Subscription::Config
  config:
    feed:
      - http://twitter.com/favorites.rss

- module: Aggregator::Simple

RSS を逆順に並べる

ここまでで,Twitter で自分が Fav したポストを最大 20 件取得しています.続いてこれらを逆順に並びかえます. ここは趣味なんですが,古い方を Tumblr で下にしたければそうしないといけません.やり方は以下のサイトで 書かれている「Filter::Reverse」プラグインをそのまま使わせて頂きました.

[sbm] del.icio.us to hatebu – nirvash の日記

そんで,そのファイルを適当なところに「PATH/lib/Plagger/Plugin/Filter/」とディレクトリ構造を作って, Filter フォルダの中に「Reverse.pm」という名前で保存しておきます.自分で適当なプラグイン作った時は とりあえず「PATH/lib/Plagger/Plugin/」の下に種類別のフォルダ作ってつっこめばおk.あとは,YAML ファイルで そのディレクトリをプラグインパスとして指定しつつ組み込むだけ.

grobal:
  plugin_path:
    - もともとあればそのままにして追加
    - PATH/lib/Plagger/Plugin

plugin:

    - module: Filter::Reverse

データを加工して Tumblr へポスト

続いて,Tumblr へのポスト用に加工してポストまでやってしまいます.探したんですが,まぁまだ 無いようでしたので自作しました.ただし,加工する部分と投稿する部分を分けるのが面倒だったので 一緒にしてしましました(というか,Filter まで調べるのが面倒だっただけ><)

僕が作ったのは「Publish::TumblrQuoteTwitter」というモジュールです.とりあえずこれを 「PATH/lib/Plagger/Plugin/Publish」に入れておきます.あとは YAML ファイルで以下のように 指示すれば,自分のメイン Tumblr の Quote として(Tombloo と似た感じ)で投稿してくれます.

global:
  plugin_path:
    - /originalPATH/lib/Plagger/Plugin
    - /PATH/lib/Plagger/Plugin
  assets_path: /PATH/plagger/assets
  log:
    level: debug
  timezone: Asia/Tokyo

plugins:
  - module: UserAgent::AuthenRequest
    config:
      host: twitter.com:80
      auth: basic
      realm: Twitter API
      username: username
      password: password

  - module: Subscription::Config
    config:
      feed:
        - http://twitter.com/favorites.rss

  - module: Aggregator::Simple

  - module: Filter::Reverse

  - module: Publish::TumblrQuoteTwitter
    config:
      username: username@mail.com
      password: password

以下,モジュールの説明をしていきます.ソースはこちらです.

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

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

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 $body = $args->{entry}->{body};
    my $url = $args->{entry}->{link};

    $body =~ /^(.+?): (.+)/o;
    my $id = $1;
    my $quote = encode_utf8($2);
    my $source = "<a href=\"" . $url . "\">Twitter / " . $id . "</a>";

    my $uri = URI->new($url);
    my $scraper = scraper {
        process 'span.meta', 'meta' => 'TEXT';
    };
    my $res = $scraper->scrape($uri);

    if($res->{meta} =~ /from/){
        $context->log(info => "Tumblr posting '$quote'");
        $self->{tumblr}->write(
            type => 'quote',
            quote => $quote,
            source => $source,
            );

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

1;

Plagger モジュール「Publish::TumblrQuoteTwitter」

まず,Tumblr の投稿は TumblrAPI を利用しています.これは CPAN に「WWW:Tumblr」というパッケージが あったので使わせてもらいます.本当は,Tumblr V4 でサブ Tumblr を作れるようになったので, そこに投稿する方向も考えたのですが,まだ API が対応していないようでしたので,今回は見送りました.

WWW::Tumblr – Perl interface for the Tumblr API – search.cpan.org

さて,投稿の部分はこれでよいので,取得できている RSS のデータを加工します.Twitter からは

  • ユーザ ID: 発言内容
  • 発言 URL

というテキストしか得られません.上のテキストを正規表現で切り取って「ユーザ ID」と「発言内容」に します.正規表現マンセー

とりあえずあとはこれを WWW::Tumblr に投げてしまえばおkなんですが,ここでちょっと問題が. このままだと,Protect の人の発言も Tumblr に流せてしまうことになります.僕は空気が 読めるのでちゃんと Protect の人はフィルタリングして Tumblr に流すようにしましょう.

そう思って,ユーザ ID から Twitter の API を叩いてその人の Protect の様子を調べてみることに しましたが,苦戦.まずもう一度 Twitter にログインしないといけないので面倒だし, API を叩きまくるのでちょっと嫌な感じもします.さらに,なんとか実装してみたら うまく Protect の判別が出なくて,もうウキーーーーッ!ってなったのでこっちはやめました.

そこで,もっと簡単に Twitter にログインせずにアクセスしてみれば,Protect かどうかわかるじゃんと いうことで,やってみました.実際,アクセスすると,Protect だったら「○○」という部分が 存在しないので,これをキーにして判別しようと思いました.

HTML ソースの解析になるので,ここでは前回指摘を頂いたこともあり「Web::Scraper」を 使いました.めっちゃ簡単でびびりましたww 使い方はこの辺のサイトを見ましたが よくわからず,単に「」というタグが存在するかどうかをチェックするだけに しましたが,これで成功しました.

use Web::Scraper; – 今日の CPAN モジュール

というわけで,これで Protect 以外の人のとっても変態なポストを Tumblr の海へと放り投げることが できることになりました^^ もちろん,後は CRON で回さないといけないのですが,やりかた よく知らないので後回し orz 暇なときに手で叩いていますww

  • rytich 08-11-09 (日) 9:07

    使わせていただきます、ありがとうございますー

    Publish::TumblrQuoteTwitter の 41 行目を
    process ‘span.entry-meta’, ‘meta’ => ‘TEXT’;
    にしたら自分の環境だと動きましたー

  • riywo 08-11-09 (日) 17:39

    なんかいろいろブクマして頂いたりしてありがとうございます> ALL

    実は,Fav の RSS はログインせずとも取れて,それだと Protect の
    判定が必要ないので実装がめっちゃ簡単です.最近それに
    変更したので,近日中にアップデートしたモノをエントリとして
    アップしますのでよろしくです.