Implement XEP-0463: MUC Affiliations Versioning

This commit is contained in:
Link Mauve 2026-05-06 20:01:44 +02:00
commit d0b28a94b0
6 changed files with 91 additions and 2 deletions

View file

@ -1,6 +1,7 @@
Version NEXT:
XXXX-YY-ZZ RELEASER <admin@example.com>
* New parsers/serialisers:
- MUC Affiliations Versioning (XEP-0463) (!668)
- Client Access Management (XEP-0494) (!641)
- Jingle Content Category (XEP-0507)
- Displayed markers (XEP-0333) (!669)

View file

@ -690,6 +690,14 @@
<xmpp:since>0.20.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0463.html"/>
<xmpp:status>complete</xmpp:status>
<xmpp:version>0.2.0</xmpp:version>
<xmpp:since>NEXT</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0478.html"/>

69
parsers/src/muc/mav.rs Normal file
View file

@ -0,0 +1,69 @@
// Copyright (c) 2026 Link Mauve <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/.
use xso::{AsXml, FromXml};
use crate::ns;
generate_id!(
/// Unique and opaque string, indicating the last affiliation version sent by the server that
/// the client has seen, and cached.
Version
);
/// A `<mav/>` element sent by the client on join, if it wants to keep track of the affiliations in
/// the room.
#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
#[xml(namespace = ns::MAV, name = "mav")]
pub struct AffiliationsVersioning {
/// Unique and opaque string, indicating the last affiliation version sent by the server that
/// the client has seen, and cached. Sending the mav element without a since attribute is a
/// called bootstrap request, which asks the server for a full response.
#[xml(attribute(default))]
since: Option<Version>,
/// The latest version the server has.
#[xml(attribute(default))]
until: Option<Version>,
}
#[cfg(test)]
mod tests {
use super::*;
use minidom::Element;
#[cfg(target_pointer_width = "32")]
#[test]
fn test_size() {
assert_size!(Version, 12);
assert_size!(AffiliationsVersioning, 24);
}
#[cfg(target_pointer_width = "64")]
#[test]
fn test_size() {
assert_size!(Version, 24);
assert_size!(AffiliationsVersioning, 48);
}
#[test]
fn test_simple() {
let elem: Element = "<mav xmlns='urn:xmpp:muc:affiliations:1'/>"
.parse()
.unwrap();
let ver = AffiliationsVersioning::try_from(elem).unwrap();
assert!(ver.since.is_none());
assert!(ver.until.is_none());
let elem: Element =
"<mav xmlns='urn:xmpp:muc:affiliations:1' since='9pacabr2q1' until='ruz41312vw'/>"
.parse()
.unwrap();
let ver = AffiliationsVersioning::try_from(elem).unwrap();
assert_eq!(ver.since.unwrap().0, "9pacabr2q1");
assert_eq!(ver.until.unwrap().0, "ruz41312vw");
}
}

View file

@ -11,5 +11,8 @@ pub mod muc;
/// The `http://jabber.org/protocol/muc#user` protocol.
pub mod user;
/// The `urn:xmpp:muc:affiliations:1` protocol.
pub mod mav;
pub use self::muc::Muc;
pub use self::user::MucUser;

View file

@ -8,6 +8,7 @@
use xso::{AsXml, FromXml};
use crate::message::MessagePayload;
use crate::muc::mav::AffiliationsVersioning;
use crate::ns;
use crate::presence::PresencePayload;
@ -302,6 +303,10 @@ pub struct MucUser {
/// A mediated invite rejection
#[xml(child(default))]
pub decline: Option<Decline>,
/// From XEP-0463: MUC Affiliations Versioning
#[xml(child(default))]
pub affiliations: Option<AffiliationsVersioning>,
}
impl MucUser {
@ -347,7 +352,7 @@ mod tests {
assert_size!(Item, 84);
assert_size!(Invite, 44);
assert_size!(Decline, 44);
assert_size!(MucUser, 112);
assert_size!(MucUser, 136);
}
#[cfg(target_pointer_width = "64")]
@ -362,7 +367,7 @@ mod tests {
assert_size!(Item, 168);
assert_size!(Invite, 88);
assert_size!(Decline, 88);
assert_size!(MucUser, 224);
assert_size!(MucUser, 272);
}
#[test]

View file

@ -304,6 +304,9 @@ pub const SASL_CB: &str = "urn:xmpp:sasl-cb:0";
/// XEP-0444: Message Reactions
pub const REACTIONS: &str = "urn:xmpp:reactions:0";
/// XEP-0463: MUC Affiliations Versioning
pub const MAV: &str = "urn:xmpp:muc:affiliations:1";
/// XEP-0478: Stream Limits Advertisement
pub const STREAM_LIMITS: &str = "urn:xmpp:stream-limits:0";