diff --git a/server/src/feeds.rs b/server/src/feeds.rs index e0a1dd3..8e89e39 100644 --- a/server/src/feeds.rs +++ b/server/src/feeds.rs @@ -3,33 +3,43 @@ extern crate htmlescape; use super::*; use crate::Settings; -use crate::db::{establish_connection, ListingType, SortType, Crud}; +use crate::db::{establish_connection, ListingType, SortType}; use crate::db::community_view::SiteView; use crate::db::post_view::PostView; use crate::db::user::User_; use crate::db::community::Community; -use actix_web::{HttpResponse, web, Result}; +use actix_web::{HttpResponse, web, Result, HttpRequest}; use actix_web::body::Body; use rss::{ChannelBuilder, Item, ItemBuilder}; use diesel::result::Error; +use std::str::FromStr; +use self::rss::Guid; -pub fn get_feed(info: web::Path<(char, String)>) -> HttpResponse { - return match get_feed_internal(info) { + +pub fn get_feed(path: web::Path<(char, String)>, req: HttpRequest) -> HttpResponse { + let sort_query = match req.match_info().query("sort").parse() { + Ok(param) => param, + Err(_) => SortType::Hot.to_string(), + }; + let sort_type = match SortType::from_str(&sort_query) { + Ok(sort) => sort, + Err(_) => return HttpResponse::BadRequest().finish(), + }; + + return match get_feed_internal(path, &sort_type) { 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(), + Err(_) => HttpResponse::InternalServerError().finish(), } - } -fn get_feed_internal(info: web::Path<(char, String)>) -> Result { +fn get_feed_internal(info: web::Path<(char, String)>, sort_type: &SortType) -> Result { let conn = establish_connection(); 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), @@ -38,7 +48,7 @@ fn get_feed_internal(info: web::Path<(char, String)>) -> Result { let post = PostView::list(&conn, ListingType::All, - &SortType::New, + sort_type, community_id, creator_id, None, @@ -52,21 +62,25 @@ fn get_feed_internal(info: web::Path<(char, String)>) -> Result { let mut items: Vec = Vec::new(); for p in post { - // 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())); + + // TODO: there is probably a better way to get the lemmy post url + let post_url = format!("https://{}/post/{}", Settings::get().hostname, p.id); + let mut guid = Guid::default(); + guid.set_permalink(true); + guid.set_value(&post_url); + i.guid(guid); + i.comments(post_url); + 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()); } @@ -78,8 +92,6 @@ fn get_feed_internal(info: web::Path<(char, String)>) -> Result { 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();