2010年8月29日

全力で

日常を進める気力が沸かずに眠ってばかりいたので、全力で現実逃避してみた。

mutt のソースの最新を取ってきて自力コンパイルしたり、MakeWorld してみたり、ふた月ほど離れていた mixi のコミュニティの話題に追いつくため、トピックの記事一括ダウンロードのスクリプト書いたり。

見るトピックがわかっていれば、スクリプト書かなくてもブラウザから全記事を見れば良い 、正しい。単に頭の体操としてスクリプト書いて遊んでいただけだ。

単に遊んでいるだけ。

mutt のコンパイル手順

  1. もし hg コマンドが使えないならば mercurial をインストール
  2. $ hg clone hg clone http://dev.mutt.org/hg/mutt workdir
  3. $ cd workdir ; ./prepare configureOptions
  4. $ make && sudo make install

私が configure オプションスを与えるのに使ったスクリプト

./prepare \
--prefix=/usr/develop \
--enable-pgp \
--disable-pop \
--enable-imap \
--enable-smtp \
--enable-debug \
--enable-inodesort \
--disable-nfs-fix \
--disable-mailtool \
--enable-locales-fix \
--enable-exact-address \
--enable-hcache --with-gdbm --without-bdb --with-tokyocabinet \
--enable-iconv \
--with-regex \
--with-ssl=/usr \
--with-gnutls=/usr/local \
--with-sasl=/usr/local \
--with-idn=/usr/local \

インストール先が /usr/develop てのは相当苦しいが、/usr/local に入れた ports からの 安定 version と別にしたかった

ports の版と違い、データベースファイルに tokyocabinet は使えないので、じつはこれを動かすと警告が出る。

GNU make でなく、BSD に元からある make が使えたのはうれしかった。気分の問題でしかないが。

いまはこんな設定を加えた。

yaemon@bouon-an$ alias muttd
alias muttd='/usr/develop/bin/mutt -F /home/yaemon/dotfiles/.muttrc-develop  -d 1'
yaemon@bouon-an$ diff ~/dotfiles/.muttrc{,-develop}
21,21
< set smtp_pass=Secret
---
> # 送信パスワードは、本家の版では保存されない。コメントアウトしておいて毎回入力
25a25,28
>
> set header_cache=/home/yaemon/var/mutt/CachesGDB/header
> set message_cachedir=/home/yaemon/var/mutt/CachesGDB/body
> set pager=

fetchMixiBBS

車輪の再発明 とかいわない。運動をしたら汗をかくようなもので、全力で現実逃避したら成果ができる。それだけ。

Objective でない考え方でスクリプトが設計できないってだけのバカです。

$ cat ~/bin/fetchMixiBBS
#!/usr/bin/env perl
#
#       $Id: fetchMixiBBS,v 1.1 2010/08/29 00:16:11 yaemon Exp $
#
use strict;
use warnings;
use FileHandle;
use WWW::Mixi::Scraper;
use lib( "/home/yaemon/lib/perl" ); use MixiToRFC2822::BBSWrapper qw( id subject pop );
sub checkMaildir($); sub getMessage( $$ );
my $mixi = WWW::Mixi::Scraper->new( 'email' => 'EmailAddressForLogin' , 'password' => 'PasswordForMixi' , );
my $storeDir = $ENV{ 'HOME' } . "/Maildir/mixi/"; checkMaildir( $storeDir );

my $list = new FileHandle( "< $ARGV[0]" ); if ( ! defined( $list ) ) { die "Can't open $ARGV[0]:$!"; }
while( my $line = $list->getline ) { chomp( $line); $line =~ s/#.*//; if ( $line !~ /^[0-9]+$/ ) { next; }
getMessage( $mixi , $line); }
sub checkMaildir( $ ) { my $maildir = shift; if ( ! -d $maildir ) { mkdir( $maildir ) or die "Can't mkdir $maildir:$!"; } if ( ! -d "$maildir/new" ) { mkdir( "$maildir/new" ) or die "Can't mkdir $maildir/new:$!"; mkdir( "$maildir/cur" ) or die "Can't mkdir $maildir/cur:$!"; mkdir( "$maildir/tmp" ) or die "Can't mkdir $maildir/tmp:$!"; } }
sub getMessage( $$ ) { my $account = shift; my $bbs = shift;
my $all = $account->parse( "/view_bbs.pl?id=$bbs&page=all" ); if ( defined ( $all ) ) { printf STDERR "%s: %s fetch success\n" , my $datestr = localtime() , $bbs ; } else { die( "Can't get $bbs. retry not implimented" ); } my $board = MixiToRFC2822::BBSWrapper->new( $all ); my $dir = $storeDir . "/" . $board ->community->id() . '-' . $board->community()->name();
checkMaildir( $dir );
while( my $comment = $board->pop() ) { if ( -f $dir . "/new/" . $comment->uniqueName() || glob( $dir . "/cur/" . $comment->uniqueName() . '*' ) ) { return; }
my $out = new FileHandle( "> $dir/new/" . $comment->uniqueName() ); if ( ! defined( $out )) { die "Can't open messagefile:$!"; } $out->print( $comment->message() ); } }
$ ls ~/lib/perl/MixiToRFC2822
BBSWrapper.pm
CVS/
Community.pm
Message.pm
$ cat ~/lib/perl/BBSWrapper.pm
#!/usr/bin/env perl
#
#   $Id: BBSWrapper.pm,v 1.1 2010/08/29 00:17:16 yaemon Exp $
#
package MixiToRFC2822::BBSWrapper;
use strict;
use warnings;
use Carp; use Exporter; use lib( "/home/yaemon/lib/perl"); use MixiToRFC2822::Community; use MixiToRFC2822::Message;
use vars qw( $VERSION @ISA @EXPORT_OK ); sub id($); sub subject($); sub child($); sub root($);

our $VERSION = "0.01"; @ISA = qw( Exporter); @EXPORT_OK = qw( id subject commuity pop);

sub new($$) { my $self = bless {} , shift; $self->{ '_data' } = shift; return $self; }
sub id($) { my $self = shift; return $self->{ '_id' } if exists $self->{ '_id' } ; my @tmp = grep( /^id=/ , split( /[\&\?]/ , $self->{'_data'}->{'link'}->opaque )); if ( @tmp != 1 ) { die "Can't parse " . $self->{'_data'}->{ '_link' } } $self->{'_id'} = $tmp[0]; $self->{'_id'} =~ s/^id=//; return $self->{'_id'}; }
sub community($) { my $self = shift; return $self->{'_community'} if exists $self->{ '_community'};
$self->{'_community'} = MixiToRFC2822::Community->new( $self->{'_data'}->{'community'} ); }
sub subject($) { my $self = shift; return $self->{'_data'}->{'subject'}; }
sub root($) { my $self = shift; return $self->{ '_root' } if exists $self->{ '_root' } ; my $message; $message->{'subject'} = $self->subject(); $message->{'name_link'} = $self->{'_data'}->{'name_link'}; $message->{'name'} = $self->{'_data'}->{'name'}; $message->{'time'} = $self->{'_data'}->{'time'}; $message->{'description'} = $self->{'_data'}->{'description'}; $message->{'to'} = $self->community(); $self->{'_root'} = MixiToRFC2822::Message->new( $message , 'bbs' ); }

sub pop($) { my $self = shift; return undef if exists $self->{'_end'} ; my $message = pop( @{ $self->{_data}->{comments}} ); if ( ! defined( $message ) ) { $self->{'_end'} = 1; return $self->root(); } $message->{'reply_to'} = "<" . $self->root()->uniqueName() . ">"; $message->{'subject'} = "Re: " . $self->subject(); $message->{'to'} = $self->community();
return MixiToRFC2822::Message->new( $message , 'bbs' ); } 1;

$ cat ~/lib/perl/Community.pm
#!/usr/bin/env perl # # $Id: Community.pm,v 1.1 2010/08/29 00:17:16 yaemon Exp $ # package MixiToRFC2822::Community; use strict; use warnings;
use Carp; use Exporter; use vars qw( $VERSION @ISA @EXPORT_OK );
sub id($); sub name($);
our $VERSION = "0.01"; @ISA = qw( Exporter); @EXPORT_OK = qw( id name );

sub new($$) { my $name = shift; my $data = shift; return bless $data , $name;
}
sub id($) { my $self = shift; return $self->{ '_id' } if exists $self->{ '_id' } ;
$self->{'_id'} = $self->{'link'}->opaque(); $self->{'_id'} =~ s/.*id=//;
return $self->{'_id'}; }

sub name($) { return shift->{'name'}; }
1;
$ cat ~/lib/perl/Message.pm
#!/usr/bin/env perl
#
#   MixiToRFC2822.pm      2010-07-07 yaemon
#   $Id: Message.pm,v 1.1 2010/08/29 00:17:16 yaemon Exp $
#
package MixiToRFC2822::Message;
use strict;
use warnings;
use Carp;
use Exporter;
use Mail::Internet;
use Mail::Header;
use Encode qw/encode/;
use DateTime;
use vars qw( $VERSION @ISA @EXPORT_OK );
sub message($); sub date( $ ); sub uniqueName($); sub messageFrom($);
our $VERSION = "0.01"; @ISA = qw( Exporter); @EXPORT_OK = qw( uniqueName message );

sub new($$$) { my $self = bless {} , shift; $self->{ '_message' } = shift; $self->{ '_kind' } = shift;
return $self; }
sub message($) { my $self = shift; return $self->{ '_mailFormat' }->as_string() if exists $self->{ '_mailFormat' }; my $myAddr = "( T.Nakagawa ) <23211\@mixi.jp>"; my $otherAddr = sprintf( "( %s )<%d\@mixi.jp> " , encode( 'MIME-Header' , $self->{ '_message'}->{ 'name' } ) , $self->messageFrom() ); my $header = Mail::Header->new(); $header->header_hashref( { 'Subject' => encode( 'MIME_Header' , $self->{ '_message'}->{'subject'} ), 'MIME-version' => "1.0" , "Message-Id" => sprintf( "<%s\@mixi.jp>" , $self->uniqueName() ), 'Content-Type' => 'text/plain; charset=utf-8' , 'Date' => $self->date->strftime( "%a, %d %b %Y %H:%M:%S %z") , } );
if ( $self->{ '_kind'} eq "inbox" ) { $header->add( 'From' , $otherAddr ); $header->add( 'To' , $myAddr ); } elsif ( $self->{ '_kind'} eq "outbox" ) { $header->add( 'To' , $otherAddr ); $header->add( 'From' , $myAddr ); } elsif ( $self->{ '_kind' } eq "bbs" ) { $header->add( 'From' , $otherAddr ); $header->add( 'To' , sprintf( "( %s )<%s%%community\@mixi.jp>" , encode( 'MIME-Header' , $self->{'_message'}->{'to'}->name() ) , $self->{'_message'}->{'to'}->id() ) ); if ( exists( $self->{'_message'}->{'reply_to'} ) ) { $header->add( 'In-Reply-To' , $self->{'_message'}->{'reply_to'} ); } } else { die "Not implementd messagebox:$self->{'_kind'}"; }

my $body = encode( 'utf-8' , $self->{ '_message' }->{ 'description'} ); $body =~ s/&#(\d+);/pack("W" , $1)/meg;
$self->{ '_mailFormat' } = Mail::Internet->new( 'Body' => [ map { "$_\r\n"; } split( "<br />" , $body ) ], 'Header' => $header, );
return $self->{ '_mailFormat' }->as_string(); }

sub uniqueName($) { my $self = shift; return $self->{ '_uniqueName' } if exists $self->{ '_uniqueName' } ; $self->{ '_uniqueName' } = sprintf( "%d.%s.%s" , $self->date()->epoch() , $self->messageFrom() , "mixi.MixiToRFC2822" );
return $self->{ '_uniqueName' }; }

sub messageFrom($) { my $self = shift; return $self->{ '_from' } if exists $self->{ '_from' }; my $tmp; if ( $self->{'_kind'} =~ /box$/ ) { $tmp = $self->{ '_message' }->{ 'link' }->opaque(), } else { $tmp = $self->{ '_message' }->{ 'name_link'}->opaque(); } $tmp =~ /id=([0-9]+)/; $self->{ '_from' } = $1; return $self->{ '_from' }; } sub date( $ ) { my $self = shift;
return $self->{ '_date'} if exists $self->{ '_date' };

my @date = split( /[\- :]/ , $self->{ '_message' }->{ 'time' } );
$self->{ '_date' } = DateTime->new( "year" => $date[0] , "month" => $date[1] , "day" => $date[2] , "hour" => $date[3] , "minute" => $date[4] , "second" => 1 , time_zone => 'Asia/Tokyo' , );

$self->{ '_date' }; }

1;
yaemon@bouon-an$  /usr/local/lib/perl5/site_perl/5.12.1/WWW/Mixi/Scraper/Plugin/ViewBBS.pm{.orig,} 
*** /usr/local/lib/perl5/site_perl/5.12.1/WWW/Mixi/Scraper/Plugin/ViewBBS.pm.orig        Sun Aug 29 13:45:12 2010
--- /usr/local/lib/perl5/site_perl/5.12.1/WWW/Mixi/Scraper/Plugin/ViewBBS.pm    Sun Aug 29 06:22:10 2010
***************
*** 36,42 ****
        description => $self->html_or_text;
      process 'dd.bbsContent>dl>dd>div.communityPhoto>table>tr>td',
        'images[]' => $scraper{images};
!     result qw( time subject description name name_link images link );
 };
# bbs topic is not an array --- 36,46 ---- description => $self->html_or_text; process 'dd.bbsContent>dl>dd>div.communityPhoto>table>tr>td', 'images[]' => $scraper{images}; ! ! process 'p.utilityLinks03>a', ! _community_name => 'TEXT', ! _community_link => '@href'; ! result qw( time subject description name name_link images link _community_name _community_link); };
# bbs topic is not an array *************** *** 84,89 **** --- 88,103 ---- } $stash->{comments} = \@comments;
+ + $stash->{_community_name} =~ s/.*\[//; + $stash->{_community_name} =~ s/\].*//; + + $stash->{community}->{name} = $stash->{_community_name}; + $stash->{community}->{link} = $stash->{_community_link}; + + undef $stash->{_community_name}; + undef $stash->{_community_link}; +
return $stash; }

2010年8月23日

少女漫画ばかり読んでいる

~14日

しばらく関西に滞在して、木曜日に帰ってきた。関西は半年ぶり。

冷房も使える東京よりも、関西の暑さに汗を流すほうが健康な気がするなんてどういうことかと到着した日に思った。なんのことはない。今年は、関西のほうが東京よりも湿気が少なかったようだ。

先に関西に滞在している娘に持っていった漫画が3つ。

めだかボックス 2~3巻

前回に娘と会った日に、彼女が口にした ぬらりひょんの孫 と少年ジャンプ掲載つながりで併せて古本屋を回り、それぞれ一巻しか贈ることができなかった本。

  • サイコロをまとめて振れば、たとえば全部が6。なにをやっても気持ちの悪い結果を出すのが異能者。 (それは、もう巡り合わせというしかない)
  • 異能者は孤独なれば、それぞれの能力は違えど互いのつながりを大事にする

しばらく前に漫画喫茶で単行本を読み返し、この辺りの考えが気に入ったので読ませたいと思っていた。

ラグトニア無番 , II

このブログで最も検索からのアクセスが多い読書感想を書いたらせつの花同じ作家さんの漫画。

古本で無番(一巻) を買ったのがあまりに気に入って、II も更本で購入してしまったわけだ。最終巻 III ももうすぐ出るという。

あんな良い人を死なせてはいけない

薬師アルジャン 1~4巻

有名作品として前から気になっていた。古本で6巻までみつけたので購入してしまったばかり。

部屋が片付いていなくて、4巻までしか渡せなかった。

互いに近くにいてこその気心のしれた深い付き合い、良いね。腹が立つくらい。

15日

下鴨神社を訪れたら、古本市をやっていた。

東京の古本屋を回っては、値段が折り合わなくて見送っていた英英辞典。Oxford の 1995年5版が 300円で投げ売りされていたのを手に入れた。

オカルト系の邦訳資料も一冊、うっかり見つけて買ってしまった。

東京に住んでいるくせに、京都にくるたびに普段より古本を仕入れている。どういうことだ。

~17日

私が学生時代に蒐め読みふけった本より、今回は15~20年前の菊池秀行を中心にいくつも読み返した。

二十代のころの元気をとりもどした。

18日

大阪市内を回って、あれこれ手続き。

堺筋本町を通るときに福島上等カレーという店を見つける。(阪神と JR の乗り換えができる、大阪市内の福島のことだ。福島県ではない)

用事が終わって、足の向くままに歩いて本町の交差点近くで感じの良いスタンドの店を見つけて入った。中に入ってよく見たら、同じチェーン店。

定価 880円を 600円にしてキャンペーン中の 薬膳カレー が大当たり。30分かけてゆっくりと食べて元気をとりもどした。東京にもこないかな。


地下鉄西梅田から、JR大阪に出ようとして迷う。足に任せて動くと、二十代の終わり頃の羽振りの良かった頃によく遊んだほうにうっかり移動してしまうという理由で。

うっかり歓楽地に遊んではいけない、と書店に入る。

一軒目でみつけ、買わざるをえないと感じたのが、ちょっとしたアンソロジーQED 鏡家の薬屋探偵 。鏡家サーガは一冊しか読んでいないが、薬屋探偵奇譚と QED はファンだし、著者の中に西澤保彦と竹本健治の名前があってはしかたがない。竹本さんの個人短篇が一冊にまとまるのを待っていたら、いつ読めるか分からん。

そこで思いついて、気になっていた漫画の新刊、傀儡師リン11巻を探しに二軒目の書店へ。

二軒目の入り口すぐに並んでいて買ってしまったのが、まず文藝別冊/萩尾望都

さらに 最強の天使ニシテ最愛の悪魔 という新刊 1~4なんか見つけてしまった。タイミングが悪い。まさに兵庫に住んでいた頃に途中まで読んでいた、同シリーズの ジャンク・ジャングル の全巻を古本で買ったところで、懐かしかったのね。兵庫でシリーズの第一部の はらったま、きよったま は読み返さなかったが。

上記、すべて東京に帰る車中で読了。

QED 鏡家の薬屋探偵 : 竹本さん以外は、キャラクタを借りて自分の持ち味で好き勝手書いている。西澤さんが…。ストーカとダイエット という西澤さんの持ちネタをこんな的確・簡潔に、アトリビュートで書いちゃってよいの ? という逸品。

最強の… : シリーズキャラクタ勢ぞろいは私のようなオールド・ファンにはうれしいけれど。べたべたの愛情少女マンガなのに、これだけシリーズキャラクタだらけでは娘に渡せない。

傀儡師リン : この巻の舞台になった学園について、河合隼雄的な分析をしてみたいような、したくないような。

19日

用事で九段下。九段下の書店で、薬師アルジャン の 11巻をみつけて、7巻から買おうと神保町に向かう。

11巻、昨年末で完結していたのね。最後の風呂敷の締め方はだいたい予想がついたが、それでもハラハラした。まとめて買うタイミングで出会ってよかった。

漫画の新刊の専門店に行っただけに、いくら古本をみても 3巻までしか見当たらなかった サタニスター最終5巻もみつけて購入してしまった。

古本ではどこに行っても見当たらないものだから、この著者のことだし完結しないまま打ちきりになった印象になっていた。mixi のコミュで、連載の終了時に讃辞を多数みた覚えもあるのにね。

総括

ブックオフなどの新古書店のせいで売上が減っている以上に、新刊の売上は上がっていると思う。少なくとも私の財布はえらい目にあっている。