From 17941d90be80f71282af53701b6b9f0eb5bbec9e Mon Sep 17 00:00:00 2001 From: Leonora Tindall Date: Mon, 31 Oct 2022 21:41:07 -0500 Subject: [PATCH] Links and correct sorting --- Cargo.lock | 1 + Cargo.toml | 1 + README.md | 2 +- src/syndication.rs | 28 ++++++++++++++++++++++++---- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8c0f62..dd56435 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -295,6 +295,7 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" name = "corobel" version = "0.1.0" dependencies = [ + "atom_syndication", "chrono", "clap", "eggbug", diff --git a/Cargo.toml b/Cargo.toml index b6eb599..0c51c74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,3 +17,4 @@ once_cell = "1.16.0" chrono = { version = "0.4.22", features = [ "serde" ] } rss = { version = "2.0.1", features = [ "builders", "atom", "chrono" ] } pulldown-cmark = "0.9.2" +atom_syndication = "0.11.0" diff --git a/README.md b/README.md index c2ae58d..3b595d7 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ ports to use for development and deployment. - [x] RSS feeds for projects - [x] Index page explaining what's going on - [ ] RSS feeds for tags -- [ ] Atom Extension pagination support +- [x] Atom Extension pagination support - [ ] Read More support - [ ] Dublin Core support - [ ] Media Envelope support diff --git a/src/syndication.rs b/src/syndication.rs index c37aaf9..c35a9af 100644 --- a/src/syndication.rs +++ b/src/syndication.rs @@ -2,13 +2,20 @@ use crate::cohost_account::CohostAccount; use crate::cohost_posts::*; use crate::ARGS; use rss::Channel; +use rss::extension::atom::{AtomExtensionBuilder, Link}; +use atom_syndication::LinkBuilder; + +fn rel_link_for(rel: &str, project_name: &str, page_number: u64) -> Link { + LinkBuilder::default().rel(rel).href(format!("https://{}{}{}/feed.rss?page={}", &ARGS.domain, &ARGS.base_url, project_name.clone(), page_number)).build() +} pub fn channel_for_posts_page( project_name: impl AsRef, page_number: u64, project: CohostAccount, - page: CohostPostsPage, + mut page: CohostPostsPage, ) -> Channel { + let project_name = project_name.as_ref().clone(); let mut builder = rss::ChannelBuilder::default(); builder .title(format!("{} Cohost Posts", project.display_name)) @@ -20,12 +27,25 @@ pub fn channel_for_posts_page( ))) .link(format!( "https://cohost.org/{}?page={}", - project_name.as_ref(), + project_name, page_number )); - let mut items = Vec::with_capacity(page.number_items); + let mut atom = AtomExtensionBuilder::default(); + let mut links = vec![rel_link_for("self", project_name, page_number), rel_link_for("first", project_name, 0)]; + if page_number > 0 { + links.push(rel_link_for("prev", project_name, page_number - 1)); + } + if page.number_items > 0 { + // Cohost API is wrong about the pagination so we can only guess. If there are posts, there might be more posts. + links.push(rel_link_for("next", project_name, page_number + 1)); + } + atom.links(links); + builder.atom_ext(Some(atom.build())); + + page.items.sort_by_key(|item| item.published_at); + let mut items = Vec::with_capacity(page.number_items); for item in page.items { let mut item_builder = rss::ItemBuilder::default(); let mut categories: Vec = Vec::with_capacity(item.tags.len()); @@ -47,7 +67,7 @@ pub fn channel_for_posts_page( .pub_date(item.published_at.to_rfc2822()) .source(Some(rss::Source { title: Some(format!("{} Cohost Posts", project.display_name)), - url: format!("https://{}/feed/{}.rss", ARGS.domain, project_name.as_ref()), + url: format!("https://{}/feed/{}.rss", ARGS.domain, project_name), })); let mut body_text = String::new();