From de68d61c3f65f55c8a3d882433519d37926c573a Mon Sep 17 00:00:00 2001 From: Awiteb Date: Sat, 24 May 2025 11:00:37 +0000 Subject: [PATCH] feat: Enter repository as nip5 For example, `4rs.nl/n34` and `_@4rs.nl/n34` Signed-off-by: Awiteb --- src/cli/commands/issue/new.rs | 7 +++--- src/cli/commands/reply.rs | 7 +++--- src/cli/commands/repo/view.rs | 7 +++--- src/cli/parsers.rs | 46 +++++++++++++++++++++++++++++------ 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/src/cli/commands/issue/new.rs b/src/cli/commands/issue/new.rs index 41e9b58..84aa217 100644 --- a/src/cli/commands/issue/new.rs +++ b/src/cli/commands/issue/new.rs @@ -39,10 +39,11 @@ use crate::{ ) )] pub struct NewArgs { - /// Repository address in `naddr` format. + /// Repository address in `naddr` format or `/repo_id`. e.g. + /// `4rs.nl/n34` and `_@4rs.nl/n34` /// - /// If not provided, `n34` will look for a `nostr-address` file. - #[arg(short, long, value_parser = parsers::repo_naddr)] + /// If not provided, `n34` will look for the `nostr-address` file. + #[arg(value_name = "NADDR-OR-NIP05", long = "repo", value_parser = parsers::repo_naddr)] naddr: Option, /// Markdown content for the issue. Cannot be used together with the /// `--editor` flag. diff --git a/src/cli/commands/reply.rs b/src/cli/commands/reply.rs index e7e1342..3b88a05 100644 --- a/src/cli/commands/reply.rs +++ b/src/cli/commands/reply.rs @@ -90,16 +90,17 @@ impl FromStr for NostrEvent { )] pub struct ReplyArgs { /// The issue, patch, or comment to reply to - #[arg(long)] + #[arg(long, value_name = "nevent1-or-note1")] to: NostrEvent, /// Quote the replied-to event in the editor #[arg(long)] quote_to: bool, - /// Repository address in `naddr` format. + /// Repository address in `naddr` format or `/repo_id`. e.g. + /// `4rs.nl/n34` and `_@4rs.nl/n34` /// /// If not provided, `n34` will look for the `nostr-address` file and if not /// found, will get it from the root event if found. - #[arg(short, long, value_parser = parsers::repo_naddr)] + #[arg(value_name = "NADDR-OR-NIP05", long = "repo", value_parser = parsers::repo_naddr)] naddr: Option, /// The comment (cannot be used with --editor) #[arg(short, long)] diff --git a/src/cli/commands/repo/view.rs b/src/cli/commands/repo/view.rs index ffbfa7b..b6100d2 100644 --- a/src/cli/commands/repo/view.rs +++ b/src/cli/commands/repo/view.rs @@ -28,10 +28,11 @@ use crate::{ /// Arguments for the `repo view` command #[derive(Args, Debug)] pub struct ViewArgs { - /// Repository address in `naddr` format. + /// Repository address in `naddr` format or `/repo_id`. e.g. + /// `4rs.nl/n34` and `_@4rs.nl/n34` /// - /// If not provided, `n34` will look for a `nostr-address` file. - #[arg(short, long, value_parser = parsers::repo_naddr)] + /// If not provided, `n34` will look for the `nostr-address` file. + #[arg(value_name = "NADDR-OR-NIP05", long = "repo", value_parser = parsers::repo_naddr)] naddr: Option, } diff --git a/src/cli/parsers.rs b/src/cli/parsers.rs index 782c7fd..09c2cc8 100644 --- a/src/cli/parsers.rs +++ b/src/cli/parsers.rs @@ -16,17 +16,47 @@ use nostr::{ Kind, - nips::nip19::{FromBech32, Nip19Coordinate}, + nips::{ + self, + nip01::Coordinate, + nip19::{FromBech32, Nip19Coordinate}, + }, }; +use tokio::runtime::Handle; -/// Parses a Nostr naddr string into a Git repository announcement coordinate. +fn parse_nip5_repo(nip5: &str, repo_id: &str) -> Result { + let (username, domain) = nip5.split_once("@").unwrap_or(("_", nip5)); + + let nip5_profile = tokio::task::block_in_place(|| { + Handle::current().block_on(async { + nips::nip05::profile(format!("{username}@{domain}"), None) + .await + .map_err(|err| err.to_string()) + }) + })?; + + Ok(Nip19Coordinate::new( + Coordinate::new(Kind::GitRepoAnnouncement, nip5_profile.public_key).identifier(repo_id), + nip5_profile.relays, + ) + .expect("The relays is `RelayUrl`")) +} + +/// Parses a Git repository address which can be either: +/// - A bech32-encoded naddr (e.g. "naddr1...") for Git repository announcements +/// (kind 30617) +/// - A NIP-05 identifier with repository ID (e.g. "4rs.nl/n34" or +/// "_@4rs.nl/n34") /// -/// # Errors -/// Returns an error if: -/// - The bech32 decoding fails -/// - The naddr doesn't represent a Git repository announcement (kind != 30617) -pub fn repo_naddr(naddr: &str) -> Result { - let naddr = Nip19Coordinate::from_bech32(naddr).map_err(|err| err.to_string())?; +/// Returns an error for invalid formats, failed bech32 decoding, wrong event +/// kind. +pub fn repo_naddr(repo_address: &str) -> Result { + if repo_address.contains("/") { + let (nip5, repo_id) = repo_address.split_once("/").expect("There is a `/`"); + return parse_nip5_repo(nip5, repo_id); + } + + let naddr = Nip19Coordinate::from_bech32(repo_address).map_err(|err| err.to_string())?; if naddr.kind != Kind::GitRepoAnnouncement { return Err("The naddr is not repo announcement address".to_owned()); }