86 lines
2.1 KiB
Rust
86 lines
2.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
use axum::extract::State;
|
|
use axum::http::StatusCode;
|
|
use axum::response::{IntoResponse, Json};
|
|
use serde::{Deserialize, Serialize};
|
|
use tracing::warn;
|
|
|
|
use crate::state::SharedState;
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct StreetViewQuery {
|
|
lat: f64,
|
|
lon: f64,
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
struct GoogleMetadataResponse {
|
|
status: String,
|
|
#[serde(default)]
|
|
pano_id: String,
|
|
}
|
|
|
|
#[derive(Serialize)]
|
|
struct StreetViewResponse {
|
|
status: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pano_id: Option<String>,
|
|
}
|
|
|
|
pub async fn get_streetview(
|
|
State(shared): State<Arc<SharedState>>,
|
|
query: axum::extract::Query<StreetViewQuery>,
|
|
) -> impl IntoResponse {
|
|
let state = shared.load_state();
|
|
let url = format!(
|
|
"https://maps.googleapis.com/maps/api/streetview/metadata?location={},{}&radius=1000&source=outdoor&key={}",
|
|
query.lat, query.lon, state.google_maps_api_key
|
|
);
|
|
|
|
let resp = match state.http_client.get(&url).send().await {
|
|
Ok(r) => r,
|
|
Err(e) => {
|
|
warn!("Street View metadata request failed: {e}");
|
|
return (
|
|
StatusCode::BAD_GATEWAY,
|
|
Json(StreetViewResponse {
|
|
status: "ERROR".to_string(),
|
|
pano_id: None,
|
|
}),
|
|
);
|
|
}
|
|
};
|
|
|
|
let meta: GoogleMetadataResponse = match resp.json().await {
|
|
Ok(m) => m,
|
|
Err(e) => {
|
|
warn!("Failed to parse Street View metadata: {e}");
|
|
return (
|
|
StatusCode::BAD_GATEWAY,
|
|
Json(StreetViewResponse {
|
|
status: "ERROR".to_string(),
|
|
pano_id: None,
|
|
}),
|
|
);
|
|
}
|
|
};
|
|
|
|
if meta.status == "OK" {
|
|
(
|
|
StatusCode::OK,
|
|
Json(StreetViewResponse {
|
|
status: "OK".to_string(),
|
|
pano_id: Some(meta.pano_id),
|
|
}),
|
|
)
|
|
} else {
|
|
(
|
|
StatusCode::OK,
|
|
Json(StreetViewResponse {
|
|
status: meta.status,
|
|
pano_id: None,
|
|
}),
|
|
)
|
|
}
|
|
}
|