#![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.weatherbit.io/v2.0";
const ENV_KEY: &str = "WEATHERBIT_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(&[("key", &credential)]);
Ok(builder)
}
#[actor(
WeatherbitReadCurrentWeatherActor,
inports::<100>(lat, lon, city, units),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_current_weather(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/current".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", 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 /current failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadForecastActor,
inports::<100>(lat, lon, days),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_forecast(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/forecast/daily".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("days") {
query_pairs.push(("days", 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 /forecast/daily failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadWeatherAlertsActor,
inports::<100>(lat, lon, city, city_id, postal_code, country, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_weather_alerts(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/alerts".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city_id") {
query_pairs.push(("city_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("key") {
query_pairs.push(("key", 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 /alerts failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadCurrentAirQualityActor,
inports::<100>(lat, lon, city, city_id, postal_code, country, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_current_air_quality(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/current/airquality".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city_id") {
query_pairs.push(("city_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("key") {
query_pairs.push(("key", 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 /current/airquality failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadCurrentLightningActor,
inports::<100>(lat, lon, radius, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_current_lightning(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/current/lightning".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("radius") {
query_pairs.push(("radius", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /current/lightning failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadForecastDailyActor,
inports::<100>(lat, lon, city, city_id, postal_code, country, days, units, lang, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_forecast_daily(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/forecast/daily".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city_id") {
query_pairs.push(("city_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("days") {
query_pairs.push(("days", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lang") {
query_pairs.push(("lang", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /forecast/daily failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadForecastHourlyActor,
inports::<100>(lat, lon, city, city_id, postal_code, country, hours, units, lang, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_forecast_hourly(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/forecast/hourly".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city_id") {
query_pairs.push(("city_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("hours") {
query_pairs.push(("hours", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lang") {
query_pairs.push(("lang", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /forecast/hourly failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadForecastMinutelyActor,
inports::<100>(lat, lon, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_forecast_minutely(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/forecast/minutely".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /forecast/minutely failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadForecastAirQualityActor,
inports::<100>(lat, lon, city, city_id, postal_code, country, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_forecast_air_quality(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/forecast/airquality".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city_id") {
query_pairs.push(("city_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("key") {
query_pairs.push(("key", 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 /forecast/airquality failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadForecastEnergyActor,
inports::<100>(lat, lon, city, postal_code, country, tp, threshold, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_forecast_energy(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/forecast/energy".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("tp") {
query_pairs.push(("tp", super::message_to_str(val)));
}
if let Some(val) = inputs.get("threshold") {
query_pairs.push(("threshold", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /forecast/energy failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadForecastAgweatherActor,
inports::<100>(lat, lon, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_forecast_agweather(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/forecast/agweather".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /forecast/agweather failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadHistoryDailyActor,
inports::<100>(lat, lon, city, city_id, postal_code, country, start_date, end_date, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_history_daily(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/history/daily".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city_id") {
query_pairs.push(("city_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("start_date") {
query_pairs.push(("start_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("end_date") {
query_pairs.push(("end_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /history/daily failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadHistoryHourlyActor,
inports::<100>(lat, lon, city, city_id, postal_code, country, start_date, end_date, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_history_hourly(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/history/hourly".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city_id") {
query_pairs.push(("city_id", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("start_date") {
query_pairs.push(("start_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("end_date") {
query_pairs.push(("end_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /history/hourly failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadHistorySubhourlyActor,
inports::<100>(lat, lon, city, start_date, end_date, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_history_subhourly(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/history/subhourly".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("start_date") {
query_pairs.push(("start_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("end_date") {
query_pairs.push(("end_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /history/subhourly failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadHistoryAirQualityActor,
inports::<100>(lat, lon, city, postal_code, country, start_date, end_date, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_history_air_quality(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/history/airquality".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("start_date") {
query_pairs.push(("start_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("end_date") {
query_pairs.push(("end_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /history/airquality failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadHistoryEnergyActor,
inports::<100>(lat, lon, city, postal_code, country, start_date, end_date, threshold, tp, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_history_energy(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/history/energy".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("start_date") {
query_pairs.push(("start_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("end_date") {
query_pairs.push(("end_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("threshold") {
query_pairs.push(("threshold", super::message_to_str(val)));
}
if let Some(val) = inputs.get("tp") {
query_pairs.push(("tp", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /history/energy failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadHistoryAgweatherActor,
inports::<100>(lat, lon, start_date, end_date, tp, units, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_history_agweather(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/history/agweather".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("start_date") {
query_pairs.push(("start_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("end_date") {
query_pairs.push(("end_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("tp") {
query_pairs.push(("tp", super::message_to_str(val)));
}
if let Some(val) = inputs.get("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /history/agweather failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadHistoryLightningActor,
inports::<100>(lat, lon, radius, start_date, end_date, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_history_lightning(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/history/lightning".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("radius") {
query_pairs.push(("radius", super::message_to_str(val)));
}
if let Some(val) = inputs.get("start_date") {
query_pairs.push(("start_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("end_date") {
query_pairs.push(("end_date", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /history/lightning failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadClimateNormalsActor,
inports::<100>(lat, lon, city, postal_code, country, units, tp, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_climate_normals(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/normals".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("lat") {
query_pairs.push(("lat", super::message_to_str(val)));
}
if let Some(val) = inputs.get("lon") {
query_pairs.push(("lon", super::message_to_str(val)));
}
if let Some(val) = inputs.get("city") {
query_pairs.push(("city", super::message_to_str(val)));
}
if let Some(val) = inputs.get("postal_code") {
query_pairs.push(("postal_code", 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("units") {
query_pairs.push(("units", super::message_to_str(val)));
}
if let Some(val) = inputs.get("tp") {
query_pairs.push(("tp", super::message_to_str(val)));
}
if let Some(val) = inputs.get("key") {
query_pairs.push(("key", 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 /normals failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadGeocodingActor,
inports::<100>(q, country, key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_geocoding(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/geocoding/search".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("q") {
query_pairs.push(("q", 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("key") {
query_pairs.push(("key", 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/search failed: {}", e).into()),
);
}
}
Ok(output)
}
#[actor(
WeatherbitReadSubscriptionUsageActor,
inports::<100>(key),
outports::<50>(response, error),
state(MemoryState)
)]
pub async fn weatherbit_read_subscription_usage(
context: ActorContext,
) -> Result<HashMap<String, Message>, Error> {
let inputs = context.get_payload();
let actor_config = context.get_config();
let endpoint = "/subscription/usage".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("key") {
query_pairs.push(("key", 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 /subscription/usage failed: {}", e).into()),
);
}
}
Ok(output)
}