Entry state update

This commit is contained in:
Greg Shuflin 2025-02-05 00:44:13 -08:00
parent ab5e187212
commit 70a13235ac
6 changed files with 113 additions and 2 deletions

View File

@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE feed_entries SET marked_read = ? WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "ad2e09903009082ca746a9dc75cb04831b016d17cc7ce32fa86681431071fef6"
}

View File

@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE feed_entries SET marked_read = NULL WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "c64e0927e594985ee8d2be7190c8f76fea57c4c815981673c92e709b17b9204b"
}

View File

@ -0,0 +1,20 @@
{
"db_name": "SQLite",
"query": "\n SELECT 1 as found FROM feed_entries e\n JOIN feeds f ON e.feed_id = f.feed_id\n WHERE e.id = ? AND f.user_id = ?\n ",
"describe": {
"columns": [
{
"name": "found",
"ordinal": 0,
"type_info": "Int"
}
],
"parameters": {
"Right": 2
},
"nullable": [
false
]
},
"hash": "ce12e0b02596a4045fb2cd91d566aa633109a65afcecc92564a785282e67e193"
}

View File

@ -1,6 +1,6 @@
use feed_rs;
use url::Url;
use tracing::{error, info};
use url::Url;
#[derive(Debug)]
pub struct FeedError;

View File

@ -160,6 +160,7 @@ fn rocket() -> _ {
feeds::list_feeds,
feeds::delete_feed,
poll::poll_feed,
poll::update_entry_state,
],
)
.mount("/static", FileServer::from("static"))

View File

@ -4,7 +4,7 @@ use chrono::{DateTime, Duration, Utc};
use feed_rs::model::Text;
use rocket::http::Status;
use rocket::serde::uuid::Uuid;
use rocket::serde::{self, json::Json, Serialize};
use rocket::serde::{self, json::Json, Deserialize, Serialize};
use rocket_db_pools::Connection;
use sqlx::{Acquire, SqliteConnection};
use tracing::{error, info};
@ -33,6 +33,12 @@ struct Entry {
link: Option<String>,
}
#[derive(Debug, Deserialize)]
#[serde(crate = "rocket::serde")]
pub struct EntryStateUpdate {
read: Option<bool>,
}
async fn update_entry_db(
entries: &Vec<Entry>,
feed_id: &str,
@ -231,3 +237,63 @@ pub async fn poll_feed(
Ok(Json(FeedPollResponse { count, entries }))
}
#[patch("/entries/<entry_id>/state", data = "<state>")]
pub async fn update_entry_state(
mut db: Connection<Db>,
entry_id: &str,
user: AuthenticatedUser,
state: Json<EntryStateUpdate>,
) -> Result<Status, Status> {
let state = state.into_inner();
let user_id = user.user_id.to_string();
// Verify the entry exists and belongs to a feed owned by this user
let exists = sqlx::query!(
r#"
SELECT 1 as found FROM feed_entries e
JOIN feeds f ON e.feed_id = f.feed_id
WHERE e.id = ? AND f.user_id = ?
"#,
entry_id,
user_id,
)
.fetch_optional(&mut **db)
.await
.map_err(|e| {
error!("Database error checking entry ownership: {}", e);
Status::InternalServerError
})?;
if exists.is_none() {
return Ok(Status::NotFound);
}
// Update read state if provided
if let Some(read) = state.read {
let now = Utc::now();
let result = if read {
sqlx::query!(
"UPDATE feed_entries SET marked_read = ? WHERE id = ?",
now,
entry_id
)
.execute(&mut **db)
.await
} else {
sqlx::query!(
"UPDATE feed_entries SET marked_read = NULL WHERE id = ?",
entry_id
)
.execute(&mut **db)
.await
};
if let Err(e) = result {
error!("Failed to update entry read state: {}", e);
return Ok(Status::InternalServerError);
}
}
Ok(Status::NoContent)
}