forked from lavina/lavina
xmpp: add support leaving MUCs via unavailable presence
This commit is contained in:
parent
43d105ab23
commit
8a0a0c0935
|
@ -23,36 +23,17 @@ impl<'a> XmppConnection<'a> {
|
|||
server,
|
||||
// resources in MUCs are members' personas – not implemented (yet?)
|
||||
resource: Some(_),
|
||||
}) if server.0 == self.hostname_rooms => {
|
||||
let mut muc_presence = self.retrieve_muc_presence(&name).await?;
|
||||
muc_presence.id = p.id;
|
||||
let subject = Message::<()> {
|
||||
from: Some(Jid {
|
||||
name: Some(name.clone()),
|
||||
server: Server(self.hostname_rooms.clone()),
|
||||
resource: None,
|
||||
}),
|
||||
id: None,
|
||||
to: Some(Jid {
|
||||
name: Some(self.user.xmpp_name.clone()),
|
||||
server: Server(self.hostname.clone()),
|
||||
resource: Some(self.user.xmpp_resource.clone()),
|
||||
}),
|
||||
r#type: MessageType::Groupchat,
|
||||
lang: None,
|
||||
subject: Some(Subject(None)),
|
||||
body: None,
|
||||
custom: vec![],
|
||||
};
|
||||
muc_presence.serialize(output);
|
||||
|
||||
let messages = self.retrieve_message_history(&name).await?;
|
||||
for message in messages {
|
||||
message.serialize(output)
|
||||
}) if server.0 == self.hostname_rooms => match p.r#type.as_deref() {
|
||||
None => {
|
||||
self.join_muc(output, p.id, name).await?;
|
||||
}
|
||||
// The subject is the last stanza sent during a MUC join process.
|
||||
subject.serialize(output);
|
||||
}
|
||||
Some("unavailable") => {
|
||||
self.leave_muc(output, p.id, name).await?;
|
||||
}
|
||||
_ => {
|
||||
tracing::error!("Unimplemented case")
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// TODO other presence cases
|
||||
let response = Presence::<()>::default();
|
||||
|
@ -62,6 +43,74 @@ impl<'a> XmppConnection<'a> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn join_muc(&mut self, output: &mut Vec<Event<'static>>, id: Option<String>, name: Name) -> Result<()> {
|
||||
// Response presence
|
||||
let mut muc_presence = self.retrieve_muc_presence(&name).await?;
|
||||
muc_presence.id = id;
|
||||
muc_presence.serialize(output);
|
||||
|
||||
// N last messages from the room history before the user joined
|
||||
let messages = self.retrieve_message_history(&name).await?;
|
||||
for message in messages {
|
||||
message.serialize(output)
|
||||
}
|
||||
|
||||
// The subject is the last stanza sent during a MUC join process.
|
||||
let subject = Message::<()> {
|
||||
from: Some(Jid {
|
||||
name: Some(name.clone()),
|
||||
server: Server(self.hostname_rooms.clone()),
|
||||
resource: None,
|
||||
}),
|
||||
id: None,
|
||||
to: Some(Jid {
|
||||
name: Some(self.user.xmpp_name.clone()),
|
||||
server: Server(self.hostname.clone()),
|
||||
resource: Some(self.user.xmpp_resource.clone()),
|
||||
}),
|
||||
r#type: MessageType::Groupchat,
|
||||
lang: None,
|
||||
subject: Some(Subject(None)),
|
||||
body: None,
|
||||
custom: vec![],
|
||||
};
|
||||
subject.serialize(output);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn leave_muc(&mut self, output: &mut Vec<Event<'static>>, id: Option<String>, name: Name) -> Result<()> {
|
||||
self.user_handle.leave_room(RoomId::try_from(name.0.clone())?).await?;
|
||||
let response = Presence {
|
||||
to: Some(Jid {
|
||||
name: Some(self.user.xmpp_name.clone()),
|
||||
server: Server(self.hostname.clone()),
|
||||
resource: Some(self.user.xmpp_resource.clone()),
|
||||
}),
|
||||
from: Some(Jid {
|
||||
name: Some(name.clone()),
|
||||
server: Server(self.hostname_rooms.clone()),
|
||||
resource: Some(self.user.xmpp_muc_name.clone()),
|
||||
}),
|
||||
r#type: Some("unavailable".into()),
|
||||
custom: vec![XUser {
|
||||
item: XUserItem {
|
||||
affiliation: Affiliation::Member,
|
||||
role: Role::None,
|
||||
jid: Jid {
|
||||
name: Some(self.user.xmpp_name.clone()),
|
||||
server: Server(self.hostname.clone()),
|
||||
resource: Some(self.user.xmpp_resource.clone()),
|
||||
},
|
||||
},
|
||||
self_presence: true,
|
||||
just_created: false,
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
response.serialize(output);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self, output, r#type), name = "XmppConnection::self_presence")]
|
||||
async fn self_presence(&mut self, output: &mut Vec<Event<'static>>, r#type: Option<&str>) {
|
||||
match r#type {
|
||||
|
@ -92,7 +141,7 @@ impl<'a> XmppConnection<'a> {
|
|||
|
||||
#[tracing::instrument(skip(self), name = "XmppConnection::retrieve_muc_presence")]
|
||||
async fn retrieve_muc_presence(&mut self, name: &Name) -> Result<Presence<XUser>> {
|
||||
let a = self.user_handle.join_room(RoomId::try_from(name.0.clone())?).await?;
|
||||
let _ = self.user_handle.join_room(RoomId::try_from(name.0.clone())?).await?;
|
||||
// TODO handle bans
|
||||
let response = Presence {
|
||||
to: Some(Jid {
|
||||
|
@ -273,7 +322,7 @@ mod tests {
|
|||
just_created: false,
|
||||
}],
|
||||
..Default::default()
|
||||
};
|
||||
};
|
||||
assert_eq!(expected, response);
|
||||
|
||||
drop(conn);
|
||||
|
|
Loading…
Reference in New Issue