swarm-scout 0.6.1

scout — a light, no-node client for reading content from Swarm: point at a gateway (or any Bee) and cat / get / bytes by reference.
Documentation
//! Local registry of shares the user has created, so they can be managed
//! by a short id instead of long hex refs. Stored at `~/.scout/shares.json`.

use std::fs;
use std::path::PathBuf;

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Default)]
pub struct Registry {
    pub shares: Vec<Share>,
}

#[derive(Serialize, Deserialize, Clone)]
pub struct Share {
    pub id: String,
    pub file: String,
    pub file_ref: String,
    pub history: String,
    pub grantee_ref: String,
    pub grantee_history: String,
    pub publisher: String,
    pub grantees: Vec<String>,
    pub ts: u64,
}

fn path() -> anyhow::Result<PathBuf> {
    let home = std::env::var("HOME").map_err(|_| anyhow::anyhow!("HOME not set"))?;
    let dir = PathBuf::from(home).join(".scout");
    fs::create_dir_all(&dir)?;
    Ok(dir.join("shares.json"))
}

pub fn load() -> Registry {
    path()
        .ok()
        .and_then(|p| fs::read(p).ok())
        .and_then(|b| serde_json::from_slice(&b).ok())
        .unwrap_or_default()
}

pub fn save(r: &Registry) -> anyhow::Result<()> {
    fs::write(path()?, serde_json::to_vec_pretty(r)?)?;
    Ok(())
}

impl Registry {
    pub fn find(&self, id: &str) -> Option<&Share> {
        self.shares.iter().find(|s| s.id == id)
    }
    pub fn find_mut(&mut self, id: &str) -> Option<&mut Share> {
        self.shares.iter_mut().find(|s| s.id == id)
    }
}

pub fn now_secs() -> u64 {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .map(|d| d.as_secs())
        .unwrap_or(0)
}