iTunes playing track その後

んで出来た。まともに動作させようとしたら思ったより太ったコードになってしまいましたね。動作は至ってサクサクですが。

ステップは前回のエントリで上げたとおり、
 1. iTunes 情報取得
 2. Amazon アフィリエイトリンク作成
 3. java script ファイルへ出力
 4. FTP で java script を Upload
です。active perl で実装。

さて実際に自分で目的の機能を果たそうと試していたところ1つの事実が発覚したのであります。Amazon ってば、中途半端に日本盤のアルバムタイトルをカタカナ表記にしちゃってるのね…そりゃ一部アルバム引っかからないわけだわ。
まあリンク精度よりもジャケット写真のほうが個人的には重きに置きたいところなので、リンク生成する際国内の amazon.co.jp の商品に向けて生成するものの、もしその CD のジャケット写真がなかった場合は amazon.com の方も検索をかけて画像リンクのみ引っ張ってくるという流れを作ってみました。洋盤ならではの作戦なり。

以下ソース。

use strict;
use Encode;
use Win32::OLE;
use Net::Amazon;
use Net::Amazon::Request::Keyword;
use HTML::Template;
use LWP::Simple;
use File::Temp qw(tempfile);
use Image::Size qw(imgsize);
use Net::FTP;

our $DeveloperToken = 'YOUR-TOKEN';
our $AssociateID    = 'AssociateID';
our $FtpHost = 'example.com';
our $FtpUser = 'username';
our $FtpPass = 'password';
our $FtpFilePath = 'path/to/music.js';
our $encode = 'euc-jp';
our $output_message = 1;
our $html_head = '';
our $html_foot = '';

my $itunes  = Win32::OLE->new('iTunes.Application')
  or die "iTunes not start.
";
my ($old, $amazon);

while (1) {
    until ($itunes->PlayerState) {
        sleep 5;
    }
    my $track  = $itunes->CurrentTrack;
    if ($old->{album} ne $track->Album) {
        my ($item, $link, $imageJP, $imageUS);
        $amazon->{uri_start} = '';
        $amazon->{uri_end} = '';
        $amazon->{image} = '';

        $item = search_aws($track->Artist, $track->Album,
                           "jp", "music-jp");
        if ($item) {
            $link = $item->url;
            $imageJP = $item->ImageUrlMedium;

            if (check_image($imageJP)) {
                $amazon->{image} = qq[<img src="$imageJP" border="0" />];
            } else {
                $item = search_aws($track->Artist, $track->Album,
                                   "", "music");
                $imageUS = $item->ImageUrlMedium;
                $amazon->{image} = qq[<img src="$imageUS" border="0" />] if check_image($imageUS);
            }
            if ($link) {
                $amazon->{uri_start} = qq[<a href="$link" target="_blank">];
                $amazon->{uri_end} = '</a>';
            }
        }
        $old->{album} = $track->Album;
    }

    if ($old->{name} ne $track->Name &&
        (($track->Duration / 2) < $itunes->PlayerPosition ||
         $itunes->PlayerPosition > 30)
       ) {
        my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
          = localtime(time);
        my $date = sprintf("%04d/%02d/%02d %02d:%02d:%02d",
                           $year + 1900, $mon +1, $mday, $hour, $min, $sec);
        my $template = HTML::Template->new(filename => 'music.tmpl');
        $template->param(
                         AMAZON_LINK_START => $amazon->{uri_start},
                         AMAZON_LINK_END => $amazon->{uri_end},
                         IMAGE           => $amazon->{image},
                         NAME            => $track->Name,
                         ALBUM           => $track->Album,
                         ARTIST          => $track->Artist,
                         DATE            => $date,
                         HTML_HEAD       => $html_head,
                         HTML_FOOT       => $html_foot
                        );
        $old->{name} = $track->Name;

        my($fh, $tempfile) = tempfile();
        $fh->print(html2js($template->output));
        $fh->close;
        ftp_put($FtpHost, $FtpUser, $FtpPass, $tempfile, $FtpFilePath);
        unlink($tempfile);
    }
    sleep 5;
}

sub search_aws {
    my($artist, $title, $locale, $mode) = @_;
    my $attr;
    $attr->{token}  = $DeveloperToken;
    $attr->{locale} = $locale if $locale;
    $attr->{affiliate_id} = $AssociateID;
    warn "Searching $artist - $title on Amazon $attr->{locale}...
" if $output_message;
    my $ua = Net::Amazon->new(%$attr);

    my $keyword = "$artist $title";
    Encode::from_to($keyword, "Shift_JIS" => "UTF-8");
    my $req = Net::Amazon::Request::Keyword->new(keyword => $keyword,
                                                 mode => $mode);

    my $response = $ua->request($req);
    my $item = ($response->properties())[0];
    return $item;
}

sub check_image {
    my $image = shift;

    my($fh, $tempimg) = tempfile();
    $fh->print(get($image));
    $fh->close;
    my($x, $y) = imgsize($tempimg);
    unlink($tempimg);
    ($x <= 1 || $y <= 1) ? return 0 : return 1;
}

sub ftp_put {
    my ($host, $user, $pass, $tmpfile, $putpath) = @_;
    warn "Uploading new Track...
" if $output_message;
    my $ftp = Net::FTP->new($host);
    $ftp->login($user, $pass);
    $ftp->put($tmpfile, $putpath);
    $ftp->quit;
}

sub html2js {
    my $html= shift;
    my $js = "";
    for (split(/[
]+/, $html)) {
        s/x27/'/g; 
        $js .= "document.writeln('$_');
";
    }
    Encode::from_to($js, 'utf-8', $encode);
    return $js;
}

sub _encode {
    my $str = shift;
    $str =~ s/([^w,])/'%'.unpack("H2", $1)/ego; #'
    return $str;
}
music.tmpl
<TMPL_VAR NAME=HTML_HEAD>

<p>
<TMPL_VAR NAME=AMAZON_LINK_START>
<TMPL_VAR NAME=IMAGE><br />
<TMPL_VAR NAME=NAME><br />
<TMPL_VAR NAME=ALBUM><br />
<TMPL_VAR NAME=ARTIST>
<TMPL_VAR NAME=AMAZON_LINK_END><br />
(<TMPL_VAR NAME=DATE>)<br />
</p>

<TMPL_VAR NAME=HTML_FOOT>

宮川さんの iTunes で聴いてる曲に Amazon アフィリエイトしてさらに画像もBlog Hacks の Hack#93 あたりを参考。iTunes を立ち上げている裏でグルングルン回して search -> ftp を繰り返します。Win32::OLE->new() で iTunes を指定しておけばアプリそのものを立ち上げてくれるので、iTunes 起動はこのスクリプトを実行するバッチファイルを実行すると手間いらずです。

過去数件のアルバムも一緒に表示しようと適当に xml ファイルにでも吐いてやろうかなと思いましたが、ぶっちゃけ面倒なのでやめた(笑) iTunes 自体が情報を xml で保持しているので、そこから再生回数 TOP10 を引っ張ってきてうちランダムに選んだ3枚を別途リンク作成とかすると面白いかもしれません。

(2004-11-23 コード若干調整。いつの間にか $amazon, $old が毎ループで初期化されるようになってて、常に search -> ftp するウザイ動作になってしまっていました。)

トラックバック(0)

このブログ記事を参照しているブログ一覧: iTunes playing track その後

このブログ記事に対するトラックバックURL: http://hatotech.org/mt-admin/mt-tb.cgi/378

コメントする

このブログ記事について

このページは、が2004年11月22日 16:19に書いたブログ記事です。

ひとつ前のブログ記事は「iTunes playing track out and Amazon アフィリエイト」です。

次のブログ記事は「acvice perl で CPAN」です。

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

Powered by Movable Type 4.01