diff options
-rw-r--r-- | src/micropub/post.rs | 57 |
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 |