From 45df3425d17c0112c7cf7e41eb19c473299c638e Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Tue, 19 Nov 2019 18:07:10 +0100 Subject: [PATCH] basic, working rss feeds --- docker/dev/Dockerfile | 2 +- server/src/feeds.rs | 97 ++++++++++++++++++++++++++----------------- server/src/main.rs | 2 +- 3 files changed, 62 insertions(+), 39 deletions(-) diff --git a/docker/dev/Dockerfile b/docker/dev/Dockerfile index 83a93e362..203643e1d 100644 --- a/docker/dev/Dockerfile +++ b/docker/dev/Dockerfile @@ -21,7 +21,7 @@ COPY server/Cargo.toml server/Cargo.lock ./ RUN sudo chown -R rust:rust . RUN mkdir -p ./src/bin \ && echo 'fn main() { println!("Dummy") }' > ./src/bin/main.rs -RUN cargo build --releasecargo +RUN cargo build --release RUN rm -f ./target/x86_64-unknown-linux-musl/release/deps/lemmy_server* COPY server/src ./src/ COPY server/migrations ./migrations/ diff --git a/server/src/feeds.rs b/server/src/feeds.rs index e7281f7ec..e0a1dd33b 100644 --- a/server/src/feeds.rs +++ b/server/src/feeds.rs @@ -1,28 +1,46 @@ extern crate rss; extern crate htmlescape; -use rss::ChannelBuilder; -use rss::ItemBuilder; -use actix_web::HttpResponse; -use actix_web::body::Body; +use super::*; use crate::Settings; -use crate::db::{establish_connection, ListingType, SortType}; +use crate::db::{establish_connection, ListingType, SortType, Crud}; use crate::db::community_view::SiteView; use crate::db::post_view::PostView; -use self::rss::Item; +use crate::db::user::User_; +use crate::db::community::Community; +use actix_web::{HttpResponse, web, Result}; +use actix_web::body::Body; +use rss::{ChannelBuilder, Item, ItemBuilder}; +use diesel::result::Error; -pub fn get_feed() -> HttpResponse { +pub fn get_feed(info: web::Path<(char, String)>) -> HttpResponse { + return match get_feed_internal(info) { + Ok(body) => HttpResponse::Ok() + .content_type("application/rss+xml") + .body(body), + // TODO: handle the specific type of error (403, 500, etc) + Err(e) => HttpResponse::InternalServerError().finish(), + } + +} + +fn get_feed_internal(info: web::Path<(char, String)>) -> Result { let conn = establish_connection(); - let site_view = match SiteView::read(&conn) { - Ok(site_view) => site_view, - Err(_e) => return HttpResponse::InternalServerError().finish(), - }; - let post = match PostView::list(&conn, + let mut community_id: Option = None; + let mut creator_id: Option = None; + // TODO: add a feed for /type/all + match info.0 { + 'c' => community_id = Some(Community::read_from_name(&conn,info.1.clone())?.id), + 'u' => creator_id = Some(User_::find_by_email_or_username(&conn,&info.1)?.id), + _ => return Err(Error::NotFound), + } + + let post = PostView::list(&conn, ListingType::All, &SortType::New, - None, - None, + community_id, + creator_id, None, None, None, @@ -30,35 +48,40 @@ pub fn get_feed() -> HttpResponse { false, false, None, - None,) { - Ok(post) => post, - Err(_e) => return HttpResponse::InternalServerError().finish(), - }; + None,)?; let mut items: Vec = Vec::new(); for p in post { - let i = ItemBuilder::default() - .title(p.name) - .link(p.url) - .content(p.body) - .author(p.creator_id) - .pub_date(p.published) - .build() - .unwrap(); - items.append(&i); + // TODO: this may cause a lot of db queries + let user = User_::read(&conn, p.creator_id)?; + let dt = DateTime::::from_utc(p.published, Utc); + let mut i = ItemBuilder::default(); + i.title(htmlescape::encode_minimal(&p.name)); + i.author(htmlescape::encode_minimal(&user.name)); + i.pub_date(htmlescape::encode_minimal(&dt.to_rfc2822())); + if p.url.is_some() { + i.link(p.url.unwrap()); + } + if p.body.is_some() { + i.content(p.body.unwrap()); + } + // TODO: any other fields? + // https://rust-syndication.github.io/rss/rss/struct.ItemBuilder.html + items.push(i.build().unwrap()); } - let channel = ChannelBuilder::default() - .title(htmlescape::encode_minimal(&site_view.name)) + let site_view = SiteView::read(&conn)?; + let mut channel_builder = ChannelBuilder::default(); + channel_builder.title(htmlescape::encode_minimal(&site_view.name)) .link(format!("https://{}", Settings::get().hostname)) - .description(htmlescape::encode_minimal(&site_view.description.unwrap())) - .pub_date("asd") - .items(items) - .build() - .unwrap(); + .items(items); + if site_view.description.is_some() { + channel_builder.description(htmlescape::encode_minimal(&site_view.description.unwrap())); + } + // TODO: any other fields? + // https://rust-syndication.github.io/rss/rss/struct.ChannelBuilder.html + let channel = channel_builder.build().unwrap(); channel.write_to(::std::io::sink()).unwrap(); - return HttpResponse::Ok() - .content_type("application/rss+xml") - .body(channel.to_string()); + return Ok(channel.to_string()); } \ No newline at end of file diff --git a/server/src/main.rs b/server/src/main.rs index d85f5ecae..ecda777e5 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -206,7 +206,7 @@ fn main() { "/.well-known/nodeinfo", web::get().to(nodeinfo::node_info_well_known), ) - .route("/feed.xml", web::get().to(feeds::get_feed)) + .route("/feeds/{type}/{name}.xml", web::get().to(feeds::get_feed)) // static resources .service(actix_files::Files::new("/static", front_end_dir())) })