xesite/lib/jsonfeed/src/builder.rs

205 lines
5.2 KiB
Rust
Raw Normal View History

Rewrite site backend in Rust (#178) * add shell.nix changes for Rust #176 * set up base crate layout * add first set of dependencies * start adding basic app modules * start html templates * serve index page * add contact and feeds pages * add resume rendering support * resume cleanups * get signalboost page working * rewrite config to be in dhall * more work * basic generic post loading * more tests * initial blog index support * fix routing? * render blogposts * X-Clacks-Overhead * split blog handlers into blog.rs * gallery index * gallery posts * fix hashtags * remove instantpage (it messes up the metrics) * talk support + prometheus * Create rust.yml * Update rust.yml * Update codeql-analysis.yml * add jsonfeed library * jsonfeed support * rss/atom * go mod tidy * atom: add posted date * rss: add publishing date * nix: build rust program * rip out go code * rip out go templates * prepare for serving in docker * create kubernetes deployment * create automagic deployment * build docker images on non-master * more fixes * fix timestamps * fix RSS/Atom/JSONFeed validation errors * add go vanity import redirecting * templates/header: remove this * atom feed: fixes * fix? * fix?? * fix rust tests * Update rust.yml * automatically show snow during the winter * fix dates * show commit link in footer * sitemap support * fix compiler warning * start basic patreon client * integrate kankyo * fix patreon client * add patrons page * remove this * handle patron errors better * fix build * clean up deploy * sort envvars for deploy * remove deps.nix * shell.nix: remove go * update README * fix envvars for tests * nice * blog: add rewrite in rust post * blog/site-update: more words
2020-07-16 19:32:30 +00:00
use std::default::Default;
use errors::*;
use feed::{Feed, Author, Attachment};
use item::{Content, Item};
/// Feed Builder
///
/// This is used to programmatically build up a Feed object,
/// which can be serialized later into a JSON string
pub struct Builder(Feed);
impl Builder {
pub fn new() -> Builder {
Builder(Feed::default())
}
pub fn title<I: Into<String>>(mut self, t: I) -> Builder {
self.0.title = t.into();
self
}
pub fn home_page_url<I: Into<String>>(mut self, url: I) -> Builder {
self.0.home_page_url = Some(url.into());
self
}
pub fn feed_url<I: Into<String>>(mut self, url: I) -> Builder {
self.0.feed_url = Some(url.into());
self
}
pub fn description<I: Into<String>>(mut self, desc: I) -> Builder {
self.0.description = Some(desc.into());
self
}
pub fn user_comment<I: Into<String>>(mut self, cmt: I) -> Builder {
self.0.user_comment = Some(cmt.into());
self
}
pub fn next_url<I: Into<String>>(mut self, url: I) -> Builder {
self.0.next_url = Some(url.into());
self
}
pub fn icon<I: Into<String>>(mut self, url: I) -> Builder {
self.0.icon = Some(url.into());
self
}
pub fn favicon<I: Into<String>>(mut self, url: I) -> Builder {
self.0.favicon = Some(url.into());
self
}
pub fn author(mut self, author: Author) -> Builder {
self.0.author = Some(author);
self
}
pub fn expired(mut self) -> Builder {
self.0.expired = Some(true);
self
}
pub fn item(mut self, item: Item) -> Builder {
self.0.items.push(item);
self
}
pub fn build(self) -> Feed {
self.0
}
}
/// Builder object for an item in a feed
pub struct ItemBuilder {
pub id: Option<String>,
pub url: Option<String>,
pub external_url: Option<String>,
pub title: Option<String>,
pub content: Option<Content>,
pub summary: Option<String>,
pub image: Option<String>,
pub banner_image: Option<String>,
pub date_published: Option<String>,
pub date_modified: Option<String>,
pub author: Option<Author>,
pub tags: Option<Vec<String>>,
pub attachments: Option<Vec<Attachment>>,
}
impl ItemBuilder {
pub fn new() -> ItemBuilder {
ItemBuilder {
id: None,
url: None,
external_url: None,
title: None,
content: None,
summary: None,
image: None,
banner_image: None,
date_published: None,
date_modified: None,
author: None,
tags: None,
attachments: None,
}
}
pub fn title<I: Into<String>>(mut self, i: I) -> ItemBuilder {
self.title = Some(i.into());
self
}
pub fn image<I: Into<String>>(mut self, i: I) -> ItemBuilder {
self.image = Some(i.into());
self
}
pub fn id<I: Into<String>>(mut self, i: I) -> ItemBuilder {
self.id = Some(i.into());
self
}
pub fn url<I: Into<String>>(mut self, i: I) -> ItemBuilder {
self.url = Some(i.into());
self
}
pub fn external_url<I: Into<String>>(mut self, i: I) -> ItemBuilder {
self.external_url = Some(i.into());
self
}
pub fn date_modified<I: Into<String>>(mut self, i: I) -> ItemBuilder {
self.date_modified = Some(i.into());
self
}
pub fn date_published<I: Into<String>>(mut self, i: I) -> ItemBuilder {
self.date_published = Some(i.into());
self
}
pub fn tags(mut self, tags: Vec<String>) -> ItemBuilder {
self.tags = Some(tags);
self
}
pub fn author(mut self, who: Author) -> ItemBuilder {
self.author = Some(who);
self
}
pub fn content_html<I: Into<String>>(mut self, i: I) -> ItemBuilder {
match self.content {
Some(Content::Text(t)) => {
self.content = Some(Content::Both(i.into(), t));
},
_ => {
self.content = Some(Content::Html(i.into()));
}
}
self
}
pub fn content_text<I: Into<String>>(mut self, i: I) -> ItemBuilder {
match self.content {
Some(Content::Html(s)) => {
self.content = Some(Content::Both(s, i.into()));
},
_ => {
self.content = Some(Content::Text(i.into()));
},
}
self
}
pub fn build(self) -> Result<Item> {
if self.id.is_none() || self.content.is_none() {
return Err("missing field 'id' or 'content_*'".into());
}
Ok(Item {
id: self.id.unwrap(),
url: self.url,
external_url: self.external_url,
title: self.title,
content: self.content.unwrap(),
summary: self.summary,
image: self.image,
banner_image: self.banner_image,
date_published: self.date_published,
date_modified: self.date_modified,
author: self.author,
tags: self.tags,
attachments: self.attachments
})
}
}