nostr_types/types/
relay_message.rs1use crate::types::{Event, Id, SubscriptionId};
2use serde::de::Error as DeError;
3use serde::de::{Deserialize, Deserializer, IgnoredAny, SeqAccess, Visitor};
4use serde::ser::{Serialize, SerializeSeq, Serializer};
5use std::fmt;
6
7#[derive(Clone, Debug, Eq, PartialEq)]
9pub enum RelayMessage {
10 Auth(String),
12
13 Closed(SubscriptionId, String),
19
20 Eose(SubscriptionId),
22
23 Event(SubscriptionId, Box<Event>),
25
26 Notice(String),
28
29 Notify(String),
31
32 Ok(Id, bool, String),
38
39 Count(SubscriptionId, CountResult),
41}
42
43#[derive(Debug, Clone, Eq, PartialEq, Hash, serde::Serialize, serde::Deserialize)]
45pub struct CountResult {
46 pub count: usize,
48
49 #[serde(default)]
51 pub approximate: bool,
52
53 #[serde(default)]
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub hll: Option<String>,
57}
58
59#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
61pub enum Why {
62 AuthRequired,
64
65 Blocked,
67
68 Duplicate,
70
71 Error,
73
74 Invalid,
76
77 Pow,
79
80 RateLimited,
82
83 Restricted,
85}
86
87impl RelayMessage {
88 pub fn why(&self) -> Option<Why> {
90 let s = match *self {
91 RelayMessage::Closed(_, ref s) => s,
92 RelayMessage::Ok(_, _, ref s) => s,
93 _ => return None,
94 };
95
96 match s.split(':').next() {
97 Some("auth-required") => Some(Why::AuthRequired),
98 Some("blocked") => Some(Why::Blocked),
99 Some("duplicate") => Some(Why::Duplicate),
100 Some("error") => Some(Why::Error),
101 Some("invalid") => Some(Why::Invalid),
102 Some("pow") => Some(Why::Pow),
103 Some("rate-limited") => Some(Why::RateLimited),
104 Some("restricted") => Some(Why::Restricted),
105 _ => None,
106 }
107 }
108
109 #[allow(dead_code)]
111 pub(crate) async fn mock() -> RelayMessage {
112 RelayMessage::Event(SubscriptionId::mock(), Box::new(Event::mock().await))
113 }
114}
115
116impl Serialize for RelayMessage {
117 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
118 where
119 S: Serializer,
120 {
121 match self {
122 RelayMessage::Auth(challenge) => {
123 let mut seq = serializer.serialize_seq(Some(2))?;
124 seq.serialize_element("AUTH")?;
125 seq.serialize_element(&challenge)?;
126 seq.end()
127 }
128 RelayMessage::Closed(id, message) => {
129 let mut seq = serializer.serialize_seq(Some(3))?;
130 seq.serialize_element("CLOSED")?;
131 seq.serialize_element(&id)?;
132 seq.serialize_element(&message)?;
133 seq.end()
134 }
135 RelayMessage::Eose(id) => {
136 let mut seq = serializer.serialize_seq(Some(2))?;
137 seq.serialize_element("EOSE")?;
138 seq.serialize_element(&id)?;
139 seq.end()
140 }
141 RelayMessage::Event(id, event) => {
142 let mut seq = serializer.serialize_seq(Some(3))?;
143 seq.serialize_element("EVENT")?;
144 seq.serialize_element(&id)?;
145 seq.serialize_element(&event)?;
146 seq.end()
147 }
148 RelayMessage::Notice(s) => {
149 let mut seq = serializer.serialize_seq(Some(2))?;
150 seq.serialize_element("NOTICE")?;
151 seq.serialize_element(&s)?;
152 seq.end()
153 }
154 RelayMessage::Notify(s) => {
155 let mut seq = serializer.serialize_seq(Some(2))?;
156 seq.serialize_element("NOTIFY")?;
157 seq.serialize_element(&s)?;
158 seq.end()
159 }
160 RelayMessage::Ok(id, ok, message) => {
161 let mut seq = serializer.serialize_seq(Some(4))?;
162 seq.serialize_element("OK")?;
163 seq.serialize_element(&id)?;
164 seq.serialize_element(&ok)?;
165 seq.serialize_element(&message)?;
166 seq.end()
167 }
168 RelayMessage::Count(sub, result) => {
169 let mut seq = serializer.serialize_seq(Some(3))?;
170 seq.serialize_element("COUNT")?;
171 seq.serialize_element(&sub)?;
172 seq.serialize_element(&result)?;
173 seq.end()
174 }
175 }
176 }
177}
178
179impl<'de> Deserialize<'de> for RelayMessage {
180 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
181 where
182 D: Deserializer<'de>,
183 {
184 deserializer.deserialize_seq(RelayMessageVisitor)
185 }
186}
187
188struct RelayMessageVisitor;
189
190impl<'de> Visitor<'de> for RelayMessageVisitor {
191 type Value = RelayMessage;
192
193 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
194 write!(f, "a sequence of strings")
195 }
196
197 fn visit_seq<A>(self, mut seq: A) -> Result<RelayMessage, A::Error>
198 where
199 A: SeqAccess<'de>,
200 {
201 let word: &str = seq
202 .next_element()?
203 .ok_or_else(|| DeError::custom("Message missing initial string field"))?;
204 let mut output: Option<RelayMessage> = None;
205 if word == "EVENT" {
206 let id: SubscriptionId = seq
207 .next_element()?
208 .ok_or_else(|| DeError::custom("Message missing id field"))?;
209 let event: Event = seq
210 .next_element()?
211 .ok_or_else(|| DeError::custom("Message missing event field"))?;
212 output = Some(RelayMessage::Event(id, Box::new(event)));
213 } else if word == "NOTICE" {
214 let s: String = seq
215 .next_element()?
216 .ok_or_else(|| DeError::custom("Message missing string field"))?;
217 output = Some(RelayMessage::Notice(s));
218 } else if word == "NOTIFY" {
219 let s: String = seq
220 .next_element()?
221 .ok_or_else(|| DeError::custom("Message missing string field"))?;
222 output = Some(RelayMessage::Notify(s));
223 } else if word == "EOSE" {
224 let id: SubscriptionId = seq
225 .next_element()?
226 .ok_or_else(|| DeError::custom("Message missing id field"))?;
227 output = Some(RelayMessage::Eose(id))
228 } else if word == "OK" {
229 let id: Id = seq
230 .next_element()?
231 .ok_or_else(|| DeError::custom("Message missing id field"))?;
232 let ok: bool = seq
233 .next_element()?
234 .ok_or_else(|| DeError::custom("Message missing ok field"))?;
235 let message: String = seq
236 .next_element()?
237 .ok_or_else(|| DeError::custom("Message missing string field"))?;
238 output = Some(RelayMessage::Ok(id, ok, message));
239 } else if word == "AUTH" {
240 let challenge: String = seq
241 .next_element()?
242 .ok_or_else(|| DeError::custom("Message missing challenge field"))?;
243 output = Some(RelayMessage::Auth(challenge));
244 } else if word == "CLOSED" {
245 let id: SubscriptionId = seq
246 .next_element()?
247 .ok_or_else(|| DeError::custom("Message messing id field"))?;
248 let message: String = seq
249 .next_element()?
250 .ok_or_else(|| DeError::custom("Message missing string field"))?;
251 output = Some(RelayMessage::Closed(id, message));
252 } else if word == "COUNT" {
253 let id: SubscriptionId = seq
254 .next_element()?
255 .ok_or_else(|| DeError::custom("Message messing id field"))?;
256 let count_result: CountResult = seq
257 .next_element()?
258 .ok_or_else(|| DeError::custom("Message messing count result object field"))?;
259 output = Some(RelayMessage::Count(id, count_result));
260 }
261
262 while let Some(_ignored) = seq.next_element::<IgnoredAny>()? {}
264
265 match output {
266 Some(rm) => Ok(rm),
267 None => Err(DeError::custom(format!("Unknown Message: {word}"))),
268 }
269 }
270}
271
272#[cfg(test)]
273mod test {
274 use super::*;
275
276 test_serde_async! {RelayMessage, test_relay_message_serde}
277}