90 lines
2.2 KiB
Rust
90 lines
2.2 KiB
Rust
use std::collections::HashMap;
|
|
use std::fmt;
|
|
|
|
use askama::Template;
|
|
use futures::future::join_all;
|
|
use rss::{GuidBuilder, Item, ItemBuilder};
|
|
use serde::Deserialize;
|
|
use time::format_description::well_known::iso8601::FormattedComponents;
|
|
use time::format_description::well_known::{iso8601, Iso8601};
|
|
use time::Date;
|
|
|
|
use crate::scrapers::page_url;
|
|
use crate::{hash, scrapers};
|
|
|
|
use self::template::FeedEntryTemplate;
|
|
|
|
pub mod route;
|
|
pub mod template;
|
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
pub struct Feed {
|
|
pub title: String,
|
|
pub url: String,
|
|
pub id: String,
|
|
}
|
|
|
|
impl fmt::Display for Feed {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
write!(f, "{} ({})", self.title, self.url)
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, Deserialize)]
|
|
pub struct Footprint {
|
|
pub title: String,
|
|
pub text: String,
|
|
pub url: String,
|
|
pub date: Date,
|
|
pub page: u8,
|
|
pub images: Vec<String>,
|
|
}
|
|
|
|
const ISO8601_DATE: u128 = iso8601::Config::DEFAULT
|
|
.set_formatted_components(FormattedComponents::Date)
|
|
.encode();
|
|
|
|
impl Footprint {
|
|
pub fn into_rss_item(self, root_url: &str) -> Item {
|
|
let text = if String::is_empty(&self.text) {
|
|
"No text"
|
|
} else {
|
|
&self.text
|
|
};
|
|
|
|
let page_url = page_url(root_url, self.page);
|
|
|
|
let template = FeedEntryTemplate {
|
|
text: text.to_string(),
|
|
page_url,
|
|
page: self.page,
|
|
images: self.images,
|
|
};
|
|
let content = template.render().ok();
|
|
|
|
ItemBuilder::default()
|
|
.title(Some(self.title))
|
|
.pub_date(self.date.format(&Iso8601::<ISO8601_DATE>).ok())
|
|
.link(Some(self.url.clone()))
|
|
.content(content)
|
|
.guid(Some(GuidBuilder::default().value(self.url).build()))
|
|
.build()
|
|
}
|
|
}
|
|
|
|
pub async fn enrich_feeds(feed_urls: Vec<String>) -> HashMap<String, Feed> {
|
|
let feeds = join_all(feed_urls.iter().map(|feed_url| async {
|
|
let title = scrapers::feed_title(feed_url).await.unwrap();
|
|
let id = hash::fnv_str(feed_url);
|
|
|
|
Feed {
|
|
title,
|
|
url: feed_url.clone(),
|
|
id,
|
|
}
|
|
}))
|
|
.await;
|
|
|
|
feeds.iter().map(|x| (x.id.clone(), x.clone())).collect()
|
|
}
|