diff --git a/src/handlers.rs b/src/handlers.rs index 7b65472..697f181 100644 --- a/src/handlers.rs +++ b/src/handlers.rs @@ -27,7 +27,10 @@ use xmpp_parsers::{ disco::{DiscoInfoQuery, DiscoInfoResult, Feature, Identity}, iq::{Iq, IqType}, message::Message, - muc::Muc, + muc::{ + user::{Affiliation, Item as MucItem, Reason, Role, Status as MucStatus}, + Muc, MucUser, + }, ns, ping::Ping, presence::{Presence, Type as PresenceType}, @@ -244,8 +247,8 @@ async fn handle_presence( Ok(_) => (), Err(Error::NickAlreadyAssigned(nick)) => { let error = Presence::new(PresenceType::Error) - .with_from(participant) - .with_to(realjid) + .with_from(participant.clone()) + .with_to(realjid.clone()) .with_payloads(vec![ StanzaError::new( ErrorType::Cancel, @@ -259,10 +262,28 @@ async fn handle_presence( err => err.unwrap(), } } else if let ControlFlow::Continue(_) = muc { - if room.is_joined(&realjid) { - room.update_presence(component, presence.clone()).await? - } else { - // TODO: We don't want to support GC1. Error + match room.update_presence(component, presence.clone()).await { + Ok(()) => (), + Err(Error::ParticipantNotFound(_)) => { + let error = Presence::new(PresenceType::Unavailable) + .with_from(participant) + .with_to(realjid) + .with_payloads(vec![MucUser { + status: vec![ + MucStatus::SelfPresence, + MucStatus::Kicked, + MucStatus::ServiceErrorKick, + ], + items: { + let mut item = MucItem::new(Affiliation::None, Role::None); + item.reason = Some(Reason(String::from("You are not in the room."))); + vec![item] + }, + } + .into()]); + component.send_stanza(error).await? + }, + err => err?, } } } else { diff --git a/src/tests/presence.rs b/src/tests/presence.rs index 3ace761..328359a 100644 --- a/src/tests/presence.rs +++ b/src/tests/presence.rs @@ -18,7 +18,7 @@ use crate::handlers::handle_stanza; use crate::room::Room; use crate::tests::templates::{ two_participant_room, LOUISE_FULL1, LOUISE_FULL2, LOUISE_NICK, LOUISE_ROOM1_PART, ROOM1_BARE, - SUGAKO_FULL1, SUGAKO_ROOM1_PART, + ROSA_FULL1, ROSA_ROOM1_PART, SUGAKO_FULL1, SUGAKO_ROOM1_PART, }; use std::collections::{BTreeMap, HashMap}; @@ -28,7 +28,7 @@ use xmpp_parsers::{ delay::Delay, message::{Message, MessageType, Subject as MessageSubject}, muc::{ - user::{Affiliation, Item as MucItem, Role, Status as MucStatus}, + user::{Affiliation, Item as MucItem, Reason, Role, Status as MucStatus}, Muc, MucUser, }, presence::{Presence, Show as PresenceShow, Type as PresenceType}, @@ -633,26 +633,40 @@ async fn test_presence_update_joined() { handle_stanza(&mut component, &mut rooms).await.unwrap(); } -#[ignore] #[tokio::test] async fn test_presence_update_not_joined() { // https://xmpp.org/extensions/xep-0045.html#example-43 // GC1 join presence - // - // - // - // You are not in the room. - // - // - // - // - // - // - todo!() + let update: Element = Presence::new(PresenceType::None) + .with_from(Jid::Full(ROSA_FULL1.clone())) + .with_to(Jid::Full(ROSA_ROOM1_PART.clone())) + .into(); + + let mut component = TestComponent::new(vec![update]); + let mut rooms: HashMap = HashMap::new(); + rooms.insert(ROOM1_BARE.clone(), two_participant_room(ROOM1_BARE.clone())); + + component.expect( + Presence::new(PresenceType::Unavailable) + .with_from(Jid::Full(ROSA_ROOM1_PART.clone())) + .with_to(Jid::Full(ROSA_FULL1.clone())) + .with_payloads(vec![MucUser { + status: vec![ + MucStatus::SelfPresence, + MucStatus::Kicked, + MucStatus::ServiceErrorKick, + ], + items: { + let mut item = MucItem::new(Affiliation::None, Role::None); + item.reason = Some(Reason(String::from("You are not in the room."))); + vec![item] + }, + } + .into()]), + ); + + handle_stanza(&mut component, &mut rooms).await.unwrap(); } #[ignore]