diff --git a/src/avatar.rs b/src/avatar.rs index b0e1f44..56aac06 100644 --- a/src/avatar.rs +++ b/src/avatar.rs @@ -6,7 +6,7 @@ use crate::Event; use futures::{sync::mpsc, Sink}; -use std::fs::{create_dir_all, File}; +use std::fs::{self, File}; use std::io::{self, Write}; use tokio_xmpp::Packet; use xmpp_parsers::{ @@ -18,19 +18,39 @@ use xmpp_parsers::{ pubsub::{Items, PubSub}, NodeName, }, + hashes::Hash, Jid, TryFrom, }; -pub(crate) fn handle_metadata_pubsub_event(from: &Jid, tx: &mut mpsc::UnboundedSender, items: Vec) { +// TODO: Update xmpp-parsers to get this function for free on Hash. +fn hash_to_hex(hash: &Hash) -> String { + let mut bytes = vec![]; + for byte in hash.hash.iter() { + bytes.push(format!("{:02x}", byte)); + } + bytes.join("") +} + +pub(crate) fn handle_metadata_pubsub_event(from: &Jid, tx: &mut mpsc::UnboundedSender, items: Vec) -> impl IntoIterator { + let mut events = Vec::new(); for item in items { let payload = item.payload.clone().unwrap(); if payload.is("metadata", ns::AVATAR_METADATA) { - // TODO: do something with these metadata. - let _metadata = Metadata::try_from(payload).unwrap(); - let iq = download_avatar(from); - tx.start_send(Packet::Stanza(iq.into())).unwrap(); + let metadata = Metadata::try_from(payload).unwrap(); + for info in metadata.infos { + let filename = format!("data/{}/{}", from, hash_to_hex(&*info.id)); + let metadata = fs::metadata(filename.clone()).unwrap(); + // TODO: Also check the hash. + if info.bytes as u64 == metadata.len() { + events.push(Event::AvatarRetrieved(from.clone(), filename)); + } else { + let iq = download_avatar(from); + tx.start_send(Packet::Stanza(iq.into())).unwrap(); + } + } } } + events } fn download_avatar(from: &Jid) -> Iq { @@ -66,7 +86,7 @@ pub(crate) fn handle_data_pubsub_iq<'a>( fn save_avatar(from: &Jid, id: String, data: &[u8]) -> io::Result { let directory = format!("data/{}", from); let filename = format!("data/{}/{}", from, id); - create_dir_all(directory)?; + fs::create_dir_all(directory)?; let mut file = File::create(&filename)?; file.write_all(data)?; Ok(filename) diff --git a/src/lib.rs b/src/lib.rs index 93089b6..20fd1ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -266,7 +266,8 @@ impl ClientBuilder<'_> { let event = PubSubEvent::try_from(child).unwrap(); if let PubSubEvent::PublishedItems { node, items } = event { if node.0 == ns::AVATAR_METADATA { - avatar::handle_metadata_pubsub_event(&from, &mut sender_tx, items); + let new_events = avatar::handle_metadata_pubsub_event(&from, &mut sender_tx, items); + events.extend(new_events); } else if node.0 == ns::BOOKMARKS { // TODO: Check that our bare JID is the sender. assert_eq!(items.len(), 1);