001 #!/usr/local/bin/perl -w
002 use strict;
003 use Tk;
004 use Tk::JPEG;
005 use POE;
006 use LWP::UserAgent::POE;
007 use Net::Amazon;
008 use Net::Amazon::Request::UPC;
009 use MIME::Base64;
010 use Rose::DB::Object::Loader;
011 use Log::Log4perl qw(:easy);
012
013 my @MODES = qw(books music dvd);
014
015 my $UA = LWP::UserAgent::POE->new();
016
017 my $loader = Rose::DB::Object::Loader->new(
018   db_dsn =>
019     "dbi:SQLite:dbname=articles.dat",
020   db_options   => {
021     AutoCommit => 1, RaiseError => 1 },
022 );
023 $loader->make_classes();
024
025 my $top = $poe_main_window;
026 $top->configure(-title     => "UPC Reader",
027                 -background=> "#a2b2a3");
028 $top->geometry("200x300");
029
030 my $FOOTER = $top->Label();
031 $FOOTER->configure(-text =>
032                    "Scan next item");
033
034 my $BYWHO = $top->Label();
035 my $UPC   = $top->Label();
036 my $PHOTO = $top->Photo(-format => 'jpeg');
037 my $photolabel =
038              $top->Label(-image => $PHOTO);
039 my $entry = $top->Entry(
040             -textvariable => \my $UPC_VAR);
041
042 my $PRODUCT = $top->Label();
043
044 $entry->focus();
045
046 for my $w ($entry, $photolabel, $PRODUCT,
047            $BYWHO, $UPC, $FOOTER) {
048   $w->pack(-side => 'top', -expand => 1,
049            -fill => "x" );
050 }
051
052 $entry->bind("<Return>", \&scan_done);
053
054 my $session = POE::Session->create(
055   inline_states => {
056     _start => sub{
057       $poe_kernel->delay("_start", 60);
058   }
059 });
060
061 POE::Kernel->run();
062
063 ###########################################
064 sub scan_done {
065 ###########################################
066   $PHOTO->blank();
067   $PRODUCT->configure(-text => "");
068   $FOOTER->configure(-text =>
069                      "Processing ...");
070   $BYWHO->configure(-text => "");
071   $UPC->configure(-text => $UPC_VAR);
072   resp_process(
073           amzn_fetch( $UPC_VAR ) );
074   $UPC_VAR = "";
075 }
076
077 ###########################################
078 sub amzn_fetch {
079 ###########################################
080   my($upc) = @_;
081
082   my $resp;
083
084   my $amzn = Net::Amazon->new(
085       token => 'XXXXXXXXXXXXXXXXXXXX',
086       ua    => $UA,
087   );
088
089   for my $mode (@MODES) {
090
091     my $req =
092       Net::Amazon::Request::UPC->new(
093           upc  => $upc,
094           mode => $mode,
095       );
096
097      $resp = $amzn->request($req);
098
099      if($resp->is_success()) {
100          return($resp, $mode, $upc);
101          last;
102      }
103
104      WARN "Nothing found in mode '$mode'";
105   }
106   return $resp;
107 }
108
109 ###########################################
110 sub resp_process {
111 ###########################################
112   my($resp, $mode, $upc) = @_;
113
114   if($resp->is_error()) {
115     $PRODUCT->configure(
116                  -text => "NOT FOUND");
117     return 0;
118   }
119
120   my ($property) = $resp->properties();
121   my $imgurl = $property->ImageUrlMedium();
122   img_display( $imgurl );
123
124   my $a = Article->new();
125   $a->upc($upc);
126   $a->type($mode);
127   $a->title( $property->Title() );
128
129   if($mode eq "books") {
130     $a->bywho( $property->author() );
131   } elsif( $mode eq "music") {
132     $a->bywho( $property->artist() );
133   } else {
134     $a->bywho( "" );
135   }
136
137   $BYWHO->configure(-text => $a->bywho() );
138   $PRODUCT->configure(
139                     -text => $a->title() );
140
141   if($a->load( speculative => 1 )) {
142       $PRODUCT->configure(
143                 -text => "ALREADY EXISTS");
144   } else {
145     $a->save();
146   }
147
148   $FOOTER->configure(
149                 -text => "Scan next item");
150   return 1;
151 }
152
153 ###########################################
154 sub img_display {
155 ###########################################
156   my($imgurl) = @_;
157
158   my $imgresp = $UA->get( $imgurl );
159
160   if($imgresp->is_success()) {
161     $PHOTO->configure( -data =>
162      encode_base64( $imgresp->content() ));
163   }
164 }