xmpp/message/receive/
chat.rs

1// Copyright (c) 2023 xmpp-rs contributors.
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 tokio_xmpp::{
8    jid::Jid,
9    parsers::{confirm::Confirm, message::Message, message_correct::Replace, muc::user::MucUser},
10};
11
12use crate::{Agent, Event, RoomNick, delay::StanzaTimeInfo};
13
14pub async fn handle_message_chat(
15    agent: &mut Agent,
16    events: &mut Vec<Event>,
17    from: Jid,
18    message: &mut Message,
19    time_info: StanzaTimeInfo,
20) {
21    let config = agent.get_config().await;
22    let langs: Vec<&str> = config.lang.iter().map(String::as_str).collect();
23
24    let confirm = message.extract_valid_payload::<Confirm>();
25    let is_muc_pm = message.extract_valid_payload::<MucUser>().is_some();
26
27    // First process events that do not require the message body
28    if !is_muc_pm && confirm.is_some() {
29        events.push(Event::AuthConfirm(
30            from.to_bare(),
31            confirm.unwrap(),
32            time_info,
33        ));
34        return;
35    }
36
37    // For other events, a message body is required, so stop here if there isn't one
38    let Some((_lang, body)) = message.get_best_body_cloned(langs) else {
39        debug!("Received normal/chat message without body:\n{:#?}", message);
40        return;
41    };
42
43    let correction = message.extract_valid_payload::<Replace>();
44
45    if is_muc_pm {
46        if from.resource().is_none() {
47            warn!(
48                "Received malformed MessageType::Chat in muc#user namespace from a bare JID:\n{message:#?}"
49            );
50        } else {
51            let full_from = from.clone().try_into_full().unwrap();
52
53            let event = if let Some(correction) = correction {
54                Event::RoomPrivateMessageCorrection(
55                    correction.id,
56                    full_from.to_bare(),
57                    RoomNick::from_resource_ref(full_from.resource()),
58                    body.clone(),
59                    time_info,
60                )
61            } else {
62                Event::RoomPrivateMessage(
63                    message.id.clone(),
64                    from.to_bare(),
65                    RoomNick::from_resource_ref(full_from.resource()),
66                    body.clone(),
67                    time_info,
68                )
69            };
70            events.push(event);
71        }
72    } else {
73        let event = if let Some(correction) = correction {
74            // TODO: Check that correction is valid (only for last N minutes or last N messages)
75            Event::ChatMessageCorrection(correction.id, from.to_bare(), body.clone(), time_info)
76        } else {
77            Event::ChatMessage(message.id.clone(), from.to_bare(), body, time_info)
78        };
79        events.push(event);
80    }
81}
82
83pub async fn handle_message_error(
84    _agent: &mut Agent,
85    events: &mut Vec<Event>,
86    from: Jid,
87    message: &mut Message,
88    time_info: StanzaTimeInfo,
89) {
90    let confirm = message.extract_valid_payload::<Confirm>();
91    if let Some(confirm) = confirm {
92        events.push(Event::AuthReject(from.to_bare(), confirm, time_info));
93    }
94}