From e73c695acdbd87d1bb58ceda123060d1ac35d9c7 Mon Sep 17 00:00:00 2001 From: Joe Date: Mon, 22 Dec 2025 22:15:16 -0800 Subject: [PATCH] add removal, limit posts, have better message framing --- src/lib.rs | 23 ++++++++++++++++++----- src/server.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 365e510..b971fe0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -171,6 +171,14 @@ impl BlogdorTheAggregator { feed_id, received, .. } = posts.last().unwrap(); let mut success = true; + let Ok(user) = sqlx::query!("select added_by from feeds where id = ?", feed_id) + .fetch_one(&self.db) + .await + else { + tracing::error!("could not get user from db"); + return; + }; + let user = user.added_by; for post in posts.iter() { let body = post.body.as_deref().unwrap_or("Blogdor Says: NO BODY!"); @@ -180,17 +188,21 @@ impl BlogdorTheAggregator { "..." }; + let url = post.post_url.as_str(); + let title = post.title.as_str(); + + let header = format!("New post in a feed added by @**|{user}**: {title}"); + let content = format!( - "{body}{tail}\n\n---\noriginally published on [{}]({})", + "{header}\n---\n{body}{tail}\n\n---\noriginally posted to {url}, on {}", post.published.format("%B %e, %Y"), - post.post_url ); let msg = ZulipMessage { to: self.channel_id, typ: "stream", content, - topic: Some(&post.title), + topic: Some(title), }; match self.send_zulip_message(&msg).await { @@ -267,9 +279,10 @@ async fn check_feed( .bytes() .await .map_err(|e| format!("could not get bytes from response from {url}, got {e}"))?; - let feed = + let mut feed = parse(feed.reader()).map_err(|e| format!("could not parse feed from {url}, got {e}"))?; - for post in feed.entries { + feed.entries.sort_by_key(|e| e.published); + for post in feed.entries.into_iter().rev().take(5) { let last_year = now - ONE_YEAR; if post.published.unwrap_or(last_year) > last_fetched { let entry = FeedEntry { diff --git a/src/server.rs b/src/server.rs index 907b39d..0b924c7 100644 --- a/src/server.rs +++ b/src/server.rs @@ -115,7 +115,14 @@ async fn handle_manage_feed( resp.insert("content", format!("Blogdor Says: OH NO! {e}")); } }, - Action::Remove => return StatusCode::UNAVAILABLE_FOR_LEGAL_REASONS.into_response(), + Action::Remove => match remove_feed(&state.db, sender_id, command.feed).await { + Ok(_) => { + resp.insert("content", "Blogdor Says: BURNINATED!".to_string()); + } + Err(e) => { + resp.insert("content", e); + } + }, Action::Help => { resp.insert("content", "DM or `@blogdor's manager` with `add `, `remove `, or `help` to get this message (duh).".to_string()); } @@ -127,8 +134,46 @@ async fn handle_manage_feed( } } +async fn remove_feed(db: &SqlitePool, user: u32, feed: &str) -> Result<(), String> { + sqlx::query!( + "update feeds set active = false where url = ? and added_by = ?", + feed, + user + ) + .execute(db) + .await + .map_err(|e| { + tracing::error!("could not set {feed} inactive by {user}, got {e}"); + "sorry buddy, Blogdor couldn't do that".to_string() + })?; + sqlx::query!( + "select * from feeds where added_by = ? and active = false", + user + ) + .fetch_one(db) + .await + .map_err(|e| { + tracing::error!("could not set {feed} inactive by {user}, got {e}"); + "sorry buddy, Blogdor couldn't do that".to_string() + })?; + Ok(()) +} + async fn add_feed(db: &SqlitePool, user: u32, feed: &str) -> Result<(), String> { add_user(db, user).await?; + if sqlx::query!( + "update feeds set active = true where url = ? and added_by = ?", + feed, + user + ) + .execute(db) + .await + .is_err() + { + tracing::debug!("{feed} is new, adding new row"); + } else { + return Ok(()); + } sqlx::query!( "insert into feeds (url, added_by, active) values (?, ?, true)", @@ -167,10 +212,6 @@ async fn add_user(db: &SqlitePool, user: u32) -> Result<(), String> { Ok(()) } -async fn _remove_feed() -> Result<(), String> { - todo!() -} - async fn graceful_shutdown(cancel: CancellationToken) { use tokio::signal; let ctrl_c = async {