Uses exif location data to fill data.txt if empty

This commit is contained in:
hbrain 2026-06-05 13:05:42 +02:00
parent fc25d8e7f4
commit 3ea09af486

View file

@ -373,12 +373,93 @@ function read_data($dir){
}
return $data;
}
function location_language_for_country($countryCode){
$map = ['dk'=>'da','de'=>'de','at'=>'de','ch'=>'de','hr'=>'hr','se'=>'sv','no'=>'no','fi'=>'fi','pl'=>'pl','cz'=>'cs','sk'=>'sk','fr'=>'fr','it'=>'it','es'=>'es','pt'=>'pt','nl'=>'nl','be'=>'nl','ba'=>'bs','rs'=>'sr','si'=>'sl','hu'=>'hu','gb'=>'en','uk'=>'en','ie'=>'en'];
$countryCode = strtolower(trim((string)$countryCode));
return $map[$countryCode] ?? 'en';
}
function nominatim_reverse_json($lat, $lon, $language){
$url = 'https://nominatim.openstreetmap.org/reverse?' . http_build_query(['format'=>'jsonv2','lat'=>sprintf('%.8F', $lat),'lon'=>sprintf('%.8F', $lon),'addressdetails'=>'1','accept-language'=>$language]);
$context = stream_context_create(['http'=>['method'=>'GET','header'=>'User-Agent: mvlog-admin/1.0 (reverse geocoding media metadata)\r\n','timeout'=>12]]);
$json = @file_get_contents($url, false, $context);
$data = $json !== false ? json_decode((string)$json, true) : null;
return is_array($data) ? $data : [];
}
function reverse_geocode_place($lat, $lon){
$cacheFile = __DIR__ . '/cache/reverse-geocode.json';
$cache = is_file($cacheFile) ? json_decode((string)file_get_contents($cacheFile), true) : [];
if (!is_array($cache)) $cache = [];
$key = sprintf('%.5F,%.5F', $lat, $lon);
if (isset($cache[$key]) && is_string($cache[$key])) return $cache[$key];
$first = nominatim_reverse_json($lat, $lon, 'en');
$countryCode = (string)($first['address']['country_code'] ?? '');
$language = location_language_for_country($countryCode);
$data = ($language === 'en') ? $first : nominatim_reverse_json($lat, $lon, $language);
$address = is_array($data['address'] ?? null) ? $data['address'] : [];
$city = (string)($address['city'] ?? $address['town'] ?? $address['village'] ?? $address['island'] ?? $address['suburb'] ?? $address['hamlet'] ?? $address['municipality'] ?? '');
$country = (string)($address['country'] ?? '');
$place = trim(implode(', ', array_filter([$city, $country], fn($v)=>trim((string)$v) !== '')));
if ($place === '') $place = trim($country);
if ($place !== '') {
$cache[$key] = $place;
@file_put_contents($cacheFile, json_encode($cache, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n", LOCK_EX);
@chmod($cacheFile, 0664);
}
return $place;
}
function media_gps_coordinates($path){
$exiftool = trim((string)shell_exec('command -v exiftool 2>/dev/null'));
if ($exiftool === '' || !is_file($path)) return null;
$cmd = escapeshellarg($exiftool) . ' -json -n -GPSLatitude -GPSLongitude -GPSCoordinates ' . escapeshellarg($path) . ' 2>/dev/null';
$rows = json_decode((string)shell_exec($cmd), true);
$row = is_array($rows) && isset($rows[0]) && is_array($rows[0]) ? $rows[0] : [];
$lat = $row['GPSLatitude'] ?? null;
$lon = $row['GPSLongitude'] ?? null;
if ((!is_numeric($lat) || !is_numeric($lon)) && !empty($row['GPSCoordinates']) && preg_match('/(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)/', (string)$row['GPSCoordinates'], $m)) {
$lat = $m[1];
$lon = $m[2];
}
if (!is_numeric($lat) || !is_numeric($lon)) return null;
$lat = (float)$lat;
$lon = (float)$lon;
if (abs($lat) < 0.000001 && abs($lon) < 0.000001) return null;
return [$lat, $lon];
}
function infer_location_from_first_media($dir){
foreach (visual_order_files($dir) as $name) {
$gps = media_gps_coordinates($dir . '/' . $name);
if (!$gps) continue;
$place = reverse_geocode_place($gps[0], $gps[1]);
if ($place !== '') return $place;
}
return '';
}
function display_month_year_from_media_datetime($value){
$value = preg_replace('/[^0-9]/', '', (string)$value);
if (strlen($value) < 8) return '';
$year = (int)substr($value, 0, 4);
$month = (int)substr($value, 4, 2);
$day = (int)substr($value, 6, 2);
if (!checkdate($month, $day, $year)) return '';
return date('F Y', mktime(0, 0, 0, $month, $day, $year));
}
function infer_date_from_first_media($dir){
foreach (visual_order_files($dir) as $name) {
$date = media_file_date($dir . '/' . $name);
if ($date === null) continue;
$display = display_month_year_from_media_datetime($date);
if ($display !== '') return $display;
}
return '';
}
function write_data($dir, $post){
$title = trim($post['title'] ?? '');
$teaser = trim($post['teaser'] ?? '');
$quote_da = trim($post['quote_da'] ?? '');
$place = trim($post['place'] ?? '');
if ($place === '') $place = infer_location_from_first_media($dir);
$date = trim($post['date'] ?? '');
if ($date === '') $date = infer_date_from_first_media($dir);
$description = trim($post['description'] ?? '');
if (function_exists('mb_substr')) $description = mb_substr($description, 0, 5000, 'UTF-8'); else $description = substr($description, 0, 5000);
$lines = [];