2019-09-29 01:47:21 +02:00
// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
2023-12-16 13:03:22 +01:00
//!
//! Chatroom bookmarks from [XEP-0402](https://xmpp.org/extensions/xep-0402.html) for newer servers
//! which advertise `urn:xmpp:bookmarks:1#compat` on the user's BareJID in a disco info request.
2023-12-16 15:23:20 +01:00
//! On legacy non-compliant servers, use the [`private`][crate::private] module instead.
2023-12-16 13:03:22 +01:00
//!
//! See [ModernXMPP docs](https://docs.modernxmpp.org/client/groupchat/#bookmarks) on how to handle all historic
//! and newer specifications for your clients.
//!
//! This module exposes the [`Autojoin`][crate::bookmarks2::Autojoin] boolean flag, the [`Conference`][crate::bookmarks2::Conference] chatroom element, and the [BOOKMARKS2][crate::ns::BOOKMARKS2] XML namespace.
2024-08-05 17:42:23 +02:00
use xso ::{ AsXml , FromXml } ;
2020-10-31 13:27:58 +01:00
use crate ::ns ;
2024-07-24 20:28:22 +02:00
use minidom ::Element ;
2019-09-29 01:47:21 +02:00
generate_attribute! (
/// Whether a conference bookmark should be joined automatically.
Autojoin ,
" autojoin " ,
bool
) ;
2024-08-05 17:42:23 +02:00
/// Potential extensions in a conference.
#[ derive(FromXml, AsXml, Debug, Clone, Default) ]
#[ xml(namespace = ns::BOOKMARKS2, name = " extensions " ) ]
pub struct Extensions {
/// Extension elements.
#[ xml(element(n = ..)) ]
pub payloads : Vec < Element > ,
}
2020-10-31 13:27:58 +01:00
/// A conference bookmark.
2024-08-05 17:42:23 +02:00
#[ derive(FromXml, AsXml, Debug, Clone, Default) ]
#[ xml(namespace = ns::BOOKMARKS2, name = " conference " ) ]
2020-10-31 13:27:58 +01:00
pub struct Conference {
/// Whether a conference bookmark should be joined automatically.
2024-08-05 17:42:23 +02:00
#[ xml(attribute(default)) ]
2020-10-31 13:27:58 +01:00
pub autojoin : Autojoin ,
/// A user-defined name for this conference.
2024-08-05 17:42:23 +02:00
#[ xml(attribute(default)) ]
2020-10-31 13:27:58 +01:00
pub name : Option < String > ,
/// The nick the user will use to join this conference.
2024-08-05 17:42:23 +02:00
#[ xml(extract(default, fields(text(type_ = String)))) ]
2020-10-31 13:27:58 +01:00
pub nick : Option < String > ,
/// The password required to join this conference.
2024-08-05 17:42:23 +02:00
#[ xml(extract(default, fields(text(type_ = String)))) ]
2020-10-31 13:27:58 +01:00
pub password : Option < String > ,
2024-08-05 17:42:23 +02:00
/// Extension elements.
#[ xml(child(default)) ]
pub extensions : Option < Extensions > ,
2020-10-31 13:27:58 +01:00
}
2019-09-29 01:47:21 +02:00
impl Conference {
/// Create a new conference.
pub fn new ( ) -> Conference {
2021-10-11 15:22:19 +02:00
Conference ::default ( )
2020-10-31 13:27:58 +01:00
}
}
2019-09-29 01:47:21 +02:00
#[ cfg(test) ]
mod tests {
use super ::* ;
2022-03-21 19:44:07 +01:00
use crate ::pubsub ::{ pubsub ::Item as PubSubItem , PubSubEvent } ;
2019-09-29 01:47:21 +02:00
#[ cfg(target_pointer_width = " 32 " ) ]
#[ test ]
fn test_size ( ) {
2020-10-31 13:27:58 +01:00
assert_size! ( Conference , 52 ) ;
2019-09-29 01:47:21 +02:00
}
#[ cfg(target_pointer_width = " 64 " ) ]
#[ test ]
fn test_size ( ) {
2020-10-31 13:27:58 +01:00
assert_size! ( Conference , 104 ) ;
2019-09-29 01:47:21 +02:00
}
#[ test ]
fn simple ( ) {
2020-09-29 18:12:18 +02:00
let elem : Element = " <conference xmlns='urn:xmpp:bookmarks:1'/> "
2019-10-23 01:32:41 +02:00
. parse ( )
. unwrap ( ) ;
2019-09-29 01:47:21 +02:00
let elem1 = elem . clone ( ) ;
let conference = Conference ::try_from ( elem ) . unwrap ( ) ;
assert_eq! ( conference . autojoin , Autojoin ::False ) ;
assert_eq! ( conference . name , None ) ;
assert_eq! ( conference . nick , None ) ;
assert_eq! ( conference . password , None ) ;
let elem2 = Element ::from ( Conference ::new ( ) ) ;
2019-11-29 14:33:17 +01:00
assert_eq! ( elem1 , elem2 ) ;
2019-09-29 01:47:21 +02:00
}
#[ test ]
fn complete ( ) {
2020-10-31 13:27:58 +01:00
let elem : Element = " <conference xmlns='urn:xmpp:bookmarks:1' autojoin='true' name='Test MUC'><nick>Coucou</nick><password>secret</password><extensions><test xmlns='urn:xmpp:unknown' /></extensions></conference> " . parse ( ) . unwrap ( ) ;
2019-09-29 01:47:21 +02:00
let conference = Conference ::try_from ( elem ) . unwrap ( ) ;
assert_eq! ( conference . autojoin , Autojoin ::True ) ;
assert_eq! ( conference . name , Some ( String ::from ( " Test MUC " ) ) ) ;
assert_eq! ( conference . clone ( ) . nick . unwrap ( ) , " Coucou " ) ;
assert_eq! ( conference . clone ( ) . password . unwrap ( ) , " secret " ) ;
2024-08-05 17:42:23 +02:00
let payloads = conference . clone ( ) . extensions . unwrap ( ) . payloads ;
assert_eq! ( payloads . len ( ) , 1 ) ;
assert! ( payloads [ 0 ] . is ( " test " , " urn:xmpp:unknown " ) ) ;
2019-09-29 01:47:21 +02:00
}
#[ test ]
fn wrapped ( ) {
2020-09-29 18:12:18 +02:00
let elem : Element = " <item xmlns='http://jabber.org/protocol/pubsub' id='test-muc@muc.localhost'><conference xmlns='urn:xmpp:bookmarks:1' autojoin='true' name='Test MUC'><nick>Coucou</nick><password>secret</password></conference></item> " . parse ( ) . unwrap ( ) ;
2019-09-29 01:47:21 +02:00
let item = PubSubItem ::try_from ( elem ) . unwrap ( ) ;
let payload = item . payload . clone ( ) . unwrap ( ) ;
2020-03-28 13:07:26 +01:00
println! ( " FOO: payload: {:?} " , payload ) ;
// let conference = Conference::try_from(payload).unwrap();
2022-03-21 19:44:07 +01:00
let conference = Conference ::try_from ( payload ) . unwrap ( ) ;
2020-03-28 13:07:26 +01:00
println! ( " FOO: conference: {:?} " , conference ) ;
2019-09-29 01:47:21 +02:00
assert_eq! ( conference . autojoin , Autojoin ::True ) ;
assert_eq! ( conference . name , Some ( String ::from ( " Test MUC " ) ) ) ;
assert_eq! ( conference . clone ( ) . nick . unwrap ( ) , " Coucou " ) ;
assert_eq! ( conference . clone ( ) . password . unwrap ( ) , " secret " ) ;
2020-09-29 18:12:18 +02:00
let elem : Element = " <event xmlns='http://jabber.org/protocol/pubsub#event'><items node='urn:xmpp:bookmarks:1'><item xmlns='http://jabber.org/protocol/pubsub#event' id='test-muc@muc.localhost'><conference xmlns='urn:xmpp:bookmarks:1' autojoin='true' name='Test MUC'><nick>Coucou</nick><password>secret</password></conference></item></items></event> " . parse ( ) . unwrap ( ) ;
2019-09-29 01:47:21 +02:00
let mut items = match PubSubEvent ::try_from ( elem ) {
Ok ( PubSubEvent ::PublishedItems { node , items } ) = > {
assert_eq! ( & node . 0 , ns ::BOOKMARKS2 ) ;
items
2019-10-23 01:32:41 +02:00
}
2019-09-29 01:47:21 +02:00
_ = > panic! ( ) ,
} ;
assert_eq! ( items . len ( ) , 1 ) ;
let item = items . pop ( ) . unwrap ( ) ;
let payload = item . payload . clone ( ) . unwrap ( ) ;
let conference = Conference ::try_from ( payload ) . unwrap ( ) ;
assert_eq! ( conference . autojoin , Autojoin ::True ) ;
assert_eq! ( conference . name , Some ( String ::from ( " Test MUC " ) ) ) ;
assert_eq! ( conference . clone ( ) . nick . unwrap ( ) , " Coucou " ) ;
assert_eq! ( conference . clone ( ) . password . unwrap ( ) , " secret " ) ;
}
}