muc.rs

  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}