muc.rs

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