use crate::{
serve::domain_is_empty,
util::{
BASE32_ALPHABET, SNEAKERWEB_NAMESPACE_ID_BYTES, domain_style, secret_style, sneakerweb_dir,
},
};
use anyhow::Result;
use clap::{Args, Subcommand};
use rand::rngs::OsRng;
use std::path::PathBuf;
use ufotofu::IntoConsumer;
use willow25::{
entry::{NamespaceId, randomly_generate_subspace},
storage::PersistentStore,
};
#[derive(Args)]
pub struct DomainArgs {
#[command(subcommand)]
pub command: Option<DomainCommands>,
}
#[derive(Subcommand)]
pub enum DomainCommands {
List(ListArgs),
}
#[derive(Args)]
pub struct ListArgs {
#[arg(long)]
pub show_empty: bool,
#[arg(short, long)]
collection: Option<PathBuf>,
}
pub fn generate_domain(_args: &DomainArgs) {
let mut csprng = OsRng;
let (subspace_id, subspace_secret) = randomly_generate_subspace(&mut csprng);
let b32_id = base32::encode(BASE32_ALPHABET, subspace_id.as_bytes());
let b32_secret = base32::encode(BASE32_ALPHABET, subspace_secret.as_bytes());
println!("Domain: {}", domain_style(&b32_id));
println!("Secret: {}", secret_style(&b32_secret));
println!(
"{} It is the password for publishing to this domain.",
secret_style("Keep this secret somewhere safe."),
);
}
pub async fn list_domains(args: &ListArgs) -> Result<()> {
let sneakerweb_fs_path = sneakerweb_dir(args.collection.as_ref()).await?;
let mut store = PersistentStore::new(sneakerweb_fs_path).await?;
let namespace = NamespaceId::from_bytes(&SNEAKERWEB_NAMESPACE_ID_BYTES);
let mut subspace_consumer = vec![].into_consumer();
store.subspaces(&namespace, &mut subspace_consumer).await?;
for domain in Vec::from(subspace_consumer) {
if args.show_empty || !domain_is_empty(&mut store, &domain).await? {
println!("{}", base32::encode(BASE32_ALPHABET, domain.as_bytes()));
}
}
Ok(())
}