From 5172fb5e0f04e3c8dfdefde1198d24ae9cf95fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Sch=C3=A4fer?= Date: Fri, 18 Apr 2025 12:26:27 +0200 Subject: [PATCH] parsers: port Message to use the derive macros --- parsers/ChangeLog | 10 + parsers/src/carbons.rs | 8 +- parsers/src/forwarding.rs | 4 +- parsers/src/mam.rs | 4 +- parsers/src/message.rs | 307 +++++++++++-------------- tokio-xmpp/examples/echo_bot.rs | 12 +- tokio-xmpp/examples/echo_component.rs | 6 +- xmpp/examples/hello_bot.rs | 4 +- xmpp/src/event.rs | 24 +- xmpp/src/message/receive/group_chat.rs | 2 +- xmpp/src/message/send.rs | 4 +- 11 files changed, 183 insertions(+), 202 deletions(-) diff --git a/parsers/ChangeLog b/parsers/ChangeLog index fb142a2efb7b610000b11a9f7d344e26e40beff1..2296fca05077bf3212a11b1f4ffe42d4250a77da 100644 --- a/parsers/ChangeLog +++ b/parsers/ChangeLog @@ -74,6 +74,16 @@ XXXX-YY-ZZ RELEASER - the `from_type` member was replaced by a pair of functions. - if the form contains a FORM_TYPE field, it will be part of the `fields` member (unlike before, where that field was removed). + - message::Message has been ported to use xso (!560). This causes several + breaking changes: + + 1. the message::Body and message::Subject newtypes have been removed + and replaced by bare Strings + 2. a message::Lang newtype has been introduced for the language of + message parts. + 3. the message::Thread type was converted from a single-element + tuple-like struct to a struct with named fields to support the + optional `parent` attribute. * New parsers/serialisers: - Stream Features (RFC 6120) (!400) - Spam Reporting (XEP-0377) (!506) diff --git a/parsers/src/carbons.rs b/parsers/src/carbons.rs index 2225f5bb3a832cf0dd29742349dae52d9d8af393..002a49404a4132c6929f0d9031778469c370db9b 100644 --- a/parsers/src/carbons.rs +++ b/parsers/src/carbons.rs @@ -67,8 +67,8 @@ mod tests { assert_size!(Enable, 0); assert_size!(Disable, 0); assert_size!(Private, 0); - assert_size!(Received, 140); - assert_size!(Sent, 140); + assert_size!(Received, 152); + assert_size!(Sent, 152); } #[cfg(target_pointer_width = "64")] @@ -77,8 +77,8 @@ mod tests { assert_size!(Enable, 0); assert_size!(Disable, 0); assert_size!(Private, 0); - assert_size!(Received, 264); - assert_size!(Sent, 264); + assert_size!(Received, 288); + assert_size!(Sent, 288); } #[test] diff --git a/parsers/src/forwarding.rs b/parsers/src/forwarding.rs index 2584fc8006233dae93a3da2606f51f7f81b4dd57..202ac4cb559c1885e0d66a097bc5f832aaacf90b 100644 --- a/parsers/src/forwarding.rs +++ b/parsers/src/forwarding.rs @@ -37,13 +37,13 @@ mod tests { #[cfg(target_pointer_width = "32")] #[test] fn test_size() { - assert_size!(Forwarded, 140); + assert_size!(Forwarded, 152); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { - assert_size!(Forwarded, 264); + assert_size!(Forwarded, 288); } #[test] diff --git a/parsers/src/mam.rs b/parsers/src/mam.rs index d1435c1fd0467b0a832c2adb93350c09fc8b9bb7..ed5f0f5618694ccd8111409c9745fc927197d381 100644 --- a/parsers/src/mam.rs +++ b/parsers/src/mam.rs @@ -150,7 +150,7 @@ mod tests { fn test_size() { assert_size!(QueryId, 12); assert_size!(Query, 108); - assert_size!(Result_, 164); + assert_size!(Result_, 176); assert_size!(Fin, 44); assert_size!(Start, 28); assert_size!(End, 28); @@ -163,7 +163,7 @@ mod tests { fn test_size() { assert_size!(QueryId, 24); assert_size!(Query, 216); - assert_size!(Result_, 312); + assert_size!(Result_, 336); assert_size!(Fin, 88); assert_size!(Start, 40); assert_size!(End, 40); diff --git a/parsers/src/message.rs b/parsers/src/message.rs index b1dbbbb4ed4b2a2a704b1a03b2a32e2e48ed88da..35fd173b198406944870e576f81d8a08898faa2f 100644 --- a/parsers/src/message.rs +++ b/parsers/src/message.rs @@ -4,11 +4,18 @@ // 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 core::fmt; +use core::ops::{Deref, DerefMut}; +use std::borrow::{Borrow, Cow}; + use crate::ns; use alloc::collections::BTreeMap; use jid::Jid; use minidom::Element; -use xso::error::{Error, FromElementError}; +use xso::{ + error::{Error, FromElementError}, + AsOptionalXmlText, AsXml, FromXml, FromXmlText, +}; /// Should be implemented on every known payload of a ``. pub trait MessagePayload: TryFrom + Into {} @@ -34,8 +41,6 @@ generate_attribute!( }, Default = Normal ); -type Lang = String; - generate_id!( /// Id field in a [`Message`], if any. /// @@ -44,59 +49,145 @@ generate_id!( Id ); -generate_elem_id!( - /// Represents one `` element, that is the free form text content of - /// a message. - Body, - "body", - DEFAULT_NS -); +/// Wrapper type to represent an optional `xml:lang` attribute. +/// +/// This is necessary because we do not want to emit empty `xml:lang` +/// attributes. +#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] +pub struct Lang(pub String); -generate_elem_id!( - /// Defines the subject of a room, or of an email-like normal message. - Subject, - "subject", - DEFAULT_NS -); +impl Deref for Lang { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Lang { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl fmt::Display for Lang { + fn fmt<'f>(&self, f: &'f mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + +impl FromXmlText for Lang { + fn from_xml_text(s: String) -> Result { + Ok(Self(s)) + } +} + +impl AsOptionalXmlText for Lang { + fn as_optional_xml_text(&self) -> Result>, Error> { + if self.0.is_empty() { + Ok(None) + } else { + Ok(Some(Cow::Borrowed(&self.0))) + } + } +} + +impl Borrow for Lang { + fn borrow(&self) -> &str { + &self.0 + } +} + +impl From for Lang { + fn from(other: String) -> Self { + Self(other) + } +} + +impl From<&str> for Lang { + fn from(other: &str) -> Self { + Self(other.to_owned()) + } +} + +impl PartialEq for Lang { + fn eq(&self, rhs: &str) -> bool { + self.0 == rhs + } +} + +impl PartialEq<&str> for Lang { + fn eq(&self, rhs: &&str) -> bool { + self.0 == *rhs + } +} + +impl Lang { + /// Create a new, empty `Lang`. + pub fn new() -> Self { + Self(String::new()) + } +} + +/// Threading meta-information. +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::DEFAULT_NS, name = "thread")] +pub struct Thread { + /// The parent of the thread, when creating a subthread. + #[xml(attribute(default))] + pub parent: Option, -generate_elem_id!( /// A thread identifier, so that other people can specify to which message /// they are replying. - Thread, - "thread", - DEFAULT_NS -); + #[xml(text)] + pub id: String, +} /// The main structure representing the `` stanza. -#[derive(Debug, Clone, PartialEq)] +#[derive(FromXml, AsXml, Debug, Clone, PartialEq)] +#[xml(namespace = ns::DEFAULT_NS, name = "message")] pub struct Message { /// The JID emitting this stanza. + #[xml(attribute(default))] pub from: Option, /// The recipient of this stanza. + #[xml(attribute(default))] pub to: Option, /// The @id attribute of this stanza, which is required in order to match a /// request with its response. + #[xml(attribute(default))] pub id: Option, /// The type of this message. + #[xml(attribute(name = "type", default))] pub type_: MessageType, /// A list of bodies, sorted per language. Use /// [get_best_body()](#method.get_best_body) to access them on reception. - pub bodies: BTreeMap, + #[xml(extract(n = .., name = "body", fields( + attribute(name = "xml:lang", type_ = Lang, default), + text(type_ = String), + )))] + pub bodies: BTreeMap, /// A list of subjects, sorted per language. Use /// [get_best_subject()](#method.get_best_subject) to access them on /// reception. - pub subjects: BTreeMap, + #[xml(extract(n = .., name = "subject", fields( + attribute(name = "xml:lang", type_ = Lang, default), + text(type_ = String), + )))] + pub subjects: BTreeMap, /// An optional thread identifier, so that other people can reply directly /// to this message. + #[xml(child(default))] pub thread: Option, /// A list of the extension payloads contained in this stanza. + #[xml(element(n = ..))] pub payloads: Vec, } @@ -157,7 +248,7 @@ impl Message { /// Appends a body in given lang to the Message pub fn with_body(mut self, lang: Lang, body: String) -> Message { - self.bodies.insert(lang, Body(body)); + self.bodies.insert(lang, body); self } @@ -209,13 +300,13 @@ impl Message { /// `Some(("fr", the_second_body))` will be returned. /// /// If no body matches, an undefined body will be returned. - pub fn get_best_body(&self, preferred_langs: Vec<&str>) -> Option<(Lang, &Body)> { - Message::get_best::(&self.bodies, preferred_langs) + pub fn get_best_body(&self, preferred_langs: Vec<&str>) -> Option<(Lang, &String)> { + Message::get_best::(&self.bodies, preferred_langs) } /// Cloned variant of [`Message::get_best_body`] - pub fn get_best_body_cloned(&self, preferred_langs: Vec<&str>) -> Option<(Lang, Body)> { - Message::get_best_cloned::(&self.bodies, preferred_langs) + pub fn get_best_body_cloned(&self, preferred_langs: Vec<&str>) -> Option<(Lang, String)> { + Message::get_best_cloned::(&self.bodies, preferred_langs) } /// Returns the best matching subject from a list of languages. @@ -225,13 +316,13 @@ impl Message { /// languages, `Some(("fr", the_second_subject))` will be returned. /// /// If no subject matches, an undefined subject will be returned. - pub fn get_best_subject(&self, preferred_langs: Vec<&str>) -> Option<(Lang, &Subject)> { - Message::get_best::(&self.subjects, preferred_langs) + pub fn get_best_subject(&self, preferred_langs: Vec<&str>) -> Option<(Lang, &String)> { + Message::get_best::(&self.subjects, preferred_langs) } /// Cloned variant of [`Message::get_best_subject`] - pub fn get_best_subject_cloned(&self, preferred_langs: Vec<&str>) -> Option<(Lang, Subject)> { - Message::get_best_cloned::(&self.subjects, preferred_langs) + pub fn get_best_subject_cloned(&self, preferred_langs: Vec<&str>) -> Option<(Lang, String)> { + Message::get_best_cloned::(&self.subjects, preferred_langs) } /// Try to extract the given payload type from the message's payloads. @@ -287,141 +378,24 @@ impl Message { } } -impl TryFrom for Message { - type Error = FromElementError; - - fn try_from(root: Element) -> Result { - check_self!(root, "message", DEFAULT_NS); - let from = get_attr!(root, "from", Option); - let to = get_attr!(root, "to", Option); - let id = get_attr!(root, "id", Option); - let type_ = get_attr!(root, "type", Default); - let mut bodies = BTreeMap::new(); - let mut subjects = BTreeMap::new(); - let mut thread = None; - let mut payloads = vec![]; - for elem in root.children() { - if elem.is("body", ns::DEFAULT_NS) { - check_no_children!(elem, "body"); - let lang = get_attr!(elem, "xml:lang", Default); - let body = Body(elem.text()); - if bodies.insert(lang, body).is_some() { - return Err( - Error::Other("Body element present twice for the same xml:lang.").into(), - ); - } - } else if elem.is("subject", ns::DEFAULT_NS) { - check_no_children!(elem, "subject"); - let lang = get_attr!(elem, "xml:lang", Default); - let subject = Subject(elem.text()); - if subjects.insert(lang, subject).is_some() { - return Err(Error::Other( - "Subject element present twice for the same xml:lang.", - ) - .into()); - } - } else if elem.is("thread", ns::DEFAULT_NS) { - if thread.is_some() { - return Err(Error::Other("Thread element present twice.").into()); - } - check_no_children!(elem, "thread"); - thread = Some(Thread(elem.text())); - } else { - payloads.push(elem.clone()) - } - } - Ok(Message { - from, - to, - id, - type_, - bodies, - subjects, - thread, - payloads, - }) - } -} - -impl From for Element { - fn from(message: Message) -> Element { - Element::builder("message", ns::DEFAULT_NS) - .attr("from", message.from) - .attr("to", message.to) - .attr("id", message.id) - .attr("type", message.type_) - .append_all(message.subjects.into_iter().map(|(lang, subject)| { - let mut subject = Element::from(subject); - subject.set_attr( - "xml:lang", - match lang.as_ref() { - "" => None, - lang => Some(lang), - }, - ); - subject - })) - .append_all(message.bodies.into_iter().map(|(lang, body)| { - let mut body = Element::from(body); - body.set_attr( - "xml:lang", - match lang.as_ref() { - "" => None, - lang => Some(lang), - }, - ); - body - })) - .append_all(message.payloads) - .build() - } -} - -impl ::xso::FromXml for Message { - type Builder = ::xso::minidom_compat::FromEventsViaElement; - - fn from_events( - qname: ::xso::exports::rxml::QName, - attrs: ::xso::exports::rxml::AttrMap, - ) -> Result { - if qname.0 != crate::ns::DEFAULT_NS || qname.1 != "message" { - return Err(::xso::error::FromEventsError::Mismatch { name: qname, attrs }); - } - Self::Builder::new(qname, attrs) - } -} - -impl ::xso::AsXml for Message { - type ItemIter<'x> = ::xso::minidom_compat::AsItemsViaElement<'x>; - - fn as_xml_iter(&self) -> Result, ::xso::error::Error> { - ::xso::minidom_compat::AsItemsViaElement::new(self.clone()) - } -} - #[cfg(test)] mod tests { use super::*; - use core::str::FromStr; #[cfg(target_pointer_width = "32")] #[test] fn test_size() { assert_size!(MessageType, 1); - assert_size!(Body, 12); - assert_size!(Subject, 12); - assert_size!(Thread, 12); - assert_size!(Message, 96); + assert_size!(Thread, 24); + assert_size!(Message, 108); } #[cfg(target_pointer_width = "64")] #[test] fn test_size() { assert_size!(MessageType, 1); - assert_size!(Body, 24); - assert_size!(Subject, 24); - assert_size!(Thread, 24); - assert_size!(Message, 192); + assert_size!(Thread, 48); + assert_size!(Message, 216); } #[test] @@ -462,12 +436,12 @@ mod tests { let elem: Element = "Hello world!".parse().unwrap(); let elem1 = elem.clone(); let message = Message::try_from(elem).unwrap(); - assert_eq!(message.bodies[""], Body::from_str("Hello world!").unwrap()); + assert_eq!(message.bodies[""], "Hello world!"); { let (lang, body) = message.get_best_body(vec!["en"]).unwrap(); assert_eq!(lang, ""); - assert_eq!(body, &Body::from_str("Hello world!").unwrap()); + assert_eq!(body, &"Hello world!"); } let elem2 = message.into(); @@ -483,7 +457,7 @@ mod tests { let mut message = Message::new(Jid::new("coucou@example.org").unwrap()); message .bodies - .insert(String::from(""), Body::from_str("Hello world!").unwrap()); + .insert(Lang::from(""), "Hello world!".to_owned()); let elem2 = message.into(); assert_eq!(elem, elem2); } @@ -496,22 +470,19 @@ mod tests { let elem: Element = "Hello world!".parse().unwrap(); let elem1 = elem.clone(); let message = Message::try_from(elem).unwrap(); - assert_eq!( - message.subjects[""], - Subject::from_str("Hello world!").unwrap() - ); + assert_eq!(message.subjects[""], "Hello world!",); { let (lang, subject) = message.get_best_subject(vec!["en"]).unwrap(); assert_eq!(lang, ""); - assert_eq!(subject, &Subject::from_str("Hello world!").unwrap()); + assert_eq!(subject, "Hello world!"); } // Test cloned variant. { let (lang, subject) = message.get_best_subject_cloned(vec!["en"]).unwrap(); assert_eq!(lang, ""); - assert_eq!(subject, Subject::from_str("Hello world!").unwrap()); + assert_eq!(subject, "Hello world!"); } let elem2 = message.into(); @@ -530,35 +501,35 @@ mod tests { { let (lang, body) = message.get_best_body(vec!["fr"]).unwrap(); assert_eq!(lang, "fr"); - assert_eq!(body, &Body::from_str("Salut le monde !").unwrap()); + assert_eq!(body, "Salut le monde !"); } // Tests order. { let (lang, body) = message.get_best_body(vec!["en", "de"]).unwrap(); assert_eq!(lang, "de"); - assert_eq!(body, &Body::from_str("Hallo Welt!").unwrap()); + assert_eq!(body, "Hallo Welt!"); } // Tests fallback. { let (lang, body) = message.get_best_body(vec![]).unwrap(); assert_eq!(lang, ""); - assert_eq!(body, &Body::from_str("Hello world!").unwrap()); + assert_eq!(body, "Hello world!"); } // Tests fallback. { let (lang, body) = message.get_best_body(vec!["ja"]).unwrap(); assert_eq!(lang, ""); - assert_eq!(body, &Body::from_str("Hello world!").unwrap()); + assert_eq!(body, "Hello world!"); } // Test cloned variant. { let (lang, body) = message.get_best_body_cloned(vec!["ja"]).unwrap(); assert_eq!(lang, ""); - assert_eq!(body, Body::from_str("Hello world!").unwrap()); + assert_eq!(body, "Hello world!"); } let message = Message::new(None); diff --git a/tokio-xmpp/examples/echo_bot.rs b/tokio-xmpp/examples/echo_bot.rs index 204d2d01d76704250aeef3c6167509df5d5afd7c..4be87a4e1c54b0fe5e659b1dadeb249346214c2a 100644 --- a/tokio-xmpp/examples/echo_bot.rs +++ b/tokio-xmpp/examples/echo_bot.rs @@ -4,7 +4,7 @@ use std::process::exit; use std::str::FromStr; use tokio_xmpp::Client; use xmpp_parsers::jid::{BareJid, Jid}; -use xmpp_parsers::message::{Body, Message, MessageType}; +use xmpp_parsers::message::{Lang, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; #[tokio::main] @@ -39,14 +39,14 @@ async fn main() { .and_then(|stanza| Message::try_from(stanza).ok()) { match (message.from, message.bodies.get("")) { - (Some(ref from), Some(ref body)) if body.0 == "die" => { + (Some(ref from), Some(body)) if body == "die" => { println!("Secret die command triggered by {}", from); break; } - (Some(ref from), Some(ref body)) => { + (Some(ref from), Some(body)) => { if message.type_ != MessageType::Error { // This is a message we'll echo - let reply = make_reply(from.clone(), &body.0); + let reply = make_reply(from.clone(), body.to_owned()); client.send_stanza(reply.into()).await.unwrap(); } } @@ -69,8 +69,8 @@ fn make_presence() -> Presence { } // Construct a chat -fn make_reply(to: Jid, body: &str) -> Message { +fn make_reply(to: Jid, body: String) -> Message { let mut message = Message::new(Some(to)); - message.bodies.insert(String::new(), Body(body.to_owned())); + message.bodies.insert(Lang::default(), body); message } diff --git a/tokio-xmpp/examples/echo_component.rs b/tokio-xmpp/examples/echo_component.rs index 6c5493492b37b8df094fa8053c4b68d3f875cbcc..de01d8f8213cb0aaf2f221f59a2bd9b3bf3b2329 100644 --- a/tokio-xmpp/examples/echo_component.rs +++ b/tokio-xmpp/examples/echo_component.rs @@ -3,7 +3,7 @@ use std::env::args; use std::process::exit; use std::str::FromStr; use xmpp_parsers::jid::Jid; -use xmpp_parsers::message::{Body, Message, MessageType}; +use xmpp_parsers::message::{Lang, Message, MessageType}; use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType}; use tokio_xmpp::{connect::DnsConfig, Component}; @@ -52,7 +52,7 @@ async fn main() { match (message.from, message.bodies.get("")) { (Some(from), Some(body)) => { if message.type_ != MessageType::Error { - let reply = make_reply(from, &body.0); + let reply = make_reply(from, &body); component.send_stanza(reply.into()).await.unwrap(); } } @@ -80,6 +80,6 @@ fn make_presence(from: Jid, to: Jid) -> Presence { // Construct a chat fn make_reply(to: Jid, body: &str) -> Message { let mut message = Message::new(Some(to)); - message.bodies.insert(String::new(), Body(body.to_owned())); + message.bodies.insert(Lang::default(), body.to_owned()); message } diff --git a/xmpp/examples/hello_bot.rs b/xmpp/examples/hello_bot.rs index 61dc2818cf728c2b5c6dbb9c27e75482cd22562d..e826ebb5bb5ec35bcde120b8454ff84fdfb20563 100644 --- a/xmpp/examples/hello_bot.rs +++ b/xmpp/examples/hello_bot.rs @@ -99,7 +99,7 @@ async fn handle_events(client: &mut Agent, event: Event, rooms: &Vec) { "{} {}: {}", time_info.received.time().format("%H:%M"), jid, - body.0 + body ); } Event::RoomJoined(jid) => { @@ -111,7 +111,7 @@ async fn handle_events(client: &mut Agent, event: Event, rooms: &Vec) { Event::RoomMessage(_id, jid, nick, body, time_info) => { println!( "Message in room {} from {} at {}: {}", - jid, nick, time_info.received, body.0 + jid, nick, time_info.received, body ); } _ => { diff --git a/xmpp/src/event.rs b/xmpp/src/event.rs index f6dc97a6dc9c199dd84b543051547e445b796822..cbb898c0d76ca33bcf8dd3c24be943aa5d739870 100644 --- a/xmpp/src/event.rs +++ b/xmpp/src/event.rs @@ -7,7 +7,7 @@ use tokio_xmpp::jid::BareJid; #[cfg(feature = "avatars")] use tokio_xmpp::jid::Jid; -use tokio_xmpp::parsers::{message::Body, roster::Item as RosterItem}; +use tokio_xmpp::parsers::roster::Item as RosterItem; use crate::{delay::StanzaTimeInfo, Error, MessageId, RoomNick}; @@ -23,25 +23,25 @@ pub enum Event { /// A chat message was received. It may have been delayed on the network. /// - The [`MessageId`] is a unique identifier for this message. /// - The [`BareJid`] is the sender's JID. - /// - The [`Body`] is the message body. + /// - The [`String`] is the message body. /// - The [`StanzaTimeInfo`] about when message was received, and when the message was claimed sent. - ChatMessage(Option, BareJid, Body, StanzaTimeInfo), + ChatMessage(Option, BareJid, String, StanzaTimeInfo), /// A message in a one-to-one chat was corrected/edited. /// - The [`MessageId`] is the ID of the message that was corrected. /// - The [`BareJid`] is the JID of the other participant in the chat. - /// - The [`Body`] is the new body of the message, to replace the old one. + /// - The [`String`] is the new body of the message, to replace the old one. /// - The [`StanzaTimeInfo`] is the time the message correction was sent/received - ChatMessageCorrection(MessageId, BareJid, Body, StanzaTimeInfo), + ChatMessageCorrection(MessageId, BareJid, String, StanzaTimeInfo), RoomJoined(BareJid), RoomLeft(BareJid), - RoomMessage(Option, BareJid, RoomNick, Body, StanzaTimeInfo), + RoomMessage(Option, BareJid, RoomNick, String, StanzaTimeInfo), /// A message in a MUC was corrected/edited. /// - The [`MessageId`] is the ID of the message that was corrected. /// - The [`BareJid`] is the JID of the room where the message was sent. /// - The [`RoomNick`] is the nickname of the sender of the message. - /// - The [`Body`] is the new body of the message, to replace the old one. + /// - The [`String`] is the new body of the message, to replace the old one. /// - The [`StanzaTimeInfo`] is the time the message correction was sent/received - RoomMessageCorrection(MessageId, BareJid, RoomNick, Body, StanzaTimeInfo), + RoomMessageCorrection(MessageId, BareJid, RoomNick, String, StanzaTimeInfo), /// The subject of a room was received. /// - The BareJid is the room's address. /// - The RoomNick is the nickname of the room member who set the subject. @@ -49,14 +49,14 @@ pub enum Event { RoomSubject(BareJid, Option, String, StanzaTimeInfo), /// A private message received from a room, containing the message ID, the room's BareJid, /// the sender's nickname, and the message body. - RoomPrivateMessage(Option, BareJid, RoomNick, Body, StanzaTimeInfo), + RoomPrivateMessage(Option, BareJid, RoomNick, String, StanzaTimeInfo), /// A private message in a MUC was corrected/edited. /// - The [`MessageId`] is the ID of the message that was corrected. /// - The [`BareJid`] is the JID of the room where the message was sent. /// - The [`RoomNick`] is the nickname of the sender of the message. - /// - The [`Body`] is the new body of the message, to replace the old one. + /// - The [`String`] is the new body of the message, to replace the old one. /// - The [`StanzaTimeInfo`] is the time the message correction was sent/received - RoomPrivateMessageCorrection(MessageId, BareJid, RoomNick, Body, StanzaTimeInfo), - ServiceMessage(Option, BareJid, Body, StanzaTimeInfo), + RoomPrivateMessageCorrection(MessageId, BareJid, RoomNick, String, StanzaTimeInfo), + ServiceMessage(Option, BareJid, String, StanzaTimeInfo), HttpUploadedFile(String), } diff --git a/xmpp/src/message/receive/group_chat.rs b/xmpp/src/message/receive/group_chat.rs index 8ea22a32e7ae13299339b82feb70ffc76dac94c1..da1713057fccf9625598df23cf356e3c0174e209 100644 --- a/xmpp/src/message/receive/group_chat.rs +++ b/xmpp/src/message/receive/group_chat.rs @@ -25,7 +25,7 @@ pub async fn handle_message_group_chat( events.push(Event::RoomSubject( from.to_bare(), from.resource().map(RoomNick::from_resource_ref), - subject.0.clone(), + subject.clone(), time_info.clone(), )); found_subject = true; diff --git a/xmpp/src/message/send.rs b/xmpp/src/message/send.rs index 3098a5cb4b424cb3814a7dff2ecc1733bbda67ab..e4e5637b9e6132c83fe6a45761af21ae95187ce3 100644 --- a/xmpp/src/message/send.rs +++ b/xmpp/src/message/send.rs @@ -7,7 +7,7 @@ use crate::{ jid::{BareJid, Jid}, minidom::Element, - parsers::message::{Body, Message, MessagePayload, MessageType}, + parsers::message::{Message, MessagePayload, MessageType}, }; use crate::Agent; @@ -66,7 +66,7 @@ pub async fn send_raw_message<'a>(agent: &mut Agent, settings: RawMessageSetting stanza.type_ = message_type; stanza .bodies - .insert(lang.unwrap_or("").to_string(), Body(String::from(message))); + .insert(lang.unwrap_or("").into(), String::from(message)); agent.client.send_stanza(stanza.into()).await.unwrap(); }