diff --git a/src/handlers/presence.rs b/src/handlers/presence.rs index bf532f9..fc8d957 100644 --- a/src/handlers/presence.rs +++ b/src/handlers/presence.rs @@ -41,7 +41,28 @@ pub async fn handle_presence( if let Ok(presence) = PresenceFull::try_from(presence.clone()) { match presence.type_ { PresenceType::None => { - handle_presence_full_available(component, presence.clone(), rooms).await? + match handle_presence_full_available(component, presence.clone(), rooms).await { + Ok(()) => (), + Err(Error::NickAlreadyAssigned(nick)) => { + let realjid = presence.from.clone().unwrap(); + let participant = presence.to.clone().unwrap(); + let error = Presence::new(PresenceType::Error) + .with_from(participant) + .with_to(realjid) + .with_payloads(vec![ + Muc::new().into(), + StanzaError::new( + ErrorType::Cancel, + DefinedCondition::Conflict, + "en", + format!("Nickname conflict: {nick}"), + ) + .into(), + ]); + component.send_stanza(error).await?; + } + Err(_) => todo!(), + } } PresenceType::Unavailable => { handle_presence_full_unavailable(component, presence.clone(), rooms).await? @@ -85,23 +106,7 @@ async fn handle_presence_full_available( debug!("Presence received to existing room: {}", &roomjid); if let ControlFlow::Break(_) = muc { // <{muc}x/> was found - match room.add_session(component, presence.clone()).await { - Ok(_) => (), - Err(Error::NickAlreadyAssigned(nick)) => { - let error = Presence::new(PresenceType::Error) - .with_from(participant.clone()) - .with_to(realjid.clone()) - .with_payloads(vec![StanzaError::new( - ErrorType::Cancel, - DefinedCondition::Conflict, - "en", - format!("Nickname conflict: {nick}"), - ) - .into()]); - component.send_stanza(error).await?; - } - err => err.unwrap(), - } + room.add_session(component, presence.clone()).await?; } else if let ControlFlow::Continue(_) = muc { // <{muc}x/> wasn't found diff --git a/src/tests/presence.rs b/src/tests/presence.rs index 6072f42..f31a093 100644 --- a/src/tests/presence.rs +++ b/src/tests/presence.rs @@ -141,13 +141,16 @@ async fn join_nick_already_assigned() { Presence::new(PresenceType::Error) .with_from(LOUISE_ROOM1_PART.clone()) .with_to(Jid::Full(SUGAKO_FULL1.clone())) - .with_payloads(vec![StanzaError::new( - ErrorType::Cancel, - DefinedCondition::Conflict, - "en", - format!("Nickname conflict: {}", LOUISE_NICK), - ) - .into()]), + .with_payloads(vec![ + Muc::new().into(), + StanzaError::new( + ErrorType::Cancel, + DefinedCondition::Conflict, + "en", + format!("Nickname conflict: {}", LOUISE_NICK), + ) + .into(), + ]), ); handle_stanza(&mut component, &mut rooms).await.unwrap(); @@ -638,3 +641,45 @@ async fn nickname_change() { handle_stanza(&mut component, &mut rooms).await.unwrap(); } + +#[tokio::test] +async fn nickname_conflict() { + let mut rooms: HashMap = HashMap::new(); + rooms.insert( + ROOM1_BARE.clone(), + new_room( + ROOM1_BARE.clone(), + vec![ + (LOUISE_NICK, vec![LOUISE_FULL1.clone()]), + (SUGAKO_NICK, vec![SUGAKO_FULL1.clone()]), + ], + ) + .await, + ); + + let update: Element = Presence::new(PresenceType::None) + .with_from(Jid::Full(LOUISE_FULL1.clone())) + .with_to(Jid::Full(SUGAKO_ROOM1_PART.clone())) + .into(); + + let mut component = TestComponent::new(vec![update]); + + // Conflict presence + component.expect( + Presence::new(PresenceType::Error) + .with_from(Jid::Full(SUGAKO_ROOM1_PART.clone())) + .with_to(Jid::Full(LOUISE_FULL1.clone())) + .with_payloads(vec![ + Muc::new().into(), + StanzaError::new( + ErrorType::Cancel, + DefinedCondition::Conflict, + "en", + format!("Nickname conflict: {}", SUGAKO_NICK), + ) + .into(), + ]), + ); + + handle_stanza(&mut component, &mut rooms).await.unwrap(); +}