diff options
Diffstat (limited to '')
| -rw-r--r-- | filamento/src/logic/online.rs | 67 | 
1 files changed, 60 insertions, 7 deletions
| diff --git a/filamento/src/logic/online.rs b/filamento/src/logic/online.rs index c560b9b..767f923 100644 --- a/filamento/src/logic/online.rs +++ b/filamento/src/logic/online.rs @@ -94,16 +94,69 @@ pub async fn handle_get_roster<Fs: FileStore + Clone>(      }  } +// this can't query the client... otherwise there is a hold-up and the connection can't complete  pub async fn handle_get_roster_with_users<Fs: FileStore + Clone>(      logic: &ClientLogic<Fs>, +    connection: Connected,  ) -> Result<Vec<(Contact, User)>, RosterError> { -    let roster = logic.client.get_roster().await?; -    let mut users = Vec::new(); -    for contact in &roster { -        let user = logic.db().read_user(contact.user_jid.clone()).await?; -        users.push(user); +    let iq_id = Uuid::new_v4().to_string(); +    let stanza = Stanza::Iq(Iq { +        from: Some(connection.jid().clone()), +        id: iq_id.to_string(), +        to: None, +        r#type: IqType::Get, +        lang: None, +        query: Some(iq::Query::Roster(stanza::roster::Query { +            ver: None, +            items: Vec::new(), +        })), +        errors: Vec::new(), +    }); +    let response = logic +        .pending() +        .request(&connection, stanza, iq_id.clone()) +        .await?; +    // TODO: timeout +    match response { +        Stanza::Iq(Iq { +            from: _, +            id, +            to: _, +            r#type, +            lang: _, +            query: Some(iq::Query::Roster(stanza::roster::Query { ver: _, items })), +            errors: _, +        }) if id == iq_id && r#type == IqType::Result => { +            let contacts: Vec<Contact> = items.into_iter().map(|item| item.into()).collect(); +            if let Err(e) = logic.db().replace_cached_roster(contacts.clone()).await { +                logic +                    .handle_error(Error::Roster(RosterError::Cache(e.into()))) +                    .await; +            }; +            let mut users = Vec::new(); +            for contact in &contacts { +                let user = logic.db().read_user(contact.user_jid.clone()).await?; +                users.push(user); +            } +            Ok(contacts.into_iter().zip(users).collect()) +        } +        ref s @ Stanza::Iq(Iq { +            from: _, +            ref id, +            to: _, +            r#type, +            lang: _, +            query: _, +            ref errors, +        }) if *id == iq_id && r#type == IqType::Error => { +            if let Some(error) = errors.first() { +                Err(RosterError::StanzaError(error.clone())) +            } else { +                Err(RosterError::UnexpectedStanza(s.clone())) +            } +        } +        s => Err(RosterError::UnexpectedStanza(s)),      } -    Ok(roster.into_iter().zip(users).collect())  }  pub async fn handle_add_contact<Fs: FileStore + Clone>( @@ -1031,7 +1084,7 @@ pub async fn handle_online_result<Fs: FileStore + Clone>(              let _ = result_sender.send(roster);          }          Command::GetRosterWithUsers(result_sender) => { -            let roster = handle_get_roster_with_users(logic).await; +            let roster = handle_get_roster_with_users(logic, connection).await;              let _ = result_sender.send(roster);          }          Command::GetChats(sender) => { | 
