diff options
author | Vika <vika@fireburn.ru> | 2021-12-05 22:55:32 +0300 |
---|---|---|
committer | Vika <vika@fireburn.ru> | 2021-12-05 22:55:32 +0300 |
commit | c0b552318cb08872c7deae82a10122b0e16b7ae8 (patch) | |
tree | ec372ac488be069c0897338ca15ea08b7abca683 /src/database/file | |
parent | 24b109448bc8f1d30c88bbb9d01a05eec74b3d51 (diff) | |
download | kittybox-c0b552318cb08872c7deae82a10122b0e16b7ae8.tar.zst |
Added author mini-cards on h-entries
Diffstat (limited to 'src/database/file')
-rw-r--r-- | src/database/file/mod.rs | 106 |
1 files changed, 69 insertions, 37 deletions
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<S: Storage>(feed: &mut serde_json::Value, user: &'_ Option<String>, 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<serde_json::Value> = 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::<Vec<_>>().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<bool> { @@ -386,50 +415,53 @@ impl Storage for FileStorage { limit: usize, user: &'a Option<String>, ) -> Result<Option<serde_json::Value>> { - 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<serde_json::Value>| async move { Ok(post) }) - .try_filter_map(|post| async move { Ok(filter_post(post, user)) }) - .take(limit); - - match posts.try_collect::<Vec<serde_json::Value>>().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<serde_json::Value>| 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::<Vec<serde_json::Value>>().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) } } |