relay-cli 0.1.2

CLI interface for Relay Agents.
use crate::{parsers::parse_address, progress::Progress, qrcode, storage::Storage};
use clap::Subcommand;
use relay_lib::prelude::Address;

#[derive(Debug, Clone, Subcommand)]
pub enum SubCmd {
    #[clap(about = "View identity details")]
    View {
        #[arg(value_parser = parse_address)]
        address: Address,
    },

    #[clap(about = "Export the identity")]
    Export {
        #[arg(value_parser = parse_address)]
        addresses: Vec<Address>,

        #[clap(long, help = "Print a QR code with the exported data")]
        qr: bool,
    },

    #[clap(about = "Import an identity")]
    Import {
        data: String,

        #[clap(short, long, help = "Replace existing identity if it exists")]
        replace: bool,
    },
}

#[derive(Debug, Clone, clap::Parser)]
#[clap(about = "Commands related to a specific identity")]
pub struct IdentityCmd {
    #[clap(subcommand)]
    pub subcmd: SubCmd,

    #[clap(short, long, default_value_t = false)]
    pub raw: bool,
}

impl IdentityCmd {
    pub fn execute(&self, storage: &mut Storage) -> anyhow::Result<()> {
        let mut progress = Progress::new(self.raw);
        progress.commit();

        let mut identities = storage.root.identities.values().collect::<Vec<_>>();
        identities.sort_by(|a, b| a.pub_record.id.cmp(&b.pub_record.id));

        match &self.subcmd {
            SubCmd::View { address } => {
                storage
                    .root
                    .get_identity(address)
                    .ok_or_else(|| {
                        progress.abort("No identity found for the given address");
                    })?
                    .print(0, &mut progress);
            }

            SubCmd::Export { addresses, qr } => {
                progress.nested_section(0, "Exporting Identities");
                for address in addresses.iter() {
                    storage
                        .root
                        .get_identity(address)
                        .ok_or_else(|| {
                            progress.abort("No identity found for the given address");
                        })?
                        .print(1, &mut progress);
                }

                let exported = storage.root.export(&mut progress, addresses)?;
                progress.commit();
                progress.arrow("Identities exported successfully");

                if *qr {
                    qrcode::print(exported);
                } else {
                    println!("{}", exported);
                }
            }

            SubCmd::Import { data, replace } => {
                let addresses = storage.root.import(&mut progress, data, *replace)?;
                progress.commit();
                progress.arrow("Identities imported successfully");
                for address in addresses.iter() {
                    storage
                        .root
                        .get_identity(address)
                        .ok_or_else(|| {
                            progress.abort("No identity found for the given address");
                        })?
                        .print(1, &mut progress);
                }
            }
        }

        Ok(())
    }
}