57 lines
1.8 KiB
Rust
57 lines
1.8 KiB
Rust
use axum::{extract::Query, Json};
|
|
use reqwest::Response;
|
|
use serde::Deserialize;
|
|
use serde_json::{from_str, json, Value};
|
|
use std::collections::HashMap;
|
|
|
|
pub async fn search(params: Params) -> Result<Response, reqwest::Error> {
|
|
let client = reqwest::Client::builder()
|
|
.user_agent("JustLearningRust/1.0")
|
|
.build()?;
|
|
|
|
let mut query = String::new();
|
|
|
|
if let Some(q) = params.q {
|
|
query.push_str(&format!("&q={}", q));
|
|
}
|
|
if let Some(latitude) = params.latitude {
|
|
query.push_str(&format!("&lat={}", latitude));
|
|
}
|
|
if let Some(longitude) = params.longitude {
|
|
query.push_str(&format!("&lon={}", longitude));
|
|
}
|
|
|
|
let url = format!(
|
|
"https://nominatim.openstreetmap.org/search?format=json{}",
|
|
query
|
|
);
|
|
let res = client.get(url).send().await?;
|
|
|
|
Ok(res)
|
|
}
|
|
|
|
#[derive(Deserialize)]
|
|
pub struct Params {
|
|
q: Option<String>,
|
|
latitude: Option<f32>,
|
|
longitude: Option<f32>,
|
|
}
|
|
|
|
pub async fn search_handler(Query(params): Query<Params>) -> Json<Value> {
|
|
let res = search(params).await.expect("Failed to get response body");
|
|
let str = &res.text().await.expect("Failed to get response body");
|
|
let json: Vec<HashMap<String, Value>> = from_str(str).unwrap();
|
|
let mut ret = Vec::new();
|
|
for el in json.iter() {
|
|
let display_name = el.get("display_name").unwrap().as_str().unwrap();
|
|
if display_name.contains("United States")
|
|
|| display_name.contains("Canada")
|
|
|| display_name.contains("Brasil")
|
|
// there's no way to filter by population
|
|
{
|
|
ret.push(json!({"name": el.get("display_name"), "latitude": el.get("lat"), "longitude": el.get("lon"), "score": el.get("importance")}));
|
|
}
|
|
}
|
|
Json(json!({ "suggestions": ret }))
|
|
}
|