about summary refs log tree commit diff
path: root/src/micropub
diff options
context:
space:
mode:
authorVika <vika@fireburn.ru>2021-05-09 18:03:49 +0300
committerVika <vika@fireburn.ru>2021-05-09 18:03:49 +0300
commit002dc24c1440ad1d1fab0fc901fb0d6ff457b7a2 (patch)
tree44235ece104c1d73e261f633e193be8154b9cfda /src/micropub
parent22f5a47425dc677294b6ae9ebf7ffe949e9dc903 (diff)
downloadkittybox-002dc24c1440ad1d1fab0fc901fb0d6ff457b7a2.tar.zst
Added support for more default feeds, added a feed for vCards
Diffstat (limited to 'src/micropub')
-rw-r--r--src/micropub/post.rs57
1 files changed, 42 insertions, 15 deletions
diff --git a/src/micropub/post.rs b/src/micropub/post.rs
index ce9e6fa..69b74e9 100644
--- a/src/micropub/post.rs
+++ b/src/micropub/post.rs
@@ -1,7 +1,7 @@
 use core::iter::Iterator;
 use std::str::FromStr;
 use std::convert::TryInto;
-use log::error;
+use log::{warn, error};
 use futures::stream;
 use futures::StreamExt;
 use chrono::prelude::*;
@@ -15,6 +15,8 @@ use crate::indieauth::User;
 
 static DEFAULT_CHANNEL_PATH: &str = "/feeds/main";
 static DEFAULT_CHANNEL_NAME: &str = "Main feed";
+static CONTACTS_CHANNEL_PATH: &str = "/feeds/vcards";
+static CONTACTS_CHANNEL_NAME: &str = "My address book";
 
 macro_rules! response {
     ($($code:expr, $json:tt)+) => {
@@ -38,7 +40,9 @@ macro_rules! error_json {
 fn get_folder_from_type(post_type: &str) -> String {
     (match post_type {
         "h-feed" => "feeds/",
+        "h-card" => "vcards/",
         "h-event" => "events/",
+        "h-food" => "food/",
         _ => "posts/"
     }).to_string()
 }
@@ -122,11 +126,20 @@ fn normalize_mf2(mut body: serde_json::Value, user: &User) -> (String, serde_jso
             "value": body["properties"]["content"][0]
         }])
     }
-    if body["properties"]["channel"][0].as_str().is_none() && body["type"][0] != "h-feed" {
-        // Set the channel to the main channel...
-        let default_channel = me.join("/feeds/main").unwrap().to_string();
+    if body["properties"]["channel"][0].as_str().is_none() {
+        if body["type"][0] == "h-entry" {
+            // Set the channel to the main channel...
+            let default_channel = me.join(DEFAULT_CHANNEL_PATH).unwrap().to_string();
 
-        body["properties"]["channel"] = json!([default_channel]);
+            body["properties"]["channel"] = json!([default_channel]);
+        } else if body["type"][0] == "h-card" {
+            let default_channel = me.join(CONTACTS_CHANNEL_PATH).unwrap().to_string();
+
+            body["properties"]["channel"] = json!([default_channel]);
+        } else {
+            body["properties"]["channel"] = json!([]);
+        }
+        // TODO: Sort other types of posts into channels too
     }
     body["properties"]["posted-with"] = json!([user.client_id]);
     if body["properties"]["author"][0].as_str().is_none() {
@@ -175,6 +188,7 @@ async fn new_post<S: Storage>(req: Request<ApplicationState<S>>, body: serde_jso
         .collect::<Vec<_>>()
     {
         let default_channel = user.me.join(DEFAULT_CHANNEL_PATH).unwrap().to_string();
+        let vcards_channel = user.me.join(CONTACTS_CHANNEL_PATH).unwrap().to_string();
         match storage.post_exists(&channel).await {
             Ok(exists) => if exists {
                 if let Err(err) = storage.update_post(&channel, json!({
@@ -184,18 +198,12 @@ async fn new_post<S: Storage>(req: Request<ApplicationState<S>>, body: serde_jso
                 })).await {
                     return error_json!(500, "database_error", format!("Couldn't insert post into the channel due to a database error: {}", err))
                 }
-            } else if channel == default_channel {
-                let (_, feed) = normalize_mf2(json!({
-                    "type": ["h-feed"],
-                    "properties": {
-                        "name": [DEFAULT_CHANNEL_NAME],
-                        "mp-slug": ["main"],
-                    },
-                    "children": [uid]
-                }), &user);
-                if let Err(err) = storage.put_post(&feed).await {
+            } else if channel == default_channel || channel == vcards_channel {
+                if let Err(err) = create_feed(storage, &uid, &channel, &user).await {
                     return error_json!(500, "database_error", format!("Couldn't save feed: {}", err))
                 }
+            } else {
+                warn!("Ignoring request to post to a non-existent feed: {}", channel);
             },
             Err(err) => return error_json!(500, "database_error", err)
         }
@@ -211,6 +219,25 @@ async fn new_post<S: Storage>(req: Request<ApplicationState<S>>, body: serde_jso
         .build());
 }
 
+async fn create_feed(storage: &impl Storage, uid: &str, channel: &str, user: &User) -> crate::database::Result<()> {
+    let path = url::Url::parse(channel).unwrap().path().to_string();
+    let (name, slug) = if path == DEFAULT_CHANNEL_PATH {
+        (DEFAULT_CHANNEL_NAME, "main")
+    } else if path == CONTACTS_CHANNEL_PATH {
+        (CONTACTS_CHANNEL_NAME, "vcards")
+    } else { panic!("Tried to create an unknown default feed!"); };
+
+    let (_, feed) = normalize_mf2(json!({
+        "type": ["h-feed"],
+        "properties": {
+            "name": [name],
+            "mp-slug": [slug],
+        },
+        "children": [uid]
+    }), &user);
+    storage.put_post(&feed).await
+}
+
 async fn post_process_new_post<S: Storage>(req: Request<ApplicationState<S>>, post: serde_json::Value) {
     // TODO: Post-processing the post (aka second write pass)
     // - [-] Download rich reply contexts