use std::fs;
use std::path::PathBuf;
use netsky_core::paths::handoff_archive_dir;
pub fn run(which: &str, limit: usize) -> netsky_core::Result<()> {
let dir = handoff_archive_dir();
if !dir.exists() {
println!(
"archive not present: {} (no restart since the archive-feature shipped)",
dir.display()
);
return Ok(());
}
let files = newest_first_jsons(&dir)?;
if files.is_empty() {
println!("(archive empty)");
return Ok(());
}
match which {
"list" => list(&files, limit),
"last" => dump(&files[0]),
s if s.chars().all(|c| c.is_ascii_digit()) => {
let idx: usize = s.parse()?;
if idx == 0 || idx > files.len() {
netsky_core::bail!("index {idx} out of range (have {} entries)", files.len());
}
dump(&files[idx - 1])
}
other => netsky_core::bail!("unknown selector '{other}' (use: list | last | <N>)"),
}
}
fn newest_first_jsons(dir: &PathBuf) -> netsky_core::Result<Vec<PathBuf>> {
let mut entries: Vec<(std::time::SystemTime, PathBuf)> = Vec::new();
for e in fs::read_dir(dir)? {
let e = e?;
let p = e.path();
if p.extension().and_then(|s| s.to_str()) != Some("json") {
continue;
}
let mtime = e.metadata()?.modified()?;
entries.push((mtime, p));
}
entries.sort_by(|a, b| b.0.cmp(&a.0));
Ok(entries.into_iter().map(|(_, p)| p).collect())
}
fn list(files: &[PathBuf], limit: usize) -> netsky_core::Result<()> {
for f in files.iter().take(limit) {
let md = fs::metadata(f)?;
let ts: chrono::DateTime<chrono::Utc> = md.modified()?.into();
let size = md.len();
let preview = preview_of(f).unwrap_or_else(|| "(preview unavailable)".to_string());
println!(
" {} {:>5}B {preview}",
ts.format("%Y-%m-%dT%H:%M:%SZ"),
size
);
}
Ok(())
}
fn dump(path: &PathBuf) -> netsky_core::Result<()> {
let content = fs::read_to_string(path)?;
match serde_json::from_str::<serde_json::Value>(&content) {
Ok(v) => println!("{}", serde_json::to_string_pretty(&v)?),
Err(_) => println!("{content}"),
}
Ok(())
}
fn preview_of(path: &PathBuf) -> Option<String> {
let content = fs::read_to_string(path).ok()?;
let v: serde_json::Value = serde_json::from_str(&content).ok()?;
let text = v.get("text")?.as_str()?;
let line: String = text.chars().take(70).collect::<String>().replace('\n', " ");
Some(line)
}