Support media envelopes and feed w/o transparent shares

This commit is contained in:
Leonora Tindall 2022-11-02 14:49:54 -05:00
parent 0f7af7c13a
commit 95f6887eda
Signed by: nora
GPG Key ID: 7A8B52EC67E09AAF
5 changed files with 51 additions and 17 deletions

View File

@ -17,6 +17,7 @@ ports to use for development and deployment.
- [x] RSS feeds for projects - [x] RSS feeds for projects
- [x] Index page explaining what's going on - [x] Index page explaining what's going on
- [x] Better support for transparent shares - [x] Better support for transparent shares
- [x] Add feed without shares
- [ ] More robust parsing (defaults for all!) - [ ] More robust parsing (defaults for all!)
- [ ] RSS feeds for tags - [ ] RSS feeds for tags
- [x] Atom Extension pagination support - [x] Atom Extension pagination support

View File

@ -44,14 +44,9 @@ pub struct CohostPost {
default default
)] )]
pub url: String, pub url: String,
#[serde( #[serde(deserialize_with = "deserialize_null_default", default)]
deserialize_with = "deserialize_null_default",
default
)]
pub blocks: Vec<CohostPostBlock>, pub blocks: Vec<CohostPostBlock>,
#[serde( #[serde(rename = "transparentShareOfPostId")]
rename = "transparentShareOfPostId",
)]
pub transparent_share_of_post_id: Option<u64>, pub transparent_share_of_post_id: Option<u64>,
#[serde(rename = "postingProject")] #[serde(rename = "postingProject")]
pub poster: CohostPostingProject, pub poster: CohostPostingProject,
@ -93,7 +88,6 @@ pub struct CohostPostLink {
pub t_type: String, pub t_type: String,
} }
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct CohostPostBlock { pub struct CohostPostBlock {
pub attachment: Option<CohostPostAttachment>, pub attachment: Option<CohostPostAttachment>,
@ -101,7 +95,11 @@ pub struct CohostPostBlock {
#[derive(Debug, Clone, Deserialize)] #[derive(Debug, Clone, Deserialize)]
pub struct CohostPostAttachment { pub struct CohostPostAttachment {
#[serde(rename = "fileURL", deserialize_with = "deserialize_null_default", default)] #[serde(
rename = "fileURL",
deserialize_with = "deserialize_null_default",
default
)]
pub file_url: String, pub file_url: String,
} }

View File

@ -194,12 +194,22 @@ async fn get_project_data(project_id: String) -> Result<CohostAccount, ErrorResp
} }
} }
#[get("/<project>/originals.rss")]
async fn syndication_originals_rss_route(project: String) -> Result<RssResponse, ErrorResponse> {
let project_data = get_project_data(project.clone()).await?;
let page_data = get_full_post_data(project.clone()).await?;
Ok(RssResponse {
inner: syndication::channel_for_posts_page(project.clone(), project_data, page_data, true)
.to_string(),
})
}
#[get("/<project>/feed.rss")] #[get("/<project>/feed.rss")]
async fn syndication_rss_route(project: String) -> Result<RssResponse, ErrorResponse> { async fn syndication_rss_route(project: String) -> Result<RssResponse, ErrorResponse> {
let project_data = get_project_data(project.clone()).await?; let project_data = get_project_data(project.clone()).await?;
let page_data = get_full_post_data(project.clone()).await?; let page_data = get_full_post_data(project.clone()).await?;
Ok(RssResponse { Ok(RssResponse {
inner: syndication::channel_for_posts_page(project.clone(), project_data, page_data) inner: syndication::channel_for_posts_page(project.clone(), project_data, page_data, false)
.to_string(), .to_string(),
}) })
} }
@ -244,7 +254,13 @@ async fn main() -> Result<(), Box<dyn Error>> {
let _rocket = rocket::build() let _rocket = rocket::build()
.mount( .mount(
&ARGS.base_url, &ARGS.base_url,
routes![index, webfinger_route, syndication_rss_route, post_md_route], routes![
index,
webfinger_route,
syndication_rss_route,
syndication_originals_rss_route,
post_md_route
],
) )
.ignite() .ignite()
.await? .await?

View File

@ -22,11 +22,16 @@ pub fn channel_for_posts_page(
project_name: impl AsRef<str>, project_name: impl AsRef<str>,
project: CohostAccount, project: CohostAccount,
mut page: CohostPostsPage, mut page: CohostPostsPage,
originals_only: bool,
) -> Channel { ) -> Channel {
let project_name = project_name.as_ref().clone(); let project_name = project_name.as_ref().clone();
let mut builder = rss::ChannelBuilder::default(); let mut builder = rss::ChannelBuilder::default();
builder builder
.title(format!("{} Cohost Posts", project.display_name)) .title(format!(
"{} Cohost Posts{}",
project.display_name,
if originals_only { "" } else { " and Shares" }
))
.description(project.description) .description(project.description)
.generator(Some(format!( .generator(Some(format!(
"{} {}", "{} {}",
@ -73,7 +78,13 @@ pub fn channel_for_posts_page(
let mut body_text = String::new(); let mut body_text = String::new();
if let Some(shared_post_id) = item.transparent_share_of_post_id { if let Some(shared_post_id) = item.transparent_share_of_post_id {
body_text.push_str(&format!("(share of post {} without any commentary)\n\n---\n\n", shared_post_id)); if originals_only {
continue;
}
body_text.push_str(&format!(
"(share of post {} without any commentary)\n\n---\n\n",
shared_post_id
));
} else if item.share_tree.len() == 1 { } else if item.share_tree.len() == 1 {
body_text.push_str("(in reply to another post)\n\n---\n\n") body_text.push_str("(in reply to another post)\n\n---\n\n")
} else if item.share_tree.len() > 1 { } else if item.share_tree.len() > 1 {
@ -113,9 +124,16 @@ pub fn channel_for_posts_page(
item_builder.content(html_output); item_builder.content(html_output);
for attachment in item.blocks.into_iter().filter_map(|block| block.attachment) { for attachment in item.blocks.into_iter().filter_map(|block| block.attachment) {
use rss::EnclosureBuilder;
use mime_guess::from_path as guess_mime_from_path; use mime_guess::from_path as guess_mime_from_path;
let enclosure = EnclosureBuilder::default().mime_type(guess_mime_from_path(&attachment.file_url).first_or_octet_stream().to_string()).url(attachment.file_url).build(); use rss::EnclosureBuilder;
let enclosure = EnclosureBuilder::default()
.mime_type(
guess_mime_from_path(&attachment.file_url)
.first_or_octet_stream()
.to_string(),
)
.url(attachment.file_url)
.build();
item_builder.enclosure(enclosure); item_builder.enclosure(enclosure);
} }

View File

@ -52,8 +52,9 @@
<h2>Standard Data from Cohost Posts and Projects</h2> <h2>Standard Data from Cohost Posts and Projects</h2>
<p> <p>
<h3>Project RSS Feeds</h3> <h3>Project RSS Feeds</h3>
Go to <code>/project_name/feed.rss</code> to get a feed for a project. Go to <code>/project_name/feed.rss</code> to get a feed for a project, or <code>/project_name/originals.rss</code> for just original posts (including shared posts with commentary).
For example, <a href="/noracodes/feed.rss"><code>/noracodes/feed.rss</code></a> will give you the feed for my page. For example, <a href="/noracodes/feed.rss"><code>/noracodes/feed.rss</code></a> will give you the feed for my page,
or <a href="/noracodes/original.rss"><code>/noracodes/feed.rss</code></a> for just my original posts.
</p> </p>
<p> <p>
<h3>Markdown Extraction</h3> <h3>Markdown Extraction</h3>