use Modern::Perl;
use Image::ExifTool;
use Geo::Coder::OSM;
use JSON;
use File::Slurper qw(write_text);
use Getopt::Long;
use Data::Dumper;
binmode(STDOUT, ':utf8'); # force UTF-8 output
my $geocoder = Geo::Coder::OSM->new;
my $exifTool = Image::ExifTool->new;
$exifTool->Options(CoordFormat => q{%+.6f},
DateFormat => "%Y-%m-%d %H:%M:%S");
my %cache = ();
my $usage = <<"EOT";
$0 [--txt|--rename] [--confirm] [--verbose] [FILES...]
Print location data for all the FILES given.
--txt causes it to write a matching text file
--rename show how to rename the files
--confirm in conjunction with --rename actually does it
--verbose uses the display_name instead of the city
EOT
our ($write_text_file, $rename, $confirm, $verbose);
GetOptions("txt" => \$write_text_file,
"rename" => \$rename,
"confirm" => \$confirm,
"verbose" => \$verbose)
or die($usage);
my $i = 0;
for my $file (@ARGV) {
if (not -f $file) { warn "$file is no file"; next }
$exifTool->ExtractInfo("$file");
# Date → just the day
my $date = $exifTool->GetValue('CreateDate', '') || '';
($date) = $1 if $date =~ /^(\d\d\d\d-\d\d-\d\d)/;
# City
my $lat = $exifTool->GetValue('GPSLatitude', '');
my $long = $exifTool->GetValue('GPSLongitude', '');
if (not $lat or not $long) { warn "$file has no location data\n"; next }
my $location = $cache{"$lat, $long"};
if (!$location) {
$location = $cache{"$lat, $long"} = $geocoder->reverse_geocode(lat => $lat, lon => $long);
if (!$location) {
my $json = decode_json($geocoder->response->content);
if ($json->{error}) {
warn $file . " " . $json->{error} . " $lat, $long\n";
} else {
warn "$file unable to geocode, reason unknown\n";
}
next;
}
}
my $place;
if ($verbose) {
$place = $location->{display_name};
} else {
$place = $location->{address}->{city}
|| $location->{address}->{village}
|| $location->{address}->{county};
}
warn "No useful data in " . Dumper($location) unless $place;
my $name = "";
$name .= "$date " if $date;
$name .= "$place " if $place;
$name .= $file;
if ($rename) {
if ($confirm) {
rename($file, $name);
print substr(".oOo", $i++ % 4, 1);
STDOUT->flush();
} else {
say "mv '$file' '$name'";
}
} else {
say $name;
}
if ($write_text_file) {
$file =~ s/(jpg|png)$/txt/i;
write_text($file, $location);
}
}