Working on profile info

This commit is contained in:
notplants 2022-01-12 14:58:07 -05:00
parent 615431496b
commit ccc4a3371b
1 changed files with 73 additions and 18 deletions

View File

@ -1,4 +1,5 @@
//! Sbot type and associated methods.
use std::collections::HashMap;
use async_std::{
net::TcpStream,
stream::{Stream, StreamExt},
@ -281,33 +282,87 @@ impl Sbot {
// now we have a stream of about messages with most recent at the front of the vector
pin_mut!(about_message_stream);
// iterate through the vector looking for most recent about message with the given key
let latest_about_message: Result<SsbMessageValue, GolgiError> = about_message_stream
let latest_about_message_res: Option<Result<SsbMessageValue, GolgiError>> = about_message_stream
// find the first msg that contains the field `key`
.find(|res| match res {
Ok(msg) => msg.content.get(key).is_some(),
Err(_) => false,
})
.await
.ok_or_else(|| {
GolgiError::Sbot("error while looking for about message with given key".to_string())
})?;
let latest_about_value = match latest_about_message {
Ok(msg) => {
msg
// SsbMessageValue -> Option<&Value>
.content
.get(key)
// Option<&Value> -> <Option<&str>
.and_then(|value| value.as_str())
// Option<&str> -> Option<String>
.map(|value| value.to_string())
}
Err(_) => None,
};
.await;
// Option<Result<SsbMessageValue, GolgiError>> -> Option<SsbMessageValue>
let latest_about_message = latest_about_message_res.and_then(|msg| msg.ok());
// Option<SsbMessageValue> -> Option<String>
let latest_about_value = latest_about_message.and_then(|msg| {
msg
// SsbMessageValue -> Option<&Value>
.content
.get(key)
// Option<&Value> -> <Option<&str>
.and_then(|value| value.as_str())
// Option<&str> -> Option<String>
.map(|value| value.to_string())
});
// return value is either `Ok(Some(String))` or `Ok(None)`
Ok(latest_about_value)
}
/// Get HashMap of profile info for given user
/// by iteratively searching through a stream of about messages,
/// in order of recency,
/// until we find all about messages for all needed info
/// or reach the end of the stream.
pub async fn get_profile_info(
&mut self,
ssb_id: &str
) -> Result<HashMap<String, String>, GolgiError> {
// get about_message_stream
let about_message_stream = self.get_about_message_stream(ssb_id).await?;
// now we have a stream of about messages with most recent at the front of the vector
pin_mut!(about_message_stream); // needed for iteration
let mut profile_info: HashMap<String, String> = HashMap::new();
// these are the about message keys we are looking for
// as we find values for each of these keys,
// we will remove them from this vector (as we are no longer searching for them)
let mut keys_to_search_for = vec!["name", "description", "profile"];
// iterate through the stream while it still has more values and
// we still have keys we are looking for
while let Some(res) = about_message_stream.next().await {
println!("res: {:?}", res);
// if there are no more keys we are looking for, then we are done
if keys_to_search_for.len() == 0 {
break
}
// if there are still keys we are looking for, then continue searching
match res {
Ok(msg) => {
// for each key we are searching for, check if this about
// message contains a value for that key
for key in &keys_to_search_for.clone() {
let option_val = msg.content.get(key)
.and_then(|val| val.as_str())
.map(|val| val.to_string());
match option_val {
Some(val) => {
// if a value is found, then insert it
profile_info.insert(key.to_string(), val);
// remove this key fom keys_to_search_for, since we are no longer searching for it
keys_to_search_for.retain(|val| val != key)
}
None => {
continue
}
}
}
}
Err(err) => {
// skip errors
continue
}
}
}
Ok(profile_info)
}
/// Get latest about name from given user
///
/// # Arguments