upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.rs11
-rw-r--r--src/config.rs6
-rw-r--r--src/git.rs2
-rw-r--r--src/key_handling/encryption.rs12
-rw-r--r--src/key_handling/users.rs24
-rw-r--r--src/login.rs8
-rw-r--r--src/repo_ref.rs19
-rw-r--r--src/sub_commands/init.rs10
-rw-r--r--src/sub_commands/list.rs12
-rw-r--r--src/sub_commands/push.rs2
-rw-r--r--src/sub_commands/send.rs30
11 files changed, 81 insertions, 55 deletions
diff --git a/src/client.rs b/src/client.rs
index 539d45a..2dbd238 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -19,7 +19,7 @@ use indicatif::{MultiProgress, ProgressBar, ProgressState, ProgressStyle};
19#[cfg(test)] 19#[cfg(test)]
20use mockall::*; 20use mockall::*;
21use nostr::Event; 21use nostr::Event;
22use nostr_sdk::ClientSigner; 22use nostr_sdk::NostrSigner;
23 23
24#[allow(clippy::struct_field_names)] 24#[allow(clippy::struct_field_names)]
25pub struct Client { 25pub struct Client {
@@ -101,7 +101,7 @@ impl Connect for Client {
101 101
102 async fn set_keys(&mut self, keys: &nostr::Keys) { 102 async fn set_keys(&mut self, keys: &nostr::Keys) {
103 self.client 103 self.client
104 .set_signer(Some(ClientSigner::Keys(keys.clone()))) 104 .set_signer(Some(NostrSigner::Keys(keys.clone())))
105 .await; 105 .await;
106 } 106 }
107 107
@@ -124,8 +124,9 @@ impl Connect for Client {
124 124
125 async fn send_event_to(&self, url: &str, event: Event) -> Result<nostr::EventId> { 125 async fn send_event_to(&self, url: &str, event: Event) -> Result<nostr::EventId> {
126 self.client.add_relay(url).await?; 126 self.client.add_relay(url).await?;
127 #[allow(clippy::large_futures)]
127 self.client.connect_relay(url).await?; 128 self.client.connect_relay(url).await?;
128 Ok(self.client.send_event_to(url, event).await?) 129 Ok(self.client.send_event_to(vec![url], event).await?)
129 } 130 }
130 131
131 async fn get_events( 132 async fn get_events(
@@ -144,7 +145,7 @@ impl Connect for Client {
144 let m = MultiProgress::new(); 145 let m = MultiProgress::new();
145 let pb_style = ProgressStyle::with_template(" {spinner} {prefix} {msg} {timeout_in}")? 146 let pb_style = ProgressStyle::with_template(" {spinner} {prefix} {msg} {timeout_in}")?
146 .with_key("timeout_in", |state: &ProgressState, w: &mut dyn Write| { 147 .with_key("timeout_in", |state: &ProgressState, w: &mut dyn Write| {
147 if state.elapsed().as_secs() > 3 { 148 if state.elapsed().as_secs() > 3 && state.elapsed().as_secs() < GET_EVENTS_TIMEOUT {
148 write!( 149 write!(
149 w, 150 w,
150 "timeout in {:.1}s", 151 "timeout in {:.1}s",
@@ -200,6 +201,7 @@ impl Connect for Client {
200 } else { 201 } else {
201 None 202 None
202 }; 203 };
204 #[allow(clippy::large_futures)]
203 match get_events_of(relay, filters, &pb).await { 205 match get_events_of(relay, filters, &pb).await {
204 Err(error) => { 206 Err(error) => {
205 if let Some(pb) = pb { 207 if let Some(pb) = pb {
@@ -246,6 +248,7 @@ async fn get_events_of(
246 pb: &Option<ProgressBar>, 248 pb: &Option<ProgressBar>,
247) -> Result<Vec<Event>> { 249) -> Result<Vec<Event>> {
248 if !relay.is_connected().await { 250 if !relay.is_connected().await {
251 #[allow(clippy::large_futures)]
249 relay.connect(None).await; 252 relay.connect(None).await;
250 } 253 }
251 254
diff --git a/src/config.rs b/src/config.rs
index 2370e34..7fca446 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -4,7 +4,7 @@ use anyhow::{anyhow, Context, Result};
4use directories::ProjectDirs; 4use directories::ProjectDirs;
5#[cfg(test)] 5#[cfg(test)]
6use mockall::*; 6use mockall::*;
7use nostr::{secp256k1::XOnlyPublicKey, ToBech32}; 7use nostr::{PublicKey, ToBech32};
8use serde::{self, Deserialize, Serialize}; 8use serde::{self, Deserialize, Serialize};
9 9
10#[derive(Default)] 10#[derive(Default)]
@@ -69,7 +69,7 @@ pub struct MyConfig {
69 69
70#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)] 70#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
71pub struct UserRef { 71pub struct UserRef {
72 pub public_key: XOnlyPublicKey, 72 pub public_key: PublicKey,
73 pub encrypted_key: String, 73 pub encrypted_key: String,
74 pub metadata: UserMetadata, 74 pub metadata: UserMetadata,
75 pub relays: UserRelays, 75 pub relays: UserRelays,
@@ -77,7 +77,7 @@ pub struct UserRef {
77} 77}
78 78
79impl UserRef { 79impl UserRef {
80 pub fn new(public_key: XOnlyPublicKey, encrypted_key: String) -> Self { 80 pub fn new(public_key: PublicKey, encrypted_key: String) -> Self {
81 Self { 81 Self {
82 public_key, 82 public_key,
83 encrypted_key, 83 encrypted_key,
diff --git a/src/git.rs b/src/git.rs
index 86b59fb..77c1dcb 100644
--- a/src/git.rs
+++ b/src/git.rs
@@ -4,7 +4,7 @@ use std::{env::current_dir, path::Path};
4 4
5use anyhow::{bail, Context, Result}; 5use anyhow::{bail, Context, Result};
6use git2::{DiffOptions, Oid, Revwalk}; 6use git2::{DiffOptions, Oid, Revwalk};
7use nostr::prelude::{sha1::Hash as Sha1Hash, Hash}; 7use nostr_sdk::hashes::{sha1::Hash as Sha1Hash, Hash};
8 8
9use crate::sub_commands::list::{get_commit_id_from_patch, tag_value}; 9use crate::sub_commands::list::{get_commit_id_from_patch, tag_value};
10 10
diff --git a/src/key_handling/encryption.rs b/src/key_handling/encryption.rs
index 0ef7f69..54002fa 100644
--- a/src/key_handling/encryption.rs
+++ b/src/key_handling/encryption.rs
@@ -1,3 +1,5 @@
1use std::str::FromStr;
2
1use anyhow::{anyhow, bail, ensure, Context, Result}; 3use anyhow::{anyhow, bail, ensure, Context, Result};
2use chacha20poly1305::{ 4use chacha20poly1305::{
3 aead::{rand_core::RngCore, Aead, AeadCore, KeyInit, OsRng, Payload}, 5 aead::{rand_core::RngCore, Aead, AeadCore, KeyInit, OsRng, Payload},
@@ -6,6 +8,7 @@ use chacha20poly1305::{
6#[cfg(test)] 8#[cfg(test)]
7use mockall::*; 9use mockall::*;
8use nostr::{prelude::*, Keys}; 10use nostr::{prelude::*, Keys};
11use nostr_sdk::bech32::{self, FromBase32, ToBase32};
9use rand::{distributions::Alphanumeric, thread_rng, Rng}; 12use rand::{distributions::Alphanumeric, thread_rng, Rng};
10use zeroize::Zeroize; 13use zeroize::Zeroize;
11 14
@@ -120,10 +123,11 @@ impl EncryptDecrypt for Encryptor {
120 bail!("invalid encrypted key"); 123 bail!("invalid encrypted key");
121 } 124 }
122 125
123 let key = Keys::from_sk_str( 126 let key =
124 std::str::from_utf8(&inner_secret).context("inner secret is not [u8]")?, 127 Keys::from_str(std::str::from_utf8(&inner_secret).context("inner secret is not [u8]")?)
125 ) 128 .context(
126 .context("incorrect password. Key decrypted with password did not produce a valid nsec.")?; 129 "incorrect password. Key decrypted with password did not produce a valid nsec.",
130 )?;
127 131
128 inner_secret.zeroize(); 132 inner_secret.zeroize();
129 133
diff --git a/src/key_handling/users.rs b/src/key_handling/users.rs
index 2e88fba..1dd75a8 100644
--- a/src/key_handling/users.rs
+++ b/src/key_handling/users.rs
@@ -1,4 +1,4 @@
1use std::time::SystemTime; 1use std::{str::FromStr, time::SystemTime};
2 2
3use anyhow::{Context, Result}; 3use anyhow::{Context, Result};
4use async_trait::async_trait; 4use async_trait::async_trait;
@@ -32,13 +32,13 @@ pub trait UserManagement {
32 &self, 32 &self,
33 #[cfg(test)] client: &MockConnect, 33 #[cfg(test)] client: &MockConnect,
34 #[cfg(not(test))] client: &Client, 34 #[cfg(not(test))] client: &Client,
35 public_key: &XOnlyPublicKey, 35 public_key: &PublicKey,
36 after: u64, 36 after: u64,
37 ) -> Result<UserRef>; 37 ) -> Result<UserRef>;
38 fn get_user_from_cache(&self, public_key: &XOnlyPublicKey) -> Result<UserRef>; 38 fn get_user_from_cache(&self, public_key: &PublicKey) -> Result<UserRef>;
39 fn add_user_to_config( 39 fn add_user_to_config(
40 &self, 40 &self,
41 public_key: XOnlyPublicKey, 41 public_key: PublicKey,
42 encrypted_secret_key: Option<String>, 42 encrypted_secret_key: Option<String>,
43 overwrite: bool, 43 overwrite: bool,
44 ) -> Result<()>; 44 ) -> Result<()>;
@@ -59,7 +59,7 @@ impl UserManagement for UserManager {
59 .input(PromptInputParms::default().with_prompt(prompt)) 59 .input(PromptInputParms::default().with_prompt(prompt))
60 .context("failed to get nsec input from interactor")?, 60 .context("failed to get nsec input from interactor")?,
61 }; 61 };
62 match Keys::from_sk_str(&pk) { 62 match Keys::from_str(&pk) {
63 Ok(key) => { 63 Ok(key) => {
64 break key; 64 break key;
65 } 65 }
@@ -99,7 +99,7 @@ impl UserManagement for UserManager {
99 99
100 fn add_user_to_config( 100 fn add_user_to_config(
101 &self, 101 &self,
102 public_key: XOnlyPublicKey, 102 public_key: PublicKey,
103 encrypted_secret_key: Option<String>, 103 encrypted_secret_key: Option<String>,
104 overwrite: bool, 104 overwrite: bool,
105 ) -> Result<()> { 105 ) -> Result<()> {
@@ -129,7 +129,7 @@ impl UserManagement for UserManager {
129 .context("failed to save application configuration with new user details in") 129 .context("failed to save application configuration with new user details in")
130 } 130 }
131 131
132 fn get_user_from_cache(&self, public_key: &XOnlyPublicKey) -> Result<UserRef> { 132 fn get_user_from_cache(&self, public_key: &PublicKey) -> Result<UserRef> {
133 let cfg = self 133 let cfg = self
134 .config_manager 134 .config_manager
135 .load() 135 .load()
@@ -148,7 +148,7 @@ impl UserManagement for UserManager {
148 &self, 148 &self,
149 #[cfg(test)] client: &MockConnect, 149 #[cfg(test)] client: &MockConnect,
150 #[cfg(not(test))] client: &Client, 150 #[cfg(not(test))] client: &Client,
151 public_key: &XOnlyPublicKey, 151 public_key: &PublicKey,
152 use_cache_unless_checked_more_than_x_secs_ago: u64, 152 use_cache_unless_checked_more_than_x_secs_ago: u64,
153 ) -> Result<UserRef> { 153 ) -> Result<UserRef> {
154 let cfg = self 154 let cfg = self
@@ -249,7 +249,11 @@ impl UserManagement for UserManager {
249 relays: new_relays_event 249 relays: new_relays_event
250 .tags 250 .tags
251 .iter() 251 .iter()
252 .filter(|t| t.kind().eq(&nostr::TagKind::R)) 252 .filter(|t| {
253 t.kind().eq(&nostr::TagKind::SingleLetter(
254 SingleLetterTag::lowercase(Alphabet::R),
255 ))
256 })
253 .map(|t| UserRelayRef { 257 .map(|t| UserRelayRef {
254 url: t.as_vec()[1].clone(), 258 url: t.as_vec()[1].clone(),
255 read: t.as_vec().len() == 2 || t.as_vec()[2].eq("read"), 259 read: t.as_vec().len() == 2 || t.as_vec()[2].eq("read"),
@@ -471,7 +475,7 @@ mod tests {
471 .expect_encrypt_key() 475 .expect_encrypt_key()
472 .once() 476 .once()
473 .withf(|k, p| { 477 .withf(|k, p| {
474 k.eq(&Keys::from_sk_str(TEST_KEY_1_NSEC).unwrap()) && p.eq(TEST_PASSWORD) 478 k.eq(&Keys::from_str(TEST_KEY_1_NSEC).unwrap()) && p.eq(TEST_PASSWORD)
475 }) 479 })
476 .returning(|_, _| Ok(TEST_KEY_1_ENCRYPTED.into())); 480 .returning(|_, _| Ok(TEST_KEY_1_ENCRYPTED.into()));
477 481
diff --git a/src/login.rs b/src/login.rs
index b0fe230..4cdf3c1 100644
--- a/src/login.rs
+++ b/src/login.rs
@@ -1,5 +1,7 @@
1use std::str::FromStr;
2
1use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
2use nostr::{prelude::FromSkStr, secp256k1::XOnlyPublicKey}; 4use nostr::PublicKey;
3use zeroize::Zeroize; 5use zeroize::Zeroize;
4 6
5#[cfg(not(test))] 7#[cfg(not(test))]
@@ -25,7 +27,7 @@ pub async fn launch(
25 // if nsec parameter 27 // if nsec parameter
26 let key = if let Some(nsec_unwrapped) = nsec { 28 let key = if let Some(nsec_unwrapped) = nsec {
27 // get key or fail without prompts 29 // get key or fail without prompts
28 let key = nostr::Keys::from_sk_str(nsec_unwrapped).context("invalid nsec parameter")?; 30 let key = nostr::Keys::from_str(nsec_unwrapped).context("invalid nsec parameter")?;
29 31
30 // if password, add user to enable password login in future 32 // if password, add user to enable password login in future
31 if password.is_some() { 33 if password.is_some() {
@@ -91,7 +93,7 @@ pub async fn launch(
91} 93}
92 94
93async fn get_user_details( 95async fn get_user_details(
94 public_key: &XOnlyPublicKey, 96 public_key: &PublicKey,
95 #[cfg(test)] client: &crate::client::MockConnect, 97 #[cfg(test)] client: &crate::client::MockConnect,
96 #[cfg(not(test))] client: &Client, 98 #[cfg(not(test))] client: &Client,
97) -> Result<UserRef> { 99) -> Result<UserRef> {
diff --git a/src/repo_ref.rs b/src/repo_ref.rs
index c7b42fa..2dab79c 100644
--- a/src/repo_ref.rs
+++ b/src/repo_ref.rs
@@ -1,7 +1,7 @@
1use std::{fs::File, io::BufReader, str::FromStr}; 1use std::{fs::File, io::BufReader, str::FromStr};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use nostr::{nips::nip19::Nip19, secp256k1::XOnlyPublicKey, FromBech32, Tag, ToBech32}; 4use nostr::{nips::nip19::Nip19, FromBech32, PublicKey, Tag, ToBech32};
5use serde::{Deserialize, Serialize}; 5use serde::{Deserialize, Serialize};
6 6
7#[cfg(not(test))] 7#[cfg(not(test))]
@@ -23,7 +23,7 @@ pub struct RepoRef {
23 pub git_server: String, 23 pub git_server: String,
24 pub web: Vec<String>, 24 pub web: Vec<String>,
25 pub relays: Vec<String>, 25 pub relays: Vec<String>,
26 pub maintainers: Vec<XOnlyPublicKey>, 26 pub maintainers: Vec<PublicKey>,
27 // code languages and hashtags 27 // code languages and hashtags
28} 28}
29 29
@@ -78,7 +78,7 @@ impl TryFrom<nostr::Event> for RepoRef {
78 } 78 }
79 for pk in maintainers { 79 for pk in maintainers {
80 r.maintainers.push( 80 r.maintainers.push(
81 nostr_sdk::prelude::XOnlyPublicKey::from_str(&pk) 81 nostr_sdk::prelude::PublicKey::from_str(&pk)
82 .context(format!("cannot convert entry from maintainers tag {pk} into a valid nostr public key. it should be in hex format")) 82 .context(format!("cannot convert entry from maintainers tag {pk} into a valid nostr public key. it should be in hex format"))
83 .context("invalid repository event")?, 83 .context("invalid repository event")?,
84 ); 84 );
@@ -200,8 +200,9 @@ pub async fn fetch(
200 nostr::Filter::default().kind(nostr::Kind::Custom(REPO_REF_KIND)); 200 nostr::Filter::default().kind(nostr::Kind::Custom(REPO_REF_KIND));
201 match nip19 { 201 match nip19 {
202 Nip19::Coordinate(c) => { 202 Nip19::Coordinate(c) => {
203 repo_event_filter = 203 repo_event_filter = repo_event_filter
204 repo_event_filter.identifier(c.identifier).author(c.pubkey); 204 .identifier(c.identifier)
205 .author(c.public_key);
205 for r in c.relays { 206 for r in c.relays {
206 relays.push(r); 207 relays.push(r);
207 } 208 }
@@ -246,11 +247,11 @@ pub fn get_repo_config_from_yaml(git_repo: &Repo) -> Result<RepoConfigYaml> {
246 Ok(repo_config_yaml) 247 Ok(repo_config_yaml)
247} 248}
248 249
249pub fn extract_pks(pk_strings: Vec<String>) -> Result<Vec<XOnlyPublicKey>> { 250pub fn extract_pks(pk_strings: Vec<String>) -> Result<Vec<PublicKey>> {
250 let mut pks: Vec<XOnlyPublicKey> = vec![]; 251 let mut pks: Vec<PublicKey> = vec![];
251 for s in pk_strings { 252 for s in pk_strings {
252 pks.push( 253 pks.push(
253 nostr_sdk::prelude::XOnlyPublicKey::from_bech32(s.clone()) 254 nostr_sdk::prelude::PublicKey::from_bech32(s.clone())
254 .context(format!("cannot convert {s} into a valid nostr public key"))?, 255 .context(format!("cannot convert {s} into a valid nostr public key"))?,
255 ); 256 );
256 } 257 }
@@ -259,7 +260,7 @@ pub fn extract_pks(pk_strings: Vec<String>) -> Result<Vec<XOnlyPublicKey>> {
259 260
260pub fn save_repo_config_to_yaml( 261pub fn save_repo_config_to_yaml(
261 git_repo: &Repo, 262 git_repo: &Repo,
262 maintainers: Vec<XOnlyPublicKey>, 263 maintainers: Vec<PublicKey>,
263 relays: Vec<String>, 264 relays: Vec<String>,
264) -> Result<()> { 265) -> Result<()> {
265 let path = git_repo.get_path()?.join("maintainers.yaml"); 266 let path = git_repo.get_path()?.join("maintainers.yaml");
diff --git a/src/sub_commands/init.rs b/src/sub_commands/init.rs
index 4f098c0..56129a6 100644
--- a/src/sub_commands/init.rs
+++ b/src/sub_commands/init.rs
@@ -1,5 +1,5 @@
1use anyhow::{Context, Result}; 1use anyhow::{Context, Result};
2use nostr::{secp256k1::XOnlyPublicKey, FromBech32, ToBech32}; 2use nostr::{FromBech32, PublicKey, ToBech32};
3 3
4use super::send::send_events; 4use super::send::send_events;
5#[cfg(not(test))] 5#[cfg(not(test))]
@@ -163,7 +163,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
163 args.web.clone() 163 args.web.clone()
164 }; 164 };
165 165
166 let maintainers: Vec<XOnlyPublicKey> = { 166 let maintainers: Vec<PublicKey> = {
167 let mut dont_ask = !args.other_maintainers.is_empty(); 167 let mut dont_ask = !args.other_maintainers.is_empty();
168 let mut maintainers_string = if !args.other_maintainers.is_empty() { 168 let mut maintainers_string = if !args.other_maintainers.is_empty() {
169 [args.other_maintainers.clone()].concat().join(" ") 169 [args.other_maintainers.clone()].concat().join(" ")
@@ -185,7 +185,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
185 }; 185 };
186 // add current user if not present 186 // add current user if not present
187 if maintainers.iter().any(|m| { 187 if maintainers.iter().any(|m| {
188 if let Ok(m_pubkey) = XOnlyPublicKey::from_bech32(m) { 188 if let Ok(m_pubkey) = PublicKey::from_bech32(m) {
189 user_ref.public_key.eq(&m_pubkey) 189 user_ref.public_key.eq(&m_pubkey)
190 } else { 190 } else {
191 false 191 false
@@ -210,9 +210,9 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
210 .map(std::string::ToString::to_string) 210 .map(std::string::ToString::to_string)
211 .collect(); 211 .collect();
212 } 212 }
213 let mut maintainers: Vec<XOnlyPublicKey> = vec![]; 213 let mut maintainers: Vec<PublicKey> = vec![];
214 for m in maintainers_string.split(' ') { 214 for m in maintainers_string.split(' ') {
215 if let Ok(m_pubkey) = XOnlyPublicKey::from_bech32(m) { 215 if let Ok(m_pubkey) = PublicKey::from_bech32(m) {
216 maintainers.push(m_pubkey); 216 maintainers.push(m_pubkey);
217 } else { 217 } else {
218 println!("not a valid set of npubs seperated by a space"); 218 println!("not a valid set of npubs seperated by a space");
diff --git a/src/sub_commands/list.rs b/src/sub_commands/list.rs
index 2d81164..1a30b9b 100644
--- a/src/sub_commands/list.rs
+++ b/src/sub_commands/list.rs
@@ -730,9 +730,12 @@ pub async fn find_proposal_events(
730 vec![ 730 vec![
731 nostr::Filter::default() 731 nostr::Filter::default()
732 .kind(nostr::Kind::Custom(PATCH_KIND)) 732 .kind(nostr::Kind::Custom(PATCH_KIND))
733 .custom_tag(nostr::Alphabet::T, vec!["root"])
734 .custom_tag( 733 .custom_tag(
735 nostr::Alphabet::A, 734 nostr::SingleLetterTag::lowercase(nostr::Alphabet::T),
735 vec!["root"],
736 )
737 .custom_tag(
738 nostr::SingleLetterTag::lowercase(nostr::Alphabet::A),
736 repo_ref 739 repo_ref
737 .maintainers 740 .maintainers
738 .iter() 741 .iter()
@@ -742,7 +745,10 @@ pub async fn find_proposal_events(
742 // events 745 // events
743 nostr::Filter::default() 746 nostr::Filter::default()
744 .kind(nostr::Kind::Custom(PATCH_KIND)) 747 .kind(nostr::Kind::Custom(PATCH_KIND))
745 .custom_tag(nostr::Alphabet::T, vec!["root"]) 748 .custom_tag(
749 nostr::SingleLetterTag::lowercase(nostr::Alphabet::T),
750 vec!["root"],
751 )
746 .reference(root_commit), 752 .reference(root_commit),
747 ], 753 ],
748 ) 754 )
diff --git a/src/sub_commands/push.rs b/src/sub_commands/push.rs
index 651b250..bb50ee2 100644
--- a/src/sub_commands/push.rs
+++ b/src/sub_commands/push.rs
@@ -1,5 +1,5 @@
1use anyhow::{bail, Context, Result}; 1use anyhow::{bail, Context, Result};
2use nostr::prelude::sha1::Hash as Sha1Hash; 2use nostr_sdk::hashes::sha1::Hash as Sha1Hash;
3 3
4#[cfg(not(test))] 4#[cfg(not(test))]
5use crate::client::Client; 5use crate::client::Client;
diff --git a/src/sub_commands/send.rs b/src/sub_commands/send.rs
index 35c2c81..d9caf9b 100644
--- a/src/sub_commands/send.rs
+++ b/src/sub_commands/send.rs
@@ -5,9 +5,10 @@ use console::Style;
5use futures::future::join_all; 5use futures::future::join_all;
6use indicatif::{MultiProgress, ProgressBar, ProgressStyle}; 6use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
7use nostr::{ 7use nostr::{
8 nips::nip19::Nip19, prelude::sha1::Hash as Sha1Hash, EventBuilder, FromBech32, Marker, Tag, 8 nips::{nip01::Coordinate, nip19::Nip19},
9 TagKind, UncheckedUrl, 9 EventBuilder, FromBech32, Marker, Tag, TagKind, UncheckedUrl,
10}; 10};
11use nostr_sdk::hashes::sha1::Hash as Sha1Hash;
11 12
12use super::list::tag_value; 13use super::list::tag_value;
13#[cfg(not(test))] 14#[cfg(not(test))]
@@ -541,11 +542,13 @@ pub fn generate_cover_letter_and_patch_events(
541 vec![ 542 vec![
542 // TODO: why not tag all maintainer identifiers? 543 // TODO: why not tag all maintainer identifiers?
543 Tag::A { 544 Tag::A {
544 kind: nostr::Kind::Custom(REPO_REF_KIND), 545 coordinate: Coordinate {
545 public_key: *repo_ref.maintainers.first() 546 kind: nostr::Kind::Custom(REPO_REF_KIND),
546 .context("repo reference should always have at least one maintainer - the issuer of the repo event") 547 public_key: *repo_ref.maintainers.first()
547 ?, 548 .context("repo reference should always have at least one maintainer")?,
548 identifier: repo_ref.identifier.to_string(), 549 identifier: repo_ref.identifier.to_string(),
550 relays: repo_ref.relays.clone(),
551 },
549 relay_url: repo_ref.relays.first().map(nostr::UncheckedUrl::from).clone(), 552 relay_url: repo_ref.relays.first().map(nostr::UncheckedUrl::from).clone(),
550 }, 553 },
551 Tag::Reference(format!("{root_commit}")), 554 Tag::Reference(format!("{root_commit}")),
@@ -797,11 +800,14 @@ pub fn generate_patch_event(
797 [ 800 [
798 vec![ 801 vec![
799 Tag::A { 802 Tag::A {
800 kind: nostr::Kind::Custom(REPO_REF_KIND), 803 coordinate: Coordinate {
801 public_key: *repo_ref.maintainers.first() 804 kind: nostr::Kind::Custom(REPO_REF_KIND),
802 .context("repo reference should always have at least one maintainer - the issuer of the repo event") 805 public_key: *repo_ref.maintainers.first()
803 ?, 806 .context("repo reference should always have at least one maintainer - the issuer of the repo event")
804 identifier: repo_ref.identifier.to_string(), 807 ?,
808 identifier: repo_ref.identifier.to_string(),
809 relays: repo_ref.relays.clone(),
810 },
805 relay_url: relay_hint.clone(), 811 relay_url: relay_hint.clone(),
806 }, 812 },
807 Tag::Reference(format!("{root_commit}")), 813 Tag::Reference(format!("{root_commit}")),