forked from lavina/lavina
send subject
This commit is contained in:
parent
a22017ee8f
commit
8b05c852e7
|
@ -5,7 +5,7 @@ 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, Server};
|
||||||
use proto_xmpp::client::Presence;
|
use proto_xmpp::client::{Message, MessageType, Presence};
|
||||||
use proto_xmpp::muc::XUser;
|
use proto_xmpp::muc::XUser;
|
||||||
use proto_xmpp::xml::{Ignore, ToXml};
|
use proto_xmpp::xml::{Ignore, ToXml};
|
||||||
|
|
||||||
|
@ -23,11 +23,30 @@ 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 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);
|
response.serialize(output);
|
||||||
|
message.serialize(output);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// TODO other presence cases
|
// TODO other presence casess
|
||||||
let response = Presence::<()>::default();
|
let response = Presence::<()>::default();
|
||||||
response.serialize(output);
|
response.serialize(output);
|
||||||
}
|
}
|
||||||
|
@ -56,15 +75,18 @@ impl<'a> XmppConnection<'a> {
|
||||||
};
|
};
|
||||||
response.serialize(output);
|
response.serialize(output);
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => {
|
||||||
|
tracing::error!("TODO");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo: return Presence and serialize on the outside.
|
// 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, id: Option<&String>, name: &Name) -> Result<(Presence<XUser>)> {
|
||||||
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 {
|
||||||
|
id: id.map(ToOwned::to_owned),
|
||||||
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()),
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub struct Message<T> {
|
||||||
// default is Normal
|
// default is Normal
|
||||||
pub r#type: MessageType,
|
pub r#type: MessageType,
|
||||||
pub lang: Option<Str>,
|
pub lang: Option<Str>,
|
||||||
pub subject: Option<Str>,
|
pub subject: Option<Str>, // TODO there are three states of <subject -- not present, empty and some string
|
||||||
pub body: Str,
|
pub body: Str,
|
||||||
pub custom: Vec<T>,
|
pub custom: Vec<T>,
|
||||||
}
|
}
|
||||||
|
@ -50,6 +50,7 @@ enum MessageParserInner<T: FromXml> {
|
||||||
InBody(MessageParserState<T>),
|
InBody(MessageParserState<T>),
|
||||||
InCustom(MessageParserState<T>, T::P),
|
InCustom(MessageParserState<T>, T::P),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct MessageParserState<T> {
|
struct MessageParserState<T> {
|
||||||
from: Option<Jid>,
|
from: Option<Jid>,
|
||||||
|
@ -61,6 +62,7 @@ struct MessageParserState<T> {
|
||||||
body: Option<Str>,
|
body: Option<Str>,
|
||||||
custom: Vec<T>,
|
custom: Vec<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromXml> Parser for MessageParser<T> {
|
impl<T: FromXml> Parser for MessageParser<T> {
|
||||||
type Output = Result<Message<T>>;
|
type Output = Result<Message<T>>;
|
||||||
|
|
||||||
|
@ -208,9 +210,18 @@ impl<T: ToXml> ToXml for Message<T> {
|
||||||
value: self.r#type.as_str().as_bytes().into(),
|
value: self.r#type.as_str().as_bytes().into(),
|
||||||
});
|
});
|
||||||
events.push(Event::Start(bytes));
|
events.push(Event::Start(bytes));
|
||||||
|
if self.subject.is_none() {
|
||||||
|
// TODO make body optional
|
||||||
events.push(Event::Start(BytesStart::new("body")));
|
events.push(Event::Start(BytesStart::new("body")));
|
||||||
events.push(Event::Text(BytesText::new(&self.body).into_owned()));
|
events.push(Event::Text(BytesText::new(&self.body).into_owned()));
|
||||||
events.push(Event::End(BytesEnd::new("body")));
|
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")));
|
events.push(Event::End(BytesEnd::new("message")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +277,7 @@ pub struct IqError {
|
||||||
pub enum IqErrorCondition {
|
pub enum IqErrorCondition {
|
||||||
ItemNotFound,
|
ItemNotFound,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IqErrorCondition {
|
impl IqErrorCondition {
|
||||||
pub fn as_str(&self) -> &'static str {
|
pub fn as_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
|
@ -286,6 +298,7 @@ pub enum IqErrorType {
|
||||||
/// Retry after waiting (the error is temporary)
|
/// Retry after waiting (the error is temporary)
|
||||||
Wait,
|
Wait,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IqErrorType {
|
impl IqErrorType {
|
||||||
pub fn as_str(&self) -> &'static str {
|
pub fn as_str(&self) -> &'static str {
|
||||||
match self {
|
match self {
|
||||||
|
@ -345,6 +358,7 @@ enum IqParserInner<T: FromXml> {
|
||||||
ParsingBody(IqParserState<T>, T::P),
|
ParsingBody(IqParserState<T>, T::P),
|
||||||
Final(IqParserState<T>),
|
Final(IqParserState<T>),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IqParserState<T> {
|
struct IqParserState<T> {
|
||||||
pub from: Option<Jid>,
|
pub from: Option<Jid>,
|
||||||
pub id: Option<String>,
|
pub id: Option<String>,
|
||||||
|
@ -706,7 +720,7 @@ mod tests {
|
||||||
to: Some(Jid {
|
to: Some(Jid {
|
||||||
name: Some(Name("chelik".into())),
|
name: Some(Name("chelik".into())),
|
||||||
server: Server("xmpp.ru".into()),
|
server: Server("xmpp.ru".into()),
|
||||||
resource: None
|
resource: None,
|
||||||
}),
|
}),
|
||||||
r#type: MessageType::Chat,
|
r#type: MessageType::Chat,
|
||||||
lang: None,
|
lang: None,
|
||||||
|
@ -729,7 +743,7 @@ mod tests {
|
||||||
to: Some(Jid {
|
to: Some(Jid {
|
||||||
name: Some(Name("chelik".into())),
|
name: Some(Name("chelik".into())),
|
||||||
server: Server("xmpp.ru".into()),
|
server: Server("xmpp.ru".into()),
|
||||||
resource: None
|
resource: None,
|
||||||
}),
|
}),
|
||||||
r#type: MessageType::Chat,
|
r#type: MessageType::Chat,
|
||||||
lang: None,
|
lang: None,
|
||||||
|
@ -751,7 +765,7 @@ mod tests {
|
||||||
id: "bind_1".to_string(),
|
id: "bind_1".to_string(),
|
||||||
to: None,
|
to: None,
|
||||||
r#type: IqType::Set,
|
r#type: IqType::Set,
|
||||||
body: BindRequest(Resource("mobile".into()))
|
body: BindRequest(Resource("mobile".into())),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,13 +155,9 @@ impl ToXml for XUser {
|
||||||
let mut meg = BytesStart::new("item");
|
let mut meg = BytesStart::new("item");
|
||||||
meg.push_attribute(("affiliation", "owner"));
|
meg.push_attribute(("affiliation", "owner"));
|
||||||
meg.push_attribute(("role", "moderator"));
|
meg.push_attribute(("role", "moderator"));
|
||||||
meg.push_attribute(("jid", "sauer@localhost"));
|
meg.push_attribute(("jid", "user@localhost/user"));
|
||||||
output.push(Event::Empty(meg));
|
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");
|
let mut veg = BytesStart::new("status");
|
||||||
veg.push_attribute(("code", "110"));
|
veg.push_attribute(("code", "110"));
|
||||||
output.push(Event::Empty(veg));
|
output.push(Event::Empty(veg));
|
||||||
|
|
Loading…
Reference in New Issue