spam_reporting.rs

  1// Copyright (c) 2024 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
  2//
  3// This Source Code Form is subject to the terms of the Mozilla Public
  4// License, v. 2.0. If a copy of the MPL was not distributed with this
  5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6
  7use xso::{AsXml, FromXml};
  8
  9use crate::ns;
 10use crate::stanza_id::StanzaId;
 11use alloc::collections::BTreeMap;
 12
 13generate_attribute!(
 14    /// The possible reasons for a report.
 15    Reason, "reason", {
 16        /// Used for reporting a JID that is sending unwanted messages.
 17        Spam => "urn:xmpp:reporting:spam",
 18
 19        /// Used for reporting general abuse.
 20        Abuse => "urn:xmpp:reporting:abuse",
 21    }
 22);
 23
 24type Lang = String;
 25
 26/// Represents an abuse or spam report.
 27#[derive(FromXml, AsXml, Debug, Clone, PartialEq)]
 28#[xml(namespace = ns::SPAM_REPORTING, name = "report")]
 29pub struct Report {
 30    /// The reason for this report.
 31    #[xml(attribute)]
 32    reason: Reason,
 33
 34    /// Ids of the incriminated stanzas.
 35    #[xml(child(n = ..))]
 36    stanza_ids: Vec<StanzaId>,
 37
 38    /// Some text explaining the reason for this report.
 39    #[xml(extract(n = .., name = "text", fields(
 40        lang(type_ = Lang, default),
 41        text(type_ = String)
 42    )))]
 43    texts: BTreeMap<Lang, String>,
 44}
 45
 46#[cfg(test)]
 47mod tests {
 48    use super::*;
 49    use jid::Jid;
 50    use minidom::Element;
 51
 52    #[cfg(target_pointer_width = "32")]
 53    #[test]
 54    fn test_size() {
 55        assert_size!(Reason, 1);
 56        assert_size!(Report, 28);
 57    }
 58
 59    #[cfg(target_pointer_width = "64")]
 60    #[test]
 61    fn test_size() {
 62        assert_size!(Reason, 1);
 63        assert_size!(Report, 56);
 64    }
 65
 66    #[test]
 67    // Comes from https://xmpp.org/extensions/xep-0377.html#example-2
 68    fn test_example_1() {
 69        let elem: Element =
 70            "<report xmlns='urn:xmpp:reporting:1' reason='urn:xmpp:reporting:spam'/>"
 71                .parse()
 72                .unwrap();
 73        let report = Report::try_from(elem).unwrap();
 74        assert_eq!(report.reason, Reason::Spam);
 75        assert!(report.stanza_ids.is_empty());
 76        assert!(report.texts.is_empty());
 77    }
 78
 79    #[test]
 80    // Comes from https://xmpp.org/extensions/xep-0377.html#example-5
 81    fn test_example_5() {
 82        let elem: Element = "<report xmlns='urn:xmpp:reporting:1' reason='urn:xmpp:reporting:spam'>
 83            <stanza-id xmlns='urn:xmpp:sid:0' by='romeo@example.net' id='28482-98726-73623'/>
 84            <stanza-id xmlns='urn:xmpp:sid:0' by='romeo@example.net' id='38383-38018-18385'/>
 85            <text xml:lang='en'>Never came trouble to my house like this.</text>
 86        </report>"
 87            .parse()
 88            .unwrap();
 89        let report = Report::try_from(elem).unwrap();
 90        let romeo = Jid::new("romeo@example.net").unwrap();
 91        assert_eq!(report.reason, Reason::Spam);
 92        assert_eq!(report.stanza_ids.len(), 2);
 93        assert_eq!(report.stanza_ids[0].by, romeo);
 94        assert_eq!(report.stanza_ids[0].id, "28482-98726-73623");
 95        assert_eq!(report.stanza_ids[1].by, romeo);
 96        assert_eq!(report.stanza_ids[1].id, "38383-38018-18385");
 97        assert_eq!(
 98            report.texts["en"],
 99            "Never came trouble to my house like this."
100        );
101    }
102}