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}