aboutsummaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorFuwn <[email protected]>2022-06-12 02:32:47 -0700
committerFuwn <[email protected]>2022-06-12 02:32:47 -0700
commitd2da92336fb109600e59c9ed1e4976ebf891d82c (patch)
treea124de93b3aedf04aee8f9d3e21b987ea2bb150f /src/modules
parentfeat(blog): projects blog (diff)
downloadlocus-d2da92336fb109600e59c9ed1e4976ebf891d82c.tar.xz
locus-d2da92336fb109600e59c9ed1e4976ebf891d82c.zip
feat(blog): sub-blog configuration
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/blog.rs22
-rw-r--r--src/modules/blog/config.rs59
-rw-r--r--src/modules/blog/module.rs (renamed from src/modules/multi_blog.rs)148
-rw-r--r--src/modules/mod.rs6
4 files changed, 211 insertions, 24 deletions
diff --git a/src/modules/blog.rs b/src/modules/blog.rs
new file mode 100644
index 0000000..4672ec2
--- /dev/null
+++ b/src/modules/blog.rs
@@ -0,0 +1,22 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+mod config;
+mod module;
+
+pub use module::module;
diff --git a/src/modules/blog/config.rs b/src/modules/blog/config.rs
new file mode 100644
index 0000000..34d9373
--- /dev/null
+++ b/src/modules/blog/config.rs
@@ -0,0 +1,59 @@
+// This file is part of Locus <https://github.com/gemrest/locus>.
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 3.
+//
+// This program is distributed in the hope that it will be useful, but
+// WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+// Copyright (C) 2022-2022 Fuwn <[email protected]>
+// SPDX-License-Identifier: GPL-3.0-only
+
+use std::collections::HashMap;
+
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Clone, Default)]
+pub struct Entry {
+ description: Option<String>,
+ author: Option<String>,
+ created: Option<String>,
+ last_modified: Option<String>,
+ name: Option<String>,
+}
+impl Entry {
+ pub const fn description(&self) -> &Option<String> { &self.description }
+
+ pub const fn author(&self) -> &Option<String> { &self.author }
+
+ pub const fn name(&self) -> &Option<String> { &self.name }
+
+ pub const fn created(&self) -> &Option<String> { &self.created }
+
+ pub const fn last_modified(&self) -> &Option<String> { &self.last_modified }
+}
+
+#[derive(Serialize, Deserialize, Clone, Default)]
+pub struct Blog {
+ name: Option<String>,
+ description: Option<String>,
+ posts: Option<HashMap<String, Entry>>,
+}
+impl Blog {
+ pub const fn description(&self) -> &Option<String> { &self.description }
+
+ pub const fn name(&self) -> &Option<String> { &self.name }
+
+ pub const fn posts(&self) -> &Option<HashMap<String, Entry>> { &self.posts }
+
+ pub fn from_string(string: &str) -> serde_json::Result<Self> {
+ serde_json::from_str(string)
+ }
+}
diff --git a/src/modules/multi_blog.rs b/src/modules/blog/module.rs
index 4dda4b0..c6e904d 100644
--- a/src/modules/multi_blog.rs
+++ b/src/modules/blog/module.rs
@@ -22,7 +22,7 @@ use std::{
io::Read,
};
-use crate::{route::track_mount, success};
+use crate::{modules::blog::config::Blog, route::track_mount, success};
#[allow(clippy::too_many_lines)]
pub fn module(router: &mut windmark::Router) {
@@ -111,14 +111,38 @@ pub fn module(router: &mut windmark::Router) {
blog_clone.len(),
blog_clone
.iter()
- .map(|(title, _)| title.clone())
- .collect::<Vec<_>>()
+ .map(|(title, entries)| (title.clone(), entries.clone()))
+ .collect::<Vec<(_, _)>>()
.into_iter()
- .map(|i| {
+ .map(|(title, entries)| {
+ let config: Option<Blog> =
+ entries.get("blog.json").and_then(|content| {
+ if let Ok(config) = Blog::from_string(content) {
+ Some(config)
+ } else {
+ None
+ }
+ });
+ let name = config
+ .clone()
+ .unwrap_or_default()
+ .name()
+ .clone()
+ .unwrap_or_else(|| title.clone());
+ let description = config
+ .unwrap_or_default()
+ .description()
+ .clone()
+ .unwrap_or_else(|| "One of Fuwn's blogs".to_string());
+
format!(
- "=> {} {}",
- format_args!("/blog/{}", i.replace(' ', "_").to_lowercase(),),
- i
+ "=> {} {} ― {}",
+ format_args!(
+ "/blog/{}",
+ name.replace(' ', "_").to_lowercase(),
+ ),
+ name,
+ description
)
})
.collect::<Vec<_>>()
@@ -129,36 +153,75 @@ pub fn module(router: &mut windmark::Router) {
}),
);
- for (blog, entries) in blogs {
+ for (blog, mut entries) in blogs {
let fixed_blog_name = blog.replace(' ', "_").to_lowercase();
- let entries_clone = entries.clone();
let fixed_blog_name_clone = fixed_blog_name.clone();
- let blog_clone = blog.clone();
+ let config: Option<Blog> =
+ entries.remove_entry("blog.json").and_then(|(_, content)| {
+ if let Ok(config) = Blog::from_string(&content) {
+ Some(config)
+ } else {
+ None
+ }
+ });
+ let entries_clone = entries.clone();
+ let name = config
+ .clone()
+ .unwrap_or_default()
+ .name()
+ .clone()
+ .unwrap_or_else(|| blog.clone());
+ let description = config
+ .clone()
+ .unwrap_or_default()
+ .description()
+ .clone()
+ .unwrap_or_else(|| "One of Fuwn's blogs".to_string());
+ let config_clone = config.clone();
track_mount(
router,
&format!("/blog/{}", fixed_blog_name),
- &format!("{} ― One of Fuwn's blogs", &blog),
+ &format!("{} ― {}", name, description),
Box::new(move |context| {
success!(
&format!(
- "# {} ({})\n\n{}",
+ "# {} ({})\n\n{}\n\n{}",
blog.to_uppercase(),
entries_clone.len(),
+ description,
entries_clone
.iter()
.map(|(title, _)| title.clone())
.collect::<Vec<_>>()
.into_iter()
- .map(|i| {
+ .map(|title| {
format!(
- "=> {} {}",
+ "=> {} {}{}",
format_args!(
"/blog/{}/{}",
fixed_blog_name_clone,
- i.to_lowercase()
+ title.to_lowercase()
),
- i
+ title,
+ {
+ let post = config_clone
+ .clone()
+ .unwrap_or_default()
+ .posts()
+ .clone()
+ .and_then(|posts| posts.get(&title).cloned())
+ .unwrap_or_default()
+ .description()
+ .clone()
+ .unwrap_or_else(|| "".to_string());
+
+ if post.is_empty() {
+ "".to_string()
+ } else {
+ format!(" ― {}", post)
+ }
+ }
)
})
.collect::<Vec<_>>()
@@ -170,15 +233,58 @@ pub fn module(router: &mut windmark::Router) {
);
for (title, contents) in entries {
+ let header = if let Ok(header) = construct_header(&config, &title) {
+ header
+ } else {
+ "".to_string()
+ };
+
track_mount(
router,
&format!("/blog/{}/{}", fixed_blog_name, title.to_lowercase()),
- &format!(
- "{}, {} ― An entry to one of Fuwn's blogs",
- blog_clone, title
- ),
- Box::new(move |context| success!(contents, context)),
+ &format!("{}, {} ― An entry to one of Fuwn's blogs", name, title),
+ Box::new(move |context| {
+ success!(format!("{}\n{}", header, contents), context)
+ }),
);
}
}
}
+
+fn construct_header(config: &Option<Blog>, name: &str) -> Result<String, ()> {
+ let post =
+ if let Some(posts) = config.clone().unwrap_or_default().posts().clone() {
+ if let Some(post) = posts.get(name) {
+ post.clone()
+ } else {
+ return Err(());
+ }
+ } else {
+ return Err(());
+ };
+
+ Ok(format!(
+ "# {}\n\n{}{}{}{}",
+ post.name().clone().unwrap_or_else(|| name.to_string()),
+ if post.author().is_some() {
+ format!("Author: {}\n", post.author().clone().unwrap())
+ } else {
+ "".to_string()
+ },
+ if post.created().is_some() {
+ format!("Created: {}\n", post.created().clone().unwrap())
+ } else {
+ "".to_string()
+ },
+ if post.last_modified().is_some() {
+ format!("Last Modified: {}\n", post.last_modified().clone().unwrap())
+ } else {
+ "".to_string()
+ },
+ if post.description().is_some() {
+ format!("\n{}\n", post.description().clone().unwrap())
+ } else {
+ "".to_string()
+ },
+ ))
+}
diff --git a/src/modules/mod.rs b/src/modules/mod.rs
index 4b67961..79025ae 100644
--- a/src/modules/mod.rs
+++ b/src/modules/mod.rs
@@ -16,7 +16,7 @@
// Copyright (C) 2022-2022 Fuwn <[email protected]>
// SPDX-License-Identifier: GPL-3.0-only
-mod multi_blog;
+mod blog;
mod random;
mod remarks;
mod robots;
@@ -28,7 +28,7 @@ mod uptime;
pub fn module(router: &mut windmark::Router) {
crate::statelesses!(
- router, uptime, sitemap, search, remarks, multi_blog, random, r#static,
- router, robots,
+ router, uptime, sitemap, search, remarks, blog, random, r#static, router,
+ robots,
);
}