From c0b552318cb08872c7deae82a10122b0e16b7ae8 Mon Sep 17 00:00:00 2001 From: Vika Date: Sun, 5 Dec 2021 22:55:32 +0300 Subject: Added author mini-cards on h-entries --- src/database/file/mod.rs | 106 ++++++++++++++++++++++++++++++----------------- 1 file changed, 69 insertions(+), 37 deletions(-) (limited to 'src/database') diff --git a/src/database/file/mod.rs b/src/database/file/mod.rs index 67b3549..d67c920 100644 --- a/src/database/file/mod.rs +++ b/src/database/file/mod.rs @@ -6,6 +6,7 @@ use async_trait::async_trait; use futures::stream; use futures_util::StreamExt; use futures_util::TryStreamExt; +use serde_json::json; use crate::database::{ErrorKind, Result, Storage, StorageError, filter_post}; use fd_lock::RwLock; use log::debug; @@ -184,6 +185,34 @@ impl FileStorage { } } +async fn hydrate_author(feed: &mut serde_json::Value, user: &'_ Option, storage: &S) { + let url = feed["properties"]["uid"][0].as_str().unwrap(); + if let Some(author) = feed["properties"]["author"].clone().as_array() { + if !feed["type"].as_array().unwrap().iter().any(|i| i == "h-card") { + let author_list: Vec = stream::iter(author.iter()) + .then(|i| async move { + if let Some(i) = i.as_str() { + match storage.get_post(i).await { + Ok(post) => match post { + Some(post) => match filter_post(post, user) { + Some(author) => author, + None => json!(i) + }, + None => json!(i) + }, + Err(e) => { + log::error!("Error while hydrating post {}: {}", url, e); + json!(i) + } + } + } else { i.clone() } + }) + .collect::>().await; + feed["properties"].as_object_mut().unwrap()["author"] = json!(author_list); + } + } +} + #[async_trait] impl Storage for FileStorage { async fn post_exists(&self, url: &str) -> Result { @@ -386,50 +415,53 @@ impl Storage for FileStorage { limit: usize, user: &'a Option, ) -> Result> { - match self.get_post(url).await? { - Some(feed) => match filter_post(feed, user) { - Some(mut feed) => { - if feed["children"].is_array() { - let children = feed["children"].as_array().unwrap().clone(); - let mut posts_iter = children.into_iter() - .map(|s: serde_json::Value| s.as_str().unwrap().to_string()); - if after.is_some() { - loop { - let i = posts_iter.next(); - if &i == after { - break; - } + if let Some(feed) = self.get_post(url).await? { + if let Some(mut feed) = filter_post(feed, user) { + if feed["children"].is_array() { + let children = feed["children"].as_array().unwrap().clone(); + let mut posts_iter = children.into_iter() + .map(|s: serde_json::Value| s.as_str().unwrap().to_string()); + if after.is_some() { + loop { + let i = posts_iter.next(); + if &i == after { + break; } } - let posts = stream::iter(posts_iter) - .map(|url: String| async move { - self.get_post(&url).await - }) - .buffered(std::cmp::min(3, limit)) - // Hack to unwrap the Option and sieve out broken links - // Broken links return None, and Stream::filter_map skips Nones. - .try_filter_map(|post: Option| async move { Ok(post) }) - .try_filter_map(|post| async move { Ok(filter_post(post, user)) }) - .take(limit); - - match posts.try_collect::>().await { - Ok(posts) => feed["children"] = serde_json::json!(posts), - Err(err) => { - return Err(StorageError::with_source( - ErrorKind::Other, "Feed assembly error", - Box::new(err) - )); - } + } + let posts = stream::iter(posts_iter) + .map(|url: String| async move { + self.get_post(&url).await + }) + .buffered(std::cmp::min(3, limit)) + // Hack to unwrap the Option and sieve out broken links + // Broken links return None, and Stream::filter_map skips Nones. + .try_filter_map(|post: Option| async move { Ok(post) }) + .and_then(|mut post| async move { hydrate_author(&mut post, user, self).await; Ok(post) }) + .try_filter_map(|post| async move { Ok(filter_post(post, user)) }) + + .take(limit); + + match posts.try_collect::>().await { + Ok(posts) => feed["children"] = serde_json::json!(posts), + Err(err) => { + return Err(StorageError::with_source( + ErrorKind::Other, "Feed assembly error", + Box::new(err) + )); } } - Ok(Some(feed)) - }, - None => Err(StorageError::new( + } + hydrate_author(&mut feed, user, self).await; + Ok(Some(feed)) + } else { + Err(StorageError::new( ErrorKind::PermissionDenied, "specified user cannot access this post", )) - }, - None => Ok(None) + } + } else { + Ok(None) } } -- cgit 1.4.1