diff options
Diffstat (limited to '')
| -rw-r--r-- | filamento/src/logic/offline.rs | 5 | ||||
| -rw-r--r-- | filamento/src/logic/online.rs | 85 | 
2 files changed, 83 insertions, 7 deletions
diff --git a/filamento/src/logic/offline.rs b/filamento/src/logic/offline.rs index 7dfb394..bc2666a 100644 --- a/filamento/src/logic/offline.rs +++ b/filamento/src/logic/offline.rs @@ -113,7 +113,10 @@ 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) => { +        Command::DiscoInfo(_jid, _node, sender) => { +            sender.send(Err(DiscoError::Write(WriteError::Disconnected))); +        } +        Command::DiscoItems(_jid, _node, sender) => {              sender.send(Err(DiscoError::Write(WriteError::Disconnected)));          }      } diff --git a/filamento/src/logic/online.rs b/filamento/src/logic/online.rs index c76907b..63a4aa3 100644 --- a/filamento/src/logic/online.rs +++ b/filamento/src/logic/online.rs @@ -6,7 +6,7 @@ use stanza::{          Stanza,          iq::{self, Iq, IqType, Query},      }, -    xep_0030::info, +    xep_0030::{info, items},      xep_0203::Delay,  };  use tokio::sync::oneshot; @@ -16,7 +16,7 @@ use uuid::Uuid;  use crate::{      Command, UpdateMessage,      chat::{Body, Message}, -    disco::Info, +    disco::{Info, Items},      error::{DatabaseError, DiscoError, Error, MessageSendError, RosterError, StatusError},      presence::{Online, Presence, PresenceType},      roster::{Contact, ContactUpdate}, @@ -534,11 +534,11 @@ pub async fn handle_send_presence(      Ok(())  } -// TODO: cache disco infos  pub async fn handle_disco_info(      logic: &ClientLogic,      connection: Connected,      jid: Option<JID>, +    node: Option<String>,  ) -> Result<Info, DiscoError> {      let id = Uuid::new_v4().to_string();      let request = Iq { @@ -548,7 +548,7 @@ pub async fn handle_disco_info(          r#type: IqType::Get,          lang: None,          query: Some(Query::DiscoInfo(info::Query { -            node: None, +            node,              features: Vec::new(),              identities: Vec::new(),          })), @@ -604,6 +604,75 @@ pub async fn handle_disco_info(      }  } +pub async fn handle_disco_items( +    logic: &ClientLogic, +    connection: Connected, +    jid: Option<JID>, +    node: Option<String>, +) -> Result<Items, 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::DiscoItems(items::Query { +            node, +            items: 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::DiscoItems(items) => Ok(items.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, @@ -701,8 +770,12 @@ 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; +        Command::DiscoInfo(jid, node, sender) => { +            let result = handle_disco_info(logic, connection, jid, node).await; +            let _ = sender.send(result); +        } +        Command::DiscoItems(jid, node, sender) => { +            let result = handle_disco_items(logic, connection, jid, node).await;              let _ = sender.send(result);          }      }  | 
