#![allow(clippy::all, unused_imports, dead_code)]
use crate::{Actor, ActorBehavior, Message, Port};
use anyhow::{Error, Result};
use reflow_actor::{message::EncodableValue, ActorContext};
use reflow_actor_macro::actor;
use serde_json::{json, Value};
use std::collections::HashMap;
use std::time::Duration;
const BASE_URL: &str = "https://api.mapbox.com";
const ENV_KEY: &str = "MAPBOX_API_KEY";
fn apply_auth(
config: &reflow_actor::ActorConfig,
mut builder: reqwest::RequestBuilder,
) -> Result<reqwest::RequestBuilder> {
let credential = config
.get_config_or_env(ENV_KEY)
.ok_or_else(|| anyhow::anyhow!("Missing env var: {}", ENV_KEY))?;
builder = builder.query(&[("access_token", &credential)]);
Ok(builder)
}
#[actor(
MapboxGeocodeAddressActor,
inports::<100>(endpoint, search_text, access_token),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_geocode_address(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/geocoding/v5/{endpoint}/{search_text}.json".to_string();
if let Some(val) = inputs.get("endpoint") {
endpoint = endpoint.replace("{{endpoint}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("search_text") {
endpoint = endpoint.replace("{{search_text}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /geocoding/v5/{{endpoint}}/{{search_text}}.json failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxReadDirectionsActor,
inports::<100>(profile, coordinates, access_token),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_directions(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/directions/v5/{profile}/{coordinates}".to_string();
if let Some(val) = inputs.get("profile") {
endpoint = endpoint.replace("{{profile}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("coordinates") {
endpoint = endpoint.replace("{{coordinates}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /directions/v5/{{profile}}/{{coordinates}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxSearchPlacesActor,
inports::<100>(endpoint, search_text, access_token, autocomplete, bbox, country, fuzzyMatch, language, limit, proximity, routing, types, worldview),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_search_places(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/geocoding/v5/{endpoint}/{search_text}.json".to_string();
if let Some(val) = inputs.get("endpoint") {
endpoint = endpoint.replace("{{endpoint}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("search_text") {
endpoint = endpoint.replace("{{search_text}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("autocomplete") {
query_pairs.push(("autocomplete", super::message_to_str(val)));
}
if let Some(val) = inputs.get("bbox") {
query_pairs.push(("bbox", super::message_to_str(val)));
}
if let Some(val) = inputs.get("country") {
query_pairs.push(("country", super::message_to_str(val)));
}
if let Some(val) = inputs.get("fuzzyMatch") {
query_pairs.push(("fuzzyMatch", super::message_to_str(val)));
}
if let Some(val) = inputs.get("language") {
query_pairs.push(("language", super::message_to_str(val)));
}
if let Some(val) = inputs.get("limit") {
query_pairs.push(("limit", super::message_to_str(val)));
}
if let Some(val) = inputs.get("proximity") {
query_pairs.push(("proximity", super::message_to_str(val)));
}
if let Some(val) = inputs.get("routing") {
query_pairs.push(("routing", super::message_to_str(val)));
}
if let Some(val) = inputs.get("types") {
query_pairs.push(("types", super::message_to_str(val)));
}
if let Some(val) = inputs.get("worldview") {
query_pairs.push(("worldview", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /geocoding/v5/{{endpoint}}/{{search_text}}.json failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxReadPlaceActor,
inports::<100>(endpoint, longitude, latitude, access_token, country, language, limit, routing, types, worldview),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_place(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/geocoding/v5/{endpoint}/{longitude},{latitude}.json".to_string();
if let Some(val) = inputs.get("endpoint") {
endpoint = endpoint.replace("{{endpoint}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("longitude") {
endpoint = endpoint.replace("{{longitude}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("latitude") {
endpoint = endpoint.replace("{{latitude}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("country") {
query_pairs.push(("country", super::message_to_str(val)));
}
if let Some(val) = inputs.get("language") {
query_pairs.push(("language", super::message_to_str(val)));
}
if let Some(val) = inputs.get("limit") {
query_pairs.push(("limit", super::message_to_str(val)));
}
if let Some(val) = inputs.get("routing") {
query_pairs.push(("routing", super::message_to_str(val)));
}
if let Some(val) = inputs.get("types") {
query_pairs.push(("types", super::message_to_str(val)));
}
if let Some(val) = inputs.get("worldview") {
query_pairs.push(("worldview", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /geocoding/v5/{{endpoint}}/{{longitude}},{{latitude}}.json failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxReadIsochroneActor,
inports::<100>(profile, coordinates, access_token, contours_minutes, contours_meters, contours_colors, polygons, denoise, generalize),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_isochrone(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/isochrone/v1/{profile}/{coordinates}".to_string();
if let Some(val) = inputs.get("profile") {
endpoint = endpoint.replace("{{profile}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("coordinates") {
endpoint = endpoint.replace("{{coordinates}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("contours_minutes") {
query_pairs.push(("contours_minutes", super::message_to_str(val)));
}
if let Some(val) = inputs.get("contours_meters") {
query_pairs.push(("contours_meters", super::message_to_str(val)));
}
if let Some(val) = inputs.get("contours_colors") {
query_pairs.push(("contours_colors", super::message_to_str(val)));
}
if let Some(val) = inputs.get("polygons") {
query_pairs.push(("polygons", super::message_to_str(val)));
}
if let Some(val) = inputs.get("denoise") {
query_pairs.push(("denoise", super::message_to_str(val)));
}
if let Some(val) = inputs.get("generalize") {
query_pairs.push(("generalize", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /isochrone/v1/{{profile}}/{{coordinates}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxReadMapMatchingActor,
inports::<100>(profile, coordinates, access_token, annotations, geometries, language, overview, radiuses, steps, timestamps, tidy, waypoints),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_map_matching(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/matching/v5/{profile}/{coordinates}".to_string();
if let Some(val) = inputs.get("profile") {
endpoint = endpoint.replace("{{profile}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("coordinates") {
endpoint = endpoint.replace("{{coordinates}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("annotations") {
query_pairs.push(("annotations", super::message_to_str(val)));
}
if let Some(val) = inputs.get("geometries") {
query_pairs.push(("geometries", super::message_to_str(val)));
}
if let Some(val) = inputs.get("language") {
query_pairs.push(("language", super::message_to_str(val)));
}
if let Some(val) = inputs.get("overview") {
query_pairs.push(("overview", super::message_to_str(val)));
}
if let Some(val) = inputs.get("radiuses") {
query_pairs.push(("radiuses", super::message_to_str(val)));
}
if let Some(val) = inputs.get("steps") {
query_pairs.push(("steps", super::message_to_str(val)));
}
if let Some(val) = inputs.get("timestamps") {
query_pairs.push(("timestamps", super::message_to_str(val)));
}
if let Some(val) = inputs.get("tidy") {
query_pairs.push(("tidy", super::message_to_str(val)));
}
if let Some(val) = inputs.get("waypoints") {
query_pairs.push(("waypoints", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("GET /matching/v5/{{profile}}/{{coordinates}} failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxReadMatrixActor,
inports::<100>(profile, coordinates, access_token, annotations, approaches, destinations, sources, fallback_speed, depart_at),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_matrix(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/directions-matrix/v1/{profile}/{coordinates}".to_string();
if let Some(val) = inputs.get("profile") {
endpoint = endpoint.replace("{{profile}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("coordinates") {
endpoint = endpoint.replace("{{coordinates}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("annotations") {
query_pairs.push(("annotations", super::message_to_str(val)));
}
if let Some(val) = inputs.get("approaches") {
query_pairs.push(("approaches", super::message_to_str(val)));
}
if let Some(val) = inputs.get("destinations") {
query_pairs.push(("destinations", super::message_to_str(val)));
}
if let Some(val) = inputs.get("sources") {
query_pairs.push(("sources", super::message_to_str(val)));
}
if let Some(val) = inputs.get("fallback_speed") {
query_pairs.push(("fallback_speed", super::message_to_str(val)));
}
if let Some(val) = inputs.get("depart_at") {
query_pairs.push(("depart_at", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!(
"GET /directions-matrix/v1/{{profile}}/{{coordinates}} failed: {}",
e
)
.into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxReadMapTileActor,
inports::<100>(username, style_id, tilesize, z, x, y, access_token),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_map_tile(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/styles/v1/{username}/{style_id}/tiles/{tilesize}/{z}/{x}/{y}".to_string();
if let Some(val) = inputs.get("username") {
endpoint = endpoint.replace("{{username}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("style_id") {
endpoint = endpoint.replace("{{style_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("tilesize") {
endpoint = endpoint.replace("{{tilesize}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("z") {
endpoint = endpoint.replace("{{z}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("x") {
endpoint = endpoint.replace("{{x}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("y") {
endpoint = endpoint.replace("{{y}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("GET /styles/v1/{{username}}/{{style_id}}/tiles/{{tilesize}}/{{z}}/{{x}}/{{y}} failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
MapboxReadStaticMapActor,
inports::<100>(username, style_id, overlay, lon, lat, zoom, bearing, pitch, width, height, access_token, logo, attribution, padding, retina),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_static_map(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/styles/v1/{username}/{style_id}/static/{overlay}/{lon},{lat},{zoom},{bearing},{pitch}/{width}x{height}".to_string();
if let Some(val) = inputs.get("username") {
endpoint = endpoint.replace("{{username}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("style_id") {
endpoint = endpoint.replace("{{style_id}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("overlay") {
endpoint = endpoint.replace("{{overlay}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("lon") {
endpoint = endpoint.replace("{{lon}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("lat") {
endpoint = endpoint.replace("{{lat}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("zoom") {
endpoint = endpoint.replace("{{zoom}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("bearing") {
endpoint = endpoint.replace("{{bearing}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("pitch") {
endpoint = endpoint.replace("{{pitch}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("width") {
endpoint = endpoint.replace("{{width}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("height") {
endpoint = endpoint.replace("{{height}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("retina") {
endpoint = endpoint.replace("{{retina}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("logo") {
query_pairs.push(("logo", super::message_to_str(val)));
}
if let Some(val) = inputs.get("attribution") {
query_pairs.push(("attribution", super::message_to_str(val)));
}
if let Some(val) = inputs.get("padding") {
query_pairs.push(("padding", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert("error".to_string(), Message::Error(format!("GET /styles/v1/{{username}}/{{style_id}}/static/{{overlay}}/{{lon}},{{lat}},{{zoom}},{{bearing}},{{pitch}}/{{width}}x{{height}} failed: {}", e).into()));
}
}
Ok(output)
}
#[actor(
MapboxListStylesActor,
inports::<100>(username, access_token, draft, start, limit),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_list_styles(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/styles/v1/{username}".to_string();
if let Some(val) = inputs.get("username") {
endpoint = endpoint.replace("{{username}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("draft") {
query_pairs.push(("draft", super::message_to_str(val)));
}
if let Some(val) = inputs.get("start") {
query_pairs.push(("start", super::message_to_str(val)));
}
if let Some(val) = inputs.get("limit") {
query_pairs.push(("limit", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /styles/v1/{{username}} failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
MapboxReadStyleActor,
inports::<100>(username, style_id, access_token, draft),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_style(context: ActorContext) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/styles/v1/{username}/{style_id}".to_string();
if let Some(val) = inputs.get("username") {
endpoint = endpoint.replace("{{username}}", &super::message_to_str(val));
}
if let Some(val) = inputs.get("style_id") {
endpoint = endpoint.replace("{{style_id}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("draft") {
query_pairs.push(("draft", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(
format!("GET /styles/v1/{{username}}/{{style_id}} failed: {}", e).into(),
),
);
}
}
Ok(output)
}
#[actor(
MapboxReadElevationActor,
inports::<100>(access_token, layer, locations),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_read_elevation(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/v4/surface/elevation.json".to_string();
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("layer") {
query_pairs.push(("layer", super::message_to_str(val)));
}
if let Some(val) = inputs.get("locations") {
query_pairs.push(("locations", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /v4/surface/elevation.json failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
MapboxListTilesetsActor,
inports::<100>(username, access_token, type_, limit, sortby, start, visibility),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn mapbox_list_tilesets(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let mut endpoint = "/tilesets/v1/{username}".to_string();
if let Some(val) = inputs.get("username") {
endpoint = endpoint.replace("{{username}}", &super::message_to_str(val));
}
let url = format!("{}{}", BASE_URL.trim_end_matches('/'), endpoint);
let client = reqwest::Client::builder()
.timeout(Duration::from_secs(30))
.build()?;
let mut builder = client.get(&url);
builder = builder.header("Content-Type", "application/json");
builder = apply_auth(actor_config, builder)?;
let mut query_pairs: Vec<(&str, String)> = Vec::new();
if let Some(val) = inputs.get("access_token") {
query_pairs.push(("access_token", super::message_to_str(val)));
}
if let Some(val) = inputs.get("type_") {
query_pairs.push(("type", super::message_to_str(val)));
}
if let Some(val) = inputs.get("limit") {
query_pairs.push(("limit", super::message_to_str(val)));
}
if let Some(val) = inputs.get("sortby") {
query_pairs.push(("sortby", super::message_to_str(val)));
}
if let Some(val) = inputs.get("start") {
query_pairs.push(("start", super::message_to_str(val)));
}
if let Some(val) = inputs.get("visibility") {
query_pairs.push(("visibility", super::message_to_str(val)));
}
if !query_pairs.is_empty() {
builder = builder.query(&query_pairs);
}
let mut output = HashMap::new();
match builder.send().await {
Ok(resp) => {
let status = resp.status().as_u16();
let headers: HashMap<String, String> = resp
.headers()
.iter()
.filter_map(|(k, v)| v.to_str().ok().map(|val| (k.to_string(), val.to_string())))
.collect();
let body_text = resp.text().await.unwrap_or_default();
let body_value: Value =
serde_json::from_str(&body_text).unwrap_or(Value::String(body_text));
output.insert(
"response".to_string(),
Message::object(EncodableValue::from(json!({
"status": status,
"headers": headers,
"body": body_value,
}))),
);
}
Err(e) => {
output.insert(
"error".to_string(),
Message::Error(format!("GET /tilesets/v1/{{username}} failed: {}", e).into()),
);
}
}
Ok(output)
}