about summary refs log tree commit diff
path: root/src/database/file
diff options
context:
space:
mode:
Diffstat (limited to 'src/database/file')
-rw-r--r--src/database/file/mod.rs106
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)
         }
     }