refactor
This commit is contained in:
@@ -1,44 +1,13 @@
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use nostr::prelude::*;
|
||||
|
||||
/// Address of a NIP-34 repository announcement: `30617:<owner-pubkey>:<repo-id>`.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct RepoAddr {
|
||||
pub owner: PublicKey,
|
||||
pub id: String,
|
||||
}
|
||||
|
||||
impl RepoAddr {
|
||||
pub fn new(owner: PublicKey, id: impl Into<String>) -> Self {
|
||||
Self {
|
||||
owner,
|
||||
id: id.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// The NIP-33 coordinate for the announcement event (`a` tag value).
|
||||
pub fn coordinate(&self) -> Coordinate {
|
||||
Coordinate::new(Kind::GitRepoAnnouncement, self.owner).identifier(self.id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for RepoAddr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.coordinate())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for RepoAddr {
|
||||
type Err = nostr::error::Error;
|
||||
|
||||
/// Parse from `<kind>:<pubkey>:<d-tag>`, `naddr1...` bech32 or `nostr:naddr1...` URI.
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let coordinate = Coordinate::parse(s)?;
|
||||
Ok(Self {
|
||||
owner: coordinate.public_key,
|
||||
id: coordinate.identifier,
|
||||
})
|
||||
}
|
||||
///
|
||||
/// The Rust Nostr SDK's [`Coordinate`] already provides parsing, formatting
|
||||
/// and hashing for this; the alias keeps the repository-specific vocabulary
|
||||
/// while reusing the SDK type.
|
||||
pub type RepoAddr = Coordinate;
|
||||
|
||||
/// Build the address of a NIP-34 repository announcement.
|
||||
pub fn repo_addr(owner: PublicKey, id: impl Into<String>) -> RepoAddr {
|
||||
Coordinate::new(Kind::GitRepoAnnouncement, owner).identifier(id)
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
use nostr::prelude::*;
|
||||
|
||||
/// Build a NIP-34 user grasp list (kind `10317`).
|
||||
pub fn grasp_list(grasp_servers: Vec<RelayUrl>) -> EventBuilder {
|
||||
GitUserGraspList { grasp_servers }.into_event_builder()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn grasp_list_tags() {
|
||||
let servers = vec![
|
||||
RelayUrl::parse("wss://gitnostr.com").unwrap(),
|
||||
RelayUrl::parse("wss://relay.ngit.dev").unwrap(),
|
||||
];
|
||||
|
||||
let builder = grasp_list(servers);
|
||||
|
||||
let urls: Vec<&str> = builder
|
||||
.tags
|
||||
.iter()
|
||||
.filter_map(|t| t.content())
|
||||
.collect();
|
||||
|
||||
assert_eq!(urls, vec!["wss://gitnostr.com", "wss://relay.ngit.dev"]);
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,7 @@ pub fn parse_clone_url(url: &str) -> Option<CloneTarget> {
|
||||
|
||||
if first.starts_with("naddr1") {
|
||||
let coordinate = Nip19Coordinate::from_bech32(first).ok()?;
|
||||
return Some(CloneTarget::Addr(RepoAddr::new(
|
||||
coordinate.coordinate.public_key,
|
||||
coordinate.coordinate.identifier,
|
||||
)));
|
||||
return Some(CloneTarget::Addr(coordinate.coordinate));
|
||||
}
|
||||
|
||||
let (relay_hint, identifier) = match third {
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
use nostr::filter::{Alphabet, SingleLetterTag};
|
||||
use nostr::prelude::*;
|
||||
|
||||
use crate::RepoAddr;
|
||||
@@ -19,16 +18,16 @@ pub const ACTIVITY_KINDS: [Kind; 8] = [
|
||||
pub fn announcement(addr: &RepoAddr) -> Filter {
|
||||
Filter::new()
|
||||
.kind(Kind::GitRepoAnnouncement)
|
||||
.author(addr.owner)
|
||||
.identifier(addr.id.clone())
|
||||
.author(addr.public_key)
|
||||
.identifier(addr.identifier.clone())
|
||||
}
|
||||
|
||||
/// Latest state event (refs / HEAD) for a repository.
|
||||
pub fn state(addr: &RepoAddr) -> Filter {
|
||||
Filter::new()
|
||||
.kind(Kind::RepoState)
|
||||
.author(addr.owner)
|
||||
.identifier(addr.id.clone())
|
||||
.author(addr.public_key)
|
||||
.identifier(addr.identifier.clone())
|
||||
}
|
||||
|
||||
/// All NIP-34 activity addressed to a repository (`#a` tag).
|
||||
@@ -36,9 +35,7 @@ pub fn state(addr: &RepoAddr) -> Filter {
|
||||
/// Note: the `a` tag on status events is optional per NIP-34, so statuses
|
||||
/// published without it won't be matched here.
|
||||
pub fn activity(addr: &RepoAddr) -> Filter {
|
||||
Filter::new()
|
||||
.kinds(ACTIVITY_KINDS)
|
||||
.custom_tag(SingleLetterTag::lowercase(Alphabet::A), addr.to_string())
|
||||
Filter::new().kinds(ACTIVITY_KINDS).coordinate(addr)
|
||||
}
|
||||
|
||||
/// Status events (`1630..=1633`) referencing a specific root event (`#e` tag).
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
pub mod addr;
|
||||
pub mod builders;
|
||||
pub mod clone_url;
|
||||
pub mod filters;
|
||||
pub mod model;
|
||||
pub mod status;
|
||||
|
||||
pub use addr::RepoAddr;
|
||||
pub use addr::{RepoAddr, repo_addr};
|
||||
pub use clone_url::{CloneTarget, parse_clone_url};
|
||||
pub use model::Announcement;
|
||||
pub use status::{RepoStatus, references_root, resolve_status};
|
||||
|
||||
@@ -40,27 +40,24 @@ impl Announcement {
|
||||
let mut maintainers: Vec<PublicKey> = Vec::new();
|
||||
|
||||
for tag in event.tags.iter() {
|
||||
let values: &[String] = tag.as_slice();
|
||||
match tag.kind() {
|
||||
"d" => id = tag.content().map(str::to_owned),
|
||||
"name" => name = tag.content().map(str::to_owned),
|
||||
"description" => description = tag.content().map(str::to_owned),
|
||||
"web" => web.extend(values.iter().skip(1).cloned()),
|
||||
"clone" => clone.extend(values.iter().skip(1).cloned()),
|
||||
"relays" => relays.extend(values.iter().skip(1).cloned()),
|
||||
"r" => {
|
||||
if values.get(2).map(String::as_str) == Some("euc") {
|
||||
euc = tag.content().map(str::to_owned);
|
||||
}
|
||||
// The `d` tag isn't part of the NIP-34 tag codec; parse it directly.
|
||||
if tag.kind() == "d" {
|
||||
id = tag.content().map(str::to_owned);
|
||||
continue;
|
||||
}
|
||||
|
||||
match Nip34Tag::parse(tag.as_slice()) {
|
||||
Ok(Nip34Tag::Name(value)) => name = Some(value),
|
||||
Ok(Nip34Tag::Description(value)) => description = Some(value),
|
||||
Ok(Nip34Tag::Web(urls)) => web.extend(urls.into_iter().map(|url| url.to_string())),
|
||||
Ok(Nip34Tag::Clone(urls)) => {
|
||||
clone.extend(urls.into_iter().map(|url| url.to_string()))
|
||||
}
|
||||
"maintainers" => {
|
||||
maintainers.extend(
|
||||
values
|
||||
.iter()
|
||||
.skip(1)
|
||||
.filter_map(|v| PublicKey::from_hex(v).ok()),
|
||||
);
|
||||
Ok(Nip34Tag::Relays(urls)) => {
|
||||
relays.extend(urls.into_iter().map(|url| url.to_string()))
|
||||
}
|
||||
Ok(Nip34Tag::EarliestUniqueCommitId(commit)) => euc = Some(commit.to_string()),
|
||||
Ok(Nip34Tag::Maintainers(keys)) => maintainers.extend(keys),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +78,6 @@ impl Announcement {
|
||||
|
||||
/// The repository address of this announcement.
|
||||
pub fn addr(&self) -> crate::RepoAddr {
|
||||
crate::RepoAddr::new(self.owner, self.id.clone())
|
||||
crate::repo_addr(self.owner, self.id.clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,7 @@ impl RepoStatus {
|
||||
|
||||
/// Check whether a status event references the given root event via an `e` tag.
|
||||
pub fn references_root(event: &Event, root: &EventId) -> bool {
|
||||
let root_hex: String = root.to_hex();
|
||||
event
|
||||
.tags
|
||||
.iter()
|
||||
.any(|t| t.kind() == "e" && t.content() == Some(root_hex.as_str()))
|
||||
event.tags.event_ids().any(|id| id == *root)
|
||||
}
|
||||
|
||||
/// Resolve the status of a root event per NIP-34:
|
||||
|
||||
Reference in New Issue
Block a user