upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-07-24 16:37:10 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-07-24 16:37:10 +0100
commit8638b321fdff94d034ec912ecd0910b6f564ff04 (patch)
tree411e0ca989d8c53be5b11b39461297bf6a92d781
parent95cb9c040dfa8ca18bf907a44a86df35b316b6ca (diff)
refactor: use nip34 kinds from rust-nostr
instead of Kind::Custom(u16) as v33 of rust-nostr introduced them
-rw-r--r--src/client.rs26
-rw-r--r--src/repo_ref.rs16
-rw-r--r--src/sub_commands/init.rs4
-rw-r--r--src/sub_commands/list.rs69
-rw-r--r--src/sub_commands/send.rs30
-rw-r--r--test_utils/src/git.rs4
-rw-r--r--test_utils/src/lib.rs7
-rw-r--r--tests/init.rs30
-rw-r--r--tests/list.rs2
-rw-r--r--tests/send.rs19
10 files changed, 99 insertions, 108 deletions
diff --git a/src/client.rs b/src/client.rs
index 29d390f..5603014 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -36,10 +36,10 @@ use nostr_sqlite::SQLiteDatabase;
36use crate::{ 36use crate::{
37 config::get_dirs, 37 config::get_dirs,
38 login::{get_logged_in_user, get_user_ref_from_cache}, 38 login::{get_logged_in_user, get_user_ref_from_cache},
39 repo_ref::{RepoRef, REPO_REF_KIND}, 39 repo_ref::RepoRef,
40 sub_commands::{ 40 sub_commands::{
41 list::status_kinds, 41 list::status_kinds,
42 send::{event_is_patch_set_root, event_is_revision_root, PATCH_KIND}, 42 send::{event_is_patch_set_root, event_is_revision_root},
43 }, 43 },
44}; 44};
45 45
@@ -212,7 +212,7 @@ impl Connect for Client {
212 }); 212 });
213 } 213 }
214 save_event_in_cache(git_repo_path, &event).await?; 214 save_event_in_cache(git_repo_path, &event).await?;
215 if event.kind().eq(&Kind::Custom(REPO_REF_KIND)) { 215 if event.kind().eq(&Kind::GitRepoAnnouncement) {
216 save_event_in_global_cache(git_repo_path, &event).await?; 216 save_event_in_global_cache(git_repo_path, &event).await?;
217 } 217 }
218 Ok(event.id()) 218 Ok(event.id())
@@ -895,7 +895,7 @@ async fn create_relays_request(
895 git_repo_path, 895 git_repo_path,
896 vec![ 896 vec![
897 nostr::Filter::default() 897 nostr::Filter::default()
898 .kinds(vec![Kind::Custom(PATCH_KIND)]) 898 .kinds(vec![Kind::GitPatch])
899 .custom_tag( 899 .custom_tag(
900 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 900 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
901 repo_coordinates_without_relays 901 repo_coordinates_without_relays
@@ -1070,7 +1070,7 @@ async fn process_fetched_events(
1070 for event in &events { 1070 for event in &events {
1071 if !request.existing_events.contains(&event.id) { 1071 if !request.existing_events.contains(&event.id) {
1072 save_event_in_cache(git_repo_path, event).await?; 1072 save_event_in_cache(git_repo_path, event).await?;
1073 if event.kind().as_u16().eq(&REPO_REF_KIND) { 1073 if event.kind().eq(&Kind::GitRepoAnnouncement) {
1074 save_event_in_global_cache(git_repo_path, event).await?; 1074 save_event_in_global_cache(git_repo_path, event).await?;
1075 let new_coordinate = !request 1075 let new_coordinate = !request
1076 .repo_coordinates_without_relays 1076 .repo_coordinates_without_relays
@@ -1172,7 +1172,7 @@ async fn process_fetched_events(
1172 if !request.existing_events.contains(&event.id) 1172 if !request.existing_events.contains(&event.id)
1173 && !event.event_ids().any(|id| report.proposals.contains(id)) 1173 && !event.event_ids().any(|id| report.proposals.contains(id))
1174 { 1174 {
1175 if event.kind().as_u16() == PATCH_KIND && !event_is_patch_set_root(event) { 1175 if event.kind().eq(&Kind::GitPatch) && !event_is_patch_set_root(event) {
1176 report.commits.insert(event.id); 1176 report.commits.insert(event.id);
1177 } else if status_kinds().contains(&event.kind()) { 1177 } else if status_kinds().contains(&event.kind()) {
1178 report.statuses.insert(event.id); 1178 report.statuses.insert(event.id);
@@ -1238,7 +1238,7 @@ pub fn get_fetch_filters(
1238 vec![ 1238 vec![
1239 get_filter_repo_events(repo_coordinates), 1239 get_filter_repo_events(repo_coordinates),
1240 nostr::Filter::default() 1240 nostr::Filter::default()
1241 .kinds(vec![Kind::Custom(PATCH_KIND), Kind::EventDeletion]) 1241 .kinds(vec![Kind::GitPatch, Kind::EventDeletion])
1242 .custom_tag( 1242 .custom_tag(
1243 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 1243 SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
1244 repo_coordinates 1244 repo_coordinates
@@ -1252,13 +1252,9 @@ pub fn get_fetch_filters(
1252 vec![] 1252 vec![]
1253 } else { 1253 } else {
1254 vec![ 1254 vec![
1255 nostr::Filter::default().events(proposal_ids.clone()).kinds( 1255 nostr::Filter::default()
1256 [ 1256 .events(proposal_ids.clone())
1257 vec![Kind::Custom(PATCH_KIND), Kind::EventDeletion], 1257 .kinds([vec![Kind::GitPatch, Kind::EventDeletion], status_kinds()].concat()),
1258 status_kinds(),
1259 ]
1260 .concat(),
1261 ),
1262 ] 1258 ]
1263 }, 1259 },
1264 if required_profiles.is_empty() { 1260 if required_profiles.is_empty() {
@@ -1272,7 +1268,7 @@ pub fn get_fetch_filters(
1272 1268
1273pub fn get_filter_repo_events(repo_coordinates: &HashSet<Coordinate>) -> nostr::Filter { 1269pub fn get_filter_repo_events(repo_coordinates: &HashSet<Coordinate>) -> nostr::Filter {
1274 nostr::Filter::default() 1270 nostr::Filter::default()
1275 .kind(Kind::Custom(REPO_REF_KIND)) 1271 .kind(Kind::GitRepoAnnouncement)
1276 .identifiers( 1272 .identifiers(
1277 repo_coordinates 1273 repo_coordinates
1278 .iter() 1274 .iter()
diff --git a/src/repo_ref.rs b/src/repo_ref.rs
index 0409502..ca196d9 100644
--- a/src/repo_ref.rs
+++ b/src/repo_ref.rs
@@ -37,7 +37,7 @@ impl TryFrom<nostr::Event> for RepoRef {
37 type Error = anyhow::Error; 37 type Error = anyhow::Error;
38 38
39 fn try_from(event: nostr::Event) -> Result<Self> { 39 fn try_from(event: nostr::Event) -> Result<Self> {
40 if !event.kind.as_u16().eq(&REPO_REF_KIND) { 40 if !event.kind.eq(&Kind::GitRepoAnnouncement) {
41 bail!("incorrect kind"); 41 bail!("incorrect kind");
42 } 42 }
43 let mut r = Self::default(); 43 let mut r = Self::default();
@@ -107,13 +107,11 @@ impl TryFrom<nostr::Event> for RepoRef {
107 } 107 }
108} 108}
109 109
110pub static REPO_REF_KIND: u16 = 30_617;
111
112impl RepoRef { 110impl RepoRef {
113 pub async fn to_event(&self, signer: &NostrSigner) -> Result<nostr::Event> { 111 pub async fn to_event(&self, signer: &NostrSigner) -> Result<nostr::Event> {
114 sign_event( 112 sign_event(
115 nostr_sdk::EventBuilder::new( 113 nostr_sdk::EventBuilder::new(
116 nostr::event::Kind::Custom(REPO_REF_KIND), 114 nostr::event::Kind::GitRepoAnnouncement,
117 "", 115 "",
118 [ 116 [
119 vec![ 117 vec![
@@ -179,7 +177,7 @@ impl RepoRef {
179 let mut res = HashSet::new(); 177 let mut res = HashSet::new();
180 for m in &self.maintainers { 178 for m in &self.maintainers {
181 res.insert(Coordinate { 179 res.insert(Coordinate {
182 kind: Kind::Custom(REPO_REF_KIND), 180 kind: Kind::GitRepoAnnouncement,
183 public_key: *m, 181 public_key: *m,
184 identifier: self.identifier.clone(), 182 identifier: self.identifier.clone(),
185 relays: vec![], 183 relays: vec![],
@@ -191,7 +189,7 @@ impl RepoRef {
191 /// coordinates without relay hints 189 /// coordinates without relay hints
192 pub fn coordinate_with_hint(&self) -> Coordinate { 190 pub fn coordinate_with_hint(&self) -> Coordinate {
193 Coordinate { 191 Coordinate {
194 kind: Kind::Custom(REPO_REF_KIND), 192 kind: Kind::GitRepoAnnouncement,
195 public_key: *self 193 public_key: *self
196 .maintainers 194 .maintainers
197 .first() 195 .first()
@@ -256,7 +254,7 @@ pub async fn try_and_get_repo_coordinates(
256 if let Some(identifier) = repo_config.identifier { 254 if let Some(identifier) = repo_config.identifier {
257 for public_key in maintainers { 255 for public_key in maintainers {
258 repo_coordinates.insert(Coordinate { 256 repo_coordinates.insert(Coordinate {
259 kind: Kind::Custom(REPO_REF_KIND), 257 kind: Kind::GitRepoAnnouncement,
260 public_key, 258 public_key,
261 identifier: identifier.clone(), 259 identifier: identifier.clone(),
262 relays: vec![], 260 relays: vec![],
@@ -283,7 +281,7 @@ pub async fn try_and_get_repo_coordinates(
283 } 281 }
284 // look find all repo refs with root_commit. for identifier 282 // look find all repo refs with root_commit. for identifier
285 let filter = nostr::Filter::default() 283 let filter = nostr::Filter::default()
286 .kind(nostr::Kind::Custom(REPO_REF_KIND)) 284 .kind(nostr::Kind::GitRepoAnnouncement)
287 .reference(git_repo.get_root_commit()?.to_string()) 285 .reference(git_repo.get_root_commit()?.to_string())
288 .authors(maintainers.clone()); 286 .authors(maintainers.clone());
289 let mut events = 287 let mut events =
@@ -306,7 +304,7 @@ pub async fn try_and_get_repo_coordinates(
306 for m in &repo_config.maintainers { 304 for m in &repo_config.maintainers {
307 if let Ok(maintainer) = PublicKey::parse(m) { 305 if let Ok(maintainer) = PublicKey::parse(m) {
308 repo_coordinates.insert(Coordinate { 306 repo_coordinates.insert(Coordinate {
309 kind: Kind::Custom(REPO_REF_KIND), 307 kind: Kind::GitRepoAnnouncement,
310 public_key: maintainer, 308 public_key: maintainer,
311 identifier: identifier.to_string(), 309 identifier: identifier.to_string(),
312 relays: vec![], 310 relays: vec![],
diff --git a/src/sub_commands/init.rs b/src/sub_commands/init.rs
index 2a97779..1c51375 100644
--- a/src/sub_commands/init.rs
+++ b/src/sub_commands/init.rs
@@ -16,7 +16,7 @@ use crate::{
16 login, 16 login,
17 repo_ref::{ 17 repo_ref::{
18 extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml, 18 extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml,
19 try_and_get_repo_coordinates, RepoRef, REPO_REF_KIND, 19 try_and_get_repo_coordinates, RepoRef,
20 }, 20 },
21 Cli, 21 Cli,
22}; 22};
@@ -336,7 +336,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> {
336 git_repo.save_git_config_item( 336 git_repo.save_git_config_item(
337 "nostr.repo", 337 "nostr.repo",
338 &Coordinate { 338 &Coordinate {
339 kind: Kind::Custom(REPO_REF_KIND), 339 kind: Kind::GitRepoAnnouncement,
340 public_key: user_ref.public_key, 340 public_key: user_ref.public_key,
341 identifier: identifier.clone(), 341 identifier: identifier.clone(),
342 relays: vec![], 342 relays: vec![],
diff --git a/src/sub_commands/list.rs b/src/sub_commands/list.rs
index cc7ac6f..73ef107 100644
--- a/src/sub_commands/list.rs
+++ b/src/sub_commands/list.rs
@@ -2,7 +2,7 @@ use std::{collections::HashSet, io::Write, ops::Add, path::Path};
2 2
3use anyhow::{bail, Context, Result}; 3use anyhow::{bail, Context, Result};
4use nostr::nips::nip01::Coordinate; 4use nostr::nips::nip01::Coordinate;
5use nostr_sdk::PublicKey; 5use nostr_sdk::{Kind, PublicKey};
6 6
7use super::send::event_is_patch_set_root; 7use super::send::event_is_patch_set_root;
8#[cfg(test)] 8#[cfg(test)]
@@ -16,7 +16,7 @@ use crate::{
16 repo_ref::{get_repo_coordinates, RepoRef}, 16 repo_ref::{get_repo_coordinates, RepoRef},
17 sub_commands::send::{ 17 sub_commands::send::{
18 commit_msg_from_patch_oneliner, event_is_cover_letter, event_is_revision_root, 18 commit_msg_from_patch_oneliner, event_is_cover_letter, event_is_revision_root,
19 event_to_cover_letter, patch_supports_commit_ids, PATCH_KIND, 19 event_to_cover_letter, patch_supports_commit_ids,
20 }, 20 },
21}; 21};
22 22
@@ -84,31 +84,31 @@ pub async fn launch() -> Result<()> {
84 .collect::<Vec<&nostr::Event>>() 84 .collect::<Vec<&nostr::Event>>()
85 .first() 85 .first()
86 { 86 {
87 e.kind().as_u16() 87 e.kind()
88 } else { 88 } else {
89 STATUS_KIND_OPEN 89 Kind::GitStatusOpen
90 }; 90 };
91 if status.eq(&STATUS_KIND_OPEN) { 91 if status.eq(&Kind::GitStatusOpen) {
92 open_proposals.push(proposal); 92 open_proposals.push(proposal);
93 } else if status.eq(&STATUS_KIND_CLOSED) { 93 } else if status.eq(&Kind::GitStatusClosed) {
94 closed_proposals.push(proposal); 94 closed_proposals.push(proposal);
95 } else if status.eq(&STATUS_KIND_DRAFT) { 95 } else if status.eq(&Kind::GitStatusDraft) {
96 draft_proposals.push(proposal); 96 draft_proposals.push(proposal);
97 } else if status.eq(&STATUS_KIND_APPLIED) { 97 } else if status.eq(&Kind::GitStatusApplied) {
98 applied_proposals.push(proposal); 98 applied_proposals.push(proposal);
99 } 99 }
100 } 100 }
101 101
102 let mut selected_status = STATUS_KIND_OPEN; 102 let mut selected_status = Kind::GitStatusOpen;
103 103
104 loop { 104 loop {
105 let proposals_for_status = if selected_status == STATUS_KIND_OPEN { 105 let proposals_for_status = if selected_status == Kind::GitStatusOpen {
106 &open_proposals 106 &open_proposals
107 } else if selected_status == STATUS_KIND_DRAFT { 107 } else if selected_status == Kind::GitStatusDraft {
108 &draft_proposals 108 &draft_proposals
109 } else if selected_status == STATUS_KIND_CLOSED { 109 } else if selected_status == Kind::GitStatusClosed {
110 &closed_proposals 110 &closed_proposals
111 } else if selected_status == STATUS_KIND_APPLIED { 111 } else if selected_status == Kind::GitStatusApplied {
112 &applied_proposals 112 &applied_proposals
113 } else { 113 } else {
114 &open_proposals 114 &open_proposals
@@ -116,15 +116,15 @@ pub async fn launch() -> Result<()> {
116 116
117 let prompt = if proposals.len().eq(&open_proposals.len()) { 117 let prompt = if proposals.len().eq(&open_proposals.len()) {
118 "all proposals" 118 "all proposals"
119 } else if selected_status == STATUS_KIND_OPEN { 119 } else if selected_status == Kind::GitStatusOpen {
120 if open_proposals.is_empty() { 120 if open_proposals.is_empty() {
121 "proposals menu" 121 "proposals menu"
122 } else { 122 } else {
123 "open proposals" 123 "open proposals"
124 } 124 }
125 } else if selected_status == STATUS_KIND_DRAFT { 125 } else if selected_status == Kind::GitStatusDraft {
126 "draft proposals" 126 "draft proposals"
127 } else if selected_status == STATUS_KIND_CLOSED { 127 } else if selected_status == Kind::GitStatusClosed {
128 "closed proposals" 128 "closed proposals"
129 } else { 129 } else {
130 "applied proposals" 130 "applied proposals"
@@ -143,16 +143,16 @@ pub async fn launch() -> Result<()> {
143 }) 143 })
144 .collect(); 144 .collect();
145 145
146 if !selected_status.eq(&STATUS_KIND_OPEN) && open_proposals.len().gt(&0) { 146 if !selected_status.eq(&Kind::GitStatusOpen) && open_proposals.len().gt(&0) {
147 choices.push(format!("({}) Open proposals...", open_proposals.len())); 147 choices.push(format!("({}) Open proposals...", open_proposals.len()));
148 } 148 }
149 if !selected_status.eq(&STATUS_KIND_DRAFT) && draft_proposals.len().gt(&0) { 149 if !selected_status.eq(&Kind::GitStatusDraft) && draft_proposals.len().gt(&0) {
150 choices.push(format!("({}) Draft proposals...", draft_proposals.len())); 150 choices.push(format!("({}) Draft proposals...", draft_proposals.len()));
151 } 151 }
152 if !selected_status.eq(&STATUS_KIND_CLOSED) && closed_proposals.len().gt(&0) { 152 if !selected_status.eq(&Kind::GitStatusClosed) && closed_proposals.len().gt(&0) {
153 choices.push(format!("({}) Closed proposals...", closed_proposals.len())); 153 choices.push(format!("({}) Closed proposals...", closed_proposals.len()));
154 } 154 }
155 if !selected_status.eq(&STATUS_KIND_APPLIED) && applied_proposals.len().gt(&0) { 155 if !selected_status.eq(&Kind::GitStatusApplied) && applied_proposals.len().gt(&0) {
156 choices.push(format!( 156 choices.push(format!(
157 "({}) Applied proposals...", 157 "({}) Applied proposals...",
158 applied_proposals.len() 158 applied_proposals.len()
@@ -167,13 +167,13 @@ pub async fn launch() -> Result<()> {
167 167
168 if (selected_index + 1).gt(&proposals_for_status.len()) { 168 if (selected_index + 1).gt(&proposals_for_status.len()) {
169 if choices[selected_index].contains("Open") { 169 if choices[selected_index].contains("Open") {
170 selected_status = STATUS_KIND_OPEN; 170 selected_status = Kind::GitStatusOpen;
171 } else if choices[selected_index].contains("Draft") { 171 } else if choices[selected_index].contains("Draft") {
172 selected_status = STATUS_KIND_DRAFT; 172 selected_status = Kind::GitStatusDraft;
173 } else if choices[selected_index].contains("Closed") { 173 } else if choices[selected_index].contains("Closed") {
174 selected_status = STATUS_KIND_CLOSED; 174 selected_status = Kind::GitStatusClosed;
175 } else if choices[selected_index].contains("Applied") { 175 } else if choices[selected_index].contains("Applied") {
176 selected_status = STATUS_KIND_APPLIED; 176 selected_status = Kind::GitStatusApplied;
177 } 177 }
178 continue; 178 continue;
179 } 179 }
@@ -804,17 +804,12 @@ pub fn get_most_recent_patch_with_ancestors(
804 Ok(res) 804 Ok(res)
805} 805}
806 806
807pub static STATUS_KIND_OPEN: u16 = 1630;
808pub static STATUS_KIND_APPLIED: u16 = 1631;
809pub static STATUS_KIND_CLOSED: u16 = 1632;
810pub static STATUS_KIND_DRAFT: u16 = 1633;
811
812pub fn status_kinds() -> Vec<nostr::Kind> { 807pub fn status_kinds() -> Vec<nostr::Kind> {
813 vec![ 808 vec![
814 nostr::Kind::Custom(STATUS_KIND_OPEN), 809 nostr::Kind::GitStatusOpen,
815 nostr::Kind::Custom(STATUS_KIND_APPLIED), 810 nostr::Kind::GitStatusApplied,
816 nostr::Kind::Custom(STATUS_KIND_CLOSED), 811 nostr::Kind::GitStatusClosed,
817 nostr::Kind::Custom(STATUS_KIND_DRAFT), 812 nostr::Kind::GitStatusDraft,
818 ] 813 ]
819} 814}
820 815
@@ -826,7 +821,7 @@ pub async fn get_proposals_and_revisions_from_cache(
826 git_repo_path, 821 git_repo_path,
827 vec![ 822 vec![
828 nostr::Filter::default() 823 nostr::Filter::default()
829 .kind(nostr::Kind::Custom(PATCH_KIND)) 824 .kind(nostr::Kind::GitPatch)
830 .custom_tag( 825 .custom_tag(
831 nostr::SingleLetterTag::lowercase(nostr_sdk::Alphabet::A), 826 nostr::SingleLetterTag::lowercase(nostr_sdk::Alphabet::A),
832 repo_coordinates 827 repo_coordinates
@@ -855,10 +850,10 @@ pub async fn get_all_proposal_patch_events_from_cache(
855 git_repo_path, 850 git_repo_path,
856 vec![ 851 vec![
857 nostr::Filter::default() 852 nostr::Filter::default()
858 .kind(nostr::Kind::Custom(PATCH_KIND)) 853 .kind(nostr::Kind::GitPatch)
859 .event(*proposal_id), 854 .event(*proposal_id),
860 nostr::Filter::default() 855 nostr::Filter::default()
861 .kind(nostr::Kind::Custom(PATCH_KIND)) 856 .kind(nostr::Kind::GitPatch)
862 .id(*proposal_id), 857 .id(*proposal_id),
863 ], 858 ],
864 ) 859 )
@@ -891,7 +886,7 @@ pub async fn get_all_proposal_patch_events_from_cache(
891 git_repo_path, 886 git_repo_path,
892 vec![ 887 vec![
893 nostr::Filter::default() 888 nostr::Filter::default()
894 .kind(nostr::Kind::Custom(PATCH_KIND)) 889 .kind(nostr::Kind::GitPatch)
895 .events(revision_roots) 890 .events(revision_roots)
896 .authors(permissioned_users.clone()), 891 .authors(permissioned_users.clone()),
897 ], 892 ],
diff --git a/src/sub_commands/send.rs b/src/sub_commands/send.rs
index 9733cfe..73c980b 100644
--- a/src/sub_commands/send.rs
+++ b/src/sub_commands/send.rs
@@ -12,7 +12,7 @@ use nostr::{
12 }, 12 },
13 EventBuilder, FromBech32, Tag, TagKind, ToBech32, UncheckedUrl, 13 EventBuilder, FromBech32, Tag, TagKind, ToBech32, UncheckedUrl,
14}; 14};
15use nostr_sdk::{hashes::sha1::Hash as Sha1Hash, NostrSigner, TagStandard}; 15use nostr_sdk::{hashes::sha1::Hash as Sha1Hash, Kind, NostrSigner, TagStandard};
16 16
17use super::list::tag_value; 17use super::list::tag_value;
18#[cfg(not(test))] 18#[cfg(not(test))]
@@ -28,7 +28,7 @@ use crate::{
28 }, 28 },
29 git::{Repo, RepoActions}, 29 git::{Repo, RepoActions},
30 login, 30 login,
31 repo_ref::{get_repo_coordinates, RepoRef, REPO_REF_KIND}, 31 repo_ref::{get_repo_coordinates, RepoRef},
32 Cli, 32 Cli,
33}; 33};
34 34
@@ -288,7 +288,10 @@ pub async fn send_events(
288) -> Result<()> { 288) -> Result<()> {
289 let fallback = [ 289 let fallback = [
290 client.get_fallback_relays().clone(), 290 client.get_fallback_relays().clone(),
291 if events.iter().any(|e| e.kind().as_u16().eq(&REPO_REF_KIND)) { 291 if events
292 .iter()
293 .any(|e| e.kind().eq(&Kind::GitRepoAnnouncement))
294 {
292 client.get_blaster_relays().clone() 295 client.get_blaster_relays().clone()
293 } else { 296 } else {
294 vec![] 297 vec![]
@@ -573,8 +576,6 @@ async fn get_root_proposal_id_and_mentions_from_in_reply_to(
573 Ok((root_proposal_id, mention_tags)) 576 Ok((root_proposal_id, mention_tags))
574} 577}
575 578
576pub static PATCH_KIND: u16 = 1617;
577
578#[allow(clippy::too_many_lines)] 579#[allow(clippy::too_many_lines)]
579pub async fn generate_cover_letter_and_patch_events( 580pub async fn generate_cover_letter_and_patch_events(
580 cover_letter_title_description: Option<(String, String)>, 581 cover_letter_title_description: Option<(String, String)>,
@@ -593,7 +594,7 @@ pub async fn generate_cover_letter_and_patch_events(
593 594
594 if let Some((title, description)) = cover_letter_title_description { 595 if let Some((title, description)) = cover_letter_title_description {
595 events.push(sign_event(EventBuilder::new( 596 events.push(sign_event(EventBuilder::new(
596 nostr::event::Kind::Custom(PATCH_KIND), 597 nostr::event::Kind::GitPatch,
597 format!( 598 format!(
598 "From {} Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/{}] {title}\n\n{description}", 599 "From {} Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/{}] {title}\n\n{description}",
599 commits.last().unwrap(), 600 commits.last().unwrap(),
@@ -601,7 +602,7 @@ pub async fn generate_cover_letter_and_patch_events(
601 ), 602 ),
602 [ 603 [
603 repo_ref.maintainers.iter().map(|m| Tag::coordinate(Coordinate { 604 repo_ref.maintainers.iter().map(|m| Tag::coordinate(Coordinate {
604 kind: nostr::Kind::Custom(REPO_REF_KIND), 605 kind: nostr::Kind::GitRepoAnnouncement,
605 public_key: *m, 606 public_key: *m,
606 identifier: repo_ref.identifier.to_string(), 607 identifier: repo_ref.identifier.to_string(),
607 relays: repo_ref.relays.clone(), 608 relays: repo_ref.relays.clone(),
@@ -789,7 +790,7 @@ pub fn event_is_cover_letter(event: &nostr::Event) -> bool {
789 // TODO: look for Subject:[ PATCH 0/n ] but watch out for: 790 // TODO: look for Subject:[ PATCH 0/n ] but watch out for:
790 // [PATCH v1 0/n ] or 791 // [PATCH v1 0/n ] or
791 // [PATCH subsystem v2 0/n ] 792 // [PATCH subsystem v2 0/n ]
792 event.kind.as_u16().eq(&PATCH_KIND) 793 event.kind.eq(&Kind::GitPatch)
793 && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) 794 && event.iter_tags().any(|t| t.as_vec()[1].eq("root"))
794 && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter")) 795 && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter"))
795} 796}
@@ -860,16 +861,15 @@ pub fn event_to_cover_letter(event: &nostr::Event) -> Result<CoverLetter> {
860} 861}
861 862
862pub fn event_is_patch_set_root(event: &nostr::Event) -> bool { 863pub fn event_is_patch_set_root(event: &nostr::Event) -> bool {
863 event.kind.as_u16().eq(&PATCH_KIND) && event.iter_tags().any(|t| t.as_vec()[1].eq("root")) 864 event.kind.eq(&Kind::GitPatch) && event.iter_tags().any(|t| t.as_vec()[1].eq("root"))
864} 865}
865 866
866pub fn event_is_revision_root(event: &nostr::Event) -> bool { 867pub fn event_is_revision_root(event: &nostr::Event) -> bool {
867 event.kind.as_u16().eq(&PATCH_KIND) 868 event.kind.eq(&Kind::GitPatch) && event.iter_tags().any(|t| t.as_vec()[1].eq("revision-root"))
868 && event.iter_tags().any(|t| t.as_vec()[1].eq("revision-root"))
869} 869}
870 870
871pub fn patch_supports_commit_ids(event: &nostr::Event) -> bool { 871pub fn patch_supports_commit_ids(event: &nostr::Event) -> bool {
872 event.kind.as_u16().eq(&PATCH_KIND) 872 event.kind.eq(&Kind::GitPatch)
873 && event 873 && event
874 .iter_tags() 874 .iter_tags()
875 .any(|t| t.as_vec()[0].eq("commit-pgp-sig")) 875 .any(|t| t.as_vec()[0].eq("commit-pgp-sig"))
@@ -897,7 +897,7 @@ pub async fn generate_patch_event(
897 897
898 sign_event( 898 sign_event(
899 EventBuilder::new( 899 EventBuilder::new(
900 nostr::event::Kind::Custom(PATCH_KIND), 900 nostr::event::Kind::GitPatch,
901 git_repo 901 git_repo
902 .make_patch_from_commit(commit, &series_count) 902 .make_patch_from_commit(commit, &series_count)
903 .context(format!("cannot make patch for commit {commit}"))?, 903 .context(format!("cannot make patch for commit {commit}"))?,
@@ -907,7 +907,7 @@ pub async fn generate_patch_event(
907 .iter() 907 .iter()
908 .map(|m| { 908 .map(|m| {
909 Tag::coordinate(Coordinate { 909 Tag::coordinate(Coordinate {
910 kind: nostr::Kind::Custom(REPO_REF_KIND), 910 kind: nostr::Kind::GitRepoAnnouncement,
911 public_key: *m, 911 public_key: *m,
912 identifier: repo_ref.identifier.to_string(), 912 identifier: repo_ref.identifier.to_string(),
913 relays: repo_ref.relays.clone(), 913 relays: repo_ref.relays.clone(),
@@ -1238,7 +1238,7 @@ mod tests {
1238 1238
1239 fn generate_cover_letter(title: &str, description: &str) -> Result<nostr::Event> { 1239 fn generate_cover_letter(title: &str, description: &str) -> Result<nostr::Event> {
1240 Ok(nostr::event::EventBuilder::new( 1240 Ok(nostr::event::EventBuilder::new(
1241 nostr::event::Kind::Custom(PATCH_KIND), 1241 nostr::event::Kind::GitPatch,
1242 format!("From ea897e987ea9a7a98e7a987e97987ea98e7a3334 Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/2] {title}\n\n{description}"), 1242 format!("From ea897e987ea9a7a98e7a987e97987ea98e7a3334 Mon Sep 17 00:00:00 2001\nSubject: [PATCH 0/2] {title}\n\n{description}"),
1243 [ 1243 [
1244 Tag::hashtag("cover-letter"), 1244 Tag::hashtag("cover-letter"),
diff --git a/test_utils/src/git.rs b/test_utils/src/git.rs
index 7aa7e84..5e8aed5 100644
--- a/test_utils/src/git.rs
+++ b/test_utils/src/git.rs
@@ -8,7 +8,7 @@ use git2::{Oid, RepositoryInitOptions, Signature, Time};
8use nostr::nips::nip01::Coordinate; 8use nostr::nips::nip01::Coordinate;
9use nostr_sdk::{Kind, ToBech32}; 9use nostr_sdk::{Kind, ToBech32};
10 10
11use crate::{generate_repo_ref_event, REPOSITORY_KIND}; 11use crate::generate_repo_ref_event;
12 12
13pub struct GitTestRepo { 13pub struct GitTestRepo {
14 pub dir: PathBuf, 14 pub dir: PathBuf,
@@ -19,7 +19,7 @@ impl Default for GitTestRepo {
19 fn default() -> Self { 19 fn default() -> Self {
20 let repo_event = generate_repo_ref_event(); 20 let repo_event = generate_repo_ref_event();
21 let coordinate = Coordinate { 21 let coordinate = Coordinate {
22 kind: Kind::Custom(REPOSITORY_KIND), 22 kind: Kind::GitRepoAnnouncement,
23 public_key: repo_event.author(), 23 public_key: repo_event.author(),
24 identifier: repo_event.identifier().unwrap().to_string(), 24 identifier: repo_event.identifier().unwrap().to_string(),
25 relays: vec![ 25 relays: vec![
diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs
index 5125d20..bccfaf5 100644
--- a/test_utils/src/lib.rs
+++ b/test_utils/src/lib.rs
@@ -21,9 +21,6 @@ use tokio::runtime::Handle;
21pub mod git; 21pub mod git;
22pub mod relay; 22pub mod relay;
23 23
24pub static PATCH_KIND: u16 = 1617;
25pub static REPOSITORY_KIND: u16 = 30617;
26
27pub static TEST_KEY_1_NSEC: &str = 24pub static TEST_KEY_1_NSEC: &str =
28 "nsec1ppsg5sm2aexq06juxmu9evtutr6jkwkhp98exxxvwamhru9lyx9s3rwseq"; 25 "nsec1ppsg5sm2aexq06juxmu9evtutr6jkwkhp98exxxvwamhru9lyx9s3rwseq";
29pub static TEST_KEY_1_SK_HEX: &str = 26pub static TEST_KEY_1_SK_HEX: &str =
@@ -158,7 +155,7 @@ pub fn generate_repo_ref_event() -> nostr::Event {
158 // author and committer from global git config 155 // author and committer from global git config
159 let root_commit = "9ee507fc4357d7ee16a5d8901bedcd103f23c17d"; 156 let root_commit = "9ee507fc4357d7ee16a5d8901bedcd103f23c17d";
160 nostr::event::EventBuilder::new( 157 nostr::event::EventBuilder::new(
161 nostr::Kind::Custom(REPOSITORY_KIND), 158 nostr::Kind::GitRepoAnnouncement,
162 "", 159 "",
163 [ 160 [
164 Tag::identifier( 161 Tag::identifier(
@@ -1244,7 +1241,7 @@ fn get_first_proposal_event_id() -> Result<nostr::EventId> {
1244 let proposals = Handle::current().block_on(client.get_events_of( 1241 let proposals = Handle::current().block_on(client.get_events_of(
1245 vec![ 1242 vec![
1246 nostr::Filter::default() 1243 nostr::Filter::default()
1247 .kind(nostr::Kind::Custom(PATCH_KIND)) 1244 .kind(nostr::Kind::GitPatch)
1248 .custom_tag( 1245 .custom_tag(
1249 nostr::SingleLetterTag::lowercase(nostr::Alphabet::T), 1246 nostr::SingleLetterTag::lowercase(nostr::Alphabet::T),
1250 vec!["root"], 1247 vec!["root"],
diff --git a/tests/init.rs b/tests/init.rs
index 7e2e080..afd3848 100644
--- a/tests/init.rs
+++ b/tests/init.rs
@@ -1,4 +1,5 @@
1use anyhow::Result; 1use anyhow::Result;
2use nostr_sdk::Kind;
2use serial_test::serial; 3use serial_test::serial;
3use test_utils::{git::GitTestRepo, *}; 4use test_utils::{git::GitTestRepo, *};
4 5
@@ -124,6 +125,7 @@ mod when_repo_not_previously_claimed {
124 } 125 }
125 126
126 mod sent_to_correct_relays { 127 mod sent_to_correct_relays {
128
127 use super::*; 129 use super::*;
128 130
129 #[tokio::test] 131 #[tokio::test]
@@ -135,7 +137,7 @@ mod when_repo_not_previously_claimed {
135 relay 137 relay
136 .events 138 .events
137 .iter() 139 .iter()
138 .filter(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 140 .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
139 .count(), 141 .count(),
140 1, 142 1,
141 ); 143 );
@@ -152,7 +154,7 @@ mod when_repo_not_previously_claimed {
152 relay 154 relay
153 .events 155 .events
154 .iter() 156 .iter()
155 .filter(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 157 .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
156 .count(), 158 .count(),
157 1, 159 1,
158 ); 160 );
@@ -169,7 +171,7 @@ mod when_repo_not_previously_claimed {
169 relay 171 relay
170 .events 172 .events
171 .iter() 173 .iter()
172 .filter(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 174 .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
173 .count(), 175 .count(),
174 1, 176 1,
175 ); 177 );
@@ -184,7 +186,7 @@ mod when_repo_not_previously_claimed {
184 assert_eq!( 186 assert_eq!(
185 r57.events 187 r57.events
186 .iter() 188 .iter()
187 .filter(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 189 .filter(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
188 .count(), 190 .count(),
189 1, 191 1,
190 ); 192 );
@@ -324,7 +326,7 @@ mod when_repo_not_previously_claimed {
324 .value() 326 .value()
325 .unwrap(), 327 .unwrap(),
326 Coordinate { 328 Coordinate {
327 kind: nostr_sdk::Kind::Custom(REPOSITORY_KIND), 329 kind: nostr_sdk::Kind::GitRepoAnnouncement,
328 identifier: "example-identifier".to_string(), 330 identifier: "example-identifier".to_string(),
329 public_key: TEST_KEY_1_KEYS.public_key(), 331 public_key: TEST_KEY_1_KEYS.public_key(),
330 relays: vec![], 332 relays: vec![],
@@ -367,7 +369,7 @@ mod when_repo_not_previously_claimed {
367 let event: &nostr::Event = relay 369 let event: &nostr::Event = relay
368 .events 370 .events
369 .iter() 371 .iter()
370 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 372 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
371 .unwrap(); 373 .unwrap();
372 374
373 assert!( 375 assert!(
@@ -387,7 +389,7 @@ mod when_repo_not_previously_claimed {
387 let event: &nostr::Event = relay 389 let event: &nostr::Event = relay
388 .events 390 .events
389 .iter() 391 .iter()
390 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 392 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
391 .unwrap(); 393 .unwrap();
392 394
393 assert!(event.tags.iter().any(|t| t.as_vec()[0].eq("r") 395 assert!(event.tags.iter().any(|t| t.as_vec()[0].eq("r")
@@ -405,7 +407,7 @@ mod when_repo_not_previously_claimed {
405 let event: &nostr::Event = relay 407 let event: &nostr::Event = relay
406 .events 408 .events
407 .iter() 409 .iter()
408 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 410 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
409 .unwrap(); 411 .unwrap();
410 412
411 assert!( 413 assert!(
@@ -426,7 +428,7 @@ mod when_repo_not_previously_claimed {
426 let event: &nostr::Event = relay 428 let event: &nostr::Event = relay
427 .events 429 .events
428 .iter() 430 .iter()
429 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 431 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
430 .unwrap(); 432 .unwrap();
431 433
432 assert!(event.tags.iter().any(|t| t.as_vec()[0].eq("alt") 434 assert!(event.tags.iter().any(|t| t.as_vec()[0].eq("alt")
@@ -443,7 +445,7 @@ mod when_repo_not_previously_claimed {
443 let event: &nostr::Event = relay 445 let event: &nostr::Event = relay
444 .events 446 .events
445 .iter() 447 .iter()
446 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 448 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
447 .unwrap(); 449 .unwrap();
448 450
449 assert!(event.tags.iter().any(|t| t.as_vec()[0].eq("description") 451 assert!(event.tags.iter().any(|t| t.as_vec()[0].eq("description")
@@ -460,7 +462,7 @@ mod when_repo_not_previously_claimed {
460 let event: &nostr::Event = relay 462 let event: &nostr::Event = relay
461 .events 463 .events
462 .iter() 464 .iter()
463 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 465 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
464 .unwrap(); 466 .unwrap();
465 467
466 assert!( 468 assert!(
@@ -479,7 +481,7 @@ mod when_repo_not_previously_claimed {
479 let event: &nostr::Event = relay 481 let event: &nostr::Event = relay
480 .events 482 .events
481 .iter() 483 .iter()
482 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 484 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
483 .unwrap(); 485 .unwrap();
484 let relays_tag = event 486 let relays_tag = event
485 .tags 487 .tags
@@ -501,7 +503,7 @@ mod when_repo_not_previously_claimed {
501 let event: &nostr::Event = relay 503 let event: &nostr::Event = relay
502 .events 504 .events
503 .iter() 505 .iter()
504 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 506 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
505 .unwrap(); 507 .unwrap();
506 let web_tag = event 508 let web_tag = event
507 .tags 509 .tags
@@ -523,7 +525,7 @@ mod when_repo_not_previously_claimed {
523 let event: &nostr::Event = relay 525 let event: &nostr::Event = relay
524 .events 526 .events
525 .iter() 527 .iter()
526 .find(|e| e.kind.as_u16().eq(&REPOSITORY_KIND)) 528 .find(|e| e.kind.eq(&Kind::GitRepoAnnouncement))
527 .unwrap(); 529 .unwrap();
528 let maintainers_tag = event 530 let maintainers_tag = event
529 .tags 531 .tags
diff --git a/tests/list.rs b/tests/list.rs
index 6e509ac..ce90ee4 100644
--- a/tests/list.rs
+++ b/tests/list.rs
@@ -88,7 +88,7 @@ mod cannot_find_repo_event {
88 let mut input = p.expect_input("repository naddr")?; 88 let mut input = p.expect_input("repository naddr")?;
89 input.succeeds_with( 89 input.succeeds_with(
90 &Coordinate { 90 &Coordinate {
91 kind: nostr::Kind::Custom(REPOSITORY_KIND), 91 kind: nostr::Kind::GitRepoAnnouncement,
92 public_key: TEST_KEY_1_KEYS.public_key(), 92 public_key: TEST_KEY_1_KEYS.public_key(),
93 identifier: repo_event.identifier().unwrap().to_string(), 93 identifier: repo_event.identifier().unwrap().to_string(),
94 relays: vec!["ws://localhost:8056".to_string()], 94 relays: vec!["ws://localhost:8056".to_string()],
diff --git a/tests/send.rs b/tests/send.rs
index 0f18bd1..57987e3 100644
--- a/tests/send.rs
+++ b/tests/send.rs
@@ -1,5 +1,6 @@
1use anyhow::Result; 1use anyhow::Result;
2use futures::join; 2use futures::join;
3use nostr_sdk::Kind;
3use serial_test::serial; 4use serial_test::serial;
4use test_utils::{git::GitTestRepo, relay::Relay, *}; 5use test_utils::{git::GitTestRepo, relay::Relay, *};
5 6
@@ -84,13 +85,11 @@ mod when_commits_behind_ask_to_proceed {
84} 85}
85 86
86fn is_cover_letter(event: &nostr::Event) -> bool { 87fn is_cover_letter(event: &nostr::Event) -> bool {
87 event.kind.as_u16().eq(&PATCH_KIND) 88 event.kind.eq(&Kind::GitPatch) && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter"))
88 && event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter"))
89} 89}
90 90
91fn is_patch(event: &nostr::Event) -> bool { 91fn is_patch(event: &nostr::Event) -> bool {
92 event.kind.as_u16().eq(&PATCH_KIND) 92 event.kind.eq(&Kind::GitPatch) && !event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter"))
93 && !event.iter_tags().any(|t| t.as_vec()[1].eq("cover-letter"))
94} 93}
95 94
96fn prep_git_repo() -> Result<GitTestRepo> { 95fn prep_git_repo() -> Result<GitTestRepo> {
@@ -386,12 +385,14 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
386 relay.events.iter().find(|e| is_cover_letter(e)).unwrap(); 385 relay.events.iter().find(|e| is_cover_letter(e)).unwrap();
387 assert!(cover_letter_event.iter_tags().any(|t| t.as_vec()[0].eq("a") 386 assert!(cover_letter_event.iter_tags().any(|t| t.as_vec()[0].eq("a")
388 && t.as_vec()[1].eq(&format!( 387 && t.as_vec()[1].eq(&format!(
389 "{REPOSITORY_KIND}:{TEST_KEY_1_PUBKEY_HEX}:{}", 388 "{}:{TEST_KEY_1_PUBKEY_HEX}:{}",
389 Kind::GitRepoAnnouncement,
390 generate_repo_ref_event().identifier().unwrap() 390 generate_repo_ref_event().identifier().unwrap()
391 )))); 391 ))));
392 assert!(cover_letter_event.iter_tags().any(|t| t.as_vec()[0].eq("a") 392 assert!(cover_letter_event.iter_tags().any(|t| t.as_vec()[0].eq("a")
393 && t.as_vec()[1].eq(&format!( 393 && t.as_vec()[1].eq(&format!(
394 "{REPOSITORY_KIND}:{TEST_KEY_2_PUBKEY_HEX}:{}", 394 "{}:{TEST_KEY_2_PUBKEY_HEX}:{}",
395 Kind::GitRepoAnnouncement,
395 generate_repo_ref_event().identifier().unwrap() 396 generate_repo_ref_event().identifier().unwrap()
396 )))); 397 ))));
397 } 398 }
@@ -577,14 +578,16 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
577 assert!(prep().await?.tags.iter().any(|t| { 578 assert!(prep().await?.tags.iter().any(|t| {
578 t.as_vec()[0].eq("a") 579 t.as_vec()[0].eq("a")
579 && t.as_vec()[1].eq(&format!( 580 && t.as_vec()[1].eq(&format!(
580 "{REPOSITORY_KIND}:{TEST_KEY_1_PUBKEY_HEX}:{}", 581 "{}:{TEST_KEY_1_PUBKEY_HEX}:{}",
582 Kind::GitRepoAnnouncement,
581 generate_repo_ref_event().identifier().unwrap() 583 generate_repo_ref_event().identifier().unwrap()
582 )) 584 ))
583 })); 585 }));
584 assert!(prep().await?.tags.iter().any(|t| { 586 assert!(prep().await?.tags.iter().any(|t| {
585 t.as_vec()[0].eq("a") 587 t.as_vec()[0].eq("a")
586 && t.as_vec()[1].eq(&format!( 588 && t.as_vec()[1].eq(&format!(
587 "{REPOSITORY_KIND}:{TEST_KEY_2_PUBKEY_HEX}:{}", 589 "{}:{TEST_KEY_2_PUBKEY_HEX}:{}",
590 Kind::GitRepoAnnouncement,
588 generate_repo_ref_event().identifier().unwrap() 591 generate_repo_ref_event().identifier().unwrap()
589 )) 592 ))
590 })); 593 }));