Compare commits

...

4 Commits

7 changed files with 56 additions and 17 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "rss"]
path = rss
url = git@github.com:NoraCodes/rss.git

4
Cargo.lock generated
View File

@ -293,7 +293,7 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]] [[package]]
name = "corobel" name = "corobel"
version = "0.1.0" version = "0.2.0"
dependencies = [ dependencies = [
"atom_syndication", "atom_syndication",
"chrono", "chrono",
@ -1643,8 +1643,6 @@ dependencies = [
[[package]] [[package]]
name = "rss" name = "rss"
version = "2.0.1" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acaf1331b7fc4edc3c2920819fee1766c27e8d40da593155832db3d6dea64e92"
dependencies = [ dependencies = [
"atom_syndication", "atom_syndication",
"chrono", "chrono",

View File

@ -1,6 +1,6 @@
[package] [package]
name = "corobel" name = "corobel"
version = "0.1.0" version = "0.2.0"
edition = "2021" edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -15,6 +15,6 @@ tokio = { version = "1.21.2", features = [ "full" ] }
serde_json = "1.0.87" serde_json = "1.0.87"
once_cell = "1.16.0" once_cell = "1.16.0"
chrono = { version = "0.4.22", features = [ "serde" ] } chrono = { version = "0.4.22", features = [ "serde" ] }
rss = { version = "2.0.1", features = [ "builders", "atom", "chrono" ] } rss = { path = "./rss/", version = "2.0.1-atom-link-fix", features = [ "builders", "atom", "chrono" ] }
pulldown-cmark = "0.9.2" pulldown-cmark = "0.9.2"
atom_syndication = "0.11.0" atom_syndication = "0.11.0"

1
rss Submodule

@ -0,0 +1 @@
Subproject commit 1b001f74ff947b70b6bfe48711a9f29f682dd988

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use std::error::Error; use std::error::Error;
#[macro_use] #[macro_use]
extern crate rocket; extern crate rocket;
use reqwest::StatusCode; use reqwest::{Client, StatusCode};
use rocket::response::content::RawHtml; use rocket::response::content::RawHtml;
use rocket::serde::json::Json; use rocket::serde::json::Json;
@ -30,6 +30,15 @@ fn default_base_url() -> String {
"/".into() "/".into()
} }
fn user_agent() -> String {
format!(
"{}/{} (RSS feed converter) on {}",
env!("CARGO_PKG_NAME"),
env!("CARGO_PKG_VERSION"),
&ARGS.domain
)
}
static ARGS: once_cell::sync::Lazy<Args> = once_cell::sync::Lazy::new(|| Args::parse()); static ARGS: once_cell::sync::Lazy<Args> = once_cell::sync::Lazy::new(|| Args::parse());
#[get("/")] #[get("/")]
@ -61,8 +70,17 @@ async fn syndication_rss_route(
let project_url = format!("{}{}", COHOST_ACCOUNT_API_URL, project); let project_url = format!("{}{}", COHOST_ACCOUNT_API_URL, project);
let posts_url = cohost_posts_api_url(project, page); let posts_url = cohost_posts_api_url(project, page);
let client = match Client::builder().user_agent(user_agent()).build() {
Ok(v) => v,
Err(e) => {
let err = format!("Couldn't build a reqwest client: {:?}", e);
eprintln!("{}", err);
return Err(ErrorResponse::InternalError(err));
}
};
eprintln!("making request to {}", project_url); eprintln!("making request to {}", project_url);
let project_data: CohostAccount = match reqwest::get(project_url).await { let project_data: CohostAccount = match client.get(project_url).send().await {
Ok(v) => match v.status() { Ok(v) => match v.status() {
StatusCode::OK => match v.json::<CohostAccount>().await { StatusCode::OK => match v.json::<CohostAccount>().await {
Ok(a) => a, Ok(a) => a,
@ -93,7 +111,7 @@ async fn syndication_rss_route(
}; };
eprintln!("making request to {}", posts_url); eprintln!("making request to {}", posts_url);
match reqwest::get(posts_url).await { match client.get(posts_url).send().await {
Ok(v) => match v.status() { Ok(v) => match v.status() {
StatusCode::OK => match v.json::<CohostPostsPage>().await { StatusCode::OK => match v.json::<CohostPostsPage>().await {
Ok(page_data) => { Ok(page_data) => {
@ -143,10 +161,18 @@ async fn webfinger_route(params: HashMap<String, String>) -> Option<Json<CohostW
); );
return None; return None;
} }
let client = match Client::builder().user_agent(user_agent()).build() {
Ok(v) => v,
Err(e) => {
let err = format!("Couldn't build a reqwest client: {:?}", e);
eprintln!("{}", err);
return None;
}
};
if let Some(param) = params.iter().next() { if let Some(param) = params.iter().next() {
let url = format!("{}{}", COHOST_ACCOUNT_API_URL, param.0); let url = format!("{}{}", COHOST_ACCOUNT_API_URL, param.0);
eprintln!("making request to {}", url); eprintln!("making request to {}", url);
match reqwest::get(url).await { match client.get(url).send().await {
Ok(v) => { Ok(v) => {
match v.status() { match v.status() {
StatusCode::OK => match v.json::<CohostAccount>().await { StatusCode::OK => match v.json::<CohostAccount>().await {

View File

@ -1,12 +1,21 @@
use crate::cohost_account::CohostAccount; use crate::cohost_account::CohostAccount;
use crate::cohost_posts::*; use crate::cohost_posts::*;
use crate::ARGS; use crate::ARGS;
use rss::Channel;
use rss::extension::atom::{AtomExtensionBuilder, Link};
use atom_syndication::LinkBuilder; use atom_syndication::LinkBuilder;
use rss::extension::atom::{AtomExtensionBuilder, Link};
use rss::Channel;
fn rel_link_for(rel: &str, project_name: &str, page_number: u64) -> Link { 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() 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( pub fn channel_for_posts_page(
@ -27,14 +36,16 @@ pub fn channel_for_posts_page(
))) )))
.link(format!( .link(format!(
"https://cohost.org/{}?page={}", "https://cohost.org/{}?page={}",
project_name, project_name, page_number
page_number
)); ));
let mut atom = AtomExtensionBuilder::default(); let mut atom = AtomExtensionBuilder::default();
let mut links = vec![rel_link_for("self", project_name, page_number), rel_link_for("first", project_name, 0)]; let mut links = vec![
rel_link_for("self", project_name, page_number),
rel_link_for("first", project_name, 0),
];
if page_number > 0 { if page_number > 0 {
links.push(rel_link_for("prev", project_name, page_number - 1)); links.push(rel_link_for("previous", project_name, page_number - 1));
} }
if page.number_items > 0 { 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. // Cohost API is wrong about the pagination so we can only guess. If there are posts, there might be more posts.

View File

@ -34,7 +34,7 @@
Webfinger resources for accounts are provided at the Webfinger well-known URL <code>/.well-known/webfinger?project_name</code>. Webfinger resources for accounts are provided at the Webfinger well-known URL <code>/.well-known/webfinger?project_name</code>.
</p> </p>
<p> <p>
Brought to you by Leonora Tindall, written in Rust with Rocket. Brought to you by <a href="https://nora.codes">Leonora Tindall</a>, written in Rust with Rocket. Code is <a href="https://git.nora.codes/nora/corobel">online</a>, bug reports should go to my email nora@nora.codes.
</p> </p>
</body> </body>
</html> </html>