From af016dd23101537ccc8ecd5a992bf3b7c6d3abe9 Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Wed, 4 Mar 2026 16:24:29 +0000 Subject: add NIP-21 content tags (q/p) to issues, comments, PRs and patches - parse nostr: URI mentions in issue bodies, comment bodies, PR descriptions, patch commit messages and cover letters - npub/nprofile mentions produce p tags; note/nevent/naddr mentions produce q tags per NIP-22 - naddr q tag value uses raw :: format - nevent pubkey field populated from embedded author or local cache lookup - dedup_tags() removes duplicate p tags and suppresses q tags whose event-id is already covered by an existing e threading tag - all parsing errors are non-fatal: invalid nostr: tokens are skipped --- src/bin/ngit/sub_commands/comment.rs | 66 +++++++++++++++++-------------- src/bin/ngit/sub_commands/issue_create.rs | 10 ++++- 2 files changed, 46 insertions(+), 30 deletions(-) (limited to 'src/bin/ngit/sub_commands') diff --git a/src/bin/ngit/sub_commands/comment.rs b/src/bin/ngit/sub_commands/comment.rs index c47a1f0..60626e5 100644 --- a/src/bin/ngit/sub_commands/comment.rs +++ b/src/bin/ngit/sub_commands/comment.rs @@ -4,6 +4,7 @@ use ngit::{ Params, get_events_from_local_cache, get_issues_from_cache, get_proposals_and_revisions_from_cache, send_events, sign_event, }, + content_tags::{dedup_tags, tags_from_content}, git_events::KIND_COMMENT, }; use nostr::{EventBuilder, Tag, nips::nip19::Nip19}; @@ -102,36 +103,43 @@ async fn publish_comment(args: CommentArgs<'_>) -> Result<()> { let root_kind_str = root_kind.as_u16().to_string(); let parent_kind_str = parent_kind.as_u16().to_string(); - // NIP-22 compliant tags + // NIP-22 compliant threading tags + let mut comment_tags: Vec = vec![ + // Root scope: uppercase E with root pubkey as 4th element + Tag::parse(vec![ + "E".to_string(), + root_event_id.to_hex(), + relay_hint.clone(), + root_pubkey.to_hex(), + ])?, + // Root kind + Tag::parse(vec!["K".to_string(), root_kind_str])?, + // Root author pubkey + Tag::parse(vec![ + "P".to_string(), + root_pubkey.to_hex(), + relay_hint.clone(), + ])?, + // Parent item: lowercase e with parent pubkey as 4th element + Tag::parse(vec![ + "e".to_string(), + parent_event_id.to_hex(), + relay_hint.clone(), + parent_pubkey.to_hex(), + ])?, + // Parent kind + Tag::parse(vec!["k".to_string(), parent_kind_str])?, + // Parent author pubkey + Tag::parse(vec!["p".to_string(), parent_pubkey.to_hex(), relay_hint])?, + ]; + + // NIP-21 mention tags: q tags for cited events/addresses, p tags for cited + // pubkeys + comment_tags.extend(tags_from_content(body, Some(git_repo_path)).await?); + let comment_tags = dedup_tags(comment_tags); + let comment_event = sign_event( - EventBuilder::new(KIND_COMMENT, body).tags(vec![ - // Root scope: uppercase E with root pubkey as 4th element - Tag::parse(vec![ - "E".to_string(), - root_event_id.to_hex(), - relay_hint.clone(), - root_pubkey.to_hex(), - ])?, - // Root kind - Tag::parse(vec!["K".to_string(), root_kind_str])?, - // Root author pubkey - Tag::parse(vec![ - "P".to_string(), - root_pubkey.to_hex(), - relay_hint.clone(), - ])?, - // Parent item: lowercase e with parent pubkey as 4th element - Tag::parse(vec![ - "e".to_string(), - parent_event_id.to_hex(), - relay_hint.clone(), - parent_pubkey.to_hex(), - ])?, - // Parent kind - Tag::parse(vec!["k".to_string(), parent_kind_str])?, - // Parent author pubkey - Tag::parse(vec!["p".to_string(), parent_pubkey.to_hex(), relay_hint])?, - ]), + EventBuilder::new(KIND_COMMENT, body).tags(comment_tags), &signer, format!("comment on {entity_name}"), ) diff --git a/src/bin/ngit/sub_commands/issue_create.rs b/src/bin/ngit/sub_commands/issue_create.rs index 0c4b677..4543823 100644 --- a/src/bin/ngit/sub_commands/issue_create.rs +++ b/src/bin/ngit/sub_commands/issue_create.rs @@ -1,5 +1,8 @@ use anyhow::{Context, Result, bail}; -use ngit::client::{Params, send_events, sign_event}; +use ngit::{ + client::{Params, send_events, sign_event}, + content_tags::{dedup_tags, tags_from_content}, +}; use nostr::{EventBuilder, Tag, TagStandard, ToBech32, nips::nip19::Nip19Event}; use nostr_sdk::Kind; @@ -74,6 +77,11 @@ pub async fn launch( tags.push(Tag::public_key(*pk)); } + // NIP-21 mention tags: q tags for cited events/addresses, p tags for cited + // pubkeys + tags.extend(tags_from_content(&body, Some(git_repo_path)).await?); + let tags = dedup_tags(tags); + let issue_event = sign_event( EventBuilder::new(Kind::GitIssue, body).tags(tags), &signer, -- cgit v1.2.3