はてなダイアリーライター 0.5.0 のパッチ
id:hyuki:20040825にて、はてダラのバージョンアップ報告があったので、昨日自サイトの日記にアップしたパッチを再度適用。あとエントリのロード機能ではtouch.txtを更新しないように修正。パッチは以下に貼り付けときます。
--- hw050.pl Wed Aug 25 12:07:56 2004 +++ hw050p1.pl Wed Aug 25 18:58:10 2004 @@ -15,7 +15,7 @@ # modify it under the same terms as Perl itself. # use strict; -my $VERSION = "0.5.0"; +my $VERSION = "0.5.0-patch1"; use LWP::UserAgent; use HTTP::Request::Common; @@ -23,11 +23,17 @@ use File::Basename; use Getopt::Std; +my $enable_encode = eval('use Encode; 1'); + # Prototypes. sub login(); sub logout(); +sub update_mode(); +sub load_mode(); +sub load_diary_entry($$$); sub update_diary_entry($$$$$$); sub delete_diary_entry($); +sub load_it($$$); sub create_it($$$); sub delete_it($); sub post_it($$$$$$); @@ -58,6 +64,13 @@ # where %s is filename, output is stdout. my $filter_command = ''; +# Proxy setting. +my $httpproxy = ''; + +# Encoding. +my $c_code = 'euc-jp'; +my $s_code = 'euc-jp'; + my $hatena_url = 'http://d.hatena.ne.jp'; my %ua_option = ( @@ -81,10 +94,12 @@ 'g' => "", # "groupname" option. 'f' => "", # "file" option. 'M' => 0, # "no timestamp" flag. + 'l' => "", # "load" option. + 'n' => "", # "coNfig file" option. ); $Getopt::Std::STANDARD_HELP_VERSION = 1; -getopts("tdu:p:a:T:cg:f:M", \%cmd_opt); +getopts("tdu:p:a:T:cg:f:Ml:n:", \%cmd_opt); if ($cmd_opt{d}) { print_debug("Debug flag on."); @@ -93,6 +108,8 @@ &VERSION_MESSAGE(); } +$config_file = $cmd_opt{n} if $cmd_opt{n}; + # Override global vars with config file. load_config() if -e($config_file); @@ -117,6 +134,16 @@ # Main sequence. sub main { + if($cmd_opt{l}) { + load_mode(); + } + else { + update_mode(); + } +} + +# Update mode. +sub update_mode() { my $count = 0; my @files; @@ -189,10 +216,30 @@ } } +# Load mode +sub load_mode() { + + # Check -s option format. + error_exit("Illegal -l option format.") if $cmd_opt{l} !~ /(\d\d\d\d)-(\d\d)-(\d\d)/; + my ($year, $month, $day) = ($1, $2, $3); + + # Login if necessary. + login unless ($user_agent); + + # Load + print_message("Load $year-$month-$day."); + load_diary_entry($year,$month,$day); + print_message("Load OK."); + + # Logout if necessary. + logout if ($user_agent); +} + # Login. sub login() { $user_agent = LWP::UserAgent->new(%ua_option); $user_agent->env_proxy; + $user_agent->proxy( 'http', $httpproxy ) if $httpproxy; # Ask username if not set. unless ($username) { @@ -276,6 +323,31 @@ print_message("Logout OK."); } +# Load entry. +sub load_diary_entry($$$) { + my ($year, $month, $day) = @_; + my $load_retry = 0; + my $ok = 0; + +LOAD_RETRY: + while ($load_retry < 2) { + # Load. + $ok = load_it($year, $month, $day); + if ($ok or not $cmd_opt{c}) { + last; + } + print_debug("load_diary_entry: LOAD_RETRY."); + unlink($cookie_file); + print_message("Old cookie. Retry login."); + login(); + $load_retry++; + } + + if (not $ok) { + error_exit("load_diary_entry: get: Check username/password."); + } +} + # Update entry. sub update_diary_entry($$$$$$) { my ($year, $month, $day, $title, $body, $imgfile) = @_; @@ -381,6 +453,70 @@ } } +# Load. +sub load_it($$$) { + my ($year, $month, $day) = @_; + + print_debug("load_it: $year-$month-$day."); + + $user_agent->cookie_jar($cookie_jar); + + my $r = $user_agent->simple_request( + HTTP::Request::Common::GET("$hatena_url/$username/edit?date=$year$month$day")); + + print_debug("load_it: " . $r->status_line); + + if (not $r->is_success()) { + error_exit("Load: Unexpected response: ", $r->status_line); + } + + # Check entry exist. + $r->content =~ /<form method="post" action="\.\/edit" .*?>(.*<\/textarea>)/s; + my $form_data = $1; + + $form_data =~ /<input type="hidden" name="date" value="(\d\d\d\d\d\d\d\d)">/; + my $resp_date = $1; + + if($resp_date ne "$year$month$day") { + error_exit("Load: Not exist entry."); + } + + $form_data =~ /<input class="field" name="title" .*?value="(.*?)">/; + my $title = $1 . "\n"; + $form_data =~ /<textarea .*?>(.*)<\/textarea>/s; + my $body = $1; + + if ($enable_encode and ($c_code ne $s_code)) { + Encode::from_to($title,$s_code,$c_code); + Encode::from_to($body,$s_code,$c_code); + } + # Save entry to file. + my $datename = "$year-$month-$day"; + + # Check if file is exist. + if(-f "$datename.txt") { + my $bakext = 0; + while(-f "$datename.$bakext") { + $bakext++; + } + if (not rename("$datename.txt", "$datename.$bakext")) { + error_exit("$!:$datename.txt"); + } + } + + if (not open(OUT, ">$datename.txt")) { + error_exit("$!:$datename.txt"); + } + + print OUT $title; + print OUT $body; + close(OUT); + + print_debug("load_it: returns 1 (OK)."); + return 1; +} + + sub create_it($$$) { my ($year, $month, $day) = @_; @@ -521,10 +657,12 @@ # Read title and body. sub read_title_body($) { my ($file) = @_; + my $title; + my $body; # Execute filter command, if any. my $input = $file; - if ($filter_command) { + if ( (!$enable_encode) and $filter_command) { $input = sprintf("$filter_command |", $file); } print_debug("read_title_body: input: $input"); @@ -535,6 +673,11 @@ chomp($title); my $body = join('', <FILE>); # rest of all. close(FILE); + + if($enable_encode and ($c_code ne $s_code)) { + Encode::from_to($title,$c_code,$s_code); + Encode::from_to($body,$c_code,$s_code); + } return($title, $body); } @@ -601,6 +744,8 @@ -g groupname Groupname. Specify groupname. -f filename File. Send only this file without checking timestamp. -M Do NOT replace *t* with current time. + -l date Load entry. Specify date. + -n conffile Config file. Specify conffile. Config file example: # @@ -610,6 +755,9 @@ password:yourpassword cookie:cookie.txt # g:yourgroup +# httpproxy:proxy +# c_code:client_encoding +# s_code:server_encoding ## for Unix. # filter:iconv -f euc-jp -t utf-8 %s EOD @@ -640,6 +788,15 @@ } elsif (/^filter:(.*)$/) { $filter_command = $1; print_debug("load_config: filter:$filter_command"); + } elsif (/^proxy:(.*)$/) { + $httpproxy = $1; + print_debug("load_config: proxy:$httpproxy"); + } elsif (/^c_code:(.*)$/) { + $c_code = $1; + print_debug("load_config: c_code:$c_code"); + } elsif (/^s_code:(.*)$/) { + $s_code = $1; + print_debug("load_config: s_code:$s_code"); } else { error_exit("Unknown option '$_' in $config_file."); }
あ〜っ、ほんとにperlは組むの楽だ…。本気でhatena-diary-modeのエンジンとして使っちゃおうかと考えてしまう。form-data形式のPOSTデータを構築するライブラリ作っててキレそうなんだもの…。
だれかAPEL/FLIM/SEMIをxyzzyに移植してやろうという猛者はいないものか…。