diff --git a/crates/projection-xmpp/src/presence.rs b/crates/projection-xmpp/src/presence.rs index 15e2ead..c43567a 100644 --- a/crates/projection-xmpp/src/presence.rs +++ b/crates/projection-xmpp/src/presence.rs @@ -5,7 +5,7 @@ use quick_xml::events::Event; use lavina_core::room::RoomId; use proto_xmpp::bind::{Jid, Name, Server}; -use proto_xmpp::client::Presence; +use proto_xmpp::client::{Message, MessageType, Presence}; use proto_xmpp::muc::XUser; use proto_xmpp::xml::{Ignore, ToXml}; @@ -23,11 +23,30 @@ impl<'a> XmppConnection<'a> { // resources in MUCs are members' personas – not implemented (yet?) resource: Some(_), }) if server.0 == self.hostname_rooms => { - let response = self.muc_presence(&name).await?; + let response = self.muc_presence(p.id.as_ref(), &name).await?; + let message = Message::<()> { + 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: None, + }), + r#type: MessageType::Groupchat, + subject: Some("".into()), + id: None, + lang: None, + body: "".into(), + custom: vec![], + }; response.serialize(output); + message.serialize(output); } _ => { - // TODO other presence cases + // TODO other presence casess let response = Presence::<()>::default(); response.serialize(output); } @@ -56,15 +75,18 @@ impl<'a> XmppConnection<'a> { }; response.serialize(output); } - _ => todo!(), + _ => { + tracing::error!("TODO"); + } } } // todo: return Presence and serialize on the outside. - async fn muc_presence(&mut self, name: &Name) -> Result<(Presence)> { + async fn muc_presence(&mut self, id: Option<&String>, name: &Name) -> Result<(Presence)> { let a = self.user_handle.join_room(RoomId::from(name.0.clone())?).await?; // TODO handle bans let response = Presence { + id: id.map(ToOwned::to_owned), to: Some(Jid { name: Some(self.user.xmpp_name.clone()), server: Server(self.hostname.clone()), diff --git a/crates/proto-xmpp/src/client.rs b/crates/proto-xmpp/src/client.rs index c9fa8db..c584469 100644 --- a/crates/proto-xmpp/src/client.rs +++ b/crates/proto-xmpp/src/client.rs @@ -20,7 +20,7 @@ pub struct Message { // default is Normal pub r#type: MessageType, pub lang: Option, - pub subject: Option, + pub subject: Option, // TODO there are three states of , } @@ -50,6 +50,7 @@ enum MessageParserInner { InBody(MessageParserState), InCustom(MessageParserState, T::P), } + #[derive(Default)] struct MessageParserState { from: Option, @@ -61,6 +62,7 @@ struct MessageParserState { body: Option, custom: Vec, } + impl Parser for MessageParser { type Output = Result>; @@ -208,9 +210,18 @@ impl ToXml for Message { value: self.r#type.as_str().as_bytes().into(), }); events.push(Event::Start(bytes)); - events.push(Event::Start(BytesStart::new("body"))); - events.push(Event::Text(BytesText::new(&self.body).into_owned())); - events.push(Event::End(BytesEnd::new("body"))); + if self.subject.is_none() { + // TODO make body optional + events.push(Event::Start(BytesStart::new("body"))); + events.push(Event::Text(BytesText::new(&self.body).into_owned())); + events.push(Event::End(BytesEnd::new("body"))); + } + if let Some(subject) = &self.subject { + // TODO make subject tri-state + events.push(Event::Start(BytesStart::new("subject"))); + events.push(Event::Text(BytesText::new(&subject).into_owned())); + events.push(Event::End(BytesEnd::new("subject"))); + } events.push(Event::End(BytesEnd::new("message"))); } } @@ -266,6 +277,7 @@ pub struct IqError { pub enum IqErrorCondition { ItemNotFound, } + impl IqErrorCondition { pub fn as_str(&self) -> &'static str { match self { @@ -286,6 +298,7 @@ pub enum IqErrorType { /// Retry after waiting (the error is temporary) Wait, } + impl IqErrorType { pub fn as_str(&self) -> &'static str { match self { @@ -345,6 +358,7 @@ enum IqParserInner { ParsingBody(IqParserState, T::P), Final(IqParserState), } + struct IqParserState { pub from: Option, pub id: Option, @@ -706,7 +720,7 @@ mod tests { to: Some(Jid { name: Some(Name("chelik".into())), server: Server("xmpp.ru".into()), - resource: None + resource: None, }), r#type: MessageType::Chat, lang: None, @@ -729,7 +743,7 @@ mod tests { to: Some(Jid { name: Some(Name("chelik".into())), server: Server("xmpp.ru".into()), - resource: None + resource: None, }), r#type: MessageType::Chat, lang: None, @@ -751,7 +765,7 @@ mod tests { id: "bind_1".to_string(), to: None, r#type: IqType::Set, - body: BindRequest(Resource("mobile".into())) + body: BindRequest(Resource("mobile".into())), } ) } diff --git a/crates/proto-xmpp/src/muc/mod.rs b/crates/proto-xmpp/src/muc/mod.rs index 8ae70d5..ef3a9f7 100644 --- a/crates/proto-xmpp/src/muc/mod.rs +++ b/crates/proto-xmpp/src/muc/mod.rs @@ -155,13 +155,9 @@ impl ToXml for XUser { let mut meg = BytesStart::new("item"); meg.push_attribute(("affiliation", "owner")); meg.push_attribute(("role", "moderator")); - meg.push_attribute(("jid", "sauer@localhost")); + meg.push_attribute(("jid", "user@localhost/user")); output.push(Event::Empty(meg)); - let mut veg = BytesStart::new("status"); - veg.push_attribute(("code", "100")); - output.push(Event::Empty(veg)); - let mut veg = BytesStart::new("status"); veg.push_attribute(("code", "110")); output.push(Event::Empty(veg));