Twitterの1日分のタイムラインをKindleで読む

この記事は2年以上前に書いたものです。
そのため情報が古い可能性があります。ご了承ください。m(_ _)m

時間かけて探せば良い感じのが有りそうだけど、すぐには見つからなかったのでで書いてみた。

仕様的なもの。

  • 常駐せずに、10分おきくらいにcronで動かす。
  • 1日分のtweetは、$timeline_fileに溜め込む。
  • 1日分の切り替えは、Log::Dispatch::FileRotateに任せる。
    (微妙にずれる場合もあるけど、細かいことは(゚ε゚)キニシナイ!!)
  • $timeline_fileへの出力は、Log::Log4perl の INFOで。
  • へ送信するタイミングは、$timeline_fileのサイズが小さくなったら。
    (FileRotateで切り替わったらファイルサイズが小さくなるので、それ契機)
  • kindleへの送信するデータは、htmlファイル。
  • 送信先は、@kindle.com or @free.kindle.com。
    (自動的に変換して、端末へ配信してくれる)

gettimeline.pl(gettimeline.zip)

#!/usr/bin/perl

use 5.010;
use strict;
use warnings;
use Encode;
use DateTime;
use DateTime::TimeZone;
use DateTime::Format::DateParse;
use Data::Dumper;
use HTML::Entities;
use MIME::Lite;

use Net::Twitter;
use Log::Log4perl qw(:easy);

# Twitter key and token
my $consumer_key = 'xxxxxxxxxxxxxxxxxxxxx';
my $consumer_secret = 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy';
my $token = 'nnnnnnnnnn-zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz';
my $token_secret = 'sssssssssssssssssssssssssssssssssssssssssss';

# log
my $logfile = '/home/user/tool/twitter.log';
my $timeline_file = '/home/user/tool/timeline.log';

# mail
my $mailfrom = 'xxxx@xxx.xxx';
my $mailto = 'yyyyy@free.kindle.com';

# title
my $title_fmt = 'Twitter_Timeline_%Y-%m-%d(%a)';


my $tid_prefix = '__TID__:';
my $tz = DateTime::TimeZone->new(name => 'local');

&loginit;

&main;

exit;

sub main{
    my $filesize = -s $timeline_file;

    &gettl;

    if($filesize > -s $timeline_file){
    say 'send to kindle';
    &send2kindle;
    }
}

sub send2kindle{
    my $dt = DateTime->now(time_zone => $tz);
    $dt->subtract(days => 1);
    my $title = $dt->strftime($title_fmt);
    my $fname = $title . '.html';

    my $timeline_file1 = $timeline_file . '.1';
    open my $fh, '<', "$timeline_file1"
    or die "failed to open file: $!";
    my $rawdata = do { local $/; <$fh> };

    my @rawdata_array = grep(!/^$tid_prefix \d+$/, split(/\n/, $rawdata));


    my $htmldata = <<_HEADER_;
<html>
  <head>
    <title>$title</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
<body>
  <h3>$title</h3>
<pre>
_HEADER_

    $htmldata .= Encode::decode_utf8(join("\n", @rawdata_array));

    $htmldata .= <<_FOOTER_;
</pre>
</body>
</html>
_FOOTER_

    my $subject = $title;

    my $msg = MIME::Lite->new(
    From => "$mailfrom",
    To => "$mailto",
    Subject => "$subject",
    Type => 'multipart/mixed'
    );
    $msg->attach(
    Type => 'text/plain; charset="iso-2022-jp"',
    Data => "no body"
    );
    $msg->attach(
    Type => 'text/html',
    Data => "$htmldata",
    Filename => "$fname",
    Disposition => 'attachment'
    );
    $msg->attr('content-type.charset' => 'UTF-8');

#    WARN Dumper($msg);
#    WARN $htmldata;

    $msg->send();

}

sub gettl{
    my $nt = Net::Twitter->new(
    traits => [qw/OAuth API::REST/],
    consumer_key => $consumer_key,
    consumer_secret => $consumer_secret,
    access_token => $token,
    access_token_secret => $token_secret,
    );

#    WARN "TWEET: " . $tweet;

    my @tl = $nt->home_timeline({count => 200});

    my @rtl = reverse(@{$tl[0]});

    my $tail_cmd = "tail -2 $timeline_file";
    my $grep_cmd = "grep -e "$tid_prefix [0-9]\\+"";
    my $sed_cmd = "sed -r "s/[^0-9]+([0-9]+)/\\1/"";
    my $lastid = `$tail_cmd | $grep_cmd | $sed_cmd`;
    chomp $lastid;

    if($lastid){
    for my $i (0 .. $#rtl) {
        if($lastid eq $rtl[$i]->{id}){
#say "0 -> " . $i . " ($#rtl)";
        splice(@rtl, 0, $i+1);
#say "  -> " . $#rtl;
        last;
        }
    }
    }

    my $id = '';
    foreach my $t(@rtl){
    WARN $t->{id};
    $id = $t->{id};
    my $s = &mklinktag($t->{text});
    my $dt = DateTime::Format::DateParse->parse_datetime($t->{created_at});
    $dt->set_time_zone($tz);

    INFO encode_utf8($t->{user}{name}) .
        ' (<a href="https://twitter.com/' . $t->{user}{screen_name} . '">' .
        '@' . $t->{user}{screen_name} . '</a>)' . "\n" .
        encode_utf8($s) . "\n" .
        $dt->strftime('(%Y/%m/%d %H:%M:%S)') . "\n";
#   WARN Dumper($t);
    WARN Dumper($s);
    }
    INFO "$tid_prefix " . $id . "\n" if $id;
}

sub mklinktag{
    my ($s) = @_;

    $s = encode_entities($s, q{&<>"'});

    $s =~ s!(https?://)([0-9a-zA-Z/\.]+)!<a href="
$1$2">$2</a>!go;

    $s =~ s!@([a-zA-Z0-9_]+)!<a href="
https://twitter.com/$1">\@$1</a>!go;

    $s;
}

sub loginit{
  my $logsize = 10*1024*1024;
  Log::Log4perl->init(\ qq{
    log4perl.logger = INFO, AppError, Tweet

    # filter range
    log4perl.filter.MatchRange               = Log::Log4perl::Filter::LevelRange
    log4perl.filter.MatchRange.LevelMin      = WARN
    log4perl.filter.MatchRange.LevelMax      = ERROR
    log4perl.filter.MatchRange.AcceptOnMatch = true

    # Error appender
    log4perl.appender.AppError = Log::Dispatch::FileRotate
    log4perl.appender.AppError.filename   = $logfile
    log4perl.appender.AppError.max   = 10
    log4perl.appender.AppError.autoflush   = 1
    log4perl.appender.AppError.size   = $logsize
    log4perl.appender.AppError.mode = append
    log4perl.appender.AppError.layout   = Log::Log4perl::Layout::PatternLayout
    log4perl.appender.AppError.layout.ConversionPattern = %d %02X{client} %p %F{1} %L: %m %n
    log4perl.appender.AppError.Filter   = MatchRange

    # Filter to match level WARN
    log4perl.filter.MatchInfo  = Log::Log4perl::Filter::LevelMatch
    log4perl.filter.MatchInfo.LevelToMatch  = INFO
    log4perl.filter.MatchInfo.AcceptOnMatch = true

    # Error appender
    log4perl.appender.Tweet = Log::Dispatch::FileRotate
    log4perl.appender.Tweet.filename   = $timeline_file
    log4perl.appender.Tweet.max   = 10
    log4perl.appender.Tweet.autoflush   = 1
    log4perl.appender.Tweet.DatePattern = yyyy-MM-dd
    log4perl.appender.Tweet.TZ = JST
    log4perl.appender.Tweet.mode = append
    log4perl.appender.Tweet.layout   = Log::Log4perl::Layout::PatternLayout
    log4perl.appender.Tweet.layout.ConversionPattern = %m %n
    log4perl.appender.Tweet.Filter   = MatchInfo
 });
}

↑のコードで送信されたファイルのスクリーンショットが↓。

screenshot_2013_05_19T09_28_12 0900

アイコンとかも持って来たほうが見栄えが良いんだろうけど、とりあえずシンプルなこれで使ってみる。

カテゴリー: ソフトウェア, プログラム タグ: , , , , パーマリンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です