forked from lavina/lavina
Compare commits
2 Commits
89918d9de1
...
d00d57ac44
Author | SHA1 | Date |
---|---|---|
Mikhail | d00d57ac44 | |
Nikita Vilunov | 1b59250042 |
|
@ -4,8 +4,9 @@ use anyhow::Result;
|
||||||
use quick_xml::events::Event;
|
use quick_xml::events::Event;
|
||||||
|
|
||||||
use lavina_core::room::RoomId;
|
use lavina_core::room::RoomId;
|
||||||
use proto_xmpp::bind::{Jid, Name, Server};
|
use proto_xmpp::bind::{Jid, Name, Resource, Server};
|
||||||
use proto_xmpp::client::Presence;
|
use proto_xmpp::client::Presence;
|
||||||
|
use proto_xmpp::muc::{Delay, HistoryMessage, XUser};
|
||||||
use proto_xmpp::xml::{Ignore, ToXml};
|
use proto_xmpp::xml::{Ignore, ToXml};
|
||||||
|
|
||||||
use crate::XmppConnection;
|
use crate::XmppConnection;
|
||||||
|
@ -22,8 +23,11 @@ impl<'a> XmppConnection<'a> {
|
||||||
// resources in MUCs are members' personas – not implemented (yet?)
|
// resources in MUCs are members' personas – not implemented (yet?)
|
||||||
resource: Some(_),
|
resource: Some(_),
|
||||||
}) if server.0 == self.hostname_rooms => {
|
}) if server.0 == self.hostname_rooms => {
|
||||||
let response = self.muc_presence(&name).await?;
|
let muc_join_response = self.muc_presence(&name).await?;
|
||||||
response.serialize(output);
|
muc_join_response.serialize(output);
|
||||||
|
|
||||||
|
let history_on_join_response = self.send_history_on_join().await?;
|
||||||
|
history_on_join_response.serialize(output)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// TODO other presence cases
|
// TODO other presence cases
|
||||||
|
@ -59,11 +63,10 @@ impl<'a> XmppConnection<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: return Presence and serialize on the outside.
|
async fn muc_presence(&mut self, name: &Name) -> Result<(Presence<XUser>)> {
|
||||||
async fn muc_presence(&mut self, name: &Name) -> Result<(Presence<()>)> {
|
|
||||||
let a = self.user_handle.join_room(RoomId::from(name.0.clone())?).await?;
|
let a = self.user_handle.join_room(RoomId::from(name.0.clone())?).await?;
|
||||||
// TODO handle bans
|
// TODO handle bans
|
||||||
let response = Presence::<()> {
|
let response = Presence {
|
||||||
to: Some(Jid {
|
to: Some(Jid {
|
||||||
name: Some(self.user.xmpp_name.clone()),
|
name: Some(self.user.xmpp_name.clone()),
|
||||||
server: Server(self.hostname.clone()),
|
server: Server(self.hostname.clone()),
|
||||||
|
@ -74,23 +77,48 @@ impl<'a> XmppConnection<'a> {
|
||||||
server: Server(self.hostname_rooms.clone()),
|
server: Server(self.hostname_rooms.clone()),
|
||||||
resource: Some(self.user.xmpp_muc_name.clone()),
|
resource: Some(self.user.xmpp_muc_name.clone()),
|
||||||
}),
|
}),
|
||||||
|
custom: vec![XUser],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
Ok(response)
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
async fn send_history_on_join(&self) -> Result<(HistoryMessage)> {
|
||||||
|
Ok(HistoryMessage {
|
||||||
|
id: "kek".to_string(),
|
||||||
|
to: Jid {
|
||||||
|
name: Some(Name("tester".into())),
|
||||||
|
server: Server("localhost".into()),
|
||||||
|
resource: Some(Resource("tester".into())),
|
||||||
|
},
|
||||||
|
from: Jid {
|
||||||
|
name: Some(Name("tester".into())),
|
||||||
|
server: Server("localhost".into()),
|
||||||
|
resource: Some(Resource("tester".into())),
|
||||||
|
},
|
||||||
|
delay: Delay::new(
|
||||||
|
Jid {
|
||||||
|
name: Some(Name("tester".into())),
|
||||||
|
server: Server("localhost".into()),
|
||||||
|
resource: Some(Resource("tester".into())),
|
||||||
|
},
|
||||||
|
"2021-10-10T10:10:10Z".to_string(),
|
||||||
|
),
|
||||||
|
body: "Vasya Pupkin says hello.".to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: set up so that the user has been previously joined.
|
|
||||||
// todo: first call to muc_presence is OK, next one is OK too.
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::testkit::{expect_user_authenticated, TestServer};
|
|
||||||
use crate::Authenticated;
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use lavina_core::player::PlayerId;
|
use lavina_core::player::PlayerId;
|
||||||
use proto_xmpp::bind::{Jid, Name, Resource, Server};
|
use proto_xmpp::bind::{Jid, Name, Resource, Server};
|
||||||
use proto_xmpp::client::Presence;
|
use proto_xmpp::client::Presence;
|
||||||
|
use proto_xmpp::muc::XUser;
|
||||||
|
|
||||||
|
use crate::testkit::{expect_user_authenticated, TestServer};
|
||||||
|
use crate::Authenticated;
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_muc_joining() -> Result<()> {
|
async fn test_muc_joining() -> Result<()> {
|
||||||
|
@ -110,7 +138,7 @@ mod tests {
|
||||||
let mut conn = expect_user_authenticated(&server, &user, &mut player_conn).await.unwrap();
|
let mut conn = expect_user_authenticated(&server, &user, &mut player_conn).await.unwrap();
|
||||||
|
|
||||||
let response = conn.muc_presence(&user.xmpp_name).await.unwrap();
|
let response = conn.muc_presence(&user.xmpp_name).await.unwrap();
|
||||||
let expected = Presence::<()> {
|
let expected = Presence {
|
||||||
to: Some(Jid {
|
to: Some(Jid {
|
||||||
name: Some(conn.user.xmpp_name.clone()),
|
name: Some(conn.user.xmpp_name.clone()),
|
||||||
server: Server(conn.hostname.clone()),
|
server: Server(conn.hostname.clone()),
|
||||||
|
@ -121,6 +149,7 @@ mod tests {
|
||||||
server: Server(conn.hostname_rooms.clone()),
|
server: Server(conn.hostname_rooms.clone()),
|
||||||
resource: Some(conn.user.xmpp_muc_name.clone()),
|
resource: Some(conn.user.xmpp_muc_name.clone()),
|
||||||
}),
|
}),
|
||||||
|
custom: vec![XUser],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
assert_eq!(expected, response);
|
assert_eq!(expected, response);
|
||||||
|
@ -149,7 +178,7 @@ mod tests {
|
||||||
let mut conn = expect_user_authenticated(&server, &user, &mut player_conn).await.unwrap();
|
let mut conn = expect_user_authenticated(&server, &user, &mut player_conn).await.unwrap();
|
||||||
|
|
||||||
let response = conn.muc_presence(&user.xmpp_name).await.unwrap();
|
let response = conn.muc_presence(&user.xmpp_name).await.unwrap();
|
||||||
let expected = Presence::<()> {
|
let expected = Presence {
|
||||||
to: Some(Jid {
|
to: Some(Jid {
|
||||||
name: Some(conn.user.xmpp_name.clone()),
|
name: Some(conn.user.xmpp_name.clone()),
|
||||||
server: Server(conn.hostname.clone()),
|
server: Server(conn.hostname.clone()),
|
||||||
|
@ -160,6 +189,7 @@ mod tests {
|
||||||
server: Server(conn.hostname_rooms.clone()),
|
server: Server(conn.hostname_rooms.clone()),
|
||||||
resource: Some(conn.user.xmpp_muc_name.clone()),
|
resource: Some(conn.user.xmpp_muc_name.clone()),
|
||||||
}),
|
}),
|
||||||
|
custom: vec![XUser],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
assert_eq!(expected, response);
|
assert_eq!(expected, response);
|
||||||
|
|
|
@ -669,6 +669,9 @@ impl<T: ToXml> ToXml for Presence<T> {
|
||||||
Event::End(BytesEnd::new("priority")),
|
Event::End(BytesEnd::new("priority")),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
for c in &self.custom {
|
||||||
|
c.serialize(events);
|
||||||
|
}
|
||||||
events.push(Event::End(BytesEnd::new("presence")));
|
events.push(Event::End(BytesEnd::new("presence")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
use quick_xml::events::Event;
|
|
||||||
use quick_xml::name::ResolveResult;
|
|
||||||
|
|
||||||
use crate::xml::*;
|
|
||||||
use anyhow::{anyhow, Result};
|
use anyhow::{anyhow, Result};
|
||||||
|
use quick_xml::events::attributes::Attribute;
|
||||||
|
use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
|
||||||
|
use quick_xml::name::{QName, ResolveResult};
|
||||||
|
|
||||||
|
use crate::bind::Jid;
|
||||||
|
use crate::xml::*;
|
||||||
|
|
||||||
pub const XMLNS: &'static str = "http://jabber.org/protocol/muc";
|
pub const XMLNS: &'static str = "http://jabber.org/protocol/muc";
|
||||||
|
pub const XMLNS_USER: &'static str = "http://jabber.org/protocol/muc#user";
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Default)]
|
#[derive(PartialEq, Eq, Debug, Default)]
|
||||||
pub struct History {
|
pub struct History {
|
||||||
|
@ -143,6 +146,90 @@ impl FromXml for X {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct XUser;
|
||||||
|
|
||||||
|
impl ToXml for XUser {
|
||||||
|
fn serialize(&self, output: &mut Vec<Event<'static>>) {
|
||||||
|
let mut tag = BytesStart::new("x");
|
||||||
|
tag.push_attribute(("xmlns", XMLNS_USER));
|
||||||
|
output.push(Event::Empty(tag));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// <message tagid="c2f06b55-73f2-41a2-8dc4-eacceb35be82" to="a@oflor.me/kek" xml:lang="en" from="zesetuz@conference.oflor.me/a" type="groupchat">
|
||||||
|
// <delay xmlns="urn:xmpp:delay" from="zesetuz@conference.oflor.me" stamp="2024-05-18T11:14:53.694657Z"/>
|
||||||
|
// <body>dddddd</body>
|
||||||
|
// </message>
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct Delay {
|
||||||
|
xmlns: String,
|
||||||
|
from: Jid,
|
||||||
|
pub stamp: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Delay {
|
||||||
|
pub fn new(from: Jid, stamp: String) -> Self {
|
||||||
|
Self {
|
||||||
|
xmlns: "urn:xmpp:delay".into(),
|
||||||
|
from,
|
||||||
|
stamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
|
pub struct HistoryMessage {
|
||||||
|
pub id: String,
|
||||||
|
pub to: Jid,
|
||||||
|
pub from: Jid,
|
||||||
|
pub delay: Delay,
|
||||||
|
pub body: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToXml for HistoryMessage {
|
||||||
|
fn serialize(&self, events: &mut Vec<Event<'static>>) {
|
||||||
|
let mut tag = BytesStart::new("message");
|
||||||
|
tag.push_attribute(Attribute {
|
||||||
|
key: QName(b"id"),
|
||||||
|
value: self.id.as_str().as_bytes().into(),
|
||||||
|
});
|
||||||
|
tag.push_attribute(Attribute {
|
||||||
|
key: QName(b"to"),
|
||||||
|
value: self.to.to_string().into_bytes().into(),
|
||||||
|
});
|
||||||
|
tag.push_attribute(Attribute {
|
||||||
|
key: QName(b"from"),
|
||||||
|
value: self.from.to_string().into_bytes().into(),
|
||||||
|
});
|
||||||
|
tag.push_attribute(Attribute {
|
||||||
|
key: QName(b"type"),
|
||||||
|
value: b"groupchat".into(),
|
||||||
|
});
|
||||||
|
events.push(Event::Start(tag));
|
||||||
|
let mut tag = BytesStart::new("delay");
|
||||||
|
tag.push_attribute(Attribute {
|
||||||
|
key: QName(b"xmlns"),
|
||||||
|
value: self.delay.xmlns.as_bytes().into(),
|
||||||
|
});
|
||||||
|
tag.push_attribute(Attribute {
|
||||||
|
key: QName(b"from"),
|
||||||
|
value: self.delay.from.to_string().into_bytes().into(),
|
||||||
|
});
|
||||||
|
tag.push_attribute(Attribute {
|
||||||
|
key: QName(b"stamp"),
|
||||||
|
value: self.delay.stamp.as_bytes().into(),
|
||||||
|
});
|
||||||
|
events.push(Event::Empty(tag));
|
||||||
|
let mut tag = BytesStart::new("body");
|
||||||
|
events.push(Event::Start(tag));
|
||||||
|
events.push(Event::Text(BytesText::new(self.body.to_string().as_str()).into_owned()));
|
||||||
|
events.push(Event::End(BytesEnd::new("body")));
|
||||||
|
events.push(Event::End(BytesEnd::new("message")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue