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());
}