RSS endpoint

This commit is contained in:
Gabriel Simmer 2024-01-28 16:25:30 +00:00
parent 408d27ebb8
commit bde3592581
Signed by: arch
SSH key fingerprint: SHA256:m3OEcdtrnBpMX+2BDGh/byv3hrCekCLzDYMdvGEKPPQ
3 changed files with 154 additions and 1 deletions

106
Cargo.lock generated
View file

@ -83,6 +83,19 @@ dependencies = [
"syn 2.0.48",
]
[[package]]
name = "atom_syndication"
version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "571832dcff775e26562e8e6930cd483de5587301d40d3a3b85d532b6383e15a7"
dependencies = [
"chrono",
"derive_builder",
"diligent-date-parser",
"never",
"quick-xml",
]
[[package]]
name = "autocfg"
version = "1.1.0"
@ -255,6 +268,15 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "derive_builder"
version = "0.12.0"
@ -338,6 +360,15 @@ dependencies = [
"crypto-common",
]
[[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"
@ -359,6 +390,15 @@ dependencies = [
"stable_deref_trait",
]
[[package]]
name = "encoding_rs"
version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1"
dependencies = [
"cfg-if",
]
[[package]]
name = "entities"
version = "1.0.1"
@ -459,8 +499,10 @@ dependencies = [
"include_dir",
"maud",
"orgize",
"rss",
"serde",
"serde_dhall",
"time",
"worker",
]
@ -703,6 +745,12 @@ dependencies = [
"adler",
]
[[package]]
name = "never"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c96aba5aa877601bb3f6dd6a63a969e1f82e60646e81e71b14496995e9853c91"
[[package]]
name = "nom"
version = "7.1.3"
@ -902,6 +950,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "pretty"
version = "0.11.3"
@ -946,6 +1000,16 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "quick-xml"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956"
dependencies = [
"encoding_rs",
"memchr",
]
[[package]]
name = "quote"
version = "1.0.35"
@ -999,6 +1063,18 @@ version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
[[package]]
name = "rss"
version = "2.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7b2c77eb4450d7d5f98df52c381cd6c4e19b75dad9209a9530b85a44510219a"
dependencies = [
"atom_syndication",
"derive_builder",
"never",
"quick-xml",
]
[[package]]
name = "rustc-demangle"
version = "0.1.23"
@ -1156,6 +1232,36 @@ dependencies = [
"syn 2.0.48",
]
[[package]]
name = "time"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
dependencies = [
"deranged",
"itoa",
"js-sys",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
dependencies = [
"time-core",
]
[[package]]
name = "tinyvec"
version = "1.6.0"

View file

@ -15,6 +15,8 @@ include_dir = "0.7.3"
frontmatter = "0.4.0"
comrak = { version = "0.21.0", default-features = false }
orgize = { git = "https://git.gmem.ca/arch/orgize.git", branch = "org-images", default-features = false }
rss = "2.0.6"
time = { version = "0.3.31", features = ["parsing", "formatting", "macros", "wasm-bindgen"] }
[profile.release]
lto = true

View file

@ -3,6 +3,7 @@ use worker::*;
use maud::{html, Markup, Render, DOCTYPE};
use serde::{Serialize, Deserialize};
use include_dir::{include_dir, Dir};
use time::{self, macros::format_description, format_description::well_known::Rfc2822};
mod posts;
@ -152,6 +153,50 @@ async fn main(req: Request, env: Env, _ctx: Context) -> Result<Response> {
cache.put(key, res.cloned()?).await?;
return Ok(res);
})
.get_async("/rss", |req, ctx| async move {
let cache = Cache::default();
let key = req.url()?.to_string();
if let Some(mut res) = cache.get(&key, false).await? {
let headers = res.headers_mut();
let _ = headers.set("cf-cache", "hit");
return Ok(res)
}
let index = ctx.env.d1("INDEX")?;
let statement = index.prepare("SELECT * FROM posts ORDER BY date DESC");
let posts: Vec<posts::PostMetadata> = statement.all().await?.results()?;
let rss_posts: Vec<rss::Item> = posts.into_iter().map(|p| {
let date = format!("{} 00:00:00 +00:00:00", p.date);
let format = format_description!("[year]-[month]-[day] [hour]:[minute]:[second] [offset_hour sign:mandatory]:[offset_minute]:[offset_second]");
let parsed_date = match time::OffsetDateTime::parse(&date, &format) {
Ok(r) => r,
Err(_e) => { time::OffsetDateTime::now_utc() },
};
let pub_date = match parsed_date.format(&Rfc2822) {
Ok(r) => r,
Err(_e) => { "".to_owned() },
};
rss::ItemBuilder::default()
.title(Some(p.title))
.link(Some(format!("https://gabrielsimmer.com/blog/{}", p.slug)))
.pub_date(Some(pub_date))
.build()
}).collect();
let channel = rss::ChannelBuilder::default()
.title("Gabriel Simmer's Blog".to_owned())
.link("https://gabrielsimmer.com/blog".to_owned())
.description("Gabriel Simmer's Blog Posts.".to_owned())
.items(rss_posts)
.build();
let mut res = Response::ok(channel.to_string())?;
let headers = res.headers_mut();
let _ = headers.set("Cache-Control", "public, max-age=14400");
let _ = headers.set("Content-Type", "application/rss+xml");
cache.put(key, res.cloned()?).await?;
Ok(res)
})
.get_async("/api/reindex", |req, ctx| async move {
let auth_header = req.headers().get("Authorization")?;
if auth_header.is_none() {