use serde_json::Value;
use super::usage::{Fetch, HttpRequest, Quota};
pub const USAGE_PATH: &str = "/usage";
pub const GATEWAY_USAGE: &str = "gateway";
pub fn read_gateway_usage(body: &Value) -> Option<Quota> {
let entry = body.get("limiting")?.as_object()?;
if entry.get("status").and_then(Value::as_str) != Some("ok") {
return None;
}
let resets_text = entry.get("resetsAt").and_then(Value::as_str)?;
let resets_at: i64 = resets_text
.parse::<jiff::Timestamp>()
.ok()?
.as_millisecond();
if entry.get("spent").and_then(Value::as_bool) == Some(true) {
return Some(Quota {
percentage: 100.0,
resets_at: Some(resets_at),
});
}
let used = match entry.get("peakUsedPercent").and_then(Value::as_f64) {
Some(peak) => Some(peak),
None => entry
.get("remainingPercent")
.and_then(Value::as_f64)
.map(|remaining| 100.0 - remaining),
};
let used = used?;
Some(Quota {
percentage: used.clamp(0.0, 99.9),
resets_at: Some(resets_at),
})
}
pub async fn fetch_gateway_usage(
base_url: &str,
key: &str,
fetch: &impl Fetch,
timeout_ms: u64,
) -> Option<Quota> {
let base = base_url.strip_suffix('/').unwrap_or(base_url);
let response = fetch
.fetch(
format!("{base}{USAGE_PATH}"),
HttpRequest {
headers: vec![
("Authorization".to_owned(), format!("Bearer {key}")),
("Accept".to_owned(), "application/json".to_owned()),
],
timeout_ms,
},
)
.await
.ok()?;
if !response.ok() {
return None;
}
read_gateway_usage(&response.body?)
}
#[cfg(test)]
mod tests;