mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-06-18 05:35:57 +02:00
Merge branch 'message-correction-new' into 'main'
Draft: Message correction (XEP-0308) See merge request xmpp-rs/xmpp-rs!279
This commit is contained in:
commit
095733d426
|
@ -67,16 +67,18 @@ async fn main() {
|
|||
.with_to(iq.from.unwrap());
|
||||
client.send_stanza(iq.into()).await.unwrap();
|
||||
}
|
||||
Err(err) => client
|
||||
.send_stanza(make_error(
|
||||
iq.from.unwrap(),
|
||||
iq.id,
|
||||
ErrorType::Modify,
|
||||
DefinedCondition::BadRequest,
|
||||
&format!("{}", err),
|
||||
))
|
||||
.await
|
||||
.unwrap(),
|
||||
Err(err) => {
|
||||
client
|
||||
.send_stanza(make_error(
|
||||
iq.from.unwrap(),
|
||||
iq.id,
|
||||
ErrorType::Modify,
|
||||
DefinedCondition::BadRequest,
|
||||
&format!("{}", err),
|
||||
))
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// We MUST answer unhandled get iqs with a service-unavailable error.
|
||||
|
|
|
@ -76,10 +76,16 @@ impl<C: ServerConnector> Client<C> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Send stanza
|
||||
pub async fn send_stanza(&mut self, stanza: Element) -> Result<(), Error> {
|
||||
self.send(Packet::Stanza(add_stanza_id(stanza, ns::JABBER_CLIENT)))
|
||||
.await
|
||||
/// Send stanza. An id will be assigned if not already present.
|
||||
pub async fn send_stanza(&mut self, stanza: Element) -> Result<String, Error> {
|
||||
let stanza = add_stanza_id(stanza, ns::JABBER_CLIENT);
|
||||
|
||||
// Get the Id. (With add_stanza_id, it should always be present)
|
||||
let id = stanza.attr("id").unwrap().to_string();
|
||||
|
||||
self.send(Packet::Stanza(stanza)).await?;
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
/// Get the stream features (`<stream:features/>`) of the underlying stream
|
||||
|
|
|
@ -76,7 +76,8 @@ async fn main() -> Result<(), Option<()>> {
|
|||
println!("Joined room {}.", jid);
|
||||
client
|
||||
.send_message(Jid::Bare(jid), MessageType::Groupchat, "en", "Hello world!")
|
||||
.await;
|
||||
.await
|
||||
.expect("Could not send message.");
|
||||
}
|
||||
Event::RoomLeft(jid) => {
|
||||
println!("Left room {}.", jid);
|
||||
|
|
|
@ -60,26 +60,111 @@ impl<C: ServerConnector> Agent<C> {
|
|||
muc::room::leave_room(self, room_jid, nickname, lang, status).await
|
||||
}
|
||||
|
||||
/// Send a message to a given recipient.
|
||||
///
|
||||
/// Returns the generated message ID.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `recipient`: The JID of the recipient.
|
||||
/// * `type_`: The type of message to send.
|
||||
/// For a message to a MUC room, this should be `MessageType::Groupchat`.
|
||||
/// For a private message to a MUC room member or regular contact,
|
||||
/// this should be `MessageType::Chat`.
|
||||
/// * `lang`: The language of the message. (See IETF RFC 5646)
|
||||
/// * `text`: The text of the message.
|
||||
pub async fn send_message(
|
||||
&mut self,
|
||||
recipient: Jid,
|
||||
type_: MessageType,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
) -> Result<String, tokio_xmpp::Error> {
|
||||
message::send::send_message(self, recipient, type_, lang, text).await
|
||||
}
|
||||
|
||||
/// Send a private message to a given MUC room member.
|
||||
///
|
||||
/// Returns the generated message ID.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `room`: The JID of the room.
|
||||
/// * `recipient`: The nickname of the recipient within the room.
|
||||
/// * `type_`: The type of message to send.
|
||||
/// For a message to a MUC room, this should be `MessageType::Groupchat`.
|
||||
/// For a private message to a MUC room member or regular contact,
|
||||
/// this should be `MessageType::Chat`.
|
||||
/// * `lang`: The language of the message. (See IETF RFC 5646)
|
||||
/// * `text`: The text of the message.
|
||||
///
|
||||
/// Returns the generated message ID, or an error if the message could not be sent.
|
||||
pub async fn send_room_private_message(
|
||||
&mut self,
|
||||
room: BareJid,
|
||||
recipient: RoomNick,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
) -> Result<String, tokio_xmpp::Error> {
|
||||
muc::private_message::send_room_private_message(self, room, recipient, lang, text).await
|
||||
}
|
||||
|
||||
/// Send a correction for a given earlier message.
|
||||
///
|
||||
/// Note: XEP-0308 is only defined for the last-sent message; this method does not enforce this
|
||||
/// restriction. Results may vary if the message being corrected is not the last-sent message.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `id`: The ID of the message to correct.
|
||||
/// - `to`: The JID of the recipient of the message.
|
||||
/// - `lang`: The language of the new message body.
|
||||
/// - `text`: The new message body, to replace the old one.
|
||||
///
|
||||
/// This method returns as soon as the correction has been sent, not when it has been received or acknowledged.
|
||||
pub async fn correct_message(&mut self, id: &str, to: BareJid, lang: &str, text: &str) {
|
||||
message::correct::send_correction(self, id, to, lang, text).await
|
||||
}
|
||||
|
||||
/// Send a correction for a given earlier message in a MUC.
|
||||
///
|
||||
/// Note: XEP-0308 is only defined for the last-sent message; this method does not enforce this
|
||||
/// restriction. Results may vary if the message being corrected is not the last-sent message.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `id`: The ID of the message to correct.
|
||||
/// - `room`: The JID of the room.
|
||||
/// - `lang`: The language of the new message body.
|
||||
/// - `text`: The new message body, to replace the old one.
|
||||
///
|
||||
/// This method returns as soon as the correction has been sent, not when it has been received or acknowledged.
|
||||
pub async fn correct_room_message(&mut self, id: &str, room: BareJid, lang: &str, text: &str) {
|
||||
message::correct::send_correction_group(self, id, room, lang, text).await
|
||||
}
|
||||
|
||||
/// Send a correction for a given earlier private message in a MUC.
|
||||
///
|
||||
/// Note: XEP-0308 is only defined for the last-sent message; this method does not enforce this
|
||||
/// restriction. Results may vary if the message being corrected is not the last-sent message.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `id`: The ID of the message to correct.
|
||||
/// - `room`: The JID of the room.
|
||||
/// - `nick`: The nickname of the recipient of the message.
|
||||
/// - `lang`: The language of the new message body.
|
||||
/// - `text`: The new message body, to replace the old one.
|
||||
///
|
||||
/// This method returns as soon as the correction has been sent, not when it has been received or acknowledged.
|
||||
pub async fn correct_room_private_message(
|
||||
&mut self,
|
||||
id: &str,
|
||||
room: BareJid,
|
||||
nick: RoomNick,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
message::correct::send_correction_private(self, id, room, nick, lang, text).await
|
||||
}
|
||||
|
||||
/// Wait for new events.
|
||||
///
|
||||
/// # Returns
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
use tokio_xmpp::parsers::Jid;
|
||||
use tokio_xmpp::parsers::{bookmarks2, message::Body, roster::Item as RosterItem, BareJid};
|
||||
|
||||
use crate::message::MucMessageId;
|
||||
use crate::{delay::StanzaTimeInfo, Error, Id, RoomNick};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -30,15 +31,59 @@ pub enum Event {
|
|||
LeaveAllRooms,
|
||||
RoomJoined(BareJid),
|
||||
RoomLeft(BareJid),
|
||||
RoomMessage(Id, BareJid, RoomNick, Body, StanzaTimeInfo),
|
||||
/// A message received from a group chat room.
|
||||
/// - The [`MucMessageId`] is the ID of the message; it contains the ID assigned by the room,
|
||||
/// and the ID assigned by the sending client.
|
||||
/// - The [`BareJid`] is the room's address.
|
||||
/// - The [`RoomNick`] is the nickname of the room member who sent the message.
|
||||
/// - The [`Body`] is the message body.
|
||||
/// - The [`StanzaTimeInfo`] about when message was received, and when the message was claimed sent.
|
||||
///
|
||||
/// Note: if the sender_assigned_id matches the ID returned by Agent::send_message,
|
||||
/// then the message is an echo of a message sent by the client.
|
||||
RoomMessage(MucMessageId, BareJid, RoomNick, Body, 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.
|
||||
/// - The String is the new subject.
|
||||
RoomSubject(BareJid, Option<RoomNick>, 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(Id, BareJid, RoomNick, Body, StanzaTimeInfo),
|
||||
/// - The MucMessageId is the ID of the message that contained the subject;
|
||||
/// it contains the ID assigned by the room, and the ID assigned by the sending client.
|
||||
/// - The [`BareJid`] is the room's address.
|
||||
/// - The [`RoomNick`] is the nickname of the room member who set the subject.
|
||||
/// - The [`String`] is the new subject.
|
||||
/// - The [`StanzaTimeInfo`] about when message was received, and when the message was claimed sent.
|
||||
RoomSubject(
|
||||
MucMessageId,
|
||||
BareJid,
|
||||
Option<RoomNick>,
|
||||
String,
|
||||
StanzaTimeInfo,
|
||||
),
|
||||
/// A private message received from a member of a room.
|
||||
/// - The [`MucMessageId`] is the ID of the message; it contains the ID assigned by the room,
|
||||
/// and the ID assigned by the sending client.
|
||||
/// - The [`BareJid`] is the room's address.
|
||||
/// - The [`RoomNick`] is the nickname of the room member who sent the message.
|
||||
/// - The [`Body`] is the message body.
|
||||
/// - The [`StanzaTimeInfo`] about when message was received, and when the message was claimed sent.
|
||||
///
|
||||
/// Note: if the sender_assigned_id matches the ID returned by Agent::send_room_private_message,
|
||||
/// then the message is an echo of a message sent by the client.
|
||||
RoomPrivateMessage(MucMessageId, BareJid, RoomNick, Body, StanzaTimeInfo),
|
||||
/// A message in a one-to-one chat was corrected/edited.
|
||||
/// - The [`Id`] is the ID of the message that was corrected. (Only
|
||||
/// - 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.
|
||||
ChatMessageCorrection(Id, BareJid, Body),
|
||||
/// A message in a MUC was corrected/edited.
|
||||
/// - The [`MucMessageId`] is the ID of the message that was corrected. (Only muc_assigned_id is set.)
|
||||
/// - 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.
|
||||
RoomMessageCorrection(MucMessageId, BareJid, RoomNick, Body),
|
||||
/// A private message in a MUC was corrected/edited.
|
||||
/// - The [`MucMessageId`] is the ID of the message that was corrected. (Only muc_assigned_id is set.)
|
||||
/// - 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.
|
||||
RoomPrivateMessageCorrection(MucMessageId, BareJid, RoomNick, Body),
|
||||
ServiceMessage(Id, BareJid, Body, StanzaTimeInfo),
|
||||
HttpUploadedFile(String),
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ pub use feature::ClientFeature;
|
|||
|
||||
pub type Error = tokio_xmpp::Error;
|
||||
pub type Id = Option<String>;
|
||||
|
||||
pub type RoomNick = String;
|
||||
|
||||
#[cfg(all(test, any(feature = "starttls-rust", feature = "starttls-native")))]
|
||||
|
|
190
xmpp/src/message/correct.rs
Normal file
190
xmpp/src/message/correct.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
use crate::message::MucMessageId;
|
||||
use crate::parsers::message::{Body, Message, MessageType};
|
||||
use crate::parsers::message_correct::Replace;
|
||||
use crate::{Agent, BareJid, Element, Event, Jid, RoomNick};
|
||||
use tokio_xmpp::connect::ServerConnector;
|
||||
|
||||
/// Send a <message> stanza that corrects an earlier message.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `agent`: The agent to use to send the message.
|
||||
/// - `id`: The ID of the message to correct.
|
||||
/// - `to`: The (original) recipient of the message.
|
||||
/// - `lang`: The language of the new message body.
|
||||
/// - `text`: The new message body, to replace the old one.
|
||||
pub async fn send_correction<C: ServerConnector>(
|
||||
agent: &mut Agent<C>,
|
||||
id: &str,
|
||||
to: BareJid,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
// Create a message stanza with the correct payload.
|
||||
let mut message = Message::new(Some(to.into()));
|
||||
|
||||
// Set the new body.
|
||||
message
|
||||
.bodies
|
||||
.insert(String::from(lang), Body(String::from(text)));
|
||||
|
||||
let replace = Replace { id: id.to_owned() };
|
||||
|
||||
// Specify that this message is a correction of an earlier message.
|
||||
message.payloads.push(replace.into());
|
||||
|
||||
agent
|
||||
.client
|
||||
.send_stanza(message.into())
|
||||
.await
|
||||
.expect("Failed to send message correction.");
|
||||
}
|
||||
|
||||
/// Send a <message> stanza that corrects an earlier message in a MUC.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `agent`: The agent to use to send the message.
|
||||
/// - `id`: The ID of the message to correct.
|
||||
/// - `room`: The JID of the room.
|
||||
/// - `lang`: The language of the new message body.
|
||||
/// - `text`: The new message body, to replace the old one.
|
||||
pub async fn send_correction_group<C: ServerConnector>(
|
||||
agent: &mut Agent<C>,
|
||||
id: &str,
|
||||
room: BareJid,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
// Create a message stanza with the correct payload.
|
||||
let mut message = Message::new(Some(room.into()));
|
||||
|
||||
// Set the new body.
|
||||
message
|
||||
.bodies
|
||||
.insert(String::from(lang), Body(String::from(text)));
|
||||
|
||||
message.type_ = MessageType::Groupchat;
|
||||
|
||||
let replace = Replace { id: id.to_owned() };
|
||||
|
||||
// Specify that this message is a correction of an earlier message.
|
||||
message.payloads.push(replace.into());
|
||||
|
||||
agent
|
||||
.client
|
||||
.send_stanza(message.into())
|
||||
.await
|
||||
.expect("Failed to send message correction.");
|
||||
}
|
||||
|
||||
/// Send a <message> stanza that corrects an earlier message in a private chat in a MUC.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `agent`: The agent to use to send the message.
|
||||
/// - `id`: The ID of the message to correct.
|
||||
/// - `room`: The JID of the room.
|
||||
/// - `nick`: The nickname of the recipient of the message.
|
||||
/// - `lang`: The language of the new message body.
|
||||
/// - `text`: The new message body, to replace the old one.
|
||||
pub async fn send_correction_private<C: ServerConnector>(
|
||||
agent: &mut Agent<C>,
|
||||
id: &str,
|
||||
room: BareJid,
|
||||
nick: RoomNick,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
// Create a message stanza with the correct payload.
|
||||
let mut message = Message::new(Some(
|
||||
room.with_resource_str(&nick)
|
||||
.expect("Failed to create JID.")
|
||||
.into(),
|
||||
));
|
||||
|
||||
// Set the new body.
|
||||
message
|
||||
.bodies
|
||||
.insert(String::from(lang), Body(String::from(text)));
|
||||
|
||||
let replace = Replace { id: id.to_owned() };
|
||||
|
||||
// Specify that this message is a correction of an earlier message.
|
||||
message.payloads.push(replace.into());
|
||||
|
||||
agent
|
||||
.client
|
||||
.send_stanza(message.into())
|
||||
.await
|
||||
.expect("Failed to send message correction.");
|
||||
}
|
||||
|
||||
/// Convert a Message with a <replace> payload into a higher-level Event.
|
||||
///
|
||||
/// # Arguments
|
||||
/// - `message`: The message to convert.
|
||||
/// - `replace`: The <replace> payload element.
|
||||
/// - `from`: The JID of the sender.
|
||||
pub fn handle_correction(
|
||||
message: &Message,
|
||||
replace: &Element,
|
||||
from: &Jid,
|
||||
langs: Vec<&str>,
|
||||
) -> Event {
|
||||
// Parse the <replace> payload.
|
||||
let replace = Replace::try_from(replace.clone())
|
||||
// TODO: Should be handled with an error stanza back to the server, but panicking is consistent with behavior when facing other parsing issues.
|
||||
.expect("Failed to parse message correction payload.");
|
||||
|
||||
// Extract the ID of the message to correct.
|
||||
let id = replace.id.clone();
|
||||
|
||||
// Extract the language and body of the new message.
|
||||
let body = message
|
||||
.get_best_body(langs)
|
||||
.map(|(_lang, body)| body.clone())
|
||||
.expect("Received a replace payload without a body.");
|
||||
|
||||
match message.type_ {
|
||||
MessageType::Chat | MessageType::Normal => {
|
||||
Event::ChatMessageCorrection(Some(id), from.to_bare(), body)
|
||||
}
|
||||
MessageType::Groupchat => {
|
||||
let groupchat_jid = from.to_bare();
|
||||
let sender_nick = from
|
||||
.resource_str()
|
||||
.expect("A message in a group chat should have a resource part.")
|
||||
.to_string();
|
||||
|
||||
// TODO: This is inconsistent with message-retraction; need to fix before merging.
|
||||
match &message
|
||||
.to
|
||||
.clone()
|
||||
.expect("A message in a group chat should have a 'to' attribute.")
|
||||
{
|
||||
Jid::Full(_) => Event::RoomMessageCorrection(
|
||||
MucMessageId {
|
||||
sender_assigned_id: None,
|
||||
room_assigned_id: Some(id), // for XEP-0308, the ID of the message to correct is the room-assigned ID.
|
||||
},
|
||||
groupchat_jid,
|
||||
sender_nick,
|
||||
body,
|
||||
),
|
||||
Jid::Bare(_) => Event::RoomPrivateMessageCorrection(
|
||||
MucMessageId {
|
||||
sender_assigned_id: None,
|
||||
room_assigned_id: Some(id), // for XEP-0308, the ID of the message to correct is the room-assigned ID.
|
||||
},
|
||||
groupchat_jid,
|
||||
sender_nick,
|
||||
body,
|
||||
),
|
||||
}
|
||||
}
|
||||
MessageType::Error => {
|
||||
unimplemented!("Received message with <replace> payload and type=error.")
|
||||
}
|
||||
MessageType::Headline => {
|
||||
unimplemented!("Received message with <replace> payload and type=headline.")
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,5 +4,25 @@
|
|||
// 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 crate::Id;
|
||||
|
||||
pub mod correct;
|
||||
pub mod receive;
|
||||
pub mod send;
|
||||
|
||||
/// A message ID for a message in a MUC room.
|
||||
///
|
||||
/// Note: this struct is a bit weird due to an inconsistency between XEPs 0308 and 0424.
|
||||
///
|
||||
/// XEP-0424 (Message Retraction) designates messages to correct by the sender-assigned ID,
|
||||
/// but XEP-0308 (Last Message Correction) designates messages to correct by the room-assigned ID.
|
||||
///
|
||||
/// Hence, both are needed, but depending on context, one or the other may be missing or may
|
||||
/// refer to something else; see the context-specific documentation for more information.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct MucMessageId {
|
||||
/// The ID of the message as assigned by the client that sent it.
|
||||
pub sender_assigned_id: Id,
|
||||
/// The ID of the message as assigned by the room.
|
||||
pub room_assigned_id: Id,
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ use tokio_xmpp::{
|
|||
Jid,
|
||||
};
|
||||
|
||||
use crate::message::receive::group_chat::extract_muc_message_id;
|
||||
use crate::{delay::StanzaTimeInfo, Agent, Event};
|
||||
|
||||
pub async fn handle_message_chat<C: ServerConnector>(
|
||||
|
@ -37,7 +38,7 @@ pub async fn handle_message_chat<C: ServerConnector>(
|
|||
)
|
||||
}
|
||||
Jid::Full(full) => Event::RoomPrivateMessage(
|
||||
message.id.clone(),
|
||||
extract_muc_message_id(message),
|
||||
full.to_bare(),
|
||||
full.resource().to_string(),
|
||||
body.clone(),
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
use tokio_xmpp::connect::ServerConnector;
|
||||
use tokio_xmpp::{parsers::message::Message, Jid};
|
||||
|
||||
use crate::message::MucMessageId;
|
||||
use crate::parsers::ns::SID;
|
||||
use crate::parsers::stanza_id::StanzaId;
|
||||
use crate::{delay::StanzaTimeInfo, Agent, Event};
|
||||
|
||||
pub async fn handle_message_group_chat<C: ServerConnector>(
|
||||
|
@ -18,8 +21,11 @@ pub async fn handle_message_group_chat<C: ServerConnector>(
|
|||
) {
|
||||
let langs: Vec<&str> = agent.lang.iter().map(String::as_str).collect();
|
||||
|
||||
let id = extract_muc_message_id(message);
|
||||
|
||||
if let Some((_lang, subject)) = message.get_best_subject(langs.clone()) {
|
||||
events.push(Event::RoomSubject(
|
||||
id.clone(),
|
||||
from.to_bare(),
|
||||
from.resource().map(|x| x.to_string()),
|
||||
subject.0.clone(),
|
||||
|
@ -30,7 +36,7 @@ pub async fn handle_message_group_chat<C: ServerConnector>(
|
|||
if let Some((_lang, body)) = message.get_best_body(langs) {
|
||||
let event = match from.clone() {
|
||||
Jid::Full(full) => Event::RoomMessage(
|
||||
message.id.clone(),
|
||||
id,
|
||||
from.to_bare(),
|
||||
full.resource().to_string(),
|
||||
body.clone(),
|
||||
|
@ -43,3 +49,23 @@ pub async fn handle_message_group_chat<C: ServerConnector>(
|
|||
events.push(event)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract the sender-assigned and room-assigned IDs from a message.
|
||||
pub fn extract_muc_message_id(message: &Message) -> MucMessageId {
|
||||
// Find a stanza-id element, if any.
|
||||
let stanza_id = message
|
||||
.payloads
|
||||
.iter()
|
||||
.find(|payload| payload.is("stanza-id", SID))
|
||||
.map(|elem| {
|
||||
StanzaId::try_from(elem.clone())
|
||||
.expect("Failed to parse stanza-id")
|
||||
.id
|
||||
});
|
||||
|
||||
let id = MucMessageId {
|
||||
sender_assigned_id: message.id.clone(),
|
||||
room_assigned_id: stanza_id,
|
||||
};
|
||||
id
|
||||
}
|
||||
|
|
|
@ -7,22 +7,38 @@
|
|||
use tokio_xmpp::connect::ServerConnector;
|
||||
use tokio_xmpp::{
|
||||
parsers::message::{Body, Message, MessageType},
|
||||
Jid,
|
||||
Error, Jid,
|
||||
};
|
||||
|
||||
use crate::Agent;
|
||||
|
||||
/// Send a message to a given recipient.
|
||||
///
|
||||
/// Returns the generated message ID.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `agent`: The agent to use to send the message.
|
||||
/// * `recipient`: The JID of the recipient.
|
||||
/// * `type_`: The type of message to send.
|
||||
/// For a message to a MUC room, this should be `MessageType::Groupchat`.
|
||||
/// For a private message to a MUC room member or regular contact,
|
||||
/// this should be `MessageType::Chat`.
|
||||
/// * `lang`: The language of the message. (See IETF RFC 5646)
|
||||
/// * `text`: The text of the message.
|
||||
///
|
||||
/// Returns the generated message ID, or an error if the message could not be sent.
|
||||
pub async fn send_message<C: ServerConnector>(
|
||||
agent: &mut Agent<C>,
|
||||
recipient: Jid,
|
||||
type_: MessageType,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
) -> Result<String, Error> {
|
||||
let mut message = Message::new(Some(recipient));
|
||||
message.type_ = type_;
|
||||
message
|
||||
.bodies
|
||||
.insert(String::from(lang), Body(String::from(text)));
|
||||
let _ = agent.client.send_stanza(message.into()).await;
|
||||
agent.client.send_stanza(message.into()).await
|
||||
}
|
||||
|
|
|
@ -10,23 +10,40 @@ use tokio_xmpp::{
|
|||
message::{Body, Message, MessageType},
|
||||
muc::user::MucUser,
|
||||
},
|
||||
BareJid, Jid,
|
||||
BareJid, Error, Jid,
|
||||
};
|
||||
|
||||
use crate::{Agent, RoomNick};
|
||||
|
||||
/// Send a private message to a given MUC room member.
|
||||
///
|
||||
/// Returns the generated message ID.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `agent`: The agent to use to send the message.
|
||||
/// * `room`: The JID of the room.
|
||||
/// * `recipient`: The nickname of the recipient within the room.
|
||||
/// * `type_`: The type of message to send.
|
||||
/// For a message to a MUC room, this should be `MessageType::Groupchat`.
|
||||
/// For a private message to a MUC room member or regular contact,
|
||||
/// this should be `MessageType::Chat`.
|
||||
/// * `lang`: The language of the message. (See IETF RFC 5646)
|
||||
/// * `text`: The text of the message.
|
||||
///
|
||||
/// Returns the generated message ID, or an error if the message could not be sent.
|
||||
pub async fn send_room_private_message<C: ServerConnector>(
|
||||
agent: &mut Agent<C>,
|
||||
room: BareJid,
|
||||
recipient: RoomNick,
|
||||
lang: &str,
|
||||
text: &str,
|
||||
) {
|
||||
) -> Result<String, Error> {
|
||||
let recipient: Jid = room.with_resource_str(&recipient).unwrap().into();
|
||||
let mut message = Message::new(recipient).with_payload(MucUser::new());
|
||||
message.type_ = MessageType::Chat;
|
||||
message
|
||||
.bodies
|
||||
.insert(String::from(lang), Body(String::from(text)));
|
||||
let _ = agent.client.send_stanza(message.into()).await;
|
||||
agent.client.send_stanza(message.into()).await
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user