Skip to main content

xmpp/message/receive/
group_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 crate::{
8    Agent, Event, RoomNick,
9    delay::StanzaTimeInfo,
10    jid::Jid,
11    parsers::{message::Message, message_correct::Replace},
12};
13
14pub async fn handle_message_group_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 Some((_lang, body)) = message.get_best_body_cloned(langs.clone()) else {
25        // 0045 ยง7.2.15
26        // a <message/> stanza from the room JID (or from the occupant JID of the entity that set
27        // the subject), with a <subject/> element but no <body/> element
28        if let Some((_lang, subject)) = message.get_best_subject(langs) {
29            events.push(Event::RoomSubject(
30                from.to_bare(),
31                from.resource().map(RoomNick::from_resource_ref),
32                subject.clone(),
33                time_info.clone(),
34            ));
35        }
36
37        return;
38    };
39
40    let correction = message.extract_payload::<Replace>().unwrap_or_else(|e| {
41        warn!("Failed to parse <replace> payload: {e}");
42        None
43    });
44
45    // Now we have a groupchat message... which can be:
46    //
47    // - a normal MUC message from a user in a room
48    // - a MUC message correction from a user in a room
49    // - a service message from a MUC channel (barejid)
50    //
51    // In theory we can have service message correction but nope nope nope
52
53    if let Some(resource) = from.resource() {
54        // User message/correction
55
56        let event = if let Some(correction) = correction {
57            Event::RoomMessageCorrection(
58                correction.id,
59                from.to_bare(),
60                RoomNick::from_resource_ref(resource),
61                body.clone(),
62                time_info,
63            )
64        } else {
65            Event::RoomMessage(
66                message.id.clone(),
67                from.to_bare(),
68                RoomNick::from_resource_ref(resource),
69                body.clone(),
70                time_info,
71            )
72        };
73        events.push(event);
74    } else {
75        // Service message
76        if correction.is_some() {
77            warn!("Found correction in service message:\n{:#?}", message);
78        } else {
79            let event = Event::ServiceMessage(message.id.clone(), from.to_bare(), body, time_info);
80            events.push(event);
81        }
82    }
83}