use crate::{Dialog, Result};
use nostr_sdk::prelude::*;
#[derive(Debug, Clone)]
pub struct Note {
pub id: EventId,
pub text: String,
pub tags: Vec<String>,
pub created_at: Timestamp,
pub is_read: bool,
pub is_synced: bool,
}
impl Dialog {
pub async fn create_note(&self, text: &str) -> Result<EventId> {
eprintln!("[lib] create_note: building event (len={})", text.len());
let tags = parse_hashtags(text);
let encrypted = nip44::encrypt(
self.keys.secret_key(),
&self.keys.public_key(), text,
nip44::Version::default(),
)?;
let mut builder = EventBuilder::new(Kind::from(1059), encrypted);
for tag in &tags {
builder = builder.tag(Tag::hashtag(tag.to_lowercase()));
}
builder = builder.tag(Tag::public_key(self.keys.public_key()));
let output = self.client.send_event_builder(builder).await?;
eprintln!("[lib] create_note: sent; id={}", output.id());
Ok(*output.id())
}
pub(crate) fn decrypt_event(&self, event: &Event) -> Result<String> {
let decrypted = nip44::decrypt(
self.keys.secret_key(),
&self.keys.public_key(),
&event.content,
)?;
Ok(decrypted)
}
}
fn parse_hashtags(text: &str) -> Vec<String> {
text.split_whitespace()
.filter(|word| word.starts_with('#') && word.len() > 1)
.map(|tag| tag[1..].to_lowercase())
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_hashtags() {
let text = "This is a #Test note with #Multiple #TAGS";
let tags = parse_hashtags(text);
assert_eq!(tags, vec!["test", "multiple", "tags"]);
}
#[test]
fn test_parse_hashtags_empty() {
let text = "This has no hashtags";
let tags = parse_hashtags(text);
assert!(tags.is_empty());
}
#[test]
fn test_parse_hashtags_just_hash() {
let text = "This has just # and nothing else";
let tags = parse_hashtags(text);
assert!(tags.is_empty());
}
}