2006年10月04日

[ blog ]

Amazonおまかせリンク

Amazonおまかせリンク」でどんな商品が出てくるかテスト。

投稿者 散財人 : 01:57 | コメント (0) | トラックバック (0)

2006年10月01日

[ blog ]

MTGoogleSearchResult

先日Movable Typeを3.33-jaに上げたらGoogle Search バージョン 1.0なんてのがデフォルトのプラグインに追加されていたので試しに有効にしてみました。

Google API Keyが必要ということでGoogleのサイトに行って取得してきたものの、入力して"変更を保存"を押すと、長すぎるといって怒られます。 SQLテーブルにはのVARCHAR型で32文字分のColumnがKeyの格納場所として用意されているのだけど、GoogleのサイトでKeyを生成させると90文字近いKeyになってしまう。 SQLコマンド打って問題のColumnを一度Dropして90文字程度のColumnをAddしたらKeyの保存は出来たけどGoogle APIプラグインは正常に動作してない感じ。

これはそもそも生成させたAPI Keyが違うんじゃないのかということでさらにググって見ると必要なのはGoogle SOAP Search API Keyだということが判明。さっき生成したのはAJAX Keyだったよ。とほほ。
このKeyは確かに32文字に収まる長さだから問題なく入力成功。 "Individual Entry Archive"テンプレートに下記みたいなサイトの再構築をすると無事、各エントリーのタイトルで検索した結果が表示されるようになりました。

<div class="module-googlesearch module">
<h2>Google Search Result</h2>
<div class="module-content">
<ul class="module-list">
<MTGoogleSearch title="1" results="3">
<li class="module-list-item">
<a href="<$MTGoogleSearchResult property="URL"$>">
<$MTGoogleSearchResult property="title" decode_html="1" $>
</a> : <$MTGoogleSearchResult property="snippet" $>
</li>
</MTGoogleSearch>
</ul>
</div>
</div>

ただ、変なタイトルとかつけてると何にも検索結果が引っかからず寂しいことになっちゃうのが欠点ですね。
エントリーごとに検索結果が出そうなKeywordを設定して、Keywordでの検索(<MTGoogleSearch keyword="1" results="3">)にさせればいいのだろうけど、いまさら面倒だしねぇ。

投稿者 散財人 : 23:07 | コメント (0) | トラックバック (0)

2006年06月04日

[ blog ]

aws.pl@MovableType3.3b1で文字化け

以前、MT3.2にバージョンアップした際に発生した、MovableTypeのプラグインaws.plが生成するAmazon.co.jp商品情報の文字化けが再発してしまいました。

前回の「aws.pl@MovableType3.2で文字化け」「MT3.2での文字化け修正版aws.pl」、あたりでやったことを思い出しながら、試行錯誤すること数時間。 「JcodeでもEncodeでもダメならそうすりゃいいってのよ!」と一度はさじを投げかけましたが、同様のプラグインであるMT-MyAmazonList v1.00のソースを眺めたりした結果、無事問題を解決することができました。
結論から言うと、Encode.pmやJcode.pmではなく、MTが提供するMT::I18Nを使えばいいようです。

例によって以下に修正したソースコードを載せておきますが、MT-MyAmazonList使えばいいんじゃねぇかという気が沸々と湧いてきたのでした。

aws_MT33.zip

# aws.pl
# (C) 2003 Daiji Hirata
#  All Right Reserved.

#use Data::Dumper;
use MT;
use MT::ConfigMgr;
use MT::Template::Context;
use LWP::UserAgent;
use XML::Simple;
##use Jcode;
#use Encode;
use MT::I18N;
use strict;

my $VERSION = '1.0a';

my %config;
$config{"dev-t"} = 'InputYourDevelopersToken';
$config{associate_id} = 'sanzairyusei-22/ref=nosim';
$config{locale} = 'jp';

my @aws_tags = (
    # lite
    'url', 'ImageUrlSmall', 'ImageUrlMedium', 'ImageUrlLarge', 'ProductName', 'Asin',
    'Manufacturer', 'Availability', 'ListPrice', 'OurPrice', 'UsedPrice', 'Catalog',
    # heavy
    'Media', 'Isbn', 'ReleaseDate', 'SalesRank', 'Upc', 'ThirdPartyNewPrice',
);

my $elements = {
    'ActorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page" ],
    'ArtistSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page" ],
    'AsinSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'AuthorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"],
    # 'BlendedSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'BrowseNodeSearch' => [ "dev-t", "t", "type", "f", "locale" ,"mode", "sort"],
    'DirectorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"],
    'KeywordSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'ListManiaSearch' => [ "dev-t", "t", "type", "f", "locale"],
    'ManufacturerSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'PowerSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'SemilaritiesSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'UpcSearch' => [ "dev-t", "t", "type", "f", "locale", "mode" ],
    'WishListSearch' => [ "dev-t", "t", "type", "f", "locale" ],
};

MT::Template::Context->add_container_tag(Aws => \&aws);

MT::Template::Context->add_tag(AwsAddCart => \&aws_addcart);

MT::Template::Context->add_tag(AwsAuthors => \&aws_authors );
MT::Template::Context->add_tag(AwsArtists => \&aws_artists );
MT::Template::Context->add_tag(AwsTracks => \&aws_tracks );
MT::Template::Context->add_tag(AwsXML => \&aws_xml );
MT::Template::Context->add_tag(AwsRequestUrl => \&aws_requesturl );
MT::Template::Context->add_tag(AwsTotalPages => \&aws_totalpages );
MT::Template::Context->add_tag(AwsTotalResults => \&aws_totalresults );
MT::Template::Context->add_tag(AwsAvgCustomerRating => \&aws_avgcustomerrating );
MT::Template::Context->add_tag(AwsTotalCustomerReviews => \&aws_totalcustomerreviews );
MT::Template::Context->add_tag(AwsVersion => \&aws_version );
MT::Template::Context->add_tag(AwsDirectors => \&aws_directors );
MT::Template::Context->add_tag(AwsStarring => \&aws_starring );

foreach my $tag (@aws_tags) {
    MT::Template::Context->add_tag('Aws'.$tag => sub { my $ctx = shift; aws_detail($ctx, $tag)});
}

sub aws {
    my ($ctx, $arg) = @_;
    my $builder = $ctx->stash('builder');
    my $tokens = $ctx->stash('tokens');
    my $res;
    my %q;

    use MT::ConfigMgr;
    my $cfg = MT::ConfigMgr->instance;
    my $charset = {'Shift_JIS'=>'sjis','ISO-2022-JP'=>'jis','EUC-JP'=> 'euc',
                   'UTF-8'=>'utf8'}->{$cfg->PublishCharset} || 'utf8';

    $q{f} = 'xml';
    $q{"dev-t"} = ($arg->{dev_token}) ? $arg->{dev_token} : $config{"dev-t"};
    if (!($q{"dev-t"})) { return $ctx->error("MTAWS needs your developer token: $q{'dev-t'}."); }
    $q{t} = ($arg->{associate_id}) ? $arg->{associate_id} : $config{associate_id};
    if (!($q{t})) { $q{t} = 'dh0dc-22'; }
    $q{type} = ($arg->{type}) ? $arg->{type} : 'lite';
    $q{mode} = ($arg->{mode}) ? $arg->{mode} : '';
    $q{page} = ($arg->{page}) ? $arg->{page} : 1;
    $q{lastn} = ($arg->{lastn}) ? $arg->{lastn} : -1;
    $q{offset} = ($arg->{offset}) ? $arg->{offset} : -1;
    $q{locale} = ($arg->{locale}) ? $arg->{locale} : $config{locale};
    $q{sort} = ($arg->{sort}) ? $arg->{sort} : '';
    if ($arg->{search} && $arg->{query}) {
        $q{search} = $arg->{search};
##       $q{query} = ($charset ne 'utf8') ? Jcode->new($arg->{query}, $charset)->utf8 : $arg->{query};
#       $q{query} = Encode::encode('utf8', $arg->{query});
        $q{query} = MT::I18N::encode_text( $arg->{query}, $charset, 'utf8' );
        $q{$arg->{search}} = utf2entity($q{query},1);
    } else {
        return $ctx->error("No search method and/or query");
    }
# my $url = 'http://xml.amazon.com/onca/xml3?';
    my $url = 'http://xml.amazon.co.jp/onca/xml3?';

    my @query;

    push @query, "$q{search}=$q{$q{search}}";
    foreach my $key (@{$elements->{$q{search}}}) {
        if (defined $q{$key}) {
            push @query, "$key=$q{$key}";
        }
    }

    $url .= join "&", @query;
    # $url .= '&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A';

    $ctx->stash('RequestUrl', $url );
    $ctx->stash('Associate_Id', $q{t} );

    my $ua = new LWP::UserAgent;
    $ua->agent("MTAWS");
    my $http_request = new HTTP::Request('GET', $url);
    my $http_response = $ua->request($http_request);
    my $content = $http_response->{'_content'};

    if ( $q{type} eq 'heavy') {
        my @content = split "\n", $content;
        $content = '';
        foreach my $line (@content) {
            if ($line) {
##               $content .= Jcode->new($line,'utf8')->utf8;
#               $content .= Encode::decode('utf8', $line);
                $content .= MT::I18N::encode_text( $line, $charset, 'utf8' );
                $content .= "\n";
            }
        }
    }

#die $q{query};

    # AWSからのレスポンスはここでUTF8フラグが立てられるっぽい
    my $tree;
    $tree = XMLin($content);
    if (!($tree)) { return $ctx->error("XML incorrect:\n"); }
    $ctx->stash('XML', $content );
    my @details;

    if (ref $tree->{Details} eq 'ARRAY') {
        push @details, @{$tree->{Details}};
    } else {
        push @details, $tree->{Details};
    }

    $ctx->stash("TotalResults", $tree->{TotalResults});
    $ctx->stash("TotalPages", $tree->{TotalPages});

    # トークンはDBにあるままなので、UTF8フラグが立っていない
    # なので、文字コードをUTF8に変換し、UTF8フラグを立てる
    for my $t (@$tokens)
    {
        if( $t->[0] eq 'TEXT' ) {
##            $t->[1] = Jcode->new($t->[1])->utf8;
##            $t->[1] = decode_utf8( $t->[1] );
#            $t->[1] = Encode::decode( $charset, $t->[1] );
             $t->[1] = MT::I18N::encode_text( $t->[1], $charset, 'utf8' );
        }
    }

    for my $detail (@details) {
    next if (($q{offset}--) > 0);
        $ctx->stash("Detail", $detail);
        defined(my $out = $builder->build($ctx, $tokens))
        or return $ctx->error($ctx->errstr);
        # $res .= sprintf($out);

        $res .= $out;
        if ($q{lastn}>0) { $q{lastn}--; }
        last if ($q{lastn} == 0);
    }

    # UTF8フラグをおろし、PublishCarsetの文字コードに変換する
##   $res = encode_utf8($res);
##   return Jcode->new($res, 'utf8')->$charset();
#   return Encode::encode( $charset, $res );
    return MT::I18N::encode_text($res, 'utf8', $charset );
}

sub utf2entity {
    my ($str, $amazon) = @_;
##     $str = Jcode->new($str)->utf8;
    $str =~ s/([^\w,])/'%'.unpack("H2", $1)/ego;

    if ($amazon ) {
      $str =~ s/%/%25/g;
    }
    $str;
}

sub aws_requesturl {
    my $ctx = shift;
    $ctx->stash("RequestUrl") || '';
}

sub aws_xml {
    my $ctx = shift;
    $ctx->stash("XML") || '';
}

sub aws_totalresults {
    my $ctx = shift;
    $ctx->stash("TotalResults") || '';
}

sub aws_totalpages {
    my $ctx = shift;
    $ctx->stash("TotalPages") || '';
}

sub aws_authors {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Authors}->{Author} eq 'ARRAY') {
        return join ", ", @{$detail->{Authors}->{Author}};
    } else {
        $detail->{Authors}->{Author} || '';
    }
}

sub aws_directors {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Directors}->{Director} eq 'ARRAY') {
        return join ", ", @{$detail->{Directors}->{Director}};
    } else {
        $detail->{Directors}->{Director} || '';
    }
}

sub aws_starring {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Starring}->{Actor} eq 'ARRAY') {
        return join ", ", @{$detail->{Starring}->{Actor}};
    } else {
        $detail->{Starring}->{Actor} || '';
    }
}

sub aws_detail {
    my ($ctx, $e) = @_;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{$e} eq 'ARRAY') {
        return join ", ", @{$detail->{$e}};
    } else {
        return $detail->{$e} || '';
    }
}

sub aws_avgcustomerrating {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    $detail->{Review}->{AvgCustomerRating} || '';
}

sub aws_totalcustomerreviews {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    $detail->{Review}->{TotalCustomerReviews} || '';
}

sub aws_artists {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Artists}->{Artist} eq 'ARRAY') {
        return join ", ", @{$detail->{Artists}->{Artist}};
    } else {
        $detail->{Artists}->{Artist} || '';
    }
}

sub aws_tracks {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Tracks}->{Track} eq 'ARRAY') {
        return join ", ", @{$detail->{Tracks}->{Track}};
    } else {
        $detail->{Tracks}->{Track} || '';
    }
}

sub aws_addcart {
    my ($ctx, $args) = @_;

    my $res;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    my $button = ($args->{label}) ? $args->{label} : "Buy";

    $res = sprintf( "<form method=\"POST\" action=\"http://www.amazon.co.jp/o/dt/assoc/handle-buy-box=%s\">\n", $detail->{Asin} );
    $res .= sprintf( "<input type=\"hidden\" name=\"asin.%s\" value=\"1\">\n", $detail->{Asin} );
    $res .= sprintf( "<input type=\"hidden\" name=\"tag-value\" value=\"%s\">\n", $ctx->stash("Associate_Id") );
    $res .= sprintf( "<input type=\"hidden\" name=\"tag_value\" value=\"%s\">\n", $ctx->stash("Associate_Id") );
    $res .= sprintf( "<input type=\"submit\" name=\"submit.add-to-cart\" value=\"%s\">\n", $button);
    $res .= "</form></span>\n";

    $res;
}

sub aws_version {
    $VERSION;
}

1;
__END__

=head1 NAME

aws.pl - Movable Type Plugin of Amazon Webservices

=head1 SYNOPUS

    <MTAws dev-t="developer-token" associate_id="dh0dc-22" search="KeywordSearch" mode="books-jp" query="weblog" locale="jp">
    <$MTAwsurl$>
    <$MTAwsAuthors$>
    <img src="<$MTAwsImageUrlSmall$>">
    <$MTAwsAddCart label="Buy from Amazon!"$>
    </MTAws>

=head1 LICENSE

Please see the file F<README> in the package.

=head1 AUTHOR

Daiji Hirata, dh@uva.jp

=cut

投稿者 散財人 : 23:12 | コメント (0) | トラックバック (0)

2006年06月03日

[ blog ]

Movable Type 3.3 ベータテスト

昨日開始されたMovable Type 3.3日本語版ベータ(3.3b1-ja)に早速アップグレードしてみたのでそのテスト投稿です。

投稿者 散財人 : 14:26 | コメント (0) | トラックバック (1)

2006年01月05日

[ blog ]

MT3.2での文字化け修正版aws.pl

昨年10月にMovableType3.2にアップグレードしたらaws.plの出力が文字化けして困った際に参考にしたサイトがなくなってしまったようなので、修正版aws.plを上げておきます。
DVDの監督情報なども取得できるように文字化け問題とは関係の無いカスタマイズも行っていますので、必要の無い人は該当部分を削除した方が再構築時などのレスポンスがよくなるかと思います。

オリジナルaws.plのライセンスには改造版の再配布について明記されて無いのが気になるんですが、自由に利用してかまわないと書いてあるからいいですかね。
利用して得られる利益/損失について、散財人は一切関知せず、また責任をとりませんし、サポートも行わないのであしからず。

このプラグインの著作権はひらたにあります。個人かつ非営利での利用(もちろん、Amazon アソシエイトはOK!) に限り、プログラムの一部、もしくは全部を自由に利用、改造していただいて構いません。利用して得られる利益/損失について、わたしは一切関知せず、また責任をとりません。

ZIPファイル (4KB)

# aws.pl
# (C) 2003 Daiji Hirata
#  All Right Reserved.

#use Data::Dumper;
use MT;
use MT::ConfigMgr;
use MT::Template::Context;
use LWP::UserAgent;
use XML::Simple;
#use Jcode;
use Encode;
use strict;

my $VERSION = '1.0a';

my %config;
$config{"dev-t"} = 'DDDDDDDDDDDDDD'; #自分で取得したdeveloper-tokenを入れる
$config{associate_id} = 'sanzairyusei-22'; #自分で取得したassociate-idを入れる。もちろんこのままでも歓迎!
$config{locale} = 'jp';

my @aws_tags = (
    # lite
    'url', 'ImageUrlSmall', 'ImageUrlMedium', 'ImageUrlLarge', 'ProductName', 'Asin',
    'Manufacturer', 'Availability', 'ListPrice', 'OurPrice', 'UsedPrice', 'Catalog',
    # heavy
    'Media', 'Isbn', 'ReleaseDate', 'SalesRank', 'Upc', 'ThirdPartyNewPrice',
);

my $elements = {
    'ActorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page" ],
    'ArtistSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page" ],
    'AsinSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'AuthorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"],
    # 'BlendedSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'BrowseNodeSearch' => [ "dev-t", "t", "type", "f", "locale" ,"mode", "sort"],
    'DirectorSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"],
    'KeywordSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'ListManiaSearch' => [ "dev-t", "t", "type", "f", "locale"],
    'ManufacturerSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'PowerSearch' => [ "dev-t", "t", "type", "f", "locale", "mode", "page"] ,
    'SemilaritiesSearch' => [ "dev-t", "t", "type", "f", "locale" ],
    'UpcSearch' => [ "dev-t", "t", "type", "f", "locale", "mode" ],
    'WishListSearch' => [ "dev-t", "t", "type", "f", "locale" ],
};

MT::Template::Context->add_container_tag(Aws => \&aws);

MT::Template::Context->add_tag(AwsAddCart => \&aws_addcart);

MT::Template::Context->add_tag(AwsAuthors => \&aws_authors );
MT::Template::Context->add_tag(AwsArtists => \&aws_artists );
MT::Template::Context->add_tag(AwsTracks => \&aws_tracks );
MT::Template::Context->add_tag(AwsXML => \&aws_xml );
MT::Template::Context->add_tag(AwsRequestUrl => \&aws_requesturl );
MT::Template::Context->add_tag(AwsTotalPages => \&aws_totalpages );
MT::Template::Context->add_tag(AwsTotalResults => \&aws_totalresults );
MT::Template::Context->add_tag(AwsAvgCustomerRating => \&aws_avgcustomerrating );
MT::Template::Context->add_tag(AwsTotalCustomerReviews => \&aws_totalcustomerreviews );
MT::Template::Context->add_tag(AwsVersion => \&aws_version );
MT::Template::Context->add_tag(AwsDirectors => \&aws_directors );
MT::Template::Context->add_tag(AwsStarring => \&aws_starring );

foreach my $tag (@aws_tags) {
    MT::Template::Context->add_tag('Aws'.$tag => sub { my $ctx = shift; aws_detail($ctx, $tag)});
}

sub aws {
    my ($ctx, $arg) = @_;
    my $builder = $ctx->stash('builder');
    my $tokens = $ctx->stash('tokens');
    my $res;
    my %q;

    use MT::ConfigMgr;
    my $cfg = MT::ConfigMgr->instance;
    my $charset = {'Shift_JIS'=>'sjis','ISO-2022-JP'=>'jis','EUC-JP'=> 'euc',
                   'UTF-8'=>'utf8'}->{$cfg->PublishCharset} || 'utf8';

    $q{f} = 'xml';
    $q{"dev-t"} = ($arg->{dev_token}) ? $arg->{dev_token} : $config{"dev-t"};
    if (!($q{"dev-t"})) { return $ctx->error("MTAWS needs your developer token: $q{'dev-t'}."); }
    $q{t} = ($arg->{associate_id}) ? $arg->{associate_id} : $config{associate_id};
    if (!($q{t})) { $q{t} = 'dh0dc-22'; }
    $q{type} = ($arg->{type}) ? $arg->{type} : 'lite';
    $q{mode} = ($arg->{mode}) ? $arg->{mode} : '';
    $q{page} = ($arg->{page}) ? $arg->{page} : 1;
    $q{lastn} = ($arg->{lastn}) ? $arg->{lastn} : -1;
    $q{offset} = ($arg->{offset}) ? $arg->{offset} : -1;
    $q{locale} = ($arg->{locale}) ? $arg->{locale} : $config{locale};
    $q{sort} = ($arg->{sort}) ? $arg->{sort} : '';
    if ($arg->{search} && $arg->{query}) {
  $q{search} = $arg->{search};
#     $q{query} = ($charset ne 'utf8') ? Jcode->new($arg->{query}, $charset)->utf8 : $arg->{query};
  $q{query} = Encode::encode('utf8', $arg->{query});
  $q{$arg->{search}} = utf2entity($q{query},1);
    } else {
  return $ctx->error("No search method and/or query");
    }
    # my $url = 'http://xml.amazon.com/onca/xml3?';
    my $url = 'http://xml.amazon.co.jp/onca/xml3?';

    my @query;

    push @query, "$q{search}=$q{$q{search}}";
    foreach my $key (@{$elements->{$q{search}}}) {
        if (defined $q{$key}) {
            push @query, "$key=$q{$key}";
        }
    }

    $url .= join "&", @query;
    # $url .= '&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A';

    $ctx->stash('RequestUrl', $url );
    $ctx->stash('Associate_Id', $q{t} );

    my $ua = new LWP::UserAgent;
    $ua->agent("MTAWS");
    my $http_request = new HTTP::Request('GET', $url);
    my $http_response = $ua->request($http_request);
    my $content = $http_response->{'_content'};

    if ( $q{type} eq 'heavy') {
  my @content = split "\n", $content;
      $content = '';
      foreach my $line (@content) {
          if ($line) {
        $content .= Encode::decode('utf8', $line);
#       $content .= Jcode->new($line,'utf8')->utf8;
        $content .= "\n";
      }
      }
     }

#die $q{query};

    # AWSからのレスポンスはここでUTF8フラグが立てられるっぽい
    my $tree;
    $tree = XMLin($content);
    if (!($tree)) { return $ctx->error("XML incorrect:\n"); }
    $ctx->stash('XML', $content );
    my @details;

    if (ref $tree->{Details} eq 'ARRAY') {
      push @details, @{$tree->{Details}};
    } else {
      push @details, $tree->{Details};
    }

    $ctx->stash("TotalResults", $tree->{TotalResults});
    $ctx->stash("TotalPages", $tree->{TotalPages});

    # トークンはDBにあるままなので、UTF8フラグが立っていない
    # なので、文字コードをUTF8に変換し、UTF8フラグを立てる
    for my $t (@$tokens)
    {
        if( $t->[0] eq 'TEXT' )
        {
            $t->[1] = Encode::decode( $charset, $t->[1] );
#            $t->[1] = Jcode->new($t->[1])->utf8;
#            $t->[1] = decode_utf8( $t->[1] );
        }
    }

    for my $detail (@details) {
    next if (($q{offset}--) > 0);
        $ctx->stash("Detail", $detail);
        defined(my $out = $builder->build($ctx, $tokens))
        or return $ctx->error($ctx->errstr);
        # $res .= sprintf($out);

        $res .= $out;
        if ($q{lastn}>0) { $q{lastn}--; }
        last if ($q{lastn} == 0);
    }

    # UTF8フラグをおろし、PublishCarsetの文字コードに変換する
#    $res = encode_utf8($res);
#    return Jcode->new($res, 'utf8')->$charset();
    return Encode::encode( $charset, $res );
}

sub utf2entity {
    my ($str, $amazon) = @_;
#     $str = Jcode->new($str)->utf8;
    $str =~ s/([^\w,])/'%'.unpack("H2", $1)/ego;

    if ($amazon ) {
      $str =~ s/%/%25/g;
    }
    $str;
}

sub aws_requesturl {
    my $ctx = shift;
    $ctx->stash("RequestUrl") || '';
}

sub aws_xml {
    my $ctx = shift;
    $ctx->stash("XML") || '';
}

sub aws_totalresults {
    my $ctx = shift;
    $ctx->stash("TotalResults") || '';
}

sub aws_totalpages {
    my $ctx = shift;
    $ctx->stash("TotalPages") || '';
}

sub aws_authors {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Authors}->{Author} eq 'ARRAY') {
        return join ", ", @{$detail->{Authors}->{Author}};
    } else {
        $detail->{Authors}->{Author} || '';
    }
}

sub aws_directors {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Directors}->{Director} eq 'ARRAY') {
        return join ", ", @{$detail->{Directors}->{Director}};
    } else {
        $detail->{Directors}->{Director} || '';
    }
}

sub aws_starring {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Starring}->{Actor} eq 'ARRAY') {
        return join ", ", @{$detail->{Starring}->{Actor}};
    } else {
        $detail->{Starring}->{Actor} || '';
    }
}

sub aws_detail {
    my ($ctx, $e) = @_;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{$e} eq 'ARRAY') {
        return join ", ", @{$detail->{$e}};
    } else {
        return $detail->{$e} || '';
    }
}

sub aws_avgcustomerrating {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    $detail->{Review}->{AvgCustomerRating} || '';
}

sub aws_totalcustomerreviews {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    $detail->{Review}->{TotalCustomerReviews} || '';
}

sub aws_artists {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Artists}->{Artist} eq 'ARRAY') {
        return join ", ", @{$detail->{Artists}->{Artist}};
    } else {
        $detail->{Artists}->{Artist} || '';
    }
}

sub aws_tracks {
    my $ctx = shift;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{Tracks}->{Track} eq 'ARRAY') {
        return join ", ", @{$detail->{Tracks}->{Track}};
    } else {
        $detail->{Tracks}->{Track} || '';
    }
}

sub aws_addcart {
    my ($ctx, $args) = @_;

    my $res;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    my $button = ($args->{label}) ? $args->{label} : "Buy";

    $res = sprintf( "<form method=\"POST\" action=\"http://www.amazon.co.jp/o/dt/assoc/handle-buy-box=%s\">\n", $detail->{Asin} );
    $res .= sprintf( "<input type=\"hidden\" name=\"asin.%s\" value=\"1\">\n", $detail->{Asin} );
    $res .= sprintf( "<input type=\"hidden\" name=\"tag-value\" value=\"%s\">\n", $ctx->stash("Associate_Id") );
    $res .= sprintf( "<input type=\"hidden\" name=\"tag_value\" value=\"%s\">\n", $ctx->stash("Associate_Id") );
    $res .= sprintf( "<input type=\"submit\" name=\"submit.add-to-cart\" value=\"%s\">\n", $button);
    $res .= "</form></span>\n";

    $res;
}

sub aws_version {
    $VERSION;
}

1;
__END__

=head1 NAME

aws.pl - Movable Type Plugin of Amazon Webservices

=head1 SYNOPUS

    <MTAws dev-t="developer-token" associate_id="dh0dc-22" search="KeywordSearch" mode="books-jp" query="weblog" locale="jp">
    <$MTAwsurl$>
    <$MTAwsAuthors$>
    <img src="<$MTAwsImageUrlSmall$>">
    <$MTAwsAddCart label="Buy from Amazon!"$>
    </MTAws>

=head1 LICENSE

Please see the file F<README> in the package.

=head1 AUTHOR

Daiji Hirata, dh@uva.jp

=cut

投稿者 散財人 : 16:25 | コメント (0) | トラックバック (4)

2005年12月30日

[ blog ]

うるう秒

2006年1月1日にはうるう秒が実施され、9時0分0秒の前に8時59分60秒がはさまれるわけですが、 Movable Typeにはうるう秒による影響は無いというアナウンスが出されました。
「影響は無い」って、8時59分60秒の投稿ができるのかしらと思い指定日投稿しようとしてみると・・・

日付 (2006-01-01 08:59:60) が正しくありません。存在しない日付が設定されています。

って怒られてしまいました。
残念。

Movable Typeユーザーの皆様 Movable Typeではすべてのバージョンにおいて、うるう秒による影響はありませんので、ご安心ください。また、年末ギリギリの告知になってしまったことを深くお詫びいたします。

投稿者 散財人 : 18:44 | コメント (0) | トラックバック (3)

2005年10月20日

[ blog ]

aws.pl@MovableType3.2で文字化け

昨晩、散財予定リストに新しいアイテムを追加したところ、aws.plによる商品情報部分だけなんか激しく文字化けするようになってしまいました。 title=""の中身などHTML elementもaws.plで取得した情報を入れていたので、文字化けするとダブルクウォーテーション文字が死んだしりしてページ全体にまで悪影響が出る始末で、見苦しいし何とかしたかったのですが夜も遅かったのでとりあえずは放置したのでした。

今日になって調べてみたところ、どうやらMovableType3.2だとUTF-8周りの処理をちゃんと行わないaws.pl等のプラグインは文字化けするという情報に行き着きました。 そちらのサイトから修正版のaws.plをダウンロードして上書きしたところ、無事解決。 文字コード処理モジュールもJcodeからEncodeに置き換えられていていい感じです。

MT-3.2にバージョンアップして発生していたaws.plの文字化けですが、暇を見て調べていたら、こちらのblogにて不具合を修正したaws.plが公開されていました。

他のサイトで書かれている修正をしてもtypeをheavyにしていろんなデータを取得したり、MTAwsタグの中に日本語の文字列を入れたりするととたんに文字化けするので、Perlはど素人なのですがわからないなりに追ってみました。

どうもUTF8フラグまわりの処理が抜けていたようです。 Jcodeモジュールでも修正できるのですけど、せっかくなのでEncodeモジュールを使ってUTF8フラグを正しく扱うように修正してみました。

投稿者 散財人 : 21:45 | コメント (0) | トラックバック (7)

2005年10月10日

[ 日記 , blog ]

Audioscrobbler AWS

4連休最終日は、Audioscrobbler(現last.fm)によって生成される最近聞いた楽曲リストをもとにAmazon.co.jpで検索を行い、ジャケット画像をこのブログに表示するスクリプトを試行錯誤しながら書いて過ごしました。

以前も書きましたがAudioscrobblerは専用プラグインを入れておくと、Windows Media PlayerやWinamp、iTunesで再生した楽曲の曲名やアーティスト名をサーバーに送信して、統計情報をまとめたり、rdfの生成を行ってくれるサービスです。 以前から、このrdfをJavaScriptとCGIで解釈して文字情報をブログのサイドバーに出すスクリプトは公開されていたのですが、音ログのようにジャケット画像を表示できるスクリプトは適当なものが見つからなかったので、XSLTの勉強がてら自分で作ってみることにしました。

現状では、検索結果に適当な画像がなかったときのエラー処理や、アーティスト名、曲名に"が含まれる時の置換処理などを行っておらず、かなり不安定なのでその辺を今後直していきたいと思います。
おとなしくiTunesに乗り換えて音ログ使えばすむ話ではあるのですが。 現状ではAudioscrobblerはアルバム情報を取得できないのでカップリング曲の検索性効率が非常に低いですし。

参考文献:
AmazonのXML Webサービス(REST)はXSLを書くだけでもかなり使える:Goodpic
drifting blog by snotch: Amazon XSLT for MT
たのしいXML: XML/XHTML入門ページです
サンプルで覚えるXSLTプログラミング
Amazon ECS 4.0 解説1 RESTリクエストのパラメータ:Goodpic

投稿者 散財人 : 21:36 | コメント (0) | トラックバック (0)

2005年09月30日

[ blog ]

MovableType3.2-ja

MovableType3.2の日本語版が出たのでアップデートしてみました。

3.17とはStaticWebPathのデフォルトの場所が変わったため若干苦戦しましたが、無事にアップデート完了できたはずです。

なお、今まで編集用CGIをSSLで利用するために、lib/MT/Template/Context.pmを書き換えていたのですが、AdminCGIPathディレクティブを利用すればmt.cgi等の管理用CGIのフルパスと、mt-tb.cgi等のトラックバック、コメント用CGIのフルパスを分離することが分かったので今回はMTのライブラリはいじってません。 mt-config.cgiの該当箇所はこんな感じになりました。

CGIPath http://www.sanzai.net/
AdminCGIPath https://admin.sanzai.net/
StaticWebPath https://admin.sanzai.net/mt-static

投稿者 散財人 : 21:02 | コメント (0) | トラックバック (0)

2005年07月05日

[ 音楽 , blog ]

Audioscrobbler

Windows Media PlayerやWinamp、iTunesで再生した曲の再生リストを自動的に登録して、自分の音楽プロフィールを作成してくれるサービス、Audioscrobblerを使い始めてみました。

利用方法は簡単で、公式サイトでサインアップした後、自分が利用している音楽プレーヤー用のプラグインをダウンロード、インストールして設定。 あとは曲を再生するたびにタイトル、アーティスト名がサーバーに送信されてプロフィールが更新されていきます。 (たまにサーバーが重いのかなかなか表示が反映されないことがありますが。)
同じ曲やアーティストを聞いている人が他にどんな曲を聴いてるか知ることもできるので、自分好みの局を探すことも出来るかもしれません。

で、XML形式でも公開されるプロフィール情報をこのblogに反映するために大黒屋本舗からjsRSS for Audioscrobbler++ v1.12をダウンロードして導入。 トップページに最近再生した3曲を表示するようにしてみました。 Amazon.co.jpにリンクするようにテンプレートを設定したのですが、Audioscrobblerに送信される情報にアルバム名情報が無いので、なかなか一発でヒットしないのがちょっと残念です。 あとIE6.0だとクリックしたときに検索キーワードが文字化けすることがあるみたい。 Firefoxなら問題ないんですが。

同じようにプラグインを導入することで再生曲情報をサーバーに送信し、ジャケット画像と、Amazon.co.jp等へのリンクを生成する音ログなんていうサービスもあるのですが、こちらはプレーヤーがiTunesしか対応してないので今回は断念しました。

しかし、ID3タグの入力サボってる曲とか、ミスタイプしてる曲があると恥ずかしいので直さないといけないですね。 あとあんまり恥ずかしい曲は再生されないようにプレイリストから外しておかないと(笑)

投稿者 散財人 : 23:42 | コメント (0) | トラックバック (0)

2005年06月18日

[ blog ]

Template等小改造

暇を持て余してブログのテンプレートなどを小改造してみました。

  • 右サイドバーの2ペインだったトップページを両サイドバーの3ペインに変更。
    • カレンダーやカテゴリー表示などサイト内へのリンクを左に。
    • トラックバックや散財予定アイテム集などサイト外へのリンクを右に。
  • シングルペインだったカテゴリーページや個々のアーカイブページを左サイドバー付きの2ペイン表示に変更。
  • トップページに表示するエントリーを1週間分表示から定数(5エントリー)表示に変更。

投稿者 散財人 : 22:14 | コメント (0) | トラックバック (0)

2005年06月12日

[ blog ]

SpamLookup with PostgreSQL

一見問題なくインストールされたかに思われたspamlookupでしたが、

The following is a list of all comments that have been posted to this Movable Type installation. Click here to start a “despam” operation for these comments, running all of your comments against the tests you have enabled in your SpamLookup configuration.

の"here"をクリックしても結局

An error occurred: Storable binary image v46.48 more recent than I am (v2.7) at blib/lib/Storable.pm (autosplit into blib/lib/auto/Storable/thaw.al) line 366, at /hogehoge/foobar/www.sanzai.net/lib/MT/PluginData.pm line 31 

が出てしまい、spam駆除機能が開始されないのでした。
悩むこと数時間。色々過去の記憶をたどったり、バックアップを取っておいたバージョンアップ前のMTディレクトリ内の各ファイルとのdiff等を見た結果、MT-Blacklistを導入した際にはlib/MT/PluginData.pmに修正を行っていたことを思い出しました。 われながら備忘録とっておけよって感じです。
MTを上げた際にPluginData.pmも上書きしてしまったのでこれが原因でMT-Blacklistやspamlookupが動かないのだろうと。 そこでまず、PluginData.pmの該当行(30行前後)あたりを下記のように修正。

sub data {
    my $data = shift;
#    $data->column('data', freeze(shift)) if @_;
#    thaw($data->column('data'));
    $data->column('data', unpack ("H*", freeze(shift))) if @_;
    my $r;
    eval {
        $r = thaw($data->column('data'));
    };
    $r = thaw(pack ("H*", $data->column('data'))) if ($@);
    $r;
}

これで試してみるとまだエラーが出ます。 おそらく修正前にPostgreSQLに書き込まれてしまったtableがまずいのだろうということで、mt_plugindata等をばっさり消してみました。

database=> drop table mt_plugindata;
database=> drop sequence mt_plugindata_id;

これで無事spamlookupの有効化に成功です。 実際にトラックバックスパムやコメントスパムを防げるかは数日様子を見てみる必要がありますけどね。

しかしPostgreSQL上でMT使ってると何かと面倒が多くて気が抜けないものですね。

投稿者 散財人 : 22:31 | コメント (1) | トラックバック (0)

2005年06月11日

[ blog ]

SpamLookup

MT3.17-jaにしたからかMT-Blacklistの設定CGIを開くと

An error occurred: Storable binary image v46.48 more recent than I am (v2.7) at blib/lib/Storable.pm (autosplit into blib/lib/auto/Storable/thaw.al) line 366, at /hogehoge/foobar/www.sanzai.net/lib/MT/PluginData.pm line 31 

と表示されるようになってしまった。 トラックバックスパムのフィルタリングも機能してないようで、わずか10分の間に8個のトラックバックスパムを被弾。
StorableのPerlモジュールのv46.48なんてどこにあるのか不明(バージョンNo.飛びすぎじゃない??)なので、この機会にSpamLookupに乗り換えてみることにした。

基本的にファイルを適切な場所にコピーして、
/plugins/spamlookup/mt-spamlookup.cgiを開くだけ。

ちなみに、これがおすすめな理由のもう一つとしてmt-blacklistの開発者がこれに 乗り換えて快適になったから開発を止めたなんて自分のHPで言っていることだ。。。

という話なので期待したいところだ。

投稿者 散財人 : 22:07 | コメント (0) | トラックバック (0)

[ blog ]

MovableType3.17-ja

MovableType3.17の日本語版が出たのでアップデートしてみました。

Trackgack URLを書き換えるため、アップデートファイル群をコピーしたあといつも通り
lib/MT/Template/Context.pmの
_hdlr_static_path
_hdlr_entry_tb_link
_hdlr_category_tb_link
内の

    my $path = $cfg->CGIPath;

をそれぞれ

    my $path = $cfg->StaticWebPath;

に書き換えた上でmt-upgrade31.cgiを実行し無事にアップデート完了。

表には見えないことだけどエントリー投稿ページ等でサブカテゴリーがネスト表示されるようになったのは便利だな。

  • ユーザー・インタフェースでのサブカテゴリーの階層表示を改善しました。サブカテゴリーは次の場所で階層型に表示されます。
    • 「新しいエントリー」画面
    • 「エントリーを編集する」画面、および「クイックポスト」画面にある「主カテゴリー」のドロップダウン・リスト
    • 「エントリーの一覧」にあるカテゴリー・フィルターのドロップダウン・リスト
    • 「一括編集」画面のカテゴリー・フィルターおよびカテゴリー割り当てドロップダウン・リスト、およびポップアップ・カテゴリー作成ウィンドウ

投稿者 散財人 : 19:55 | コメント (0) | トラックバック (1)

2005年01月25日

[ blog ]

MTBlogTimes

Blogの今月の更新時刻を数直線上に表したpngファイルを生成するMTBlogTimesを導入してみた。
B L O G T I M E S
如何に生活リズムが乱れているかということが一目瞭然になってしまうな。

以下導入メモ。

公式サイトからmtblogtimes-1.0.tar.gzをダウンロードして展開。blogtimes.plをMTをインストールしたディレクトリのpluginディレクトリに入れておく。パーミッションは644あたりで。
GD本体だけだとperlモジュールの構築に失敗したので、yumでGD周りのrpmを全てインストール。(gd-debuginfoとgd-progsのどちらかは要らないのかもしれないがまとめて入れてしまったので不明)

$ sudo yum install gd-devel gd-debuginfo gd-progs

CPANでGDのperlモジュールを構築しつつ導入。

$ sudo perl -MCPAN -e shell
> install GD
(中略)
> exit

MovableTypeのMain Indexテンプレートの適当な場所に下記のタグを記述。

<MTBlogTimes 
fillcolor="#666666" 
textcolor="#666666" 
linecolor="#ffffff" 
bordercolor="#666666" 
width="160" 
height="20" 
save_dir="images" 
show_text="on" >
<a href="http://nilesh.org/mt/blogtimes/">
<img src="<$MTBlogTimesFileURL$>" width="<$MTBlogTimesWidth$>" height="<$MTBlogTimesHeight$>" border="0" alt="B L O G T I M E S" title="B L O G T I M E S" />
</a>
</MTBlogTimes>

Main Indexの再構築をして完成。
ISP等のブログサービスだとGDのperlモジュール導入に関してバージョンの統一など厄介なようだが、自宅サーバーならyumで一発で導入できるのが楽だな。

投稿者 散財人 : 18:59 | コメント (0) | トラックバック (0)

2005年01月20日

[ blog ]

MT-Blacklist

コメントスパムが止まらないのでMT-Blacklistを入れてみた。
今のところ全てのスパムを検出してくれているようだ。

投稿者 散財人 : 22:22 | コメント (1) | トラックバック (0)

2004年12月22日

[ blog ]

コメントスパム対策

今朝あたりからコメントスパムが1時間に2通くらいの頻度で投稿されるようになったので、当面コメントにはTypeKeyでの認証を必須にしてみます。

投稿者 散財人 : 15:39 | コメント (1) | トラックバック (0)

2004年12月10日

[ blog ]

折りたたみ式追記

エントリーが長文になったときに後半を追記として記述しているのだが、全文を読むにはページを移動する必要があり面倒だという指摘がかねてからあった。
そこで、1クリックで追記を表示させたり、折りたたんだりできるようにしてみた。

1ページにEntryを複数表示させる場合、長文だとどうしてもページ全体が文字ばかりになってしまい、読む気も失せるし見た目もよろしくない。 だからExtended(追記)の部分に続きを書いて<MTEntryIfExtended>で続きが読めるようにしてたんですが、これだとPermalinkに飛んでしまうので、また戻ったりしないといけなくなる。 どうしようかと思いながら海外のBLOGサイトを見ていると、Scriptygoddess: Collapsing entries AND COMMENTSというものを発見しました。

上記サイトで説明されているように手順としては、Main Indexテンプレートの下のほうにでも下記のJavaScriptを追加。

<script language="javascript">
function showMore(varA1, varB1){
var123 = ('varXYZ' + (varA1));
varABC = ('varP' + (varA1));
if( document.getElementById ) {
if( document.getElementById(var123).style.display ) {
if( varB1 != 0 ) {
document.getElementById(var123).style.display = "block";
document.getElementById(varABC).style.display = "none";
} else { document.getElementById(var123).style.display = "none";
document.getElementById(varABC).style.display = "block"; }
} else { location.href = varB1;
return true; }
} else { location.href = varB1;
return true; }
}
</script>

<$MTEntryIfExtended$>から</$MTEntryIfExtended$>の間を下記の様に修正。

<MTEntryIfExtended>
<div id="varP<$MTEntryID$>">
<a title="続きを読む" href="<$MTEntryLink$>#<$MTEntryID pad="1"$>" onclick="showMore(<$MTEntryID$>,'<$MTEntryLink$>#a<$MTEntryID pad="1"$>');return false;">続きを読む</a>
</div>
<div id="varXYZ<$MTEntryID$>" style="display: none">
<a title="続きを隠す" href="#a<$MTEntryID pad="1"$>" onclick="showMore(<$MTEntryID$>,0);return true;">追記を隠す</a>
<$MTEntryMore$>
<a title="続きを隠す" href="#a<$MTEntryID pad="1"$>" onclick="showMore(<$MTEntryID$>,0);return true;">追記を隠す</a></div>
</MTEntryIfExtended>

JavaScript未対応ブラウザでもそれなりに表示できるように工夫されているのがすばらしいな。

投稿者 散財人 : 02:34 | コメント (0) | トラックバック (0)

2004年12月07日

[ blog ]

カレンダー

トップページに表示させているカレンダーが当月分しか表示できなくていまいちなので、diving to ...: 月間移動可能なMovableTypeのカレンダーを参考にしてカレンダーを作り変えてみた。

下記の様に設定したアーカイブテンプレート"calendar"をまず用意する。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1./ Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<$MTPublishCharset$>" />
<title><$MTBlogName$></title>
<link rel="stylesheet" href="<$MTBlogURL$>styles-cal.css" type="text/css" />

<MTBlogIfCCLicense>
<$MTCCLicenseRDF$>
</MTBlogIfCCLicense>

</head>
<body>

<div id="calendar" align="center">

<table table width="160" border="0" cellspacing="4" cellpadding="0" 
summary="投稿されたエントリーへのリンク付き月間カレンダー">

<caption>
<MTArchivePrevious>
<a href="<MTBlogURL>archives/calendar/<MTArchiveDate format="%Y/%m/index">.php"> <<</a>
</MTArchivePrevious>

<$MTArchiveDate format="%B %Y"$> 

<MTArchiveNext>
<a href="<MTBlogURL>archives/calendar/<MTArchiveDate format="%Y/%m/index">.php"> >></a>
</MTArchiveNext>
</caption>

<tr height="20">
<th abbr="Sunday" align="center">日</th>
<th abbr="Monday" align="center">月</th>
<th abbr="Tuesday" align="center">火</th>
<th abbr="Wednesday" align="center">水</th>
<th abbr="Thursday" align="center">木</th>
<th abbr="Friday" align="center">金</th>
<th abbr="Saturday" align="center">土</th>
</tr>

<MTCalendar month="this">
<MTCalendarWeekHeader><tr></MTCalendarWeekHeader>
<td align="center"><span class="calendar">
<MTCalendarIfEntries><MTEntries lastn="1">
<a href="<$MTEntryLink archive_type="Daily"$>" title="[<$MTEntryTitle$>]" target="_top">
<$MTCalendarDay$></a>
</MTEntries></MTCalendarIfEntries>
<MTCalendarIfNoEntries><$MTCalendarDay$></MTCalendarIfNoEntries>
<MTCalendarIfBlank> </MTCalendarIfBlank></span></td>

<MTCalendarWeekFooter></tr></MTCalendarWeekFooter>
</MTCalendar>
</table>

</div> 

</body>
</html>

で、"ウェブログの設定"-"アーカイブの設定"ページの、"新しく、テンプレートとアーカイブを関連付ける。"の項目で、"アーカイブの種類"を"月別"に、"テンプレート"を"Calendar"にして追加。
さらに、下記のようなCalendarページ用スタイルシートをテンプレートで定義。

body {
	margin: 0px 0px 0px 0px;
		background-color: #FFFFFF;
		text-align: center;
        }

a {
	text-decoration: underline;
	}

a:link {
	color: #8FABBE;
	}

a:visited {
	color: #8FABBE;
	}

a:active {
	color: #8FABBE;
	}

a:hover {
	color: #006699;
	}

#calendar {
  	line-height: 140%;
	color: #666666;
	font-family: Verdana, Arial, sans-serif;
	font-size: x-small;
  	padding: 2px;
	text-align: center;
	margin-bottom: 20px;
	}

#calendar table {
	padding: 2px;
	border-collapse: collapse;
	border: 0px;
	width: 100%;
	}

#calendar caption {
	color: #666666;
	font-family: Verdana, Arial, sans-serif;
	font-size: x-small;

	text-align: center;
	font-weight: bold;

	text-transform: uppercase;

	letter-spacing: .3em;
	}

#calendar th {
	text-align: center;
	font-weight: normal;
	}

#calendar td {
	text-align: center;
	}

あとは"Main Index"テンプレートの適当な場所に下記のタグを貼って再構築すれば完成。

<div align="center">
<iframe class="calendar" src="<MTBlogURL>archives/calendar/<MTDate format="%Y/%m/index">.php" 
scrolling="no" frameborder="0" marginwidth="0" marginheight="0"></iframe> 
</div>

いつ更新をサボったのか分かり易くなってしまったのがまずいな。

投稿者 散財人 : 23:59 | コメント (0) | トラックバック (0)

2004年12月02日

[ blog ]

MTImageInfo

JPEGファイルのEXIF情報を抽出してMovableTypeで表示させるためのプラグイン、MTImageInfoを導入してみる。

  1. 公式サイトからzipファイルを落としてきて、(mtのディレクトリ)/plugins/に設置。
  2. CPANでImage::InfoとかFile::Basenameをインストール。
  3. テンプレートではなくエントリーでプラグインを使うには細工が必要な気もするが、MTaws導入時に細工済みなので今回は特に問題なし。

あとはエントリーに

<MTImageInfo img="[MTBlogSitePath]archives/hogehoge.JPG"> 
<$MTImageInfoField name="DateTimeOriginal" format="%Y/%m/%d/%H:%M:%S"$>
(JST), <$MTImageInfoField name="width"$> x 
<$MTImageInfoField name="height"$>,  
<$MTImageInfoField name="ExposureTime"$>(s), 
F/<$MTImageInfoField name="FNumber"$>, 
ISO-<$MTImageInfoField name="ISOSpeedRatings"$>, 
<$MTImageInfoField name="ExposureBiasValue"$>(step),  
<$MTImageInfoField name="WhiteBalance"$>, 
<$MTImageInfoField name="FocalLength"$>(mm)
</MTImageInfo>

とか書いておけば、下の様にEXIF情報を元に撮影データを表示させることが出来る。

2004/11/27/01:59:51(JST), 3504 x 2336,
1/250(s), F/80/10, ISO-100, 738(step),
Auto white balance, 85/1(mm)

ただ、F値や焦点距離が分数で表示されるのは何とかならないものだろうか。EXIF情報としてそもそも分数の形で入っているようなので、抽出後に"/"の前後で分離して、除算を行った結果を出力する様にMTImageInfoを改変すればいいのだと思うが面倒だ・・・

投稿者 散財人 : 08:56 | コメント (0) | トラックバック (1)

2004年11月12日

[ blog ]

Blog Pet こうさぎ

"こうさぎ"を飼い始めてみる。名前は散太。

まだ産まれたばかりでご迷惑をおかけするとは思いますが、温かく見守ってくれると幸いです。

投稿者 散財人 : 15:38 | コメント (0) | トラックバック (0)

2004年11月08日

[ blog ]

指定日投稿テスト

MT3.11にアップグレードしたものの指定日投稿機能を試していなかったことを思い出し、試してみることにする。 といってもヘルプにあるように/etc/crontabに

0-59/15 * * * * apache cd <path to mt>; ./tools/run-periodic-tasks

と記述するだけなのだが。果たしてうまく行くであろうか。

指定時刻以後に自動で公開されるようにはなったけど、cronから夏季のようなエラーが来るなぁ。何でだろ。

Use of uninitialized value in substitution (s///) at lib/MT/ConfigMgr.pm line 171, <FH> line 70.
Use of uninitialized value in substitution (s///) at lib/MT/ConfigMgr.pm line 171, <FH> line 70.

crontabの実行をユーザapacheでは無く、自分のユーザに変更したらエラーが出なくなった。設定ファイルのパーミッションが一部閉じられているかも。

投稿者 散財人 : 22:29 | コメント (0) | トラックバック (0)

2004年11月07日

[ 日記 , blog ]

Amazon.co.jp アソシエイトプログラム

MTAwsを導入していながら今までなんとなく面倒で登録していなかったAmazon.co.jp アソシエイトプログラムに登録してみる。

Amazonではほとんど買い物しない自分が登録するのもいかがなものか、という気もするが。

投稿者 散財人 : 22:20 | コメント (0) | トラックバック (0)

2004年11月03日

[ 日記 , blog ]

楽天イーグルスバブル?

ふとawstatsによるアクセスログ解析結果を見てみたところ昨日の訪問数が1561件にも上っていることがわかった。
awstatsの解析結果は毎時ごとに更新されてしまっているので、毎日更新のWebalizerのほうの解析結果を見てみると、11月の時刻別アクセス数は17時代に跳ね上がっていることが判明。
2004年11月時刻別アクセス数(2004年11月3日4時現在)

プロ野球新規参入球団が東北楽天ゴールデンイーグルスと発表された11月2日17時前からアクセスが急増したのだろう。ヤフーの検索結果にも本家のサイトが登録されるようになったので、今後はこのブログの訪問者も減って"楽天イーグルスバブル"もはじけるとは思うのだけど。

投稿者 散財人 : 15:30 | コメント (0) | トラックバック (0)

2004年10月31日

[ 日記 , blog ]

SEO

なんか最近「楽天イーグルス」でのアクセスが多いなぁと思ったら、Yahoo! Japanで「楽天イーグルス」で検索する先日書いた記事がトップに来るのが原因のようだ。

特にSEOをしたというわけではないのだが、HTMLのtitleに「楽天イーグルス」が含まれていたり、TBをしてもらったお返しに10箇所くらいにTBを残してきたので多くのリンクが貼られていたりするのが上位にランクインした原因だろう。
楽天のページを探しててたどり着いてしまった人はさぞかし落胆しただろうから、そういう人に対しては申し訳ないという思いで言葉も出ない、ということはないが。

でもなぜかgoogleだとランクが全然高くないんだよな(2004/10/31現在180番目位)。まだまだgoogleのほうがYahoo!Japanより賢いということか。

投稿者 散財人 : 01:14 | コメント (0) | トラックバック (0)

2004年10月26日

[ blog ]

template_modified_on

MT3.1にして以来テンプレートを保存しようとするとエラーがでてしまうので、Perlソースを一部コメントアウトして対応していたのだが、何か副作用がありそうで気持ち悪いものがあった。
そしたら今日トラックバックを受けたサイトに興味深いことが書いてあるではないか。

どうやらMTバージョンアップに失敗(仕様?)のようで PostgreSQL特有の問題のようす・・
夜行Blog様によると日付フォーマット云々が関係しているとか そういえばPostgreSQLってtimestampの仕様がバージョンによってかなり違うよねぇ
ということで夜行Blog様の案を採用! 散財流生様はソースを追いかけられて凄そうなのだけれど ほかの影響が怖いので見送ることに

おお、もっとスマートな方法があるのか、ということでTBしてくれたやなぎもの糯さんに感謝しつつ、夜行Blogをみてみる。

夜行Blog: MovableTypeアップデート失敗っぽいその後

恐らく元のデータを読み込んだんだけど値が入っていないため日付のフォーマットを整える関数に引数としてブランクを渡してしまい、その結果0000-00-00 00:00:00なんて値を格納しようとしてエラーになっていたのではないでしょうか。(根拠なし)
というわけでもし僕と同じような現象にぶちあたってお困りの方がいらっしゃいましたらmt_templateのtemplate_created_onとtemplate_modified_onのフィールドに現在の時刻でも格納してあげると解決するかもしれません。おそらくこのフィールドはテンプレートが作成された日付と修正された日付が格納されているものと思われます。

ふむふむ。早速psqlコマンドでPostgreSQLに接続して街頭箇所にインサート。

$ psql blogdb
blogdb=# select template_modified_on from mt_template;
template_modified_on
----------------------

(中略)

 2004-10-20 00:52:09
 2004-10-20 00:52:09
(18 rows)

確かにtemplate_modified_onとtempalte_create_onの最初の16列はそれぞれ空列になっている。そこでとりあえず現在時刻で上書き

blogdb=# UPDATE mt_template SET template_created_on = '2004-10-26 02:09:00' ;
UPDATE 18
blogdb=# select template_created_on from mt_template;
 template_created_on
---------------------
 2004-10-26 02:09:00
(中略)
 2004-10-26 02:09:00
(18 rows)
blogdb=# UPDATE mt_template SET template_modified_on = '2004-10-26 02:09:00' ;
UPDATE 18
blogdb=# select template_modified_on from mt_template;
 template_modified_on
----------------------
 2004-10-26 02:09:00
(中略)
 2004-10-26 02:09:00
(18 rows)
blogdb=# \q

で、Template.pmを元に戻した上で、試しにテンプレートを更新してみると今までの問題発生がウソの様に問題なく更新できる。すばらしい。

しかし、やなぎもの糯さんや夜行さんも言ってるけど、このくらいアップデートスクリプトに仕込んで自動で上書きするようにしておいてくれよ・・・

投稿者 散財人 : 02:11 | コメント (4) | トラックバック (3)

2004年10月20日

[ blog ]

Template.pm

MovableType3.11-jaにアップグレードして色々いじってみたのだが、なんかテンプレートの保存をしようとすると

オブジェクトの保存に失敗しました: Update failed on SQL error ERROR: date/time field value out of range: "0000-00-00 00:00:00"
Use of uninitialized value in unpack at /var/www/hogehoge/lib/MT/ObjectDriver/DBI/postgres.pm line 13.
Argument "" isn't numeric in sprintf at /var/www/hogehoge/lib/MT/ObjectDriver/DBI/postgres.pm line 13.

って言うエラーが出るようになってしまった。
postgres.pmの該当する行には、

sub ts2db {
sprintf '%04d-%02d-%02d %02d:%02d:%02d', unpack 'A4A2A2A2A2A2', $_[1];
}

ってのがあって、どうもここに正しい値が渡ってないという事は分かるんだけど、この関数どこから呼んだときに問題が起こるのかが分からない。
エントリーの追加のときとかはエラーが出てないのでテンプレートの変更に関する記述を重点的に調べればいいのだろうけど・・・
PostgresSQLのエラーログにも確かにそういうエラーが出ているけどこれだけではなんとも。

とりあえずlibディレクトリをだけを3.01に戻してみてエラーが出ないことを確認。やはりlib/MT/Template.pm、lib/MT/TemplateMap.pm、lib/MT/Template/Content.pmが怪しいよなと言うことで、1つずつバージョンを変えてみて原因特定作業をすすめる。
その結果悪いのはlib/MT/Template.pmであると。(TemplateMap.pmは変更されてなかった)
diffをとると

4c4
< # $Id: Template.pm,v 1.45 2004/08/25 02:06:40 ezra Exp $
---
> # $Id: Template.pm,v 1.42 2004/04/29 02:42:57 ezra Exp $
29c29
<         'rebuild_me', 'build_dynamic'
---
>         'rebuild_me',
35d34
<         build_dynamic => 1,
37d35
<     audit => 1,

これもまた1つずつ試してみた結果、最終的に

    audit => 1,

をコメントアウトすることで問題解決。まずは一安心と言うところだが、この行ってコメントアウトしちゃって問題ないんでしょうか・・・

根本的な解決方法を教えてくださった方がいるのでそちらの方法を結局採用。
2004/11/01追記

投稿者 散財人 : 04:20 | コメント (0) | トラックバック (3)

[ blog ]

MovableType3.1日本語版提供開始

お待たせいたしました。Movable Type 3.1日本語版の提供を開始いたしました。

なお、すでにMovable Type 3.0日本語版をお買い上げの方は、無償で3.1にバージョンアップしていただけます。ダウンロードのリンクからシステムにログインし、画面右上の「すでに取得したライセンスのダウンロードはこちらへ」から最新版をダウンロードしてください。

みなさまのご利用を心よりお待ちしております。

MovableType3.1が出たと言うことなので、早速更新してみた。
"lib/MT/Template/Context.pm"に2行ほど変更を施してあったので、まずその変更を3.1の同ファイルにも施す。で、ファイル一式をコピーして、mt-upgrade31.cgiを実行しておしまい。
無事にアップグレードできたようだ。

自動投稿機能とか、カテゴリーのネストとか出来るみたいだけど、いろいろ試すのはおいおいと言うことで。

投稿者 散財人 : 00:55 | コメント (0) | トラックバック (0)

2004年09月28日

[ blog ]

mt.cgi/SSL

mt.cgiへのアクセスをSSL越しにするために悪戦苦闘する。

このサーバのHTTPSは別のバーチャルドメインfoobar.jpで既に使用しているため、https://www.sanzai.net/でのアクセスは出来ない。そこで、https://foobar.jp/cgi-bin/mt.cgiから更新できるように下記を設定

# mt.cfg
CGIPath https://foobar.jp/cgi-bin/
StaticWebPath http://www.sanzai.net/

これでhttps://foobar.jp/cgi-bin/から更新可能になったのだが、今度はmt-comment.cgi等へのリンクがhttps://foobar.jp/cgi-bin/に言ってしまうので都合が悪い。(foobar.jpは極力隠したい。)
そこで今度は、Individual Entry Archiveテンプレートを中心に"MTCGIPath"を"MTBlogURL"に書き換えていく。

これで完璧と思ったらトラックバック用URLは"$MTEntryTrackbackLink$"を見ているらしくhttps://foobar.jp/cgi-bin/mt-tb.cgiを参照してしまっている。これはどこで設定しているのよ、とMovableTypeのソースコードの海を泳ぎまわり、ようやく
Context.pm
に到達。970行目を
# my $path = $cfg->CGIPath;
my $path = $cfg->StaticWebPath;

983行目も同じく
# my $path = $cfg->CGIPath;
my $path = $cfg->StaticWebPath;
にして、トラックバックもStaticWebPathに置いたCGIスクリプトに来るように変更。

これで一応完成か。

投稿者 散財人 : 12:27 | コメント (1) | トラックバック (0)

[ blog ]

PostgreSQL

MovableTypeのデータベースをBerkeley DBからPostgreSQLに移行してみた。

ここあたりを参照しつつ作業。特記事項としてはDBD::Pgが入ってなかったのでCPANで入れた位か。

今のところ特に問題はないみたい。

投稿者 散財人 : 03:41 | コメント (0) | トラックバック (0)

2004年09月22日

[ blog ]

23:59:59

今まで、日付が変わってから前日のことを書いたエントリーなどは作成日時を前日の日付の23:59:59にして保存していたのだが、どうやらこれではDaily Archivesを作った際にその日付の空っぽのページができるだけでエントリーの中身は反映されないと言う不具合に最近になって気がついた。
今までも空っぽのDaily Archiveができることがあって、何でだろうなぁと思ってたのだけど作成日時によるものだとは思わなかった。
しょうがないので作成日時を23:59:00に修正して対処してみる。

どうやら00:00:00でも問題が起こるみたいだけど、これってMovableType使いの間では有名なバグまたは仕様なのだろうか?

気が付いたらいつの間にか問題が発生しなくなっていたみたい。
この間に変更した点と言えばMTを3.11にアップグレードしてPostgreSQLのエントリーに値を追加したぐらいか。環境によって再現したりし無かったりという話なのでPostgreSQLとの相性を疑っていたのだけど、MTのバージョンアップに伴ってバグが解消されたということなのか?
(2004/11/05/02:50:00追記)

投稿者 散財人 : 14:50 | コメント (4) | トラックバック (2)

2004年07月24日

[ blog ]

MovableType3.01D-ja

遅ればせながらMovableType3.0を日本語正式版の3.01D-jaにアップグレード。

MovableTypeのアップグレードは今回が初めてだったのだけど特に問題なくできたので一安心。

投稿者 散財人 : 01:26 | コメント (0) | トラックバック (0)

2004年07月10日

[ blog ]

AWS

MovableTypeにAmazon.co.jp用プラグインを導入してみる。

投稿者 散財人 : 23:45 | コメント (0) | トラックバック (0)

2004年06月18日

[ blog ]

初投稿

記念すべき初投稿。
いつまで続くことやら。

ところでこのブロクの名称何にしたものだろうか。

"散財日記"とかそんなところか?

投稿者 散財人 : 17:36 | コメント (1) | トラックバック (0)