aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@blos.sm>2023-06-22 21:37:10 +0100
committerLibravatar cel 🌸 <cel@blos.sm>2023-06-22 21:37:10 +0100
commitab529917847641190f21129804bbda1784b4f998 (patch)
treedfdd39286d330dd62339ade0499471b70187ae04
parentbc5ac494c6162743810b9aeb1cda4f22d94a486a (diff)
downloadblossom-ab529917847641190f21129804bbda1784b4f998.tar.gz
blossom-ab529917847641190f21129804bbda1784b4f998.tar.bz2
blossom-ab529917847641190f21129804bbda1784b4f998.zip
implement atom syndication
Diffstat (limited to '')
-rw-r--r--Cargo.lock117
-rw-r--r--Cargo.toml1
-rw-r--r--TODO.md9
-rw-r--r--src/error.rs16
-rw-r--r--src/main.rs16
-rw-r--r--src/posts/mod.rs1
-rw-r--r--src/posts/syndication.rs96
-rw-r--r--static/atombadge.pngbin0 -> 4767 bytes
-rw-r--r--static/atomfeed.gifbin0 -> 199 bytes
-rw-r--r--static/style.css8
-rw-r--r--templates/base.html.tera3
-rw-r--r--templates/contact.html.tera3
-rw-r--r--templates/home.html.tera4
-rw-r--r--templates/latestposts.html.tera2
14 files changed, 268 insertions, 8 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e65d4dd..bc79919 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -95,6 +95,19 @@ dependencies = [
]
[[package]]
+name = "atom_syndication"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca96cb38e3d8236f1573a84bbc55e130bd1ae07df770e36d0cf221ea7a50e36c"
+dependencies = [
+ "chrono",
+ "derive_builder",
+ "diligent-date-parser",
+ "never",
+ "quick-xml",
+]
+
+[[package]]
name = "atomic"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -438,6 +451,72 @@ dependencies = [
]
[[package]]
+name = "darling"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850"
+dependencies = [
+ "darling_core",
+ "darling_macro",
+]
+
+[[package]]
+name = "darling_core"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0"
+dependencies = [
+ "fnv",
+ "ident_case",
+ "proc-macro2",
+ "quote",
+ "strsim",
+ "syn 1.0.107",
+]
+
+[[package]]
+name = "darling_macro"
+version = "0.14.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e"
+dependencies = [
+ "darling_core",
+ "quote",
+ "syn 1.0.107",
+]
+
+[[package]]
+name = "derive_builder"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8d67778784b508018359cbc8696edb3db78160bab2c2a28ba7f56ef6932997f8"
+dependencies = [
+ "derive_builder_macro",
+]
+
+[[package]]
+name = "derive_builder_core"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c11bdc11a0c47bc7d37d582b5285da6849c96681023680b906673c5707af7b0f"
+dependencies = [
+ "darling",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.107",
+]
+
+[[package]]
+name = "derive_builder_macro"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebcda35c7a396850a55ffeac740804b40ffec779b98fffbb1738f4033f0ee79e"
+dependencies = [
+ "derive_builder_core",
+ "syn 1.0.107",
+]
+
+[[package]]
name = "derive_deref"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -499,6 +578,15 @@ dependencies = [
]
[[package]]
+name = "diligent-date-parser"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6cf7fe294274a222363f84bcb63cdea762979a0443b4cf1f4f8fd17c86b1182"
+dependencies = [
+ "chrono",
+]
+
+[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -973,6 +1061,12 @@ dependencies = [
]
[[package]]
+name = "ident_case"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
+
+[[package]]
name = "idna"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1378,6 +1472,12 @@ dependencies = [
]
[[package]]
+name = "never"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91"
+
+[[package]]
name = "normpath"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1750,6 +1850,16 @@ dependencies = [
]
[[package]]
+name = "quick-xml"
+version = "0.28.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce5e73202a820a31f8a0ee32ada5e21029c81fd9e3ebf668a40832e4219d9d1"
+dependencies = [
+ "encoding_rs",
+ "memchr",
+]
+
+[[package]]
name = "quote"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2179,6 +2289,7 @@ name = "site"
version = "0.1.0"
dependencies = [
"async-trait",
+ "atom_syndication",
"chrono",
"chrono-humanize",
"listenbrainz",
@@ -2275,6 +2386,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
+name = "strsim"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+[[package]]
name = "subtle"
version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index fbb29a8..edc28fd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -23,3 +23,4 @@ markdown = "1.0.0-alpha.10"
async-trait = "0.1.68"
toml = "0.7.4"
tokio-stream = { version = "0.1.14", features = ["fs"] }
+atom_syndication = "0.12.1"
diff --git a/TODO.md b/TODO.md
index f0f2e32..2ad11d1 100644
--- a/TODO.md
+++ b/TODO.md
@@ -1,8 +1,17 @@
+# TODO:
+
[x] make sure posts are organised in date order
+[x] atom feed
[x] tags
[ ] multiple tag UI
+[ ] more badges
+[ ] site translations
[ ] comments
[ ] clean up spaghetti
+[ ] brush font PLZ
+[ ] deploy database yum
+[ ] visitor counter
+[ ] guestbook
badges to steal:
[x] keith
diff --git a/src/error.rs b/src/error.rs
index eb6f6e6..42c01b1 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,3 +1,5 @@
+use std::string::FromUtf8Error;
+
use rocket::{http::Status, Responder};
#[derive(Responder, Debug)]
@@ -8,6 +10,8 @@ pub enum BlossomError {
Chrono(Status, #[response(ignore)] chrono::ParseError),
Io(Status, #[response(ignore)] std::io::Error),
Deserialization(Status, #[response(ignore)] toml::de::Error),
+ Syndicator(Status, #[response(ignore)] atom_syndication::Error),
+ Utf8Conversion(Status, #[response(ignore)] FromUtf8Error),
NotFound(Status),
NoMetadata(Status),
Unimplemented(Status),
@@ -48,3 +52,15 @@ impl From<toml::de::Error> for BlossomError {
BlossomError::Deserialization(Status::new(500), e)
}
}
+
+impl From<atom_syndication::Error> for BlossomError {
+ fn from(e: atom_syndication::Error) -> Self {
+ BlossomError::Syndicator(Status::new(500), e)
+ }
+}
+
+impl From<FromUtf8Error> for BlossomError {
+ fn from(e: FromUtf8Error) -> Self {
+ BlossomError::Utf8Conversion(Status::new(500), e)
+ }
+}
diff --git a/src/main.rs b/src/main.rs
index 40f546d..844f3aa 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,8 +7,9 @@ mod skweets;
use std::borrow::Cow;
use std::collections::HashSet;
+use atom_syndication::Feed;
use rocket::fs::{relative, FileServer};
-use rocket::http::Status;
+use rocket::http::{ContentType, Status};
use rocket::{Request, State};
use rocket_dyn_templates::{context, Template};
@@ -87,6 +88,17 @@ async fn blog(filter: Vec<String>) -> Result<Template> {
))
}
+#[get("/feed")]
+async fn feed() -> Result<(Status, (ContentType, String))> {
+ let posts = posts::get_blogposts().await?;
+ let feed = posts::syndication::atom(posts).await;
+ let feed: String = String::from_utf8(feed.write_to(Vec::new())?)?;
+ Ok((
+ Status::new(200),
+ (ContentType::new("application", "atom+xml"), feed),
+ ))
+}
+
#[get("/contact")]
async fn contact() -> Template {
Template::render("contact", context! {})
@@ -130,7 +142,7 @@ async fn main() -> std::result::Result<(), rocket::Error> {
.attach(Template::custom(|engines| {
engines.tera.autoescape_on(vec![]);
}))
- .mount("/", routes![home, contact, blog, blogpost, plants])
+ .mount("/", routes![home, contact, blog, blogpost, feed, plants])
.register("/", catchers![catcher])
.mount("/", FileServer::from(relative!("static")))
.launch()
diff --git a/src/posts/mod.rs b/src/posts/mod.rs
index 2dc5c4b..7f8e6c4 100644
--- a/src/posts/mod.rs
+++ b/src/posts/mod.rs
@@ -1,5 +1,6 @@
mod article;
mod note;
+pub mod syndication;
use std::collections::HashSet;
diff --git a/src/posts/syndication.rs b/src/posts/syndication.rs
new file mode 100644
index 0000000..f6f0b17
--- /dev/null
+++ b/src/posts/syndication.rs
@@ -0,0 +1,96 @@
+use atom_syndication::{Category, Content, Entry, Feed, Generator, Link, Person, Text, TextType};
+
+use super::{Article, Post};
+
+pub async fn atom(posts: Vec<Post<Article>>) -> Feed {
+ let me = Person {
+ name: "cel".into(),
+ email: Some("cel@blos.sm".into()),
+ uri: Some("https://blos.sm".into()),
+ };
+ let mut authors = Vec::new();
+ authors.push(me);
+ let link = Link {
+ href: "https://blos.sm/feed".into(),
+ rel: "self".into(),
+ hreflang: Some("en".into()),
+ mime_type: Some("application/atom+xml".into()),
+ title: Some("atom feed".into()),
+ length: None,
+ };
+ let mut links = Vec::new();
+ links.push(link);
+ let mut feed = Feed {
+ title: Text {
+ value: "cel's site".into(),
+ base: None,
+ lang: Some("en".into()),
+ r#type: TextType::Text,
+ },
+ id: "https://blos.sm".into(),
+ updated: posts[0].created_at.into(),
+ authors: authors.clone(),
+ categories: Vec::new(),
+ contributors: authors.clone(),
+ generator: Some(Generator {
+ value: "blos.sm".into(),
+ uri: Some("https://bunny.garden/cel/blos.sm".into()),
+ version: None,
+ }),
+ icon: Some("/icon.png".into()),
+ links: links.clone(),
+ logo: Some("/logo.png".into()),
+ rights: None,
+ subtitle: None,
+ entries: Vec::new(),
+ base: Some("https://blos.sm".into()),
+ lang: Some("en".into()),
+ ..Default::default()
+ };
+ for mut post in posts {
+ post.render().await.unwrap_or_default();
+ let mut id = String::from("https://blos.sm/blog/");
+ id.push_str(&post.data.name);
+ let categories = post
+ .tags
+ .into_iter()
+ .map(|tag| Category {
+ term: tag.clone(),
+ scheme: None,
+ label: Some(tag.clone()),
+ })
+ .collect();
+ let entry = Entry {
+ title: Text {
+ value: post.subject.unwrap_or_default(),
+ base: None,
+ lang: Some("en".into()),
+ r#type: TextType::Text,
+ },
+ id: id.clone(),
+ updated: if let Some(updated_at) = post.updated_at {
+ updated_at.into()
+ } else {
+ post.created_at.into()
+ },
+ authors: authors.clone(),
+ categories,
+ contributors: authors.clone(),
+ links: links.clone(),
+ published: Some(post.created_at.into()),
+ rights: None,
+ source: None,
+ summary: None,
+ content: Some(Content {
+ base: None,
+ lang: Some("en".into()),
+ value: post.render,
+ src: Some(id),
+ content_type: Some("html".to_string()),
+ }),
+ ..Default::default()
+ };
+ feed.entries.push(entry);
+ }
+ feed
+}
diff --git a/static/atombadge.png b/static/atombadge.png
new file mode 100644
index 0000000..db1cabf
--- /dev/null
+++ b/static/atombadge.png
Binary files differ
diff --git a/static/atomfeed.gif b/static/atomfeed.gif
new file mode 100644
index 0000000..680f096
--- /dev/null
+++ b/static/atomfeed.gif
Binary files differ
diff --git a/static/style.css b/static/style.css
index bf3f649..67cd922 100644
--- a/static/style.css
+++ b/static/style.css
@@ -166,6 +166,14 @@ footer {
background-color: #0000;
}
+.small-badge,
+.small-badge * {
+ padding: 0;
+ border: 0;
+ margin: 0;
+ font-size: 0;
+}
+
/* homepage css */
#title {
diff --git a/templates/base.html.tera b/templates/base.html.tera
index 8008b27..5ac5757 100644
--- a/templates/base.html.tera
+++ b/templates/base.html.tera
@@ -40,7 +40,7 @@
<li><a class="{% block nav_blog %}{% endblock %}" style="font-family: Sligoil" href="/blog">girlblog</a></li>
<li><a class="{% block nav_projects %}{% endblock %}" style="font-family: 'DeGerm LoCase';" href="/projects">projetos</a></li>
<li><a class="{% block nav_sound %}{% endblock %}" style="font-family: 'kirieji'" href="/sound">音</a></li>
- <li><a class="{% block nav_listens %}{% endblock %}" style="font-family: 'Almendra Display'; font-weight: 900;" href="https://listenbrainz.org/celblossom">écoute</a></li>
+ <li><a class="{% block nav_listens %}{% endblock %}" style="font-family: 'Almendra Display'; font-weight: 900;" href="https://listenbrainz.org/user/celblossom">écoute</a></li>
<li><a href="https://bimbo.video/a/cel" style="font-family: 'Mon Hugo In'">video</a></li>
<li><a href="https://weirdstar.stream" style="font-family: id_kana018" >🔴ライブ</a></li>
<li><a class="{% block nav_pix %}{% endblock %}" style="font-family: Minecraftia" href="/pix">pix</a></li>
@@ -70,6 +70,7 @@
</main>
<footer class="panel">
+ <a class="badge" href="https://blos.sm"><img src="https://blos.sm/badges/cel.png"></a>
<a class="badge" href="https://skinnyver.se"><img src="https://skinnyver.se/instance/skinnyversebadge.png"></a>
<img class="badge" src="/badges/mothracompat.gif">
<img class="badge" src="/badges/flexbox.png">
diff --git a/templates/contact.html.tera b/templates/contact.html.tera
index 1930756..5fd37b0 100644
--- a/templates/contact.html.tera
+++ b/templates/contact.html.tera
@@ -15,9 +15,8 @@
<div class="content panel h-card" rel="author">
<h1 class="p-name">cel</h1>
- <h3>pronouns: <a class="u-url" rel="me" href="https://en.pronouns.page/@celblossom"><span class="p-x-pronoun-nominative">she</span>/<span class="p-x-pronoun-accusative">her</span></a></h3>
-
<ul>
+ <li><h3>pronouns: <span class="p-x-pronoun-nominative">she</span>/<span class="p-x-pronoun-accusative">her</span></h3></li>
<li>email: <a class="u-email" href="mailto:cel@blos.sm">cel@blos.sm</a> <a href="cel.asc" class="u-key" rel="pgpkey">pgp key</a></li>
<li>xmpp: <a class="u-impp" href="xmpp:cel@blos.sm?message">cel@blos.sm</a></li>
<li>fedi: <a class="u-url" rel="me" href="https://skinnyver.se/cel">cel@skinnyver.se</a></li>
diff --git a/templates/home.html.tera b/templates/home.html.tera
index cb7fe08..1a2a453 100644
--- a/templates/home.html.tera
+++ b/templates/home.html.tera
@@ -30,10 +30,10 @@
<div class="panel content">
<h2>hallo i am celeste welcome 2 my site 🌟</h2>
- <p>this is where i dump everything</p>
+ <p>this is where i do the posting</p>
<p>i wish u a wonderful day</p>
<br>
- <img src="https://s3.eu-west-1.wasabisys.com/skinnyverse/f28c467a-0ee1-4d49-a638-08a010fd9927/quinntyping.png">
+ <img src="/quinntyping.png">
<p>perpetually under construction</p>
<img style="border: 0;" src="/barraconstruction.gif">
</div>
diff --git a/templates/latestposts.html.tera b/templates/latestposts.html.tera
index 8ab5406..5aab5cb 100644
--- a/templates/latestposts.html.tera
+++ b/templates/latestposts.html.tera
@@ -1,5 +1,5 @@
<div class="panel" id="posts">
- <h2>latest posts <!--<a class="badge" href="/feed.xml"><img class="badge" src="/rssbadge.png" alt="rss newsfeed"></a>--></h2>
+ <h2>latest posts <a class="small-badge" href="/feed"><img class="small-badge" src="/atombadge.png" alt="atom newsfeed"></a></h2>
<table id="post-list">
{% for blogpost in blogposts %}
<tr>