added timestamp for feed items

master
Mathias Rothenhaeusler 2023-10-24 19:19:47 +02:00
parent ee80cbd53b
commit e4a65416c7
11 changed files with 128 additions and 26 deletions

85
Cargo.lock generated
View File

@ -248,6 +248,21 @@ dependencies = [
"alloc-no-stdlib", "alloc-no-stdlib",
] ]
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "atom_syndication" name = "atom_syndication"
version = "0.12.2" version = "0.12.2"
@ -414,11 +429,17 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.28" version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95ed24df0632f708f5f6d8082675bef2596f7084dee3dd55f632290bf35bfe0f" checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [ dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits", "num-traits",
"serde",
"wasm-bindgen",
"windows-targets",
] ]
[[package]] [[package]]
@ -556,9 +577,12 @@ dependencies = [
[[package]] [[package]]
name = "deranged" name = "deranged"
version = "0.3.8" version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2696e8a945f658fd14dc3b87242e6b80cd0f36ff04ea560fa39082368847946" checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3"
dependencies = [
"powerfmt",
]
[[package]] [[package]]
name = "derive_builder" name = "derive_builder"
@ -612,6 +636,7 @@ checksum = "d98235fdc2f355d330a8244184ab6b4b33c28679c0b4158f63138e51d6cf7e88"
dependencies = [ dependencies = [
"bitflags 2.4.0", "bitflags 2.4.0",
"byteorder", "byteorder",
"chrono",
"diesel_derives", "diesel_derives",
"itoa 1.0.9", "itoa 1.0.9",
"pq-sys", "pq-sys",
@ -1069,6 +1094,29 @@ dependencies = [
"tokio-native-tls", "tokio-native-tls",
] ]
[[package]]
name = "iana-time-zone"
version = "0.1.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows-core",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "ident_case" name = "ident_case"
version = "1.0.1" version = "1.0.1"
@ -1531,6 +1579,12 @@ version = "0.3.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "ppv-lite86" name = "ppv-lite86"
version = "0.2.17" version = "0.2.17"
@ -1763,6 +1817,7 @@ dependencies = [
"actix-service", "actix-service",
"actix-web", "actix-web",
"bcrypt", "bcrypt",
"chrono",
"diesel", "diesel",
"dotenv", "dotenv",
"env_logger", "env_logger",
@ -2127,12 +2182,13 @@ checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c"
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.28" version = "0.3.30"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17f6bb557fd245c28e6411aa56b6403c689ad95061f50e4be16c274e70a17e48" checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5"
dependencies = [ dependencies = [
"deranged", "deranged",
"itoa 1.0.9", "itoa 1.0.9",
"powerfmt",
"serde", "serde",
"time-core", "time-core",
"time-macros", "time-macros",
@ -2140,15 +2196,15 @@ dependencies = [
[[package]] [[package]]
name = "time-core" name = "time-core"
version = "0.1.1" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.14" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a942f44339478ef67935ab2bbaec2fb0322496cf3cbe84b261e06ac3814c572" checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20"
dependencies = [ dependencies = [
"time-core", "time-core",
] ]
@ -2455,6 +2511,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-core"
version = "0.51.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64"
dependencies = [
"windows-targets",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.48.0" version = "0.48.0"

View File

@ -15,7 +15,7 @@ futures = "0.3.24"
serde = { version = "1.0.144", features = ["alloc", "derive", "serde_derive"] } serde = { version = "1.0.144", features = ["alloc", "derive", "serde_derive"] }
serde_derive = "1.0.145" serde_derive = "1.0.145"
actix-service = "2.0.2" actix-service = "2.0.2"
diesel = { version = "2.0.2", features = ["postgres"]} diesel = { version = "2.0.2", features = ["postgres", "chrono"] }
dotenv = "0.15.0" dotenv = "0.15.0"
bcrypt = "0.13.0" bcrypt = "0.13.0"
uuid = {version = "1.2.1", features=["serde", "v4"]} uuid = {version = "1.2.1", features=["serde", "v4"]}
@ -26,6 +26,7 @@ log = "0.4.17"
env_logger = "0.9.3" env_logger = "0.9.3"
scraper = "0.14.0" scraper = "0.14.0"
actix-cors = "0.6.4" actix-cors = "0.6.4"
chrono = { version = "0.4.31", features = ["serde"] }
[dependencies.serde_json] [dependencies.serde_json]
version = "1.0.86" version = "1.0.86"

View File

@ -0,0 +1,3 @@
-- This file should undo anything in `up.sql`
ALTER TABLE feed_item
DROP COLUMN created_ts;

View File

@ -0,0 +1,6 @@
-- Your SQL goes here
ALTER TABLE feed_item
ADD COLUMN created_ts TIMESTAMP;
ALTER TABLE feed_item
ALTER COLUMN created_ts SET DEFAULT now();

View File

@ -1,8 +1,5 @@
// extern crate bcrypt; use chrono::NaiveDateTime;
// use bcrypt::{hash, DEFAULT_COST};
use diesel::Insertable; use diesel::Insertable;
// use uuid::Uuid;
use crate::schema::feed_item; use crate::schema::feed_item;
@ -13,15 +10,23 @@ pub struct NewFeedItem {
pub content: String, pub content: String,
pub title: String, pub title: String,
pub url: String, pub url: String,
pub created_ts: Option<NaiveDateTime>,
} }
impl NewFeedItem { impl NewFeedItem {
pub fn new(feed_id: i32, content: String, title: String, url: String) -> Self { pub fn new(
feed_id: i32,
content: String,
title: String,
url: String,
created_ts: Option<NaiveDateTime>,
) -> Self {
Self { Self {
feed_id, feed_id,
content, content,
title, title,
url, url,
created_ts,
} }
} }
} }

View File

@ -1,8 +1,8 @@
use crate::models::feed::rss_feed::Feed; use crate::models::feed::rss_feed::Feed;
use diesel::{Associations, Identifiable, Queryable};
use crate::schema::feed_item; use crate::schema::feed_item;
#[derive(Clone, Queryable, Identifiable, Associations)] use chrono::NaiveDateTime;
use diesel::{Associations, Identifiable, Queryable};
#[derive(Clone, Identifiable, Queryable, Associations)]
#[diesel(belongs_to(Feed))] #[diesel(belongs_to(Feed))]
#[diesel(table_name=feed_item)] #[diesel(table_name=feed_item)]
pub struct FeedItem { pub struct FeedItem {
@ -12,6 +12,7 @@ pub struct FeedItem {
pub read: bool, pub read: bool,
pub title: String, pub title: String,
pub url: String, pub url: String,
pub created_ts: Option<NaiveDateTime>,
} }
impl FeedItem { impl FeedItem {
@ -22,6 +23,7 @@ impl FeedItem {
url: String, url: String,
content: String, content: String,
read: bool, read: bool,
created_ts: Option<NaiveDateTime>,
) -> Self { ) -> Self {
Self { Self {
id, id,
@ -30,6 +32,7 @@ impl FeedItem {
url, url,
content, content,
read, read,
created_ts,
} }
} }
} }

View File

@ -10,6 +10,7 @@ use crate::{
schema::feed_item, schema::feed_item,
}; };
use actix_web::{web, HttpRequest, Responder}; use actix_web::{web, HttpRequest, Responder};
use chrono::Local;
use diesel::prelude::*; use diesel::prelude::*;
use super::structs::article::Article; use super::structs::article::Article;
@ -41,10 +42,17 @@ pub async fn get(path: web::Path<JsonUser>, req: HttpRequest) -> impl Responder
let article_list: Vec<Article> = existing_item let article_list: Vec<Article> = existing_item
.into_iter() .into_iter()
.map(|feed_item: FeedItem| Article { .map(|feed_item: FeedItem| {
let time: String = match feed_item.created_ts {
Some(r) => r.to_string(),
None => Local::now().naive_local().to_string(),
};
Article {
title: feed_item.title, title: feed_item.title,
content: feed_item.content, content: feed_item.content,
url: feed_item.url, url: feed_item.url,
timestamp: time,
}
}) })
.collect(); .collect();

View File

@ -5,6 +5,7 @@ pub struct Article {
pub title: String, pub title: String,
pub content: String, pub content: String,
pub url: String, pub url: String,
pub timestamp: String,
} }
// impl Article { // impl Article {

View File

@ -12,13 +12,14 @@ use crate::{
}, },
}; };
use actix_web::{web, HttpRequest, HttpResponse, Responder}; use actix_web::{web, HttpRequest, HttpResponse, Responder};
use chrono::{Local, NaiveDateTime};
use diesel::prelude::*; use diesel::prelude::*;
use rss::Item; use rss::Item;
use scraper::{Html, Selector}; use scraper::{Html, Selector};
fn create_feed_item(item: Item, feed: &Feed, connection: &mut PgConnection) { fn create_feed_item(item: Item, feed: &Feed, connection: &mut PgConnection) {
let item_title = item.title.unwrap(); let item_title = item.title.clone().unwrap();
let frag = Html::parse_fragment(&item.content.unwrap()); let frag = Html::parse_fragment(&item.content.clone().unwrap());
let mut content = "".to_string(); let mut content = "".to_string();
let frag_clone = frag.clone(); let frag_clone = frag.clone();
frag.tree.into_iter().for_each(|node| { frag.tree.into_iter().for_each(|node| {
@ -40,13 +41,20 @@ fn create_feed_item(item: Item, feed: &Feed, connection: &mut PgConnection) {
.filter(title.eq(&item_title)) .filter(title.eq(&item_title))
.load(connection) .load(connection)
.unwrap(); .unwrap();
// todo;
if existing_item.is_empty() { if existing_item.is_empty() {
log::info!("{:?}", item.pub_date());
let mut time: NaiveDateTime = Local::now().naive_local();
if item.pub_date().is_some() {
let format_string = "%a, %d %b %Y %H:%M:%S %z";
time = NaiveDateTime::parse_from_str(item.pub_date().unwrap(), format_string).unwrap();
}
let new_feed_item = NewFeedItem::new( let new_feed_item = NewFeedItem::new(
feed.id, feed.id,
content.clone(), content.clone(),
item_title.clone(), item_title.clone(),
item.link.unwrap(), item.link.unwrap(),
Some(time),
); );
let insert_result = diesel::insert_into(feed_item::table) let insert_result = diesel::insert_into(feed_item::table)
.values(&new_feed_item) .values(&new_feed_item)

View File

@ -17,6 +17,7 @@ diesel::table! {
read -> Bool, read -> Bool,
title -> Varchar, title -> Varchar,
url -> Varchar, url -> Varchar,
created_ts -> Nullable<Timestamp>,
} }
} }

View File

@ -81,6 +81,7 @@ async function sync() {
if (response.status == 200) { if (response.status == 200) {
showMessageForXSeconds('Sync successful.', 5) showMessageForXSeconds('Sync successful.', 5)
} }
fetchData();
} catch (error) { } catch (error) {
console.error('Error sync', error) console.error('Error sync', error)
showMessageForXSeconds(error, 5) showMessageForXSeconds(error, 5)