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の
判定が必要ないので実装がめっちゃ簡単です.最近それに
変更したので,近日中にアップデートしたモノをエントリとして
アップしますのでよろしくです.