diff --git a/src/handlers/feeds.rs b/src/handlers/feeds.rs index d3f0289..3d540f6 100644 --- a/src/handlers/feeds.rs +++ b/src/handlers/feeds.rs @@ -1,5 +1,5 @@ use super::LAST_MODIFIED; -use crate::{app::State, templates}; +use crate::{app::State, post::Post, templates}; use lazy_static::lazy_static; use prometheus::{opts, register_int_counter_vec, IntCounterVec}; use std::{io, sync::Arc}; @@ -22,6 +22,14 @@ pub async fn jsonfeed(state: Arc, since: Option) -> Result) -> Result { + let state = state.clone(); + let everything = state.everything.clone(); + let p: &Post = everything.iter().next().unwrap(); + Ok(warp::reply::json(&p.new_post)) +} + #[derive(Debug)] pub enum RenderError { Build(warp::http::Error), diff --git a/src/main.rs b/src/main.rs index cac19cf..0576f97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -44,6 +44,9 @@ async fn main() -> Result<()> { ); let healthcheck = warp::get().and(warp::path(".within").and(warp::path("health")).map(|| "OK")); + let new_post = warp::path!(".within" / "website.within.xesite" / "new_post") + .and(with_state(state.clone())) + .and_then(handlers::feeds::new_post); let base = warp::path!("blog" / ..); let blog_index = base @@ -164,7 +167,7 @@ async fn main() -> Result<()> { .or(patrons) .or(jsonfeed.or(atom.or(sitemap)).or(rss)) .or(favicon.or(robots).or(sw)) - .or(contact) + .or(contact.or(new_post)) .map(|reply| { warp::reply::with_header( reply, diff --git a/src/post/mod.rs b/src/post/mod.rs index b5303a8..4c54404 100644 --- a/src/post/mod.rs +++ b/src/post/mod.rs @@ -1,6 +1,7 @@ use chrono::prelude::*; use color_eyre::eyre::{eyre, Result, WrapErr}; use glob::glob; +use serde::Serialize; use std::{cmp::Ordering, path::PathBuf}; use tokio::fs; @@ -13,6 +14,15 @@ pub struct Post { pub body_html: String, pub date: DateTime, pub mentions: Vec, + pub new_post: NewPost, +} + +/// Used with the Android app to show information in a widget. +#[derive(Eq, PartialEq, Debug, Clone, Serialize)] +pub struct NewPost { + pub title: String, + pub summary: String, + pub link: String, } impl Into for Post { @@ -70,6 +80,33 @@ impl Post { } } +fn trim(string: &str) -> String { + let mut buf = String::new(); + let mut capturing = false; + + for line in string.lines() { + if line.starts_with("#") { + continue; + } + + if line == "" { + if capturing && buf.len() > 260 { + break; + } else { + capturing = true; + continue; + } + } + + if capturing { + buf.push_str(" "); + buf.push_str(line); + } + } + + buf +} + async fn read_post(dir: &str, fname: PathBuf) -> Result { let body = fs::read_to_string(fname.clone()) .await @@ -96,12 +133,19 @@ async fn read_post(dir: &str, fname: PathBuf) -> Result { Err(_) => vec![], }; + let new_post = NewPost { + title: front_matter.title.clone(), + summary: trim(body).to_string(), + link: format!("https://christine.website/{}", link), + }; + Ok(Post { front_matter, link, body_html, date, mentions, + new_post, }) }