diff options
Diffstat (limited to '')
| -rw-r--r-- | filamento/src/logic/offline.rs | 5 | ||||
| -rw-r--r-- | filamento/src/logic/online.rs | 82 | 
2 files changed, 83 insertions, 4 deletions
| diff --git a/filamento/src/logic/offline.rs b/filamento/src/logic/offline.rs index e864f22..7dfb394 100644 --- a/filamento/src/logic/offline.rs +++ b/filamento/src/logic/offline.rs @@ -2,7 +2,7 @@ use lampada::error::WriteError;  use crate::{      Command, -    error::{DatabaseError, Error, RosterError, StatusError}, +    error::{DatabaseError, DiscoError, Error, RosterError, StatusError},      presence::Online,      roster::Contact,  }; @@ -113,6 +113,9 @@ pub async fn handle_offline_result(logic: &ClientLogic, command: Command) -> Res          Command::SendPresence(_jid, _presence, sender) => {              sender.send(Err(WriteError::Disconnected));          } +        Command::DiscoInfo(_jid, sender) => { +            sender.send(Err(DiscoError::Write(WriteError::Disconnected))); +        }      }      Ok(())  } diff --git a/filamento/src/logic/online.rs b/filamento/src/logic/online.rs index 05d3f2b..c76907b 100644 --- a/filamento/src/logic/online.rs +++ b/filamento/src/logic/online.rs @@ -4,18 +4,20 @@ use lampada::{Connected, WriteMessage, error::WriteError};  use stanza::{      client::{          Stanza, -        iq::{self, Iq, IqType}, +        iq::{self, Iq, IqType, Query},      }, +    xep_0030::info,      xep_0203::Delay,  };  use tokio::sync::oneshot; -use tracing::{debug, info}; +use tracing::{debug, error, info};  use uuid::Uuid;  use crate::{      Command, UpdateMessage,      chat::{Body, Message}, -    error::{DatabaseError, Error, MessageSendError, RosterError, StatusError}, +    disco::Info, +    error::{DatabaseError, DiscoError, Error, MessageSendError, RosterError, StatusError},      presence::{Online, Presence, PresenceType},      roster::{Contact, ContactUpdate},  }; @@ -532,6 +534,76 @@ pub async fn handle_send_presence(      Ok(())  } +// TODO: cache disco infos +pub async fn handle_disco_info( +    logic: &ClientLogic, +    connection: Connected, +    jid: Option<JID>, +) -> Result<Info, DiscoError> { +    let id = Uuid::new_v4().to_string(); +    let request = Iq { +        from: Some(connection.jid().clone()), +        id: id.clone(), +        to: jid.clone(), +        r#type: IqType::Get, +        lang: None, +        query: Some(Query::DiscoInfo(info::Query { +            node: None, +            features: Vec::new(), +            identities: Vec::new(), +        })), +        errors: Vec::new(), +    }; +    match logic +        .pending() +        .request(&connection, Stanza::Iq(request), id) +        .await? +    { +        Stanza::Iq(Iq { +            from, +            r#type, +            query, +            mut errors, +            .. +            // TODO: maybe abstract a bunch of these different errors related to iqs into an iq error thing? as in like call iq.result(), get the query from inside, error otherwise. +        }) if r#type == IqType::Result || r#type == IqType::Error => { +            if from == jid || { +                if jid == None { +                    from == Some(connection.jid().as_bare()) +                } else { +                    false +                } +            } { +                match r#type { +                    IqType::Result => { +                        if let Some(query) = query { +                            match query { +                                Query::DiscoInfo(info) => Ok(info.into()), +                                q => Err(DiscoError::MismatchedQuery(q)), +                            } +                        } else { +                            Err(DiscoError::MissingQuery) +                        } +                    } +                    IqType::Error => { +                        if let Some(error) = errors.pop() { +                            Err(error.into()) +                        } else { +                            Err(DiscoError::MissingError) +                        } +                    } +                    _ => unreachable!(), +                } +            } else { +                Err(DiscoError::IncorrectEntity( +                    from.unwrap_or_else(|| connection.jid().as_bare()), +                )) +            } +        } +        s => Err(DiscoError::UnexpectedStanza(s)), +    } +} +  // TODO: could probably macro-ise?  pub async fn handle_online_result(      logic: &ClientLogic, @@ -629,6 +701,10 @@ pub async fn handle_online_result(              let result = handle_send_presence(connection, jid, presence).await;              let _ = sender.send(result);          } +        Command::DiscoInfo(jid, sender) => { +            let result = handle_disco_info(logic, connection, jid).await; +            let _ = sender.send(result); +        }      }      Ok(())  } | 
