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(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(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::error::Error;
 98    use crate::Element;
 99    use std::convert::TryFrom;
100    use std::str::FromStr;
101
102    #[test]
103    fn test_muc_simple() {
104        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'/>"
105            .parse()
106            .unwrap();
107        Muc::try_from(elem).unwrap();
108    }
109
110    #[test]
111    fn test_muc_invalid_child() {
112        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'><coucou/></x>"
113            .parse()
114            .unwrap();
115        let error = Muc::try_from(elem).unwrap_err();
116        let message = match error {
117            Error::ParseError(string) => string,
118            _ => panic!(),
119        };
120        assert_eq!(message, "Unknown child in x element.");
121    }
122
123    #[test]
124    fn test_muc_serialise() {
125        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'/>"
126            .parse()
127            .unwrap();
128        let muc = Muc {
129            password: None,
130            history: None,
131        };
132        let elem2 = muc.into();
133        assert_eq!(elem, elem2);
134    }
135
136    #[cfg(not(feature = "disable-validation"))]
137    #[test]
138    fn test_muc_invalid_attribute() {
139        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc' coucou=''/>"
140            .parse()
141            .unwrap();
142        let error = Muc::try_from(elem).unwrap_err();
143        let message = match error {
144            Error::ParseError(string) => string,
145            _ => panic!(),
146        };
147        assert_eq!(message, "Unknown attribute in x element.");
148    }
149
150    #[test]
151    fn test_muc_simple_password() {
152        let elem: Element =
153            "<x xmlns='http://jabber.org/protocol/muc'><password>coucou</password></x>"
154                .parse()
155                .unwrap();
156        let elem1 = elem.clone();
157        let muc = Muc::try_from(elem).unwrap();
158        assert_eq!(muc.password, Some("coucou".to_owned()));
159
160        let elem2 = Element::from(muc);
161        assert_eq!(elem1, elem2);
162    }
163
164    #[test]
165    fn history() {
166        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'>
167                <history maxstanzas='0'/>
168            </x>"
169            .parse()
170            .unwrap();
171        let muc = Muc::try_from(elem).unwrap();
172        let muc2 = Muc::new().with_history(History::new().with_maxstanzas(0));
173        assert_eq!(muc, muc2);
174
175        let history = muc.history.unwrap();
176        assert_eq!(history.maxstanzas, Some(0));
177        assert_eq!(history.maxchars, None);
178        assert_eq!(history.seconds, None);
179        assert_eq!(history.since, None);
180
181        let elem: Element = "<x xmlns='http://jabber.org/protocol/muc'>
182                <history since='1970-01-01T00:00:00Z'/>
183            </x>"
184            .parse()
185            .unwrap();
186        let muc = Muc::try_from(elem).unwrap();
187        assert_eq!(
188            muc.history.unwrap().since.unwrap(),
189            DateTime::from_str("1970-01-01T00:00:00+00:00").unwrap()
190        );
191    }
192}