From d950c130981259e3432a4849b9060db67e3b19cf Mon Sep 17 00:00:00 2001 From: xeruf <27jf@pm.me> Date: Tue, 6 Aug 2024 11:34:18 +0300 Subject: [PATCH] feat: migrate to nostr-sdk 0.33 --- .gitignore | 3 +- Cargo.lock | 97 +++++++++++++++++++++++++++---------------- Cargo.toml | 2 +- src/kinds.rs | 38 +++++++++-------- src/main.rs | 12 +++--- src/task.rs | 8 ++-- src/tasks.rs | 113 +++++++++++++++++++++++++++------------------------ 7 files changed, 155 insertions(+), 118 deletions(-) diff --git a/.gitignore b/.gitignore index 726e226..0e47480 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,4 @@ relays keys *.html -/src/bin -/src/test +*.rs \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index c662102..0d07deb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -154,15 +154,15 @@ dependencies = [ [[package]] name = "async-wsocket" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c38341e6ee670913fb9dc3aba40c22d616261da4dc0928326d3168ebf576fb0" +checksum = "3445f8f330db8e5f3be7912f170f32e43fec90d995c71ced1ec3b8394b4a873c" dependencies = [ "async-utility", "futures-util", "thiserror", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tokio-socks", "tokio-tungstenite", "url", @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "atomic-destructor" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4653a42bf04120a1d4e92452e006b4e3af4ab4afff8fb4af0f1bbb98418adf3e" +checksum = "7d919cb60ba95c87ba42777e9e246c4e8d658057299b437b7512531ce0a09a23" dependencies = [ "tracing", ] @@ -755,10 +755,10 @@ dependencies = [ "http", "hyper", "hyper-util", - "rustls", + "rustls 0.22.4", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tower-service", ] @@ -977,9 +977,9 @@ checksum = "e664971378a3987224f7a0e10059782035e89899ae403718ee07de85bec42afe" [[package]] name = "nostr" -version = "0.30.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27223888faca0c4ba9b97c2b7dc776e9a33d5f54e3558887471cf17798b5fbf" +checksum = "f08db214560a34bf7c4c1fea09a8461b9412bae58ba06e99ce3177d89fa1e0a6" dependencies = [ "aes", "base64 0.21.7", @@ -1007,9 +1007,9 @@ dependencies = [ [[package]] name = "nostr-database" -version = "0.30.0" +version = "0.33.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f726b8c0904a838f64b51a931a1bf39e341f5584a5e04f06310fbfb847e2e924" +checksum = "50eebf5020d70891e3c229128de5fc73af632b651d02742383b314d3d0c7e953" dependencies = [ "async-trait", "lru", @@ -1021,9 +1021,9 @@ dependencies = [ [[package]] name = "nostr-relay-pool" -version = "0.30.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f0ccf9e81aa747abdfa130007651248b37c3699d37029bad701e68902257ce" +checksum = "afa5502a3df456790ca16d90cc688a677117d57ab56b079dcfa091390ac9f202" dependencies = [ "async-utility", "async-wsocket", @@ -1037,11 +1037,12 @@ dependencies = [ [[package]] name = "nostr-sdk" -version = "0.30.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ffedac7ab488e0dfea52804d0c43fafc7e3eefc62d97726d3927a1390db05b" +checksum = "b427dceefbbb49a9dd98abb8c4e40d25fdd467e99821aaad88615252bdb915bd" dependencies = [ "async-utility", + "atomic-destructor", "lnurl-pay", "nostr", "nostr-database", @@ -1056,9 +1057,9 @@ dependencies = [ [[package]] name = "nostr-signer" -version = "0.30.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e568670664cf5cc14a794ae32dfc04bde385d63ff0f5b1c3745dd3ea69f73a" +checksum = "665268b316f41cd8fa791be54b6c7935c5a239461708c380a699d6677be9af38" dependencies = [ "async-utility", "nostr", @@ -1070,9 +1071,9 @@ dependencies = [ [[package]] name = "nostr-zapper" -version = "0.30.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420a7c6458d5c1dc502b3d36fb9f8598837743a737b84adb4ef8ea36b98c5e07" +checksum = "69922e74f8eab1f9d287008c0c06acdec87277a2d8f44bd9d38e003422aea0ab" dependencies = [ "async-trait", "nostr", @@ -1100,9 +1101,9 @@ dependencies = [ [[package]] name = "nwc" -version = "0.30.0" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e236611ea96d3545138f7b2152f2e4571e3c93436ddc91d1c458f366e5c6430f" +checksum = "bb2e04b3edb5e9572e95b62842430625f1718e8a4a3596a30aeb04e6734764ea" dependencies = [ "async-utility", "nostr", @@ -1319,7 +1320,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls", + "rustls 0.22.4", "rustls-pemfile", "rustls-pki-types", "serde", @@ -1327,7 +1328,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "tokio-socks", "tower-service", "url", @@ -1382,6 +1383,20 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rustls" +version = "0.23.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebbbdb961df0ad3f2652da8f3fdc4b36122f568f968f45ad3316f26c025c677b" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -1459,9 +1474,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "send_wrapper" @@ -1658,7 +1673,18 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls", + "rustls 0.22.4", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls 0.23.7", "rustls-pki-types", "tokio", ] @@ -1677,16 +1703,16 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.21.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" dependencies = [ "futures-util", "log", - "rustls", + "rustls 0.23.7", "rustls-pki-types", "tokio", - "tokio-rustls", + "tokio-rustls 0.26.0", "tungstenite", "webpki-roots", ] @@ -1759,9 +1785,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.21.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" dependencies = [ "byteorder", "bytes", @@ -1770,11 +1796,10 @@ dependencies = [ "httparse", "log", "rand", - "rustls", + "rustls 0.23.7", "rustls-pki-types", "sha1", "thiserror", - "url", "utf-8", ] @@ -1934,9 +1959,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wasm-ws" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5b3a482e27ff54809c0848629d9033179705c5ea2f58e26cf45dc77c34c4984" +checksum = "688c5806d1b06b4f3d90d015e23364dc5d3af412ee64abba6dde8fdc01637e33" dependencies = [ "async_io_stream", "futures", diff --git a/Cargo.toml b/Cargo.toml index 3020739..3461360 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,6 @@ log = "0.4.21" chrono = "0.4.38" colog = "1.3.0" colored = "2.1.0" -nostr-sdk = "0.30" +nostr-sdk = "0.33" tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] } once_cell = "1.19.0" diff --git a/src/kinds.rs b/src/kinds.rs index 165f7d9..a12b2cf 100644 --- a/src/kinds.rs +++ b/src/kinds.rs @@ -1,12 +1,14 @@ use itertools::Itertools; use log::info; -use nostr_sdk::{Alphabet, EventBuilder, EventId, GenericTagValue, Kind, Tag}; +use nostr_sdk::{Alphabet, EventBuilder, EventId, Kind, Tag, TagStandard}; -pub const TASK_KIND: u64 = 1621; -pub const TRACKING_KIND: u64 = 1650; +pub const TASK_KIND: u16 = 1621; +pub const TRACKING_KIND: u16 = 1650; pub(crate) fn build_tracking(id: I) -> EventBuilder -where I: IntoIterator { +where + I: IntoIterator, +{ EventBuilder::new( Kind::from(TRACKING_KIND), "", @@ -20,19 +22,21 @@ pub(crate) fn build_task(name: &str, tags: Vec) -> EventBuilder { } fn format_tag(tag: &Tag) -> String { - tag.content().map(|c| { - match c { - GenericTagValue::PublicKey(key) => format!("Key: {}", key.to_string()[..8].to_string()), - GenericTagValue::EventId(id) => format!("Parent: {}", id.to_string()[..8].to_string()), - GenericTagValue::String(str) => { - if is_hashtag(tag) { - format!("#{str}") - } else { - str - } - } - } - }).unwrap_or_else(|| format!("Kind {}", tag.kind())) + match tag.as_standardized() { + Some(TagStandard::Event { + event_id, + .. + }) => format!("Parent: {}", event_id.to_string()[..8].to_string()), + Some(TagStandard::PublicKey { + public_key, + .. + }) => format!("Key: {}", public_key.to_string()[..8].to_string()), + Some(TagStandard::Hashtag(content)) => format!("#{content}"), + _ => tag.content().map_or_else( + || format!("Kind {}", tag.kind()), + |content| content.to_string() + ) + } } pub(crate) fn is_hashtag(tag: &Tag) -> bool { diff --git a/src/main.rs b/src/main.rs index c4f9ad8..8a89003 100644 --- a/src/main.rs +++ b/src/main.rs @@ -48,9 +48,9 @@ impl EventSender { } let mut queue = self.queue.borrow_mut(); Ok(event_builder.to_event(&self.keys).inspect(|event| { - if event.kind.as_u64() == TRACKING_KIND { + if event.kind.as_u16() == TRACKING_KIND { queue.retain(|e| { - e.kind.as_u64() != TRACKING_KIND + e.kind.as_u16() != TRACKING_KIND }); } queue.push(event.clone()); @@ -63,7 +63,7 @@ impl EventSender { } /// Sends all pending events if there is a non-tracking event fn flush(&self) { - if self.queue.borrow().iter().any(|event| event.kind.as_u64() != TRACKING_KIND) { + if self.queue.borrow().iter().any(|event| event.kind.as_u16() != TRACKING_KIND) { self.force_flush() } } @@ -187,8 +187,8 @@ async fn main() { queue: Default::default(), }); - let sub_id: SubscriptionId = client.subscribe(vec![Filter::new()], None).await; - info!("Subscribed with {}", sub_id); + let sub_id = client.subscribe(vec![Filter::new()], None).await; + info!("Subscribed with {:?}", sub_id); let mut notifications = client.notifications(); /*println!("Finding existing events"); @@ -358,7 +358,7 @@ async fn main() { Some('*') => { if let Ok(num) = arg.parse::() { - tasks.track_at(Timestamp::now() + num); + tasks.track_at(Timestamp::from(Timestamp::now().as_u64().saturating_add_signed(num))); } else if let Ok(date) = DateTime::parse_from_rfc3339(arg) { tasks.track_at(Timestamp::from(date.to_utc().timestamp() as u64)); } else { diff --git a/src/task.rs b/src/task.rs index fd4b4db..9972a12 100644 --- a/src/task.rs +++ b/src/task.rs @@ -6,7 +6,7 @@ use std::ops::Div; use itertools::Either::{Left, Right}; use itertools::Itertools; use log::{debug, error, info, trace, warn}; -use nostr_sdk::{Alphabet, Event, EventBuilder, EventId, Kind, Tag, Timestamp}; +use nostr_sdk::{Alphabet, Event, EventBuilder, EventId, Kind, Tag, TagStandard, Timestamp}; use crate::kinds::is_hashtag; @@ -22,8 +22,8 @@ pub(crate) struct Task { impl Task { pub(crate) fn new(event: Event) -> Task { - let (parents, tags) = event.tags.iter().partition_map(|tag| match tag { - Tag::Event { event_id, .. } => return Left(event_id), + let (parents, tags) = event.tags.iter().partition_map(|tag| match tag.as_standardized() { + Some(TagStandard::Event { event_id, .. }) => return Left(event_id), _ => Right(tag.clone()), }); Task { @@ -190,7 +190,7 @@ impl State { } } - pub(crate) fn kind(&self) -> u64 { + pub(crate) fn kind(&self) -> u16 { match self { State::Open => 1630, State::Done => 1631, diff --git a/src/tasks.rs b/src/tasks.rs index 89abedd..3bfc54f 100644 --- a/src/tasks.rs +++ b/src/tasks.rs @@ -8,8 +8,8 @@ use chrono::LocalResult::Single; use colored::Colorize; use itertools::Itertools; use log::{debug, error, info, trace, warn}; -use nostr_sdk::{Event, EventBuilder, EventId, GenericTagValue, Kind, PublicKey, Tag, Timestamp}; -use nostr_sdk::Tag::Hashtag; +use nostr_sdk::{Event, EventBuilder, EventId, Kind, PublicKey, Tag, TagStandard, Timestamp}; +use TagStandard::Hashtag; use crate::EventSender; use crate::kinds::*; @@ -96,26 +96,8 @@ impl Tasks { } /// Total time tracked on this task by the current user. - pub(crate) fn time_tracked(&self, id: &EventId) -> u64 { - let mut total = 0; - let mut start: Option = None; - for event in self.history.get(&self.sender.pubkey()).into_iter().flatten() { - match event.tags.first() { - Some(Tag::Event { - event_id, - .. - }) if event_id == id => { - start = start.or(Some(event.created_at)) - } - _ => if let Some(stamp) = start { - total += (event.created_at - stamp).as_u64(); - } - } - } - if let Some(start) = start { - total += (Timestamp::now() - start).as_u64(); - } - total + pub(crate) fn time_tracked(&self, id: EventId) -> u64 { + Self::time_tracked_for(self.history.get(&self.sender.pubkey()).into_iter().flatten(), &vec![id]) } /// Total time tracked on this task and its subtasks by all users. @@ -125,23 +107,30 @@ impl Tasks { let children = self.get_subtasks(id); for user in self.history.values() { - let mut start: Option = None; - for event in user { - match event.tags.first() { - Some(Tag::Event { - event_id, - .. - }) if children.contains(event_id) => { - start = start.or(Some(event.created_at)) - } - _ => if let Some(stamp) = start { - total += (event.created_at - stamp).as_u64(); - } + total += Self::time_tracked_for(user, &children); + } + total + } + + fn time_tracked_for<'a, E>(events: E, ids: &Vec) -> u64 + where E: IntoIterator { + let mut total = 0; + let mut start: Option = None; + for event in events { + match event.tags.first().and_then(|tag| tag.as_standardized()) { + Some(TagStandard::Event { + event_id, + .. + }) if ids.contains(event_id) => { + start = start.or(Some(event.created_at)) + } + _ => if let Some(stamp) = start { + total += (event.created_at - stamp).as_u64(); } } - if let Some(start) = start { - total += (Timestamp::now() - start).as_u64(); - } + } + if let Some(start) = start { + total += (Timestamp::now() - start).as_u64(); } total } @@ -246,7 +235,7 @@ impl Tasks { pub(crate) fn referenced_tasks(&mut self, event: &Event, f: F) { for tag in event.tags.iter() { - if let Tag::Event { event_id, .. } = tag { + if let Some(TagStandard::Event { event_id, .. }) = tag.as_standardized() { self.tasks.get_mut(event_id).map(|t| f(t)); } } @@ -256,7 +245,7 @@ impl Tasks { fn current_task(&self) -> Option<&Task> { self.position.and_then(|id| self.get_by_id(&id)) } - + pub(crate) fn children_of(&self, id: Option) -> impl IntoIterator + '_ { self.tasks .values() @@ -301,7 +290,7 @@ impl Tasks { lock, "{} since {} (total tracked time {}m)", state.get_label(), - match Local.timestamp_opt(state.time.as_i64(), 0) { + match Local.timestamp_opt(state.time.as_u64() as i64, 0) { Single(time) => { let date = time.date_naive(); let prefix = match Local::now() @@ -318,7 +307,7 @@ impl Tasks { } _ => state.time.to_human_datetime(), }, - self.time_tracked(t.get_id()) / 60 + self.time_tracked(*t.get_id()) / 60 )?; writeln!(lock, "{}", t.descriptions().join("\n"))?; } @@ -352,7 +341,7 @@ impl Tasks { .map_or(String::new(), |p| format!("{:2.0}%", p * 100.0)), "path" => self.get_task_path(Some(task.event.id)), "rpath" => self.relative_path(task.event.id), - "time" => display_time("MMMm", self.time_tracked(task.get_id())), + "time" => display_time("MMMm", self.time_tracked(*task.get_id())), "rtime" => display_time("HH:MMm", self.total_time_tracked(*task.get_id())), prop => task.get(prop).unwrap_or(String::new()), }) @@ -372,7 +361,7 @@ impl Tasks { pub(crate) fn add_tag(&mut self, tag: String) { self.view.clear(); - self.tags.insert(Hashtag(tag)); + self.tags.insert(Hashtag(tag).into()); } pub(crate) fn remove_tag(&mut self, tag: String) { @@ -392,7 +381,7 @@ impl Tasks { pub(crate) fn flush(&self) { self.sender.flush(); } - + /// Returns ids of tasks matching the filter. pub(crate) fn get_filtered(&self, arg: &str) -> Vec { if let Ok(id) = EventId::parse(arg) { @@ -405,7 +394,7 @@ impl Tasks { for task in tasks { let lowercase = task.event.content.to_ascii_lowercase(); if lowercase == lowercase_arg { - return vec![task.event.id] + return vec![task.event.id]; } else if task.event.content.starts_with(arg) { filtered.push(task.event.id) } else if lowercase.starts_with(&lowercase_arg) { @@ -413,9 +402,9 @@ impl Tasks { } } if filtered.len() == 0 { - return filtered_more + return filtered_more; } - return filtered + return filtered; } /// Finds out what to do with the given string. @@ -450,7 +439,7 @@ impl Tasks { } self.submit(build_tracking(id)); if !id.and_then(|id| self.tasks.get(&id)).is_some_and(|t| t.parent_id() == self.position.as_ref()) { - debug!("Flushing Tasks because of move"); + debug!("Flushing Tasks because of move beyond child"); self.flush(); } self.position = id; @@ -469,7 +458,7 @@ impl Tasks { &mut s .1 .split_ascii_whitespace() - .map(|t| Hashtag(t.to_string())) + .map(|t| Hashtag(t.to_string()).into()) .collect(), ); build_task(s.0, tags) @@ -515,7 +504,7 @@ impl Tasks { } pub(crate) fn add(&mut self, event: Event) { - match event.kind.as_u64() { + match event.kind.as_u16() { TASK_KIND => self.add_task(event), TRACKING_KIND => match self.history.get_mut(&event.pubkey) { @@ -596,7 +585,7 @@ fn display_time(format: &str, secs: u64) -> String { .map_or(String::new(), |mins| format .replace("MMM", &format!("{:3}", mins)) .replace("HH", &format!("{:02}", mins.div(60))) - .replace("MM", &format!("{:02}", mins.rem(60))) + .replace("MM", &format!("{:02}", mins.rem(60))), ) } @@ -654,9 +643,29 @@ fn stub_tasks() -> Tasks { } #[test] -fn test_depth() { +fn test_tracking() { let mut tasks = stub_tasks(); + //let task = tasks.make_task("task"); + tasks.track_at(Timestamp::from(0)); + assert_eq!(tasks.history.len(), 1); + let zero = EventId::all_zeros(); + + tasks.move_to(Some(zero)); + let now: Timestamp = Timestamp::now() - 2u64; + tasks.track_at(Timestamp::from(1)); + assert!(tasks.time_tracked(zero) > now.as_u64()); + + tasks.move_to(None); + tasks.track_at(Timestamp::from(2)); + assert_eq!(tasks.history.values().nth(0).unwrap().len(), 5); + assert_eq!(tasks.time_tracked(zero), 2); +} + +#[test] +fn test_depth() { + let mut tasks = stub_tasks(); + let t1 = tasks.make_task("t1"); let task1 = tasks.get_by_id(&t1).unwrap(); assert_eq!(tasks.depth, 1);