#[allow(unused_imports)]
use crate::*;
pub(crate) async fn notify(caller: Option<&str>, rest: &[String]) -> i32 {
const USAGE: &str = "usage: localharness notify [--as <me>] [--to <agent>] <title> [body...]";
let (to, rest) = match crate::util::take_value_flag(rest, "--to", USAGE) {
Ok(pair) => pair,
Err(e) => {
eprintln!("{e}");
return 2;
}
};
let Some(title) = rest.first().map(|s| s.trim()).filter(|s| !s.is_empty()) else {
eprintln!("{USAGE}");
return 2;
};
let body = rest[1..].join(" ").trim().to_string();
let signer = match load_signer(caller) {
Ok(s) => s,
Err(code) => return code,
};
crate::call::ensure_meter_funded(&signer).await;
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map(|d| d.as_secs())
.unwrap_or(0);
let token = registry::proxy_auth_token(&signer, now);
let endpoint = format!(
"{}/api/notify",
registry::CREDIT_PROXY_URL.trim_end_matches('/')
);
let mut payload = serde_json::json!({ "title": title, "body": body });
if let Some(target) = to.as_deref() {
payload["to"] = serde_json::Value::String(target.to_lowercase());
}
let resp = match reqwest::Client::new()
.post(&endpoint)
.header("content-type", "application/json")
.header("x-goog-api-key", token)
.json(&payload)
.send()
.await
{
Ok(r) => r,
Err(e) => {
eprintln!("notify failed: proxy unreachable ({e})");
return 1;
}
};
let status = resp.status();
let json: serde_json::Value = resp.json().await.unwrap_or_default();
if status.is_success() {
match to.as_deref() {
Some(target) => println!("notification sent to {target}'s inbox/device."),
None => println!("notification sent — check your device."),
}
return 0;
}
let msg = json
.get("error")
.and_then(|v| v.as_str())
.unwrap_or("unknown proxy error");
eprintln!("notify failed ({}): {msg}", status.as_u16());
if status.as_u16() == 404 && to.is_none() {
eprintln!(
"hint: open your subdomain in the app (admin → account → notifications → \
[enable notifications]) on the device you want buzzed, then retry."
);
}
1
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn notify_requires_a_title() {
assert_eq!(notify(None, &[]).await, 2);
assert_eq!(notify(None, &args(&[" "])).await, 2);
}
}