upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/bin/ngit
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/ngit')
-rw-r--r--src/bin/ngit/sub_commands/issue_list.rs37
-rw-r--r--src/bin/ngit/sub_commands/list.rs40
2 files changed, 59 insertions, 18 deletions
diff --git a/src/bin/ngit/sub_commands/issue_list.rs b/src/bin/ngit/sub_commands/issue_list.rs
index 8f78d5e..29845ce 100644
--- a/src/bin/ngit/sub_commands/issue_list.rs
+++ b/src/bin/ngit/sub_commands/issue_list.rs
@@ -8,9 +8,9 @@ use ngit::{
8use nostr::{ 8use nostr::{
9 FromBech32, ToBech32, 9 FromBech32, ToBech32,
10 filter::{Alphabet, SingleLetterTag}, 10 filter::{Alphabet, SingleLetterTag},
11 nips::nip19::Nip19, 11 nips::nip19::{Nip19, Nip19Event},
12}; 12};
13use nostr_sdk::Kind; 13use nostr_sdk::{Kind, RelayUrl};
14 14
15use crate::{ 15use crate::{
16 client::{Client, Connect, fetching_with_report, get_repo_ref_from_cache}, 16 client::{Client, Connect, fetching_with_report, get_repo_ref_from_cache},
@@ -247,17 +247,20 @@ pub async fn launch(
247 } else { 247 } else {
248 vec![] 248 vec![]
249 }; 249 };
250 let relay_hint = repo_ref.relays.first();
250 return show_issue_details( 251 return show_issue_details(
251 &filtered, 252 &filtered,
252 event_id_or_nevent, 253 event_id_or_nevent,
253 json, 254 json,
254 show_comments, 255 show_comments,
255 &comments, 256 &comments,
257 relay_hint,
256 ); 258 );
257 } 259 }
258 260
261 let relay_hint = repo_ref.relays.first();
259 if json { 262 if json {
260 output_json(&filtered)?; 263 output_json(&filtered, relay_hint)?;
261 } else { 264 } else {
262 output_table(&filtered, &status, &label_filter); 265 output_table(&filtered, &status, &label_filter);
263 } 266 }
@@ -298,6 +301,7 @@ fn show_issue_details(
298 json: bool, 301 json: bool,
299 show_comments: bool, 302 show_comments: bool,
300 comments: &[nostr::Event], 303 comments: &[nostr::Event],
304 relay_hint: Option<&RelayUrl>,
301) -> Result<()> { 305) -> Result<()> {
302 let target_id = if event_id_or_nevent.starts_with("nevent") { 306 let target_id = if event_id_or_nevent.starts_with("nevent") {
303 let nip19 = Nip19::from_bech32(event_id_or_nevent).context("failed to parse nevent")?; 307 let nip19 = Nip19::from_bech32(event_id_or_nevent).context("failed to parse nevent")?;
@@ -323,9 +327,10 @@ fn show_issue_details(
323 let comments_json: Vec<serde_json::Value> = comments 327 let comments_json: Vec<serde_json::Value> = comments
324 .iter() 328 .iter()
325 .map(|c| { 329 .map(|c| {
326 let reply_to = comment_reply_to(c).map(|id| id.to_string()); 330 let reply_to =
331 comment_reply_to(c).map(|id| event_id_to_nevent(id, relay_hint));
327 serde_json::json!({ 332 serde_json::json!({
328 "id": c.id.to_string(), 333 "id": event_id_to_nevent(c.id, relay_hint),
329 "author": c.pubkey.to_bech32().unwrap_or_default(), 334 "author": c.pubkey.to_bech32().unwrap_or_default(),
330 "created_at": c.created_at.as_secs(), 335 "created_at": c.created_at.as_secs(),
331 "reply_to": reply_to, 336 "reply_to": reply_to,
@@ -334,7 +339,7 @@ fn show_issue_details(
334 }) 339 })
335 .collect(); 340 .collect();
336 serde_json::json!({ 341 serde_json::json!({
337 "id": issue.id.to_string(), 342 "id": event_id_to_nevent(issue.id, relay_hint),
338 "status": status, 343 "status": status,
339 "subject": title, 344 "subject": title,
340 "author": issue.pubkey.to_bech32().unwrap_or_default(), 345 "author": issue.pubkey.to_bech32().unwrap_or_default(),
@@ -345,7 +350,7 @@ fn show_issue_details(
345 }) 350 })
346 } else { 351 } else {
347 serde_json::json!({ 352 serde_json::json!({
348 "id": issue.id.to_string(), 353 "id": event_id_to_nevent(issue.id, relay_hint),
349 "status": status, 354 "status": status,
350 "subject": title, 355 "subject": title,
351 "author": issue.pubkey.to_bech32().unwrap_or_default(), 356 "author": issue.pubkey.to_bech32().unwrap_or_default(),
@@ -463,12 +468,26 @@ fn output_table(
463 println!(); 468 println!();
464} 469}
465 470
466fn output_json(issues: &[IssueRow<'_>]) -> Result<()> { 471/// Convert an event ID to a `nevent1…` bech32 string, including a relay hint
472/// when one is available. Falls back to the plain hex string on error.
473fn event_id_to_nevent(event_id: nostr::EventId, relay: Option<&RelayUrl>) -> String {
474 let relays = relay.map(|r| vec![r.clone()]).unwrap_or_default();
475 Nip19Event {
476 event_id,
477 relays,
478 author: None,
479 kind: None,
480 }
481 .to_bech32()
482 .unwrap_or_else(|_| event_id.to_hex())
483}
484
485fn output_json(issues: &[IssueRow<'_>], relay_hint: Option<&RelayUrl>) -> Result<()> {
467 let json_output: Vec<serde_json::Value> = issues 486 let json_output: Vec<serde_json::Value> = issues
468 .iter() 487 .iter()
469 .map(|(issue, status_kind, labels, comment_count, subject_override)| { 488 .map(|(issue, status_kind, labels, comment_count, subject_override)| {
470 serde_json::json!({ 489 serde_json::json!({
471 "id": issue.id.to_string(), 490 "id": event_id_to_nevent(issue.id, relay_hint),
472 "status": status_kind_to_str(*status_kind), 491 "status": status_kind_to_str(*status_kind),
473 "subject": get_issue_title(issue, subject_override.as_deref()), 492 "subject": get_issue_title(issue, subject_override.as_deref()),
474 "author": issue.pubkey.to_bech32().unwrap_or_default(), 493 "author": issue.pubkey.to_bech32().unwrap_or_default(),
diff --git a/src/bin/ngit/sub_commands/list.rs b/src/bin/ngit/sub_commands/list.rs
index df147bc..ee9840e 100644
--- a/src/bin/ngit/sub_commands/list.rs
+++ b/src/bin/ngit/sub_commands/list.rs
@@ -24,9 +24,9 @@ use ngit::{
24use nostr::{ 24use nostr::{
25 FromBech32, ToBech32, 25 FromBech32, ToBech32,
26 filter::{Alphabet, SingleLetterTag}, 26 filter::{Alphabet, SingleLetterTag},
27 nips::nip19::Nip19, 27 nips::nip19::{Nip19, Nip19Event},
28}; 28};
29use nostr_sdk::Kind; 29use nostr_sdk::{Kind, RelayUrl};
30 30
31use crate::{ 31use crate::{
32 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms}, 32 cli_interactor::{Interactor, InteractorPrompt, PromptChoiceParms, PromptConfirmParms},
@@ -246,6 +246,7 @@ pub async fn launch(
246 .await? 246 .await?
247 .len() 247 .len()
248 }; 248 };
249 let relay_hint = repo_ref.relays.first();
249 return show_proposal_details( 250 return show_proposal_details(
250 &filtered_proposals, 251 &filtered_proposals,
251 event_id_or_nevent, 252 event_id_or_nevent,
@@ -253,11 +254,13 @@ pub async fn launch(
253 show_comments, 254 show_comments,
254 comment_count, 255 comment_count,
255 &comments, 256 &comments,
257 relay_hint,
256 ); 258 );
257 } 259 }
258 260
261 let relay_hint = repo_ref.relays.first();
259 if json { 262 if json {
260 output_json(&filtered_proposals)?; 263 output_json(&filtered_proposals, relay_hint)?;
261 } else { 264 } else {
262 output_table(&filtered_proposals, &status, &label_filter); 265 output_table(&filtered_proposals, &status, &label_filter);
263 } 266 }
@@ -384,11 +387,28 @@ fn output_table(
384 ); 387 );
385} 388}
386 389
387fn output_json(proposals: &[(&nostr::Event, Kind, Vec<String>, Option<String>)]) -> Result<()> { 390/// Convert an event ID to a `nevent1…` bech32 string, including a relay hint
391/// when one is available. Falls back to the plain hex string on error.
392fn event_id_to_nevent(event_id: nostr::EventId, relay: Option<&RelayUrl>) -> String {
393 let relays = relay.map(|r| vec![r.clone()]).unwrap_or_default();
394 Nip19Event {
395 event_id,
396 relays,
397 author: None,
398 kind: None,
399 }
400 .to_bech32()
401 .unwrap_or_else(|_| event_id.to_hex())
402}
403
404fn output_json(
405 proposals: &[(&nostr::Event, Kind, Vec<String>, Option<String>)],
406 relay_hint: Option<&RelayUrl>,
407) -> Result<()> {
388 let json_output: Vec<serde_json::Value> = proposals 408 let json_output: Vec<serde_json::Value> = proposals
389 .iter() 409 .iter()
390 .map(|(proposal, status_kind, proposal_labels, subject_override)| { 410 .map(|(proposal, status_kind, proposal_labels, subject_override)| {
391 let id = proposal.id.to_string(); 411 let id = event_id_to_nevent(proposal.id, relay_hint);
392 let status = status_kind_to_str(*status_kind).to_string(); 412 let status = status_kind_to_str(*status_kind).to_string();
393 let (title, author, branch) = if let Ok(cl) = event_to_cover_letter(proposal) { 413 let (title, author, branch) = if let Ok(cl) = event_to_cover_letter(proposal) {
394 ( 414 (
@@ -460,6 +480,7 @@ fn show_proposal_details(
460 show_comments: bool, 480 show_comments: bool,
461 comment_count: usize, 481 comment_count: usize,
462 comments: &[nostr::Event], 482 comments: &[nostr::Event],
483 relay_hint: Option<&RelayUrl>,
463) -> Result<()> { 484) -> Result<()> {
464 use nostr::ToBech32; 485 use nostr::ToBech32;
465 486
@@ -484,9 +505,10 @@ fn show_proposal_details(
484 let comments_json: Vec<serde_json::Value> = comments 505 let comments_json: Vec<serde_json::Value> = comments
485 .iter() 506 .iter()
486 .map(|c| { 507 .map(|c| {
487 let reply_to = comment_reply_to(c).map(|id| id.to_string()); 508 let reply_to =
509 comment_reply_to(c).map(|id| event_id_to_nevent(id, relay_hint));
488 serde_json::json!({ 510 serde_json::json!({
489 "id": c.id.to_string(), 511 "id": event_id_to_nevent(c.id, relay_hint),
490 "author": c.pubkey.to_bech32().unwrap_or_default(), 512 "author": c.pubkey.to_bech32().unwrap_or_default(),
491 "created_at": c.created_at.as_secs(), 513 "created_at": c.created_at.as_secs(),
492 "reply_to": reply_to, 514 "reply_to": reply_to,
@@ -495,7 +517,7 @@ fn show_proposal_details(
495 }) 517 })
496 .collect(); 518 .collect();
497 serde_json::json!({ 519 serde_json::json!({
498 "id": proposal.id.to_string(), 520 "id": event_id_to_nevent(proposal.id, relay_hint),
499 "status": status_kind_to_str(*status_kind), 521 "status": status_kind_to_str(*status_kind),
500 "subject": display_title, 522 "subject": display_title,
501 "author": proposal.pubkey.to_bech32().unwrap_or_default(), 523 "author": proposal.pubkey.to_bech32().unwrap_or_default(),
@@ -507,7 +529,7 @@ fn show_proposal_details(
507 }) 529 })
508 } else { 530 } else {
509 serde_json::json!({ 531 serde_json::json!({
510 "id": proposal.id.to_string(), 532 "id": event_id_to_nevent(proposal.id, relay_hint),
511 "status": status_kind_to_str(*status_kind), 533 "status": status_kind_to_str(*status_kind),
512 "subject": display_title, 534 "subject": display_title,
513 "author": proposal.pubkey.to_bech32().unwrap_or_default(), 535 "author": proposal.pubkey.to_bech32().unwrap_or_default(),