1// Copyright (c) 2017 Maxime “pep” Buquet <pep+code@bouah.net>
2// Copyright (c) 2017 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at http://mozilla.org/MPL/2.0/.
7
8use crate::date::DateTime;
9use crate::presence::PresencePayload;
10
11generate_element!(
12 /// Represents the query for messages before our join.
13 #[derive(PartialEq)]
14 History, "history", MUC,
15 attributes: [
16 /// How many characters of history to send, in XML characters.
17 maxchars: Option<u32> = "maxchars" => optional,
18
19 /// How many messages to send.
20 maxstanzas: Option<u32> = "maxstanzas" => optional,
21
22 /// Only send messages received in these last seconds.
23 seconds: Option<u32> = "seconds" => optional,
24
25 /// Only send messages after this date.
26 since: Option<DateTime> = "since" => optional,
27 ]
28);
29
30impl History {
31 /// Create a new empty history element.
32 pub fn new() -> Self {
33 History {
34 maxchars: None,
35 maxstanzas: None,
36 seconds: None,
37 since: None,
38 }
39 }
40
41 /// Set how many characters of history to send.
42 pub fn with_maxchars(mut self, maxchars: u32) -> Self {
43 self.maxchars = Some(maxchars);
44 self
45 }
46
47 /// Set how many messages to send.
48 pub fn with_maxstanzas(mut self, maxstanzas: u32) -> Self {
49 self.maxstanzas = Some(maxstanzas);
50 self
51 }
52
53 /// Only send messages received in these last seconds.
54 pub fn with_seconds(mut self, seconds: u32) -> Self {
55 self.seconds = Some(seconds);
56 self
57 }
58
59 /// Only send messages received since this date.
60 pub fn with_since(mut self, since: DateTime) -> Self {
61 self.since = Some(since);
62 self
63 }
64}
65
66generate_element!(
67 /// Represents a room join request.
68 #[derive(PartialEq)]
69 Muc, "x", MUC, children: [
70 /// Password to use when the room is protected by a password.
71 password: Option<String> = ("password", MUC) => String,
72
73 /// Controls how much and how old we want to receive history on join.
74 history: Option<History> = ("history", MUC) => History
75 ]
76);
77
78impl PresencePayload for Muc {}
79
80impl Muc {
81 /// Create a new MUC join element.
82 pub fn new() -> Self {
83 Muc {
84 password: None,
85 history: None,
86 }
87 }
88
89 /// Join a room with this password.
90 pub fn with_password(mut self, password: String) -> Self {
91 self.password = Some(password);
92 self
93 }
94
95 /// Join a room with only that much history.
96 pub fn with_history(mut self, history: History) -> Self {
97 self.history = Some(history);
98 self
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use crate::util::compare_elements::NamespaceAwareCompare;
106 use crate::util::error::Error;
107 use minidom::Element;
108 use std::str::FromStr;
109 use try_from::TryFrom;
110
111 #[test]
112 fn test_muc_simple() {
113 let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'/>"
114 .parse()
115 .unwrap();
116 Muc::try_from(elem).unwrap();
117 }
118
119 #[test]
120 fn test_muc_invalid_child() {
121 let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'><coucou/></x>"
122 .parse()
123 .unwrap();
124 let error = Muc::try_from(elem).unwrap_err();
125 let message = match error {
126 Error::ParseError(string) => string,
127 _ => panic!(),
128 };
129 assert_eq!(message, "Unknown child in x element.");
130 }
131
132 #[test]
133 fn test_muc_serialise() {
134 let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'/>"
135 .parse()
136 .unwrap();
137 let muc = Muc {
138 password: None,
139 history: None,
140 };
141 let elem2 = muc.into();
142 assert_eq!(elem, elem2);
143 }
144
145 #[cfg(not(feature = "disable-validation"))]
146 #[test]
147 fn test_muc_invalid_attribute() {
148 let elem: Element = "<x xmlns='http://jabber.org/protocol/muc' coucou=''/>"
149 .parse()
150 .unwrap();
151 let error = Muc::try_from(elem).unwrap_err();
152 let message = match error {
153 Error::ParseError(string) => string,
154 _ => panic!(),
155 };
156 assert_eq!(message, "Unknown attribute in x element.");
157 }
158
159 #[test]
160 fn test_muc_simple_password() {
161 let elem: Element = "
162 <x xmlns='http://jabber.org/protocol/muc'>
163 <password>coucou</password>
164 </x>"
165 .parse()
166 .unwrap();
167 let elem1 = elem.clone();
168 let muc = Muc::try_from(elem).unwrap();
169 assert_eq!(muc.password, Some("coucou".to_owned()));
170
171 let elem2 = Element::from(muc);
172 assert!(elem1.compare_to(&elem2));
173 }
174
175 #[test]
176 fn history() {
177 let elem: Element = "
178 <x xmlns='http://jabber.org/protocol/muc'>
179 <history maxstanzas='0'/>
180 </x>"
181 .parse()
182 .unwrap();
183 let muc = Muc::try_from(elem).unwrap();
184 let muc2 = Muc::new().with_history(History::new().with_maxstanzas(0));
185 assert_eq!(muc, muc2);
186
187 let history = muc.history.unwrap();
188 assert_eq!(history.maxstanzas, Some(0));
189 assert_eq!(history.maxchars, None);
190 assert_eq!(history.seconds, None);
191 assert_eq!(history.since, None);
192
193 let elem: Element = "
194 <x xmlns='http://jabber.org/protocol/muc'>
195 <history since='1970-01-01T00:00:00Z'/>
196 </x>"
197 .parse()
198 .unwrap();
199 let muc = Muc::try_from(elem).unwrap();
200 assert_eq!(
201 muc.history.unwrap().since.unwrap(),
202 DateTime::from_str("1970-01-01T00:00:00+00:00").unwrap()
203 );
204 }
205}