feat: Enter repository as nip5
For example, `4rs.nl/n34` and `_@4rs.nl/n34` Signed-off-by: Awiteb <a@4rs.nl>
This commit is contained in:
@@ -39,10 +39,11 @@ use crate::{
|
|||||||
)
|
)
|
||||||
)]
|
)]
|
||||||
pub struct NewArgs {
|
pub struct NewArgs {
|
||||||
/// Repository address in `naddr` format.
|
/// Repository address in `naddr` format or `<nip5>/repo_id`. e.g.
|
||||||
|
/// `4rs.nl/n34` and `_@4rs.nl/n34`
|
||||||
///
|
///
|
||||||
/// If not provided, `n34` will look for a `nostr-address` file.
|
/// If not provided, `n34` will look for the `nostr-address` file.
|
||||||
#[arg(short, long, value_parser = parsers::repo_naddr)]
|
#[arg(value_name = "NADDR-OR-NIP05", long = "repo", value_parser = parsers::repo_naddr)]
|
||||||
naddr: Option<Nip19Coordinate>,
|
naddr: Option<Nip19Coordinate>,
|
||||||
/// Markdown content for the issue. Cannot be used together with the
|
/// Markdown content for the issue. Cannot be used together with the
|
||||||
/// `--editor` flag.
|
/// `--editor` flag.
|
||||||
|
|||||||
@@ -90,16 +90,17 @@ impl FromStr for NostrEvent {
|
|||||||
)]
|
)]
|
||||||
pub struct ReplyArgs {
|
pub struct ReplyArgs {
|
||||||
/// The issue, patch, or comment to reply to
|
/// The issue, patch, or comment to reply to
|
||||||
#[arg(long)]
|
#[arg(long, value_name = "nevent1-or-note1")]
|
||||||
to: NostrEvent,
|
to: NostrEvent,
|
||||||
/// Quote the replied-to event in the editor
|
/// Quote the replied-to event in the editor
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
quote_to: bool,
|
quote_to: bool,
|
||||||
/// Repository address in `naddr` format.
|
/// Repository address in `naddr` format or `<nip5>/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
|
/// If not provided, `n34` will look for the `nostr-address` file and if not
|
||||||
/// found, will get it from the root event if found.
|
/// 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<Nip19Coordinate>,
|
naddr: Option<Nip19Coordinate>,
|
||||||
/// The comment (cannot be used with --editor)
|
/// The comment (cannot be used with --editor)
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ use crate::{
|
|||||||
/// Arguments for the `repo view` command
|
/// Arguments for the `repo view` command
|
||||||
#[derive(Args, Debug)]
|
#[derive(Args, Debug)]
|
||||||
pub struct ViewArgs {
|
pub struct ViewArgs {
|
||||||
/// Repository address in `naddr` format.
|
/// Repository address in `naddr` format or `<nip5>/repo_id`. e.g.
|
||||||
|
/// `4rs.nl/n34` and `_@4rs.nl/n34`
|
||||||
///
|
///
|
||||||
/// If not provided, `n34` will look for a `nostr-address` file.
|
/// If not provided, `n34` will look for the `nostr-address` file.
|
||||||
#[arg(short, long, value_parser = parsers::repo_naddr)]
|
#[arg(value_name = "NADDR-OR-NIP05", long = "repo", value_parser = parsers::repo_naddr)]
|
||||||
naddr: Option<Nip19Coordinate>,
|
naddr: Option<Nip19Coordinate>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,17 +16,47 @@
|
|||||||
|
|
||||||
use nostr::{
|
use nostr::{
|
||||||
Kind,
|
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<Nip19Coordinate, String> {
|
||||||
|
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 for invalid formats, failed bech32 decoding, wrong event
|
||||||
/// Returns an error if:
|
/// kind.
|
||||||
/// - The bech32 decoding fails
|
pub fn repo_naddr(repo_address: &str) -> Result<Nip19Coordinate, String> {
|
||||||
/// - The naddr doesn't represent a Git repository announcement (kind != 30617)
|
if repo_address.contains("/") {
|
||||||
pub fn repo_naddr(naddr: &str) -> Result<Nip19Coordinate, String> {
|
let (nip5, repo_id) = repo_address.split_once("/").expect("There is a `/`");
|
||||||
let naddr = Nip19Coordinate::from_bech32(naddr).map_err(|err| err.to_string())?;
|
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 {
|
if naddr.kind != Kind::GitRepoAnnouncement {
|
||||||
return Err("The naddr is not repo announcement address".to_owned());
|
return Err("The naddr is not repo announcement address".to_owned());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user