diff options
Diffstat (limited to '')
| -rw-r--r-- | filamento/examples/example.rs | 5 | ||||
| -rw-r--r-- | filamento/src/disco.rs | 2 | ||||
| -rw-r--r-- | filamento/src/lib.rs | 41 | ||||
| -rw-r--r-- | filamento/src/logic/offline.rs | 5 | ||||
| -rw-r--r-- | filamento/src/logic/online.rs | 85 | 
5 files changed, 123 insertions, 15 deletions
| diff --git a/filamento/examples/example.rs b/filamento/examples/example.rs index 10267bc..506d698 100644 --- a/filamento/examples/example.rs +++ b/filamento/examples/example.rs @@ -33,7 +33,8 @@ async fn main() {          .unwrap();      info!("sent message");      info!("sending disco query"); -    let info = client.disco_info(None).await.unwrap(); -    tokio::time::sleep(Duration::from_secs(5)).await; +    let info = client.disco_info(None, None).await.unwrap();      info!("got disco result: {:#?}", info); +    let items = client.disco_items(None, None).await.unwrap(); +    info!("got disco result: {:#?}", items);  } diff --git a/filamento/src/disco.rs b/filamento/src/disco.rs index ccc99cb..cc48215 100644 --- a/filamento/src/disco.rs +++ b/filamento/src/disco.rs @@ -53,6 +53,7 @@ impl From<Info> for info::Query {      }  } +#[derive(Debug, Clone)]  pub struct Items {      node: Option<String>,      items: Vec<Item>, @@ -80,6 +81,7 @@ impl From<Items> for items::Query {      }  } +#[derive(Debug, Clone)]  pub struct Item {      jid: JID,      name: Option<String>, diff --git a/filamento/src/lib.rs b/filamento/src/lib.rs index ed33e99..4d852e2 100644 --- a/filamento/src/lib.rs +++ b/filamento/src/lib.rs @@ -9,7 +9,7 @@ use std::{  use chat::{Body, Chat, Message};  use chrono::Utc;  use db::Db; -use disco::Info; +use disco::{Info, Items};  use error::{      ConnectionJobError, DatabaseError, DiscoError, Error, IqError, MessageRecvError, PresenceError,      RosterError, StatusError, @@ -102,10 +102,15 @@ pub enum Command {      /// disco info query      DiscoInfo(          Option<JID>, +        Option<String>,          oneshot::Sender<Result<disco::Info, DiscoError>>,      ), -    // /// disco items query -    // DiscoItems(JID, oneshot::Sender<Result<disco::Info, DiscoError>>), +    /// disco items query +    DiscoItems( +        Option<JID>, +        Option<String>, +        oneshot::Sender<Result<disco::Items, DiscoError>>, +    ),  }  #[derive(Debug, Clone)] @@ -480,11 +485,35 @@ impl Client {          Ok(result)      } -    pub async fn disco_info(&self, jid: Option<JID>) -> Result<Info, CommandError<DiscoError>> { +    pub async fn disco_info( +        &self, +        jid: Option<JID>, +        node: Option<String>, +    ) -> Result<Info, CommandError<DiscoError>> {          let (send, recv) = oneshot::channel(); -        self.send(CoreClientCommand::Command(Command::DiscoInfo(jid, send))) +        self.send(CoreClientCommand::Command(Command::DiscoInfo( +            jid, node, send, +        ))) +        .await +        .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; +        let result = timeout(self.timeout, recv)              .await -            .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; +            .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? +            .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; +        Ok(result) +    } + +    pub async fn disco_items( +        &self, +        jid: Option<JID>, +        node: Option<String>, +    ) -> Result<Items, CommandError<DiscoError>> { +        let (send, recv) = oneshot::channel(); +        self.send(CoreClientCommand::Command(Command::DiscoItems( +            jid, node, send, +        ))) +        .await +        .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?;          let result = timeout(self.timeout, recv)              .await              .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? 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);          }      } | 
