1use crate::{Dialog, Note, Result};
2use nostr_sdk::prelude::*;
3use std::collections::HashSet;
4use tokio::sync::mpsc;
5
6impl Dialog {
7 pub async fn watch_notes(&self) -> Result<mpsc::Receiver<Note>> {
8 let (tx, rx) = mpsc::channel(100);
9
10 let client = self.client.clone();
11 let keys = self.keys.clone();
12 let pubkey = self.keys.public_key();
13
14 let filter = Filter::new()
16 .author(pubkey)
17 .kind(Kind::from(1059))
18 .since(Timestamp::now());
19
20 eprintln!("DEBUG: Creating subscription with filter: {filter:?}");
21 let output = self.client.subscribe(vec![filter], None).await?;
22 let sub_id = output.val;
23 eprintln!("DEBUG: Subscription created with id: {sub_id}");
24
25 tokio::spawn(async move {
26 let mut notifications = client.notifications();
27 let mut seen_ids = HashSet::new();
28
29 eprintln!("DEBUG: Watch task started, entering loop");
30 loop {
31 eprintln!("DEBUG: Waiting for notification...");
32 match notifications.recv().await {
33 Ok(RelayPoolNotification::Message { message, .. }) => {
34 if let RelayMessage::Event {
35 subscription_id,
36 event,
37 } = message
38 {
39 eprintln!(
40 "DEBUG: Got event from subscription: {subscription_id} (our id: {sub_id})",
41 );
42 if subscription_id == sub_id
43 && event.kind == Kind::from(1059)
44 && event.pubkey == pubkey
45 && !seen_ids.contains(&event.id)
46 {
47 if let Ok(decrypted) = decrypt_event(&keys, &event) {
48 let note = Note {
49 id: event.id,
50 text: decrypted,
51 tags: extract_tags(&event),
52 created_at: event.created_at,
53 is_read: false, is_synced: true, };
56
57 seen_ids.insert(event.id);
58 let _ = tx.send(note).await;
59 eprintln!("DEBUG: Sent note to channel");
60 }
61 }
62 }
63 }
64 Ok(RelayPoolNotification::Event { event, .. }) => {
65 eprintln!("DEBUG: Got direct event notification");
67 if event.kind == Kind::from(1059)
68 && event.pubkey == pubkey
69 && !seen_ids.contains(&event.id)
70 {
71 if let Ok(decrypted) = decrypt_event(&keys, &event) {
72 let note = Note {
73 id: event.id,
74 text: decrypted,
75 tags: extract_tags(&event),
76 created_at: event.created_at,
77 is_read: false, is_synced: true, };
80
81 seen_ids.insert(event.id);
82 let _ = tx.send(note).await;
83 }
84 }
85 }
86 Ok(other) => {
87 eprintln!("DEBUG: Got other notification: {other:?}");
88 continue;
89 }
90 Err(e) => {
91 eprintln!("DEBUG: Error receiving notification: {e:?}");
92 break;
93 }
94 }
95 }
96 eprintln!("DEBUG: Watch loop exited!");
97 });
98
99 eprintln!("DEBUG: Returning receiver");
100 Ok(rx)
101 }
102}
103
104fn decrypt_event(keys: &Keys, event: &Event) -> Result<String> {
106 let decrypted = nip44::decrypt(keys.secret_key(), &keys.public_key(), &event.content)?;
107 Ok(decrypted)
108}
109
110fn extract_tags(event: &Event) -> Vec<String> {
112 event
113 .tags
114 .iter()
115 .filter_map(|tag| {
116 if let Some(TagStandard::Hashtag(t)) = tag.as_standardized() {
117 Some(t.to_string())
118 } else {
119 None
120 }
121 })
122 .collect()
123}