sneakerweb 1.0.0

A parallel web transported by physical media
use crate::util::*;
use anyhow::{Context, Result};
use clap::Args;
use smol::{
    fs::OpenOptions,
    io::{AsyncBufReadExt, AsyncWriteExt, BufReader},
};
use willow25::{prelude::*, storage::*};

#[derive(Args)]
pub struct BlockArgs {
    /// The sneakerweb domain to block.
    pub domain: String,
}

pub async fn block(args: &BlockArgs) -> Result<()> {
    let (domain, _) = get_domain(Some(&args.domain), "block")?;
    let sneakerweb_fs_path = sneakerweb_dir().await?;

    let mut store = PersistentStore::new(&sneakerweb_fs_path)
        .await
        .context("could not open sneakerweb storage")?;

    match store
        .forget_area(
            &NamespaceId::from_bytes(&SNEAKERWEB_NAMESPACE_ID_BYTES),
            &Area::new_subspace_area(domain),
        )
        .await
    {
        Ok(_) => {
            yay(&format!(
                "forgot entries for domain {}",
                domain_style(&args.domain)
            ))
            .await
        }
        Err(_) => {
            oh_no(&format!(
                "failed to forget sneakerweb entries for domain {}",
                domain_style(&args.domain)
            ))
            .await
        }
    }

    let blocklist_path = sneakerweb_fs_path.join("blocked");
    let blocklist = OpenOptions::new()
        .create(true)
        .read(true)
        .write(true)
        .open(blocklist_path)
        .await
        .context(
            "could neither create nor open 'blocked' file in the sneakerweb config directory",
        )?;

    let mut blocklist = BufReader::new(blocklist);

    let mut line = String::new();
    while let Ok(n) = blocklist.read_line(&mut line).await
        && n > 0
    {
        if line
            .split_ascii_whitespace()
            .next()
            .is_some_and(|domain| domain == &args.domain)
        {
            hmm(&format!(
                "domain {} is already in your list of blocked domains",
                domain_style(&args.domain)
            ))
            .await;
            return Ok(());
        }
        line.clear();
    }

    blocklist
        .write_all(format!("{}\n", args.domain).as_bytes())
        .await?;
    yay("updated list of blocked domains").await;
    Ok(())
}