Compare commits

...

2 commits

Author SHA1 Message Date
24374a266d preparing to handle media 2025-09-07 04:03:59 -04:00
1934888ee9 make cargo happy 2025-09-07 04:03:38 -04:00
3 changed files with 94 additions and 33 deletions

110
src/db.rs
View file

@ -24,7 +24,7 @@ const FEEDS_TABLE_CREATE: &str = "CREATE TABLE IF NOT EXISTS 'feeds' (
'feedID' INTEGER NOT NULL, 'feedID' INTEGER NOT NULL,
'title' TEXT NOT NULL, 'title' TEXT NOT NULL,
'description' TEXT, 'description' TEXT,
'icon' BLOB, 'icon' text,
'url' text not null unique, 'url' text not null unique,
'subscribed' INTEGER NOT NULL default 0, 'subscribed' INTEGER NOT NULL default 0,
'last_updated' TEXT , 'last_updated' TEXT ,
@ -40,7 +40,7 @@ const ITEMS_TABLE_CREATE: &str = "CREATE TABLE IF NOT EXISTS 'items' (
'itemID' INTEGER NOT NULL, 'itemID' INTEGER NOT NULL,
'feedID' INTEGER NOT NULL, 'feedID' INTEGER NOT NULL,
'title' TEXT NOT NULL, 'title' TEXT NOT NULL,
'icon' BLOB, 'icon' text,
'url' text not null unique on conflict replace, 'url' text not null unique on conflict replace,
'description' TEXT, 'description' TEXT,
'content' TEXT, 'content' TEXT,
@ -88,32 +88,71 @@ pub fn initialize() {
println!("Database Initialized.") println!("Database Initialized.")
} }
pub fn add_feed(url: &str) -> Option<usize> { pub fn get_feed_id_by_url(url: &str) -> Option<usize> {
let conn = get_db(); let conn = get_db();
let feed = load_rss(url).unwrap();
let new_feed = feed.clone();
let time = Utc::now().to_rfc2822();
match conn.execute(
"insert into feeds(title,url,description,last_updated) values(?1,?2,?3,?4)",
[feed.title, url.to_string(), feed.description, time],
) {
Ok(_) => {}
Err(e) => {
println!("Couldn't add feed:{}\nError:{}", url, e);
return None;
}
}
let mut stmt = conn let mut stmt = conn
.prepare("select feedID from feeds where url=?1") .prepare("select feedID from feeds where url=?1")
.unwrap(); .unwrap();
let id: usize = stmt.query_row([url], |row| row.get(0)).unwrap(); match stmt.query_row([url], |row| row.get(0)) {
//need to get the feed_id from the DB and then make sure items are mapped to feed Ok(i) => Some(i),
store_items(new_feed, id); Err(_) => None,
Some(id) }
}
pub fn add_feed(url: &str) -> Option<usize> {
let feed = load_rss(url).unwrap();
let time = Utc::now().to_rfc2822();
let image = if let Some(i) = feed.image() {
i.url().to_owned()
} else {
"".to_owned()
};
let mut id = get_feed_id_by_url(url);
let conn = get_db();
match id {
Some(i) => {
match conn.execute(
"update feeds set last_updated=?1,icon=?3,title=?4,description=?5 where feedID = ?2;",
[time,i.to_string(),image,feed.title.to_owned(),feed.description.to_owned()]
){
Ok(_) => {println!("Updated feed.");}
Err(e) => {println!("Error updating feed.\n{}",e);}
}
}
None => {
match conn.execute(
"insert into feeds(title,url,icon,description,last_updated) values(?1,?2,?3,?4,?5)",
[
feed.title.to_owned(),
url.to_string(),
image,
feed.description.to_owned(),
time,
],
) {
Ok(_) => {
id = get_feed_id_by_url(url)
}
Err(e) => {
println!("Couldn't add feed:{}\nError:{}", url, e);
return None;
}
}
;
}
}
match id {
Some(i) => {
store_items(feed, i);
Some(i)
}
None => {None}
}
} }
fn remove_items(feed_id: usize) -> Result<usize>{ fn remove_items(feed_id: usize) -> Result<usize> {
let conn = get_db(); let conn = get_db();
conn.execute("delete from items where feedID = ?1", [feed_id]) conn.execute("delete from items where feedID = ?1", [feed_id])
} }
@ -121,22 +160,28 @@ fn remove_items(feed_id: usize) -> Result<usize>{
pub fn remove_feed(feed_id: usize) { pub fn remove_feed(feed_id: usize) {
let _ = remove_items(feed_id); let _ = remove_items(feed_id);
let conn = get_db(); let conn = get_db();
match conn.execute("delete from feeds where feedID = ?1",[feed_id]) { match conn.execute("delete from feeds where feedID = ?1", [feed_id]) {
Ok(_) => {} Ok(_) => {}
Err(e) => { Err(e) => {
println!("Failed to delete feed by id: {}\nError:{}",feed_id,e); println!("Failed to delete feed by id: {}\nError:{}", feed_id, e);
} }
} }
} }
pub fn store_items(feed: rss::Channel, feed_id: usize) { pub fn store_items(feed: rss::Channel, feed_id: usize) {
let conn = Connection::open(get_db_path()).unwrap(); let conn = Connection::open(get_db_path()).unwrap();
feed.items.into_iter().for_each(|i: rss::Item| { feed.items.into_iter().for_each(|i: rss::Item| {
let t = i.clone(); let t = i.clone();
conn.execute( let image = match i.itunes_ext() {
"insert into items(url,title,description,content,feedID,date,media) Some(ext) => match ext.image() {
values(?1,?2,?3,?4,?5,?6,?7)", Some(img) => img.to_owned(),
None => "".to_owned(),
},
None => "".to_owned(),
};
match conn.execute(
"insert into items(url,title,description,content,feedID,date,media,icon)
values(?1,?2,?3,?4,?5,?6,?7,?8)",
[ [
i.link, i.link,
i.title, i.title,
@ -150,9 +195,14 @@ pub fn store_items(feed: rss::Channel, feed_id: usize) {
None => Some("".to_owned()), None => Some("".to_owned()),
} }
}, },
Some(image),
], ],
) ) {
.ok(); Ok(_) => {}
Err(e) => {
println!("Failed to add item.\n{}", e)
}
};
}); });
conn.close().unwrap(); conn.close().unwrap();
} }

View file

@ -11,3 +11,14 @@ pub fn get_data_directory() -> std::path::PathBuf {
}; };
dirs.data_dir().to_owned() dirs.data_dir().to_owned()
} }
pub fn get_cache_directory() -> std::path::PathBuf {
let dirs = ProjectDirs::from("rocks","gabe","RSSCar").expect("Failed to get paths");
match fs::create_dir(dirs.cache_dir()){
Ok(_) => {}
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => {}
Err(_) => {println!("Error creating cache directory")}
};
dirs.config_dir().to_owned()
}

View file

@ -54,7 +54,7 @@ pub fn list_items(feed_id: usize) -> iced::widget::Column<'static,Message> {
.padding(15) .padding(15)
} }
pub fn content_area(content: &Vec<Content>) -> iced::widget::Container<Message> { pub fn content_area(content: &'_ Vec<Content>) -> iced::widget::Container<'_, Message> {
let mut children: Vec<Element<Message>> = Vec::new(); let mut children: Vec<Element<Message>> = Vec::new();
for c in content { for c in content {
match c { match c {
@ -81,7 +81,7 @@ pub fn content_area(content: &Vec<Content>) -> iced::widget::Container<Message>
} }
pub fn media_view(state: &ui::State) -> Element<Message> { pub fn media_view(state: &'_ ui::State) -> Element<'_, Message> {
match state.current_item.clone().unwrap().media { match state.current_item.clone().unwrap().media {
Some(m) => { Some(m) => {
if m.len() > 0{ if m.len() > 0{
@ -98,7 +98,7 @@ pub fn media_view(state: &ui::State) -> Element<Message> {
} }
} }
pub fn content_view(state: &ui::State) -> iced::widget::Scrollable<Message> { pub fn content_view(state: &'_ ui::State) -> iced::widget::Scrollable<'_, Message> {
let item = state.current_item.clone().unwrap(); let item = state.current_item.clone().unwrap();
scrollable( scrollable(