response.rs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. //! Response Message
  2. //!
  3. //! Message response from relayer to clients
  4. use crate::{common::SerializeDeserialize, relayer};
  5. use serde::{
  6. de::{self, Deserializer},
  7. ser::{self, SerializeSeq, Serializer},
  8. Deserialize,
  9. };
  10. use std::collections::VecDeque;
  11. custom_derive! {
  12. #[derive(Debug, Clone, EnumFromInner)]
  13. /// Response Message
  14. ///
  15. /// All responses from relayers to clients are abstracted in this struct
  16. pub enum Response {
  17. /// Server Authentication challenge
  18. Auth(relayer::Auth),
  19. /// The server replies an OK
  20. Ok(relayer::ROk),
  21. /// This is how server communicates about errors (most likely protocol
  22. /// errors) to the client
  23. Notice(relayer::Notice),
  24. /// The relayer sends an event. This happens when an event matches
  25. /// subscription that was created by a request
  26. Event(relayer::Event),
  27. /// The relayer sent all the events that matches your request already, from
  28. /// now on, new events will be relayed as they appear and matches your
  29. /// request
  30. EndOfStoredEvents(relayer::EndOfStoredEvents),
  31. }
  32. }
  33. impl Response {
  34. /// Returns the current Message as an EndOfStorageEvent, if possible
  35. pub fn as_end_of_stored_events(&self) -> Option<&relayer::EndOfStoredEvents> {
  36. match self {
  37. Self::EndOfStoredEvents(subscription_id) => Some(subscription_id),
  38. _ => None,
  39. }
  40. }
  41. /// Returns the message as current server as an event generated by a
  42. /// relayer, if possible
  43. pub fn as_event(&self) -> Option<&relayer::Event> {
  44. match self {
  45. Self::Event(event) => Some(event),
  46. _ => None,
  47. }
  48. }
  49. /// Returns the message as auth challenge, if possible
  50. pub fn as_auth(&self) -> Option<&relayer::Auth> {
  51. match self {
  52. Self::Auth(auth) => Some(auth),
  53. _ => None,
  54. }
  55. }
  56. /// Returns the current message as a notice, if possible
  57. pub fn as_notice(&self) -> Option<&relayer::Notice> {
  58. match self {
  59. Self::Notice(x) => Some(x),
  60. _ => None,
  61. }
  62. }
  63. /// Returns the current message as a server ok if possible
  64. pub fn as_ok(&self) -> Option<&relayer::ROk> {
  65. match self {
  66. Self::Ok(server_ok) => Some(server_ok),
  67. _ => None,
  68. }
  69. }
  70. }
  71. impl ser::Serialize for Response {
  72. fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  73. where
  74. S: Serializer,
  75. {
  76. let values = match self {
  77. Self::Auth(t) => t.serialize(),
  78. Self::Ok(t) => t.serialize(),
  79. Self::Notice(t) => t.serialize(),
  80. Self::Event(t) => t.serialize(),
  81. Self::EndOfStoredEvents(t) => t.serialize(),
  82. }
  83. .map_err(ser::Error::custom)?;
  84. let mut seq = serializer.serialize_seq(Some(values.len()))?;
  85. for value in values.iter() {
  86. seq.serialize_element(value)?;
  87. }
  88. seq.end()
  89. }
  90. }
  91. impl<'de> de::Deserialize<'de> for Response {
  92. fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
  93. where
  94. D: Deserializer<'de>,
  95. {
  96. let mut array: VecDeque<serde_json::Value> = Deserialize::deserialize(deserializer)?;
  97. if array.is_empty() {
  98. return Err(de::Error::custom(
  99. "Invalid array length, expecting at least one",
  100. ));
  101. }
  102. let tag = array
  103. .remove(0)
  104. .ok_or_else(|| de::Error::custom("Invalid array length, expecting at least one"))?;
  105. let tag = tag
  106. .as_str()
  107. .ok_or_else(|| de::Error::custom("Invalid type for element 0 of the array"))?;
  108. match tag {
  109. "AUTH" => Ok(relayer::Auth::deserialize(array)
  110. .map_err(de::Error::custom)?
  111. .into()),
  112. "EOSE" => Ok(relayer::EndOfStoredEvents::deserialize(array)
  113. .map_err(de::Error::custom)?
  114. .into()),
  115. "EVENT" => Ok(relayer::Event::deserialize(array)
  116. .map_err(de::Error::custom)?
  117. .into()),
  118. "OK" => Ok(relayer::ROk::deserialize(array)
  119. .map_err(de::Error::custom)?
  120. .into()),
  121. "NOTICE" => Ok(relayer::Notice::deserialize(array)
  122. .map_err(de::Error::custom)?
  123. .into()),
  124. tag => Err(de::Error::custom(format!("{} is not a support tag", tag))),
  125. }
  126. }
  127. }
  128. #[cfg(test)]
  129. mod test {
  130. use crate::types::{content::EncryptedData, Content};
  131. use super::*;
  132. #[test]
  133. fn unsupported() {
  134. let json = "[\"CLOSEX\", \"foo\"]";
  135. let message: Result<Response, _> = serde_json::from_str(json);
  136. assert!(message.is_err());
  137. }
  138. #[test]
  139. fn event() {
  140. let json = "[\"EVENT\",\"640bddcc93eae\",{\"content\":\"🤙\",\"created_at\":1676637072,\"id\":\"a3eaa71e4f46c1a69ac0596ae7c2af35807fc0b0d3b208b79a36eef67ef51743\",\"kind\":7,\"pubkey\":\"b2815682cfc83fcd2c3add05785cf4573dd388457069974cc6d8cca06b3c3b78\",\"sig\":\"93a3e9c4f6cb9a704885c4f77f6d7b16153e8eedc967603602606147f8c78d426f547d54120b80b33bd2101de638c06f2932df4daf53d66ca9b1341f2fd45729\",\"tags\":[[\"p\",\"8fe53b37518e3dbe9bab26d912292001d8b882de9456b7b08b615f912dc8bf4a\",\"\",\"mention\"],[\"e\",\"eb278e983fcedbb0d143c4250c879d078d037586c5dca8e1cf1a104f9846a460\"],[\"p\",\"2bda4f03446bc1c6ff00594e350a1e7ec57fb9cdc4a7b52694223d56ce0599e9\"]]}]";
  141. let message: Response = serde_json::from_str(json).expect("valid message");
  142. assert!(message.as_event().is_some());
  143. let relayer_event = message.as_event().expect("event");
  144. assert_eq!(
  145. "🤙".to_owned(),
  146. relayer_event
  147. .event
  148. .inner
  149. .content
  150. .try_to_string()
  151. .expect("string")
  152. );
  153. }
  154. #[test]
  155. fn follow_list() {
  156. 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"]]}]"#;
  157. let message: Response = serde_json::from_str(json).expect("valid message");
  158. assert!(message.as_event().is_some());
  159. let relayer_event = message.as_event().expect("event");
  160. assert_eq!(relayer_event.event.inner.tags.len(), 14);
  161. relayer_event
  162. .event
  163. .inner
  164. .tags
  165. .iter()
  166. .map(|tag| {
  167. tag.is_pubkey();
  168. })
  169. .for_each(drop);
  170. }
  171. #[test]
  172. fn direct_message() {
  173. 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"]]}]"#;
  174. let message: Response = serde_json::from_str(json).expect("valid message");
  175. assert!(message.as_event().is_some());
  176. let relayer_event = message.as_event().expect("event");
  177. let content = Content::EncryptedDirectMessage(EncryptedData {
  178. encrypted_message: vec![
  179. 255, 213, 228, 224, 247, 196, 23, 200, 84, 248, 45, 112, 171, 136, 43, 195,
  180. ],
  181. iv: vec![
  182. 92, 31, 242, 180, 184, 75, 209, 98, 144, 214, 135, 248, 193, 114, 23, 10,
  183. ],
  184. });
  185. assert_eq!(relayer_event.event.inner.tags.len(), 1);
  186. assert_eq!(relayer_event.event.inner.content, content);
  187. }
  188. #[test]
  189. fn bug_parse() {
  190. let jsons = vec![
  191. r#"["EVENT","65de5ded3b1960367ccae928692544b2630896e045bb9082ddc6cb05d678ecf7",{"content":"","created_at":1679327540,"id":"56162b1e00a502b42fe16af333cda73df343deb88d763a0c723ba2fcd0ccb4b8","kind":3,"pubkey":"6adeb3c955af227fb215a6eb345144ce0fe655e81464c1b457fd51a1d6fb241d","sig":"557cb52749e5acf07c3d5600df0993870a6c668f9077ad32a781f1fc329e0cbad35c341991be304539ae75ef4e55919396de2027aae3ee5a1c9ede83016f4538","tags":[["p","82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2"],["p","1577e4599dd10c863498fe3c20bd82aafaf829a595ce83c5cf8ac3463531b09b"],["p","3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"],["p","32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245"]]}]"#,
  192. r#"["EVENT","55713e193b8e22ab26f266cb5266cc221ac3b61fb8c16d75947034730ba1e07e",{"content":"{\"wss://relay.ryzizub.com\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://nostr.zebedee.cloud\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.nostr.info\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.plebstr.com\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.current.fyi\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.nostr.band\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://nos.lol\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://offchain.pub\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.stoner.com\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.nostr.scot\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.nostrica.com\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.nostr.band/\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.snort.social\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://relay.damus.io\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://eden.nostr.land\":\"{\\\"read\\\":true,\\\"write\\\":true}\",\"wss://puravida.nostr.land\":\"{\\\"read\\\":true,\\\"write\\\":true}\"}","created_at":1679328880,"id":"606a0934dc58890c2a2ea1be31065ed7884f03ca0e069dc23bd48857f865c9b6","kind":3,"pubkey":"24692f1cd96450701c06781dcfd78c3bc010933f51364ac0c4693d4c257851d6","sig":"d78f34083b4bcbd4dd006b1b3ab2c1de747bf695ef2d160c55a74f01efad0a96c05c7b3f62a42d6d69c2dfedb8a334a562c2d6e9be386145458456c5ab81ab15","tags":[["p","24692f1cd96450701c06781dcfd78c3bc010933f51364ac0c4693d4c257851d6"],["p","5a9c48c8f4782351135dd89c5d8930feb59cb70652ffd37d9167bf922f2d1069"],["p","0fe0b18b4dbf0e0aa40fcd47209b2a49b3431fc453b460efcf45ca0bd16bd6ac"],["p","c83723d33fa86c8f01b254b1dcaaa025b2ca659320950d044d22c41b5d1daf29"],["p","2edbcea694d164629854a52583458fd6d965b161e3c48b57d3aff01940558884"],["p","82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2"],["p","85080d3bad70ccdcd7f74c29a44f55bb85cbcd3dd0cbb957da1d215bdb931204"],["p","d7f0e3917c466f1e2233e9624fbd6d4bd1392dbcfcaf3574f457569d496cb731"],["p","1989034e56b8f606c724f45a12ce84a11841621aaf7182a1f6564380b9c4276b"],["p","eaf1a13a032ce649bc60f290a000531c4d525f6a7a28f74326972c4438682f56"],["p","e75da451e9e743b43cfb9a0d7f30c4df7272e7e53b03e999e17cedc7b8eb40b8"],["p","69aeace80672c08ef7729a03e597ed4e9dd5ddaa7c457349d55d12c043e8a7ab"],["p","ecb3fd820e9a7a78bb919e5e7eb4bf256471389e896041c5e7d4d6fd4828e9dd"],["p","ec206da7bca2736b435573de731f19fccb50b7dd233bcc3b5e19436128bcf405"],["p","045745ac0e90a436141a3addd95575c2ead47b613f45287283e5802ff7fd99fd"],["p","6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93"]]}]"#,
  193. r#"["EVENT","temp:305",{"content":"","created_at":1679329202,"id":"3450f44da3b908837156d7edf7c7fb3d15a0e05dc0921f1af73428a42070114d","kind":0,"pubkey":"5d61e8ee6eedf331fe3f79e3b4ca371d2486bd275bbbc35db0c3d8f03f94af8f","sig":"9507a8f041cd4a6f48a2bdd6e3ae6d41e0e874ae2498fa4e5c81fc91b9211d08873b74ad8997a5d73cd51f3a02a1f33b3209c0830e90bc76237dac1e4a9385e8","tags":[["i","github:DarrenMedrano","a18b295404d8ee3963284927af941190"]]}]"#,
  194. ];
  195. jsons
  196. .iter()
  197. .map(|json| {
  198. let message: Response = serde_json::from_str(json).expect("valid message");
  199. assert!(message.as_event().is_some());
  200. })
  201. .for_each(drop);
  202. }
  203. }