自分のblogでamazonの商品の個別リンクを作成するのに、aws.plをずっと使っていたのだけれど、最近amazonのWSはECS4.0になって古いAPIは使えなくなってしまった。
で、まだまだ不完全なんだけど、自分の使い方では問題ないのでたぶんこれ以上手を入れないと思うので、現時点のものを公開しておく。
今の所、商品の個別リンクを貼るために、
<MTAws search="AsinSearch" query="Asinを,で並べる">
<div style="border: solid 1px #666666; padding: 1em;">
<a href="<$MTAwsurl$>"><img src="<$MTAwsImageUrlSmall$>" align="left">
『<$MTAwsProductName$>』<br/>
著者:<$MTAwsAuthors$><br/>
出版社:<$MTAwsManufacturer$><br/>
発行日:<$MTAwsReleaseDate$>
</a>
</div>
</MTAws>
みたいな使い方ならば問題ない。(blogの文字コードはutf8で確認)
上で出てこないタグについてはどうなるかわからない。
参考にしたのは、特集:前編 WebサービスをAmazonで知る――ECS 4.0でアフィリエイト
以前と違って、query=に並べた順番で結果を返してくれないので、無理やりAsinで結果をソートしている。
一応、以前書いたblogのエントリを書き換えたくなかったので、互換性を保つようにしてあるのだけれど、これ以上機能を追加するのであれば、最近のMTのpluginの書き方を勉強して、1から作り直した方が良さそうだ。
元のソースの著作権は平田さんにあります。利用条件等は元のものに従います。
aws.pl
# aws.pl
# (C) 2003 Daiji Hirata
#  All Right Reserved.

use MT::ConfigMgr;
use MT::Template::Context;
use LWP::UserAgent;
use XML::Simple;
use Jcode;
use strict;

my $VERSION = '1.0a-ecs4';

my %config;
$config{SubscriptionId} = 'あなたのSubscriptionId';
$config{associate_id} = 'あなたのアソシエイトID';

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 = {
    'ItemLookup' => [ "SubscriptionId", "AssociateTag", "Operation", "ItemId", "ResponseGroup"],
};

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 );

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{SubscriptionId} = ($arg->{SubscriptionId}) ? $arg->{SubscriptionId} : $config{SubscriptionId};
    if (!($q{SubscriptionId})) { return $ctx->error("MTAWS needs your SubscriptionId: $q{SubscriptionId}."); }
    $q{AssociateTag} = ($arg->{associate_id}) ? $arg->{associate_id} : $config{associate_id}; 
    $q{ResponseGroup} = ($arg->{ResponseGroup}) ? $arg->{ResponseGroup} : "ItemAttributes,Images";
    if (!($q{AssociateTag})) { $q{AssociateTag} = '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};
    if ($arg->{search} && $arg->{query}) { 
	#$q{search} = $arg->{search}; 
	#$q{query} = ($charset ne 'utf8') ? Jcode->new($arg->{query}, $charset)->utf8 : $arg->{query};
	#$q{$arg->{search}} = utf2entity($q{query},1); 
	if ($arg->{search} eq 'AsinSearch') {
	    $q{Operation} = 'ItemLookup';
	    $q{ItemId} = $arg->{query};
	} else {
	    return $ctx->error("Unsupported method $arg->{search}");
	}
    } else {
	return $ctx->error("No search method and/or query");
    }
    my $url = 'http://ecs.amazonaws.jp/onca/xml?Service=AWSECommerceService&';

    my @query;

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

    $url .= join "&amp;", @query;

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

    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'};

    my $tree;
    $tree = XMLin($content);
    if (!($tree)) { return $ctx->error("XML incorrect:\n"); }
    $ctx->stash('XML', $content );
    my @details;

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

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

@details = sort {$a->{ItemAttributes}->{EAN} cmp $b->{ItemAttributes}->{EAN}} @details;
    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 .= $out;
        if ($q{lastn}>0) { $q{lastn}--; }
        last if ($q{lastn} == 0);
    }
    return $res;
}

sub utf2entity {
    my ($str, $amazon) = @_;
    $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;
    my $author;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    if (ref $detail->{ItemAttributes}->{Author} eq 'ARRAY') { 
        $author = join ", ", @{$detail->{ItemAttributes}->{Author}};
    } else {
        $author = $detail->{ItemAttributes}->{Author} || '';
    }
    return Jcode->new($author, 'utf8')->utf8;
    return $author;
}

sub aws_detail {
    my ($ctx, $e) = @_;
    defined (my $detail = $ctx->stash("Detail")) or return '';
    my $t;
    if ($e eq 'url') {
	$t = $detail->{DetailPageURL};
    } elsif ($e eq 'ImageUrlSmall') {
	$t = $detail->{SmallImage}->{URL};
    } elsif ($e eq 'ImageUrlMedium') {
	$t = $detail->{MediumImage}->{URL};
    } elsif ($e eq 'ImageUrlLarge') {
	$t = $detail->{LargeImage}->{URL};
    } elsif ($e eq 'ProductName') {
	$t = $detail->{ItemAttributes}->{Title};
    } elsif ($e eq 'Asin') {
	$t = $detail->{ItemAttributes}->{EAN};
    } elsif ($e eq 'Manufacturer') {
	$t = $detail->{ItemAttributes}->{Manufacturer};
    } elsif ($e eq 'ReleaseDate') {
	$t = $detail->{ItemAttributes}->{PublicationDate};
    } else {
	# 上記以外は未対応(と言うか手抜き)
	return '';
    }
    if (ref $t eq 'ARRAY') { 
        return join ", ", @{$t};
    } else {
        return $t || '';
    }
}

# 未対応
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->{ItemAttributes}->{Artist} eq 'ARRAY') { 
        return join ", ", @{$detail->{ItemAttributes}->{Artist}};
    } else {
        $detail->{ItemAttributes}->{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

カテゴリ

トラックバック(0)

このブログ記事を参照しているブログ一覧: aws.plのECS4.0対応

このブログ記事に対するトラックバックURL: https://www.wizard-limit.net/cgi-bin/mt/mt-tb.cgi/1461

コメントする

このブログ記事について

このページは、falseが2008年4月11日 18:03に書いたブログ記事です。

ひとつ前のブログ記事は「APCのUPSの状態をcactiでグラフにする」です。

次のブログ記事は「VAIO type C」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

広告

Powered by Movable Type 6.1.1