use nostr_rs_types::types::{Event, Filter, Tag}; #[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Ord, Hash)] pub struct Subscription { author: Option>, ref_public_key: Option>, ref_id: Option>, id: Option>, kind: Option, } impl Subscription { #[inline] pub fn from_filters(filters: &[Filter]) -> Vec { let mut subs = vec![]; filters.iter().for_each(|filter| { let authors: Vec>> = if filter.authors.is_empty() { vec![None] } else { filter .authors .iter() .map(|author| Some(author.to_vec())) .collect() }; let ref_public_keys = if filter.references_to_public_key.is_empty() { vec![None] } else { filter .references_to_public_key .iter() .map(|public_key| Some((*public_key).to_vec())) .collect() }; let ref_ids = if filter.references_to_event.is_empty() { vec![None] } else { filter .references_to_event .iter() .map(|id| Some((*id).to_vec())) .collect() }; let kind = if filter.kinds.is_empty() { vec![None] } else { filter .kinds .iter() .map(|kind| Some((*kind).into())) .collect() }; let ids = if filter.ids.is_empty() { vec![None] } else { filter.ids.iter().map(|id| Some((*id).to_vec())).collect() }; for author in authors.iter() { for id in ids.iter() { for ref_public_key in ref_public_keys.iter() { for ref_id in ref_ids.iter() { for kind in kind.iter() { subs.push(Subscription { id: id.clone(), ref_public_key: ref_public_key.clone(), author: author.clone(), ref_id: ref_id.clone(), kind: *kind, }); } } } } } }); subs } #[inline] pub fn from_event(event: &Event) -> Vec { let kind = event.kind().into(); let public_keys = vec![None, Some(event.author().as_ref().to_vec())]; let id = vec![None, Some(event.id.as_ref().to_vec())]; let kind = [None, Some(kind)]; let mut ref_public_keys = vec![None]; let mut ref_ids = vec![None]; event.tags().iter().for_each(|tag| match tag { Tag::Event(x) => { ref_ids.push(Some(x.id.as_ref().to_vec())); } Tag::PubKey(x) => { ref_public_keys.push(Some(x.id.as_ref().to_vec())); } _ => {} }); let mut subs = vec![]; for ref_public_key in ref_public_keys.iter() { for ref_id in ref_ids.iter() { for public_key in public_keys.iter() { for id in id.iter() { for kind in kind.iter() { subs.push(Subscription { ref_id: ref_id.clone(), ref_public_key: ref_public_key.clone(), author: public_key.clone(), id: id.clone(), kind: *kind, }); } } } } } subs } } #[cfg(test)] mod test { use super::*; use nostr_rs_types::{types::Addr, Request}; #[test] fn test_no_listen_to_all() { let request: Request = serde_json::from_str("[\"REQ\",\"6440d5279e350\",{\"authors\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"since\":1681967101},{\"#p\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"kinds\":[1,3,6,7,9735],\"since\":1681967101},{\"#p\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"kinds\":[4]},{\"authors\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"kinds\":[4]},{\"#e\":[\"2e72250d80e9b3fd30230b3db3ed7d22f15d266ed345c36700b01ec153c9e28a\",\"a5e3369c43daf2675ecbce18831e5f4e07db0d4dde0ef4f5698e645e4c46eed1\"],\"kinds\":[1,6,7,9735]}]").expect("valid"); let mut subscriptions = Subscription::from_filters(&request.as_request().expect("req").filters); subscriptions.sort(); assert!(subscriptions .binary_search(&Subscription::default()) .is_err()) } #[test] fn from_filters() { let request: Request = serde_json::from_str("[\"REQ\",\"1298169700973717\",{\"authors\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"since\":1681939304},{\"#p\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"kinds\":[1,3,6,7,9735],\"since\":1681939304},{\"#p\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"kinds\":[4]},{\"authors\":[\"39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb\"],\"kinds\":[4]},{\"#e\":[\"2e72250d80e9b3fd30230b3db3ed7d22f15d266ed345c36700b01ec153c9e28a\",\"a5e3369c43daf2675ecbce18831e5f4e07db0d4dde0ef4f5698e645e4c46eed1\"],\"kinds\":[1,6,7,9735]}]").expect("valid object"); let mut subscriptions = Subscription::from_filters(&request.as_request().expect("req").filters); subscriptions.sort(); assert!(subscriptions .binary_search(&Subscription::default()) .is_err()) } #[test] fn from_event() { let new_event: Request = serde_json::from_str(r#"["EVENT", {"kind":1,"content":"Pong","tags":[["e","9508850d7ddc8ef58c8b392236c49d472dc23fa11f4e73eb5475dfb099ddff42","","root"],["e","2e72250d80e9b3fd30230b3db3ed7d22f15d266ed345c36700b01ec153c9e28a","","reply"],["p","39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb"],["p","ee7202ad91459e013bfef263c59e47deb0163a5e7651b026673765488bfaf102"]],"created_at":1681938616,"pubkey":"a42007e33cfa25673b26f46f39df039aa6003258a68dc88f1f1e0447607aedb3","id":"e862fe23daf52ab09b36a37fa91ca3743e0c323e630e8627891212ca147c2da9","sig":"9036150a6c8a32933cffcc42aec4d2109a22e9f10d1c3860c0435a925e6386babb7df5c95fcf68c8ed6a9726a1f07225af663d0b068eb555014130aad21674fc","meta":{"revision":0,"created":1681939266488,"version":0},"$loki":108}]"#).expect("value"); let mut subscriptions = Subscription::from_event(&new_event.as_event().expect("event")); subscriptions.sort(); let pk: Addr = "39a7d06e824c0c2523bedb93f0cef84245e4401fee03b6257a1c6dfd18b57efb" .try_into() .expect("id"); let id: Addr = "e862fe23daf52ab09b36a37fa91ca3743e0c323e630e8627891212ca147c2da9" .try_into() .expect("id"); let ref_id: Addr = "2e72250d80e9b3fd30230b3db3ed7d22f15d266ed345c36700b01ec153c9e28a" .try_into() .expect("id"); let author: Addr = "a42007e33cfa25673b26f46f39df039aa6003258a68dc88f1f1e0447607aedb3" .try_into() .expect("id"); let expected = vec![ Subscription { ref_public_key: Some(pk.as_ref().to_vec()), ..Subscription::default() }, Subscription { id: Some(id.as_ref().to_vec()), ref_public_key: Some(pk.as_ref().to_vec()), ..Subscription::default() }, Subscription { id: Some(id.as_ref().to_vec()), ref_id: Some(ref_id.as_ref().to_vec()), ref_public_key: Some(pk.as_ref().to_vec()), ..Subscription::default() }, Subscription { author: Some(author.as_ref().to_vec()), kind: Some(1), ..Subscription::default() }, Subscription { author: Some(author.as_ref().to_vec()), ..Subscription::default() }, Subscription { id: Some(id.as_ref().to_vec()), ref_id: Some(ref_id.as_ref().to_vec()), author: Some(author.as_ref().to_vec()), ..Subscription::default() }, ]; assert_eq!(subscriptions.len(), 72); expected.iter().enumerate().for_each(|(i, sub)| { assert!( subscriptions.binary_search(sub).is_ok(), "{} -> {:?}", i, sub ); }); assert!(subscriptions .binary_search(&Subscription::default()) .is_ok()); } }