Files
nap/src/main.rs

119 lines
3.3 KiB
Rust

mod manifest;
mod repo;
use crate::manifest::Manifest;
use crate::repo::Repo;
use anyhow::{anyhow, bail, Result};
use clap::Parser;
use config::{Config, File, FileSourceFile};
use log::info;
use nostr_sdk::prelude::Coordinate;
use nostr_sdk::{Client, EventBuilder, JsonUtil, Keys, Kind, Tag};
use std::path::PathBuf;
#[derive(clap::Parser)]
#[command(version, about)]
struct Args {
/// User specified config path
#[arg(long, short)]
pub config: Option<PathBuf>,
/// Relay to publish events to
#[arg(long)]
pub relay: Vec<String>,
}
#[tokio::main]
async fn main() -> Result<()> {
// Set default log level to info
if std::env::var("RUST_LOG").is_err() {
std::env::set_var("RUST_LOG", "info");
}
env_logger::init();
let args = Args::parse();
let manifest: Manifest = Config::builder()
.add_source(File::from(args.config.unwrap_or(PathBuf::from("nap.yaml"))))
.build()
.map_err(|e| anyhow!("Failed to load config: {}", e))?
.try_deserialize()?;
let repo: Box<dyn Repo> = (&manifest).try_into()?;
let releases = repo.get_releases().await?;
info!("Found {} release(s)", releases.len());
if let Some(release) = releases.first() {
info!("Starting publish of release {}", release.version);
info!("Artifacts: ");
for a in &release.artifacts {
info!(" - {}", a);
}
if !dialoguer::Confirm::new()
.default(false)
.with_prompt(format!("Publish v{}?", release.version))
.interact()?
{
return Ok(());
}
let key = dialoguer::Password::new()
.with_prompt("Enter nsec:")
.interact()?;
let key = if let Ok(nsec) = Keys::parse(&key) {
nsec
} else {
bail!("Invalid private key")
};
let ev: EventBuilder = (&manifest).into();
let app_id = release.app_id()?;
let app_coord = Coordinate::new(Kind::Custom(32_267), key.public_key).identifier(app_id);
// create release
let release_list = release
.clone()
.into_release_list_event(&key, app_coord)
.await?;
let release_coord = Coordinate::new(Kind::Custom(30_063), key.public_key)
.identifier(release.release_tag()?);
// publish application
let app_ev = ev
.tag(Tag::coordinate(release_coord))
.tags(
release
.artifacts
.iter()
.filter_map(|a| Tag::parse(["f", a.platform.to_string().as_str()]).ok()),
)
.sign_with_keys(&key)?;
info!("Publishing events..");
let client = Client::builder().build();
for r in &args.relay {
info!("Connecting to {}", r);
client.add_relay(r).await?;
}
if args.relay.is_empty() {
const DEFAULT_RELAY: &'static str = "wss://relay.zapstore.dev";
info!("Connecting to default relay {DEFAULT_RELAY}");
client.add_relay(DEFAULT_RELAY).await?;
}
client.connect().await;
client.send_event(app_ev).await?;
for ev in release_list {
client.send_event(ev).await?;
}
info!("Done.");
}
Ok(())
}