use crate::config;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PendingInboundPair {
pub peer_handle: String,
pub peer_did: String,
pub peer_card: Value,
pub peer_relay_url: String,
pub peer_slot_id: String,
pub peer_slot_token: String,
pub event_id: String,
pub event_timestamp: String,
pub received_at: String,
}
pub fn pending_inbound_dir() -> Result<PathBuf> {
Ok(config::state_dir()?.join("pending-inbound-pairs"))
}
fn pending_inbound_path(peer_handle: &str) -> Result<PathBuf> {
Ok(pending_inbound_dir()?.join(format!("{peer_handle}.json")))
}
pub fn write_pending_inbound(p: &PendingInboundPair) -> Result<()> {
let dir = pending_inbound_dir()?;
std::fs::create_dir_all(&dir)
.with_context(|| format!("creating {dir:?}"))?;
let path = pending_inbound_path(&p.peer_handle)?;
let body = serde_json::to_vec_pretty(p)?;
std::fs::write(&path, body)
.with_context(|| format!("writing pending-inbound record {path:?}"))?;
Ok(())
}
pub fn read_pending_inbound(peer_handle: &str) -> Result<Option<PendingInboundPair>> {
let path = pending_inbound_path(peer_handle)?;
if !path.exists() {
return Ok(None);
}
let body = std::fs::read(&path)
.with_context(|| format!("reading pending-inbound record {path:?}"))?;
let p: PendingInboundPair = serde_json::from_slice(&body)
.with_context(|| format!("parsing pending-inbound record {path:?}"))?;
Ok(Some(p))
}
pub fn list_pending_inbound() -> Result<Vec<PendingInboundPair>> {
let dir = pending_inbound_dir()?;
if !dir.exists() {
return Ok(Vec::new());
}
let mut entries: Vec<PendingInboundPair> = Vec::new();
for entry in std::fs::read_dir(&dir)?.flatten() {
let path = entry.path();
if path.extension().and_then(|x| x.to_str()) != Some("json") {
continue;
}
let body = match std::fs::read(&path) {
Ok(b) => b,
Err(_) => continue,
};
if let Ok(p) = serde_json::from_slice::<PendingInboundPair>(&body) {
entries.push(p);
}
}
entries.sort_by(|a, b| a.received_at.cmp(&b.received_at));
Ok(entries)
}
pub fn consume_pending_inbound(peer_handle: &str) -> Result<()> {
let path = pending_inbound_path(peer_handle)?;
if path.exists() {
std::fs::remove_file(&path)
.with_context(|| format!("deleting pending-inbound record {path:?}"))?;
}
Ok(())
}