EXIF GPS write: POST /image/exif/gps via exiftool
New endpoint accepts {path, library, latitude, longitude} and shells
out to exiftool to write GPSLatitude/GPSLongitude (with N/S, E/W refs)
into the file's EXIF in place. After the write, the handler
re-extracts EXIF and updates the image_exif row so the DB stays in
sync — the response carries the updated metadata block in one
round-trip. Falls through to store_exif if the row is missing.
`exif::write_gps` is the small helper. `-overwrite_original` so no
.orig sidecar is left behind. Validates lat/lon range + supports_exif
before spawning exiftool. Format support matches the existing read
path (JPEG / TIFF / RAW / HEIF / PNG / WebP) — videos still need a
different writer and aren't covered.
Apollo's "+ PIN" carousel button (separate commit on the Apollo side)
calls this through /api/photos/exif/gps. Drive-by: cargo fmt one-line
collapse on apollo_client.rs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -84,9 +84,7 @@ impl ApolloClient {
|
||||
match self.fetch_places_containing(base, lat, lon).await {
|
||||
Ok(places) => places,
|
||||
Err(err) => {
|
||||
log::warn!(
|
||||
"apollo_client: places_containing({lat:.4}, {lon:.4}) failed: {err}"
|
||||
);
|
||||
log::warn!("apollo_client: places_containing({lat:.4}, {lon:.4}) failed: {err}");
|
||||
Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2120,7 +2120,10 @@ Return ONLY the summary, nothing else."#,
|
||||
} else {
|
||||
p.description.clone()
|
||||
};
|
||||
format!("- {}{}: {} (radius {} m)", p.name, category, desc, p.radius_m)
|
||||
format!(
|
||||
"- {}{}: {} (radius {} m)",
|
||||
p.name, category, desc, p.radius_m
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
@@ -3367,7 +3370,8 @@ Return ONLY the summary, nothing else."#,
|
||||
// 10. Define tools. Hybrid mode omits `describe_photo` since the
|
||||
// chat model receives the visual description inline.
|
||||
let offer_describe_tool = has_vision && !is_hybrid;
|
||||
let tools = Self::build_tool_definitions(offer_describe_tool, self.apollo_client.is_enabled());
|
||||
let tools =
|
||||
Self::build_tool_definitions(offer_describe_tool, self.apollo_client.is_enabled());
|
||||
|
||||
// 11. Build initial messages. In hybrid mode images are never
|
||||
// attached to the wire message — the description is part of
|
||||
|
||||
Reference in New Issue
Block a user