about summary refs log tree commit diff
path: root/kittybox-rs/src/micropub
diff options
context:
space:
mode:
Diffstat (limited to 'kittybox-rs/src/micropub')
-rw-r--r--kittybox-rs/src/micropub/mod.rs45
1 files changed, 28 insertions, 17 deletions
diff --git a/kittybox-rs/src/micropub/mod.rs b/kittybox-rs/src/micropub/mod.rs
index a55ea15..fe3db57 100644
--- a/kittybox-rs/src/micropub/mod.rs
+++ b/kittybox-rs/src/micropub/mod.rs
@@ -56,9 +56,9 @@ fn populate_reply_context(
     mf2: &serde_json::Value,
     prop: &str,
     ctxs: &[FetchedPostContext],
-) -> Option<serde_json::Value> {
+) -> Option<Vec<serde_json::Value>> {
     mf2["properties"][prop].as_array().map(|array| {
-        json!(array
+        array
             .iter()
             // TODO: This seems to be O(n^2) and I don't like it.
             // Switching `ctxs` to a hashmap might speed it up to O(n)
@@ -68,7 +68,8 @@ fn populate_reply_context(
                 .find(|ctx| Some(ctx.url.as_str()) == i.as_str())
                 .and_then(|ctx| ctx.mf2["items"].get(0))
                 .unwrap_or(i))
-            .collect::<Vec<&serde_json::Value>>())
+            .cloned()
+            .collect::<Vec<serde_json::Value>>()
     })
 }
 
@@ -147,13 +148,16 @@ async fn background_processing<D: 'static + Storage>(
             .await
     };
 
-    let mut update = json!({ "replace": {} });
-    for prop in &context_props {
+    let mut update = MicropubUpdate {
+        replace: Some(Default::default()),
+        ..Default::default()
+    };
+    for prop in context_props {
         if let Some(json) = populate_reply_context(&mf2, prop, &post_contexts) {
-            update["replace"][prop] = json;
+            update.replace.as_mut().unwrap().insert(prop.to_owned(), json);
         }
     }
-    if !update["replace"].as_object().unwrap().is_empty() {
+    if !update.replace.as_ref().unwrap().is_empty() {
         if let Err(err) = db.update_post(uid, update).await {
             error!("Failed to update post with rich reply contexts: {}", err);
         }
@@ -323,7 +327,7 @@ enum ActionType {
 #[serde(untagged)]
 pub enum MicropubPropertyDeletion {
     Properties(Vec<String>),
-    Values(HashMap<String, serde_json::Value>)
+    Values(HashMap<String, Vec<serde_json::Value>>)
 }
 #[derive(Serialize, Deserialize)]
 struct MicropubFormAction {
@@ -335,12 +339,20 @@ struct MicropubFormAction {
 pub struct MicropubAction {
     action: ActionType,
     url: String,
+    #[serde(flatten)]
     #[serde(skip_serializing_if = "Option::is_none")]
-    replace: Option<HashMap<String, serde_json::Value>>,
+    update: Option<MicropubUpdate>
+}
+
+#[derive(Serialize, Deserialize, Debug, Default)]
+pub struct MicropubUpdate {
     #[serde(skip_serializing_if = "Option::is_none")]
-    add: Option<HashMap<String, serde_json::Value>>,
+    pub replace: Option<HashMap<String, Vec<serde_json::Value>>>,
     #[serde(skip_serializing_if = "Option::is_none")]
-    delete: Option<MicropubPropertyDeletion>,
+    pub add: Option<HashMap<String, Vec<serde_json::Value>>>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub delete: Option<MicropubPropertyDeletion>,
+
 }
 
 impl From<MicropubFormAction> for MicropubAction {
@@ -349,9 +361,7 @@ impl From<MicropubFormAction> for MicropubAction {
         Self {
             action: a.action,
             url: a.url,
-            replace: None,
-            add: None,
-            delete: None,
+            update: None
         }
     }
 }
@@ -407,9 +417,10 @@ async fn post_action<D: Storage, A: AuthBackend>(
 
             db.update_post(
                 &action.url,
-                // Here, unwrapping is safe, because this value
-                // was recently deserialized from JSON already.
-                serde_json::to_value(&action).unwrap(),
+                action.update.ok_or(MicropubError {
+                    error: ErrorType::InvalidRequest,
+                    error_description: "Update request is not set.".to_owned(),
+                })?
             )
             .await?
         }