lib.rs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. use serde::{
  2. de::{self, Deserializer},
  3. Deserialize, Serialize,
  4. };
  5. use std::convert::TryFrom;
  6. use thiserror::Error;
  7. use types::{Event, SubscriptionId};
  8. pub mod client;
  9. pub mod types;
  10. #[derive(Debug, Error)]
  11. pub enum Error {}
  12. #[derive(Serialize, Debug, Clone)]
  13. pub enum Message {
  14. Close(types::SubscriptionId),
  15. EventFromClient(types::Event),
  16. EventFromServer(types::SubscriptionId, types::Event),
  17. Request(client::Request),
  18. Notice(String),
  19. EndOfStoredEvents(String),
  20. }
  21. impl Message {
  22. pub fn as_request(&self) -> Option<&client::Request> {
  23. match self {
  24. Self::Request(x) => Some(x),
  25. _ => None,
  26. }
  27. }
  28. pub fn as_end_of_stored_events(&self) -> Option<&str> {
  29. match self {
  30. Self::EndOfStoredEvents(subscription_id) => Some(subscription_id),
  31. _ => None,
  32. }
  33. }
  34. pub fn as_event_from_server(&self) -> Option<(&types::SubscriptionId, &types::Event)> {
  35. match self {
  36. Self::EventFromServer(id, event) => Some((id, event)),
  37. _ => None,
  38. }
  39. }
  40. pub fn as_event_from_client(&self) -> Option<&types::Event> {
  41. match self {
  42. Self::EventFromClient(event) => Some(event),
  43. _ => None,
  44. }
  45. }
  46. pub fn as_notice(&self) -> Option<&str> {
  47. match self {
  48. Self::Notice(x) => Some(x),
  49. _ => None,
  50. }
  51. }
  52. pub fn as_close_subscription_id(&self) -> Option<&types::SubscriptionId> {
  53. match self {
  54. Self::Close(x) => Some(x),
  55. _ => None,
  56. }
  57. }
  58. }
  59. impl<'de> de::Deserialize<'de> for Message {
  60. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  61. where
  62. D: Deserializer<'de>,
  63. {
  64. let array: Vec<serde_json::Value> = Deserialize::deserialize(deserializer)?;
  65. if array.is_empty() {
  66. return Err(de::Error::custom(
  67. "Invalid array length, expecting at least one",
  68. ));
  69. }
  70. let tag = array
  71. .get(0)
  72. .ok_or_else(|| de::Error::custom("Invalid array length, expecting at least one"))?
  73. .as_str()
  74. .ok_or_else(|| de::Error::custom("Invalid type for element 0 of the array"))?;
  75. match tag {
  76. "EOSE" => {
  77. if array.len() != 2 {
  78. Err(de::Error::custom("Invalid length for EOSE"))
  79. } else {
  80. Ok(Self::EndOfStoredEvents(
  81. array[1]
  82. .as_str()
  83. .ok_or_else(|| {
  84. de::Error::custom("Invalid subscription_id, expecting string")
  85. })?
  86. .to_owned(),
  87. ))
  88. }
  89. }
  90. "EVENT" => match array.len() {
  91. 3 => {
  92. let subscription_id: SubscriptionId = array[1]
  93. .as_str()
  94. .map(TryFrom::try_from)
  95. .transpose()
  96. .map_err(|e: types::subscription_id::Error| {
  97. de::Error::custom(e.to_string())
  98. })?
  99. .ok_or_else(|| de::Error::custom("Invalid subscription ID"))?;
  100. let event: Event = serde_json::from_value(array[2].clone())
  101. .map_err(|e: serde_json::Error| de::Error::custom(e.to_string()))?;
  102. event
  103. .is_valid()
  104. .map_err(|e| de::Error::custom(e.to_string()))?;
  105. Ok(Self::EventFromServer(subscription_id, event))
  106. }
  107. 2 => {
  108. let event: Event = serde_json::from_value(array[1].clone())
  109. .map_err(|e: serde_json::Error| de::Error::custom(e.to_string()))?;
  110. event
  111. .is_valid()
  112. .map_err(|e| de::Error::custom(e.to_string()))?;
  113. Ok(Self::EventFromClient(event))
  114. }
  115. _ => Err(de::Error::custom("Invalid length for EVENT")),
  116. },
  117. "NOTICE" => Ok(Self::Notice(
  118. serde_json::from_value(
  119. array
  120. .get(1)
  121. .ok_or_else(|| de::Error::custom("Missing element 1 of the array"))?
  122. .clone(),
  123. )
  124. .map_err(|e: serde_json::Error| de::Error::custom(e.to_string()))?,
  125. )),
  126. "CLOSE" => Ok(Self::Close(
  127. serde_json::from_value(
  128. array
  129. .get(1)
  130. .ok_or_else(|| de::Error::custom("Missing element 1 of the array"))?
  131. .clone(),
  132. )
  133. .map_err(|e: serde_json::Error| de::Error::custom(e.to_string()))?,
  134. )),
  135. "REQ" => {
  136. let subscription_id = array
  137. .get(1)
  138. .ok_or_else(|| de::Error::custom("Missing element 1 in the array"))?
  139. .as_str()
  140. .ok_or_else(|| {
  141. de::Error::custom("Invalid type for element 1, expecting a string")
  142. })?
  143. .try_into()
  144. .map_err(|e: types::subscription_id::Error| {
  145. de::Error::custom(format!("Invalid subscription id: {}", e))
  146. })?;
  147. Ok(Self::Request(client::Request {
  148. subscription_id,
  149. filters: if array.len() > 2 {
  150. serde_json::from_value::<Vec<types::Filter>>(serde_json::Value::Array(
  151. array[2..].to_owned(),
  152. ))
  153. .map_err(|e: serde_json::Error| de::Error::custom(e.to_string()))?
  154. } else {
  155. vec![]
  156. },
  157. }))
  158. }
  159. tag => Err(de::Error::custom(format!("{} is not a support tag", tag))),
  160. }
  161. }
  162. }
  163. #[cfg(test)]
  164. mod test {
  165. use crate::types::{content::EncryptedData, Content};
  166. use super::*;
  167. #[test]
  168. fn unsupported() {
  169. let json = "[\"CLOSEX\", \"foo\"]";
  170. let message: Result<Message, _> = serde_json::from_str(json);
  171. assert!(message.is_err());
  172. }
  173. #[test]
  174. fn event_from_server() {
  175. let json = "[\"EVENT\",\"640bddcc93eae\",{\"content\":\"🤙\",\"created_at\":1676637072,\"id\":\"a3eaa71e4f46c1a69ac0596ae7c2af35807fc0b0d3b208b79a36eef67ef51743\",\"kind\":7,\"pubkey\":\"b2815682cfc83fcd2c3add05785cf4573dd388457069974cc6d8cca06b3c3b78\",\"sig\":\"93a3e9c4f6cb9a704885c4f77f6d7b16153e8eedc967603602606147f8c78d426f547d54120b80b33bd2101de638c06f2932df4daf53d66ca9b1341f2fd45729\",\"tags\":[[\"p\",\"8fe53b37518e3dbe9bab26d912292001d8b882de9456b7b08b615f912dc8bf4a\",\"\",\"mention\"],[\"e\",\"eb278e983fcedbb0d143c4250c879d078d037586c5dca8e1cf1a104f9846a460\"],[\"p\",\"2bda4f03446bc1c6ff00594e350a1e7ec57fb9cdc4a7b52694223d56ce0599e9\"]]}]";
  176. let message: Message = serde_json::from_str(json).expect("valid message");
  177. assert!(message.as_event_from_server().is_some());
  178. let (_, event) = message.as_event_from_server().expect("event");
  179. assert_eq!(
  180. "🤙".to_owned(),
  181. event.data.content.try_to_string().expect("string")
  182. );
  183. }
  184. #[test]
  185. fn follow_list() {
  186. let json = r#"["EVENT","640e914a22321",{"content":"{\"wss:\\/\\/nos.lol\":{\"write\":true,\"read\":true},\"wss:\\/\\/relay.damus.io\":{\"write\":true,\"read\":true},\"wss:\\/\\/brb.io\":{\"write\":true,\"read\":true},\"wss:\\/\\/nostr.orangepill.dev\":{\"write\":true,\"read\":true},\"wss:\\/\\/relay.current.fyi\":{\"write\":true,\"read\":true},\"wss:\\/\\/eden.nostr.land\":{\"write\":true,\"read\":true},\"wss:\\/\\/relay.snort.social\":{\"write\":true,\"read\":true}}","created_at":1678476548,"id":"b8d7f6a19c3d9625b9aade947166708fbc6ab2dd7e3f3af84f1de08ea10d6f38","kind":3,"pubkey":"b2815682cfc83fcd2c3add05785cf4573dd388457069974cc6d8cca06b3c3b78","sig":"352485a162805e72a1e278a4a7bc33facd54a71e0f4c23934f35eee57eaa38c62e6260bf7624e2bd96bc6bcf93373b06c5245e28a266bfe2fbf064224e713fd6","tags":[["p","3efdaebb1d8923ebd99c9e7ace3b4194ab45512e2be79c1b7d68d9243e0d2681"],["p","b2815682cfc83fcd2c3add05785cf4573dd388457069974cc6d8cca06b3c3b78"],["p","387519cafd325668ecffe59577f37238638da4cf2d985b82f932fc81d33da1e8"],["p","81d0ccce4591fc4e19e3ef752a2b003ef23a986cb31e7835ea7d8d7cd96d47ea"],["p","0861144c765ea10e39a48473a51bee604886e18abd0f831cc5ed7651e68a1caf"],["p","1779284c21126b5e1af6dcb84949ceacad781ce4ce0d1691292a41229465a54a"],["p","d7df5567015930b17c125b3a7cf29bef23aa5a68d09cd6518d291359606aab7b"],["p","82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2"],["p","32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"],["p","a47457722e10ba3a271fbe7040259a3c4da2cf53bfd1e198138214d235064fc2"],["p","e1055729d51e037b3c14e8c56e2c79c22183385d94aadb32e5dc88092cd0fef4"],["p","2bda4f03446bc1c6ff00594e350a1e7ec57fb9cdc4a7b52694223d56ce0599e9"],["p","c57717ec7a6af20b836a9468282948dc0adba64d30abfb40aa8c6664dde3cfc7"],["p","6094dd769f94fab1a2915c1a3d8360e49cec84977f433a872bea1763466db784"]]}]"#;
  187. let message: Message = serde_json::from_str(json).expect("valid message");
  188. assert!(message.as_event_from_server().is_some());
  189. let (_, event) = message.as_event_from_server().expect("event");
  190. assert_eq!(event.data.tags.len(), 14);
  191. event
  192. .data
  193. .tags
  194. .iter()
  195. .map(|tag| {
  196. tag.is_pubkey();
  197. })
  198. .for_each(drop);
  199. }
  200. #[test]
  201. fn direct_message() {
  202. let json = r#"["EVENT","640e9851d461a",{"content":"/9Xk4PfEF8hU+C1wq4grww==?iv=XB/ytLhL0WKQ1of4wXIXCg==","created_at":1677726088,"id":"4643c79276730e25a8510163622335bb9d44aecdd0c596409804abb29910652d","kind":4,"pubkey":"b2815682cfc83fcd2c3add05785cf4573dd388457069974cc6d8cca06b3c3b78","sig":"23790fae080eaa87f2abf2df4e5fd49cecc67e58271910d7e871fb197641294cad92c2a6fff1501982d776648eecb1e4650ccfbb742a2d901226a9b00c310489","tags":[["p","b2815682cfc83fcd2c3add05785cf4573dd388457069974cc6d8cca06b3c3b78"]]}]"#;
  203. let message: Message = serde_json::from_str(json).expect("valid message");
  204. assert!(message.as_event_from_server().is_some());
  205. let (_, event) = message.as_event_from_server().expect("event");
  206. let content = Content::DirectMessage(EncryptedData {
  207. encrypted_message: vec![
  208. 255, 213, 228, 224, 247, 196, 23, 200, 84, 248, 45, 112, 171, 136, 43, 195,
  209. ],
  210. iv: vec![
  211. 255, 213, 228, 224, 247, 196, 23, 200, 84, 248, 45, 112, 171, 136, 43, 195,
  212. ],
  213. });
  214. assert_eq!(event.data.tags.len(), 1);
  215. assert_eq!(event.data.content, content);
  216. }
  217. #[test]
  218. fn close() {
  219. let json = "[\"CLOSE\", \"foo\"]";
  220. let message: Message = serde_json::from_str(json).expect("valid message");
  221. let subscription_id = message
  222. .as_close_subscription_id()
  223. .expect("valid subscription_id");
  224. assert_eq!("foo".to_owned(), subscription_id.to_string());
  225. }
  226. }