From b1d938acbaebd66636ccd3193aa22504aded33f7 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Sun, 13 Oct 2024 15:42:23 -0500 Subject: [PATCH 01/10] make service_model public --- src/rust/core/service_items.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/rust/core/service_items.rs b/src/rust/core/service_items.rs index 8224aff..222f2d6 100644 --- a/src/rust/core/service_items.rs +++ b/src/rust/core/service_items.rs @@ -15,7 +15,7 @@ pub struct ServiceItem { } #[derive(Debug, Default, PartialEq)] -struct ServiceItemModel { +pub struct ServiceItemModel { items: Vec, } From 6fe0bf8fe2f666914780ab22c1b5bcab0b122c27 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Sun, 13 Oct 2024 15:42:35 -0500 Subject: [PATCH 02/10] updating --- Cargo.lock | 53 +++++++++++++++++++++++++++-------------------------- Cargo.toml | 1 + 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7f30019..acd433e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -490,32 +490,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "core" -version = "0.1.0" -dependencies = [ - "color-eyre", - "configparser", - "dirs", - "fastrand 2.1.1", - "obws", - "pretty_assertions", - "quote", - "reqwest", - "rfd", - "serde", - "serde_derive", - "serde_json", - "sqlx", - "tar", - "time", - "tokio", - "tracing", - "tracing-subscriber", - "youtube_dl", - "zstd", -] - [[package]] name = "core-foundation" version = "0.9.4" @@ -1490,6 +1464,7 @@ dependencies = [ "cxx-qt-lib", "dirs", "fastrand 2.1.1", + "lumina-core", "obws", "qt-build-utils", "quote", @@ -1573,6 +1548,32 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lumina-core" +version = "0.1.0" +dependencies = [ + "color-eyre", + "configparser", + "dirs", + "fastrand 2.1.1", + "obws", + "pretty_assertions", + "quote", + "reqwest", + "rfd", + "serde", + "serde_derive", + "serde_json", + "sqlx", + "tar", + "time", + "tokio", + "tracing", + "tracing-subscriber", + "youtube_dl", + "zstd", +] + [[package]] name = "malloc_buf" version = "0.0.6" diff --git a/Cargo.toml b/Cargo.toml index 5d20d7c..a5ce271 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ path = "src/rust/lib.rs" # path = "src/rust/main.rs" [dependencies] +lumina-core = { path = "src/rust/core" } configparser = "3.0.2" serde = "1.0.152" serde_derive = "1.0.152" From da735aa00b4c867c58b3028aeaac2f832a857e16 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 14 Oct 2024 10:58:21 -0500 Subject: [PATCH 03/10] Error handling..... grrr --- src/rust/core/file.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/rust/core/file.rs b/src/rust/core/file.rs index 8a9aa9e..e3d5c8f 100644 --- a/src/rust/core/file.rs +++ b/src/rust/core/file.rs @@ -1,8 +1,8 @@ use tar::{Archive, Builder}; use tracing::error; use zstd::Encoder; -use std::{fs::{self, File}, future::Future, iter, path::{Path, PathBuf}}; -use color_eyre::eyre::{eyre, Result}; +use std::{fs::{self, File}, iter, path::{Path, PathBuf}}; +use color_eyre::eyre::{eyre, Context, Result}; use serde_json::Value; use sqlx::{query, query_as, FromRow, SqliteConnection}; use crate::{images::{get_image_from_db, Image}, kinds::ServiceItemKind, model::get_db, presentations::{get_presentation_from_db, PresKind, Presentation}, service_items::ServiceItem, slides::Background, songs::{get_song_from_db, Song}, videos::{get_video_from_db, Video}}; @@ -66,17 +66,23 @@ async fn store_service_items(items: &Vec, db: &mut SqliteConnection }; if let Some(file) = audio { let audio_file = temp_dir.join(file.file_name().expect("Audio file couldn't be added to temp_dir")); - match fs::File::create(&audio_file) { - Ok(_) => Ok(fs::copy(file, &audio_file)?), - Err(e) => Err(eyre!("Couldn't create audio file: {e}")), - }?; + if let Ok(file) = file.strip_prefix("file://") { + fs::File::create(&audio_file).wrap_err("Couldn't create audio file")?; + fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found"); + } else { + fs::File::create(&audio_file).wrap_err("Couldn't create audio file")?; + fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found"); + } }; if let Some(file) = background { let background_file = temp_dir.join(file.path.file_name().expect("Background file couldn't be added to temp_dir")); - match fs::File::create(&background_file) { - Ok(_) => Ok(fs::copy(file.path, &background_file)?), - Err(e) => Err(eyre!("Couldn't create background file: {e}")), - }?; + if let Ok(file) = file.path.strip_prefix("file://") { + fs::File::create(&background_file).wrap_err("Couldn't create background file")?; + fs::copy(file, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found"); + } else { + fs::File::create(&background_file).wrap_err("Couldn't create background file")?; + fs::copy(file.path, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found"); + } } } Ok(()) @@ -157,7 +163,7 @@ mod test { use fs::canonicalize; use sqlx::Connection; - use pretty_assertions::{assert_eq, assert_ne}; + use pretty_assertions::assert_eq; use tracing::debug; use super::*; From 0ba3e7588b0eaf083b9a383e2a18c1478de976b0 Mon Sep 17 00:00:00 2001 From: Chris Cochrun Date: Mon, 10 Mar 2025 23:18:30 -0500 Subject: [PATCH 04/10] fixing lots of bugs --- Cargo.lock | 4 +- Cargo.toml | 2 +- justfile | 2 +- src/rust/core/Cargo.toml | 2 +- src/rust/core/file.rs | 214 ++++++++++++++++++++--------- src/rust/core/images.rs | 19 ++- src/rust/core/kinds.rs | 4 +- src/rust/core/lib.rs | 2 +- src/rust/core/model.rs | 13 +- src/rust/core/presentations.rs | 27 ++-- src/rust/core/service_items.rs | 22 ++- src/rust/core/slides.rs | 32 +++-- src/rust/core/songs.rs | 35 +++-- src/rust/core/videos.rs | 20 ++- src/rust/image_model.rs | 63 ++++++--- src/rust/lib.rs | 3 +- src/rust/obs.rs | 12 +- src/rust/presentation_model.rs | 72 ++++++---- src/rust/service_item_model.rs | 85 +++++++----- src/rust/slide_model.rs | 239 +++++++++++++++++++-------------- src/rust/slide_object.rs | 19 ++- src/rust/songs/song_model.rs | 228 +++++++++++++++++-------------- src/rust/video_model.rs | 130 ++++++++++++------ src/rust/ytdl.rs | 18 +-- 24 files changed, 781 insertions(+), 486 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index acd433e..7c6439a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1464,7 +1464,7 @@ dependencies = [ "cxx-qt-lib", "dirs", "fastrand 2.1.1", - "lumina-core", + "lumina_core", "obws", "qt-build-utils", "quote", @@ -1549,7 +1549,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] -name = "lumina-core" +name = "lumina_core" version = "0.1.0" dependencies = [ "color-eyre", diff --git a/Cargo.toml b/Cargo.toml index a5ce271..c82317b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ path = "src/rust/lib.rs" # path = "src/rust/main.rs" [dependencies] -lumina-core = { path = "src/rust/core" } +lumina_core = { path = "src/rust/core" } configparser = "3.0.2" serde = "1.0.152" serde_derive = "1.0.152" diff --git a/justfile b/justfile index a332b6d..f98c2c4 100644 --- a/justfile +++ b/justfile @@ -15,7 +15,7 @@ test: RUST_LOG=debug cargo test --benches --tests --all-features -- --nocapture testcore: - RUST_LOG=debug cargo test -p core --benches --tests --all-features -- --nocapture + RUST_LOG=debug cargo test -p lumina_core --benches --tests --all-features -- --nocapture alias b := build alias r := run diff --git a/src/rust/core/Cargo.toml b/src/rust/core/Cargo.toml index 1be6c9d..d6abb8b 100644 --- a/src/rust/core/Cargo.toml +++ b/src/rust/core/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "lumina-core" +name = "lumina_core" version = "0.1.0" edition = "2021" authors = [ diff --git a/src/rust/core/file.rs b/src/rust/core/file.rs index e3d5c8f..ef5163d 100644 --- a/src/rust/core/file.rs +++ b/src/rust/core/file.rs @@ -1,86 +1,131 @@ -use tar::{Archive, Builder}; -use tracing::error; -use zstd::Encoder; -use std::{fs::{self, File}, iter, path::{Path, PathBuf}}; +use crate::{ + images::{get_image_from_db, Image}, + kinds::ServiceItemKind, + model::get_db, + presentations::{ + get_presentation_from_db, PresKind, Presentation, + }, + service_items::ServiceItem, + slides::Background, + songs::{get_song_from_db, Song}, + videos::{get_video_from_db, Video}, +}; use color_eyre::eyre::{eyre, Context, Result}; use serde_json::Value; use sqlx::{query, query_as, FromRow, SqliteConnection}; -use crate::{images::{get_image_from_db, Image}, kinds::ServiceItemKind, model::get_db, presentations::{get_presentation_from_db, PresKind, Presentation}, service_items::ServiceItem, slides::Background, songs::{get_song_from_db, Song}, videos::{get_video_from_db, Video}}; +use std::{ + fs::{self, File}, + iter, + path::{Path, PathBuf}, +}; +use tar::{Archive, Builder}; +use tracing::error; +use zstd::Encoder; -pub async fn save(list: Vec, path: impl AsRef) -> Result<()> { +pub async fn save( + list: Vec, + path: impl AsRef, +) -> Result<()> { let path = path.as_ref(); let save_file = File::create(path)?; let mut db = get_db().await; let json = process_service_items(&list, &mut db).await?; - let archive = store_service_items(&list, &mut db, &save_file, &json).await?; + let archive = + store_service_items(&list, &mut db, &save_file, &json) + .await?; Ok(()) } -async fn store_service_items(items: &Vec, db: &mut SqliteConnection, save_file: &File, json: &Value) -> Result<()> { +async fn store_service_items( + items: &Vec, + db: &mut SqliteConnection, + save_file: &File, + json: &Value, +) -> Result<()> { let encoder = Encoder::new(save_file, 3).unwrap(); let mut tar = Builder::new(encoder); let mut temp_dir = dirs::data_dir().unwrap(); temp_dir.push("lumina"); let mut s: String = - iter::repeat_with(fastrand::alphanumeric) - .take(5) - .collect(); + iter::repeat_with(fastrand::alphanumeric).take(5).collect(); s.insert_str(0, "temp_"); temp_dir.push(s); fs::create_dir_all(&temp_dir)?; let service_file = temp_dir.join("serviceitems.json"); fs::File::create(&service_file)?; - match fs::File::options().read(true).write(true).open(service_file) { + match fs::File::options() + .read(true) + .write(true) + .open(service_file) + { Ok(f) => { serde_json::to_writer_pretty(f, json)?; - }, - Err(e) => error!("There were problems making a file i guess: {e}"), + } + Err(e) => { + error!("There were problems making a file i guess: {e}") + } }; for item in items { let background; let audio: Option; match item.kind { ServiceItemKind::Song => { - let song = get_song_from_db(item.database_id, db).await?; + let song = + get_song_from_db(item.database_id, db).await?; background = song.background; audio = song.audio; - }, + } ServiceItemKind::Image => { - let image = get_image_from_db(item.database_id, db).await?; + let image = + get_image_from_db(item.database_id, db).await?; background = Some(Background::try_from(image.path)?); audio = None; - }, + } ServiceItemKind::Video => { - let video = get_video_from_db(item.database_id, db).await?; + let video = + get_video_from_db(item.database_id, db).await?; background = Some(Background::try_from(video.path)?); audio = None; - }, + } ServiceItemKind::Presentation(_) => { - let presentation = get_presentation_from_db(item.database_id, db).await?; - background = Some(Background::try_from(presentation.path)?); + let presentation = + get_presentation_from_db(item.database_id, db) + .await?; + background = + Some(Background::try_from(presentation.path)?); audio = None; - }, + } ServiceItemKind::Content => { todo!() - }, + } }; if let Some(file) = audio { - let audio_file = temp_dir.join(file.file_name().expect("Audio file couldn't be added to temp_dir")); + let audio_file = + temp_dir.join(file.file_name().expect( + "Audio file couldn't be added to temp_dir", + )); if let Ok(file) = file.strip_prefix("file://") { - fs::File::create(&audio_file).wrap_err("Couldn't create audio file")?; + fs::File::create(&audio_file) + .wrap_err("Couldn't create audio file")?; fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found"); } else { - fs::File::create(&audio_file).wrap_err("Couldn't create audio file")?; + fs::File::create(&audio_file) + .wrap_err("Couldn't create audio file")?; fs::copy(file, audio_file).wrap_err("Audio file could not be copied, the source file doesn't exist not be found"); } }; if let Some(file) = background { - let background_file = temp_dir.join(file.path.file_name().expect("Background file couldn't be added to temp_dir")); + let background_file = + temp_dir.join(file.path.file_name().expect( + "Background file couldn't be added to temp_dir", + )); if let Ok(file) = file.path.strip_prefix("file://") { - fs::File::create(&background_file).wrap_err("Couldn't create background file")?; + fs::File::create(&background_file) + .wrap_err("Couldn't create background file")?; fs::copy(file, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found"); } else { - fs::File::create(&background_file).wrap_err("Couldn't create background file")?; + fs::File::create(&background_file) + .wrap_err("Couldn't create background file")?; fs::copy(file.path, background_file).wrap_err("Background file could not be copied, the source file doesn't exist not be found"); } } @@ -92,66 +137,96 @@ async fn clear_temp_dir(temp_dir: &Path) -> Result<()> { todo!() } -async fn process_service_items(items: &Vec, db: &mut SqliteConnection) -> Result { +async fn process_service_items( + items: &Vec, + db: &mut SqliteConnection, +) -> Result { let mut values: Vec = vec![]; for item in items { match item.kind { ServiceItemKind::Song => { - let value = process_song(item.database_id, db).await?; + let value = + process_song(item.database_id, db).await?; values.push(value); - }, + } ServiceItemKind::Image => { - let value = process_image(item.database_id, db).await?; + let value = + process_image(item.database_id, db).await?; values.push(value); - }, + } ServiceItemKind::Video => { - let value = process_video(item.database_id, db).await?; + let value = + process_video(item.database_id, db).await?; values.push(value); - }, + } ServiceItemKind::Presentation(_) => { - let value = process_presentation(item.database_id, db).await?; + let value = + process_presentation(item.database_id, db) + .await?; values.push(value); - }, + } ServiceItemKind::Content => { todo!() - }, + } } } let json = Value::from(values); Ok(json) } -async fn process_song(database_id: i32, db: &mut SqliteConnection) -> Result { +async fn process_song( + database_id: i32, + db: &mut SqliteConnection, +) -> Result { let song = get_song_from_db(database_id, db).await?; let song_json = serde_json::to_value(&song)?; let kind_json = serde_json::to_value(ServiceItemKind::Song)?; - let json = serde_json::json!({"item": song_json, "kind": kind_json}); + let json = + serde_json::json!({"item": song_json, "kind": kind_json}); Ok(json) } -async fn process_image(database_id: i32, db: &mut SqliteConnection) -> Result { +async fn process_image( + database_id: i32, + db: &mut SqliteConnection, +) -> Result { let image = get_image_from_db(database_id, db).await?; let image_json = serde_json::to_value(&image)?; let kind_json = serde_json::to_value(ServiceItemKind::Image)?; - let json = serde_json::json!({"item": image_json, "kind": kind_json}); + let json = + serde_json::json!({"item": image_json, "kind": kind_json}); Ok(json) } -async fn process_video(database_id: i32, db: &mut SqliteConnection) -> Result { +async fn process_video( + database_id: i32, + db: &mut SqliteConnection, +) -> Result { let video = get_video_from_db(database_id, db).await?; let video_json = serde_json::to_value(&video)?; let kind_json = serde_json::to_value(ServiceItemKind::Video)?; - let json = serde_json::json!({"item": video_json, "kind": kind_json}); + let json = + serde_json::json!({"item": video_json, "kind": kind_json}); Ok(json) } -async fn process_presentation(database_id: i32, db: &mut SqliteConnection) -> Result { - let presentation = get_presentation_from_db(database_id, db).await?; +async fn process_presentation( + database_id: i32, + db: &mut SqliteConnection, +) -> Result { + let presentation = + get_presentation_from_db(database_id, db).await?; let presentation_json = serde_json::to_value(&presentation)?; let kind_json = match presentation.kind { - PresKind::Html => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Html))?, - PresKind::Pdf => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Pdf))?, - PresKind::Generic => serde_json::to_value(ServiceItemKind::Presentation(PresKind::Generic))?, + PresKind::Html => serde_json::to_value( + ServiceItemKind::Presentation(PresKind::Html), + )?, + PresKind::Pdf => serde_json::to_value( + ServiceItemKind::Presentation(PresKind::Pdf), + )?, + PresKind::Generic => serde_json::to_value( + ServiceItemKind::Presentation(PresKind::Generic), + )?, }; let json = serde_json::json!({"item": presentation_json, "kind": kind_json}); Ok(json) @@ -161,11 +236,11 @@ async fn process_presentation(database_id: i32, db: &mut SqliteConnection) -> Re mod test { use std::path::PathBuf; - use fs::canonicalize; - use sqlx::Connection; - use pretty_assertions::assert_eq; - use tracing::debug; use super::*; + use fs::canonicalize; + use pretty_assertions::assert_eq; + use sqlx::Connection; + use tracing::debug; async fn get_db() -> SqliteConnection { let mut data = dirs::data_local_dir().unwrap(); @@ -173,9 +248,7 @@ mod test { data.push("library-db.sqlite3"); let mut db_url = String::from("sqlite://"); db_url.push_str(data.to_str().unwrap()); - SqliteConnection::connect(&db_url) - .await - .expect("problems") + SqliteConnection::connect(&db_url).await.expect("problems") } #[tokio::test(flavor = "current_thread")] @@ -245,7 +318,8 @@ mod test { async fn test_process_presentation() { let mut db = get_db().await; let result = process_presentation(54, &mut db).await; - let json_presentation_file = PathBuf::from("./test/test_presentation.json"); + let json_presentation_file = + PathBuf::from("./test/test_presentation.json"); if let Ok(path) = canonicalize(json_presentation_file) { debug!(file = ?&path); if let Ok(s) = fs::read_to_string(path) { @@ -258,7 +332,9 @@ mod test { panic!("String wasn't read from file"); } } else { - panic!("Cannot find absolute path to test_presentation.json"); + panic!( + "Cannot find absolute path to test_presentation.json" + ); } } @@ -287,7 +363,8 @@ mod test { async fn test_service_items() { let mut db = get_db().await; let items = get_items(); - let json_item_file = PathBuf::from("./test/test_service_items.json"); + let json_item_file = + PathBuf::from("./test/test_service_items.json"); let result = process_service_items(&items, &mut db).await; if let Ok(path) = canonicalize(json_item_file) { if let Ok(s) = fs::read_to_string(path) { @@ -311,16 +388,23 @@ mod test { #[tokio::test] async fn test_store() { - let path = PathBuf::from("/home/chris/dev/lumina/src/rust/core/test.pres"); - let save_file = match File::create(path) { + let path = PathBuf::from( + "/home/chris/dev/lumina/src/rust/core/test.pres", + ); + let save_file = match File::create(path) { Ok(f) => f, Err(e) => panic!("Couldn't create save_file: {e}"), }; let mut db = get_db().await; let list = get_items(); - if let Ok(json) = process_service_items(&list, &mut db).await { + if let Ok(json) = process_service_items(&list, &mut db).await + { println!("{:?}", json); - match store_service_items(&list, &mut db, &save_file, &json).await { + match store_service_items( + &list, &mut db, &save_file, &json, + ) + .await + { Ok(_) => assert!(true), Err(e) => panic!("There was an error: {e}"), } diff --git a/src/rust/core/images.rs b/src/rust/core/images.rs index 96a74a0..9e7d832 100644 --- a/src/rust/core/images.rs +++ b/src/rust/core/images.rs @@ -5,7 +5,9 @@ use sqlx::{query_as, SqliteConnection}; use std::path::PathBuf; use tracing::error; -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Serialize, Deserialize, +)] pub struct Image { pub id: i32, pub title: String, @@ -16,7 +18,7 @@ impl Model { pub fn load_from_db(&mut self) { let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { - let result = query_as!(Image, r#"SELECT title as "title!", filePath as "path!", id as "id: i32" from images"#).fetch_all(&mut self.db).await; + let result = query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images"#).fetch_all(&mut self.db).await; match result { Ok(v) => { for image in v.into_iter() { @@ -29,9 +31,11 @@ impl Model { } } - -pub async fn get_image_from_db(database_id: i32, db: &mut SqliteConnection) -> Result { - Ok(query_as!(Image, r#"SELECT title as "title!", filePath as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await?) +pub async fn get_image_from_db( + database_id: i32, + db: &mut SqliteConnection, +) -> Result { + Ok(query_as!(Image, r#"SELECT title as "title!", file_path as "path!", id as "id: i32" from images where id = ?"#, database_id).fetch_one(db).await?) } #[cfg(test)] @@ -67,7 +71,10 @@ mod test { let new_image = test_image("A newer image".into()); match result { Ok(_) => { - assert_eq!(&image, image_model.find(|i| i.id == 0).unwrap()); + assert_eq!( + &image, + image_model.find(|i| i.id == 0).unwrap() + ); assert_ne!( &new_image, image_model.find(|i| i.id == 0).unwrap() diff --git a/src/rust/core/kinds.rs b/src/rust/core/kinds.rs index 3660b78..7ffa001 100644 --- a/src/rust/core/kinds.rs +++ b/src/rust/core/kinds.rs @@ -4,7 +4,9 @@ use serde::{Deserialize, Serialize}; use crate::presentations::PresKind; -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum ServiceItemKind { #[default] Song, diff --git a/src/rust/core/lib.rs b/src/rust/core/lib.rs index bb3db24..10bb770 100644 --- a/src/rust/core/lib.rs +++ b/src/rust/core/lib.rs @@ -1,3 +1,4 @@ +pub mod file; pub mod images; pub mod kinds; pub mod model; @@ -6,4 +7,3 @@ pub mod service_items; pub mod slides; pub mod songs; pub mod videos; -pub mod file; diff --git a/src/rust/core/model.rs b/src/rust/core/model.rs index bb94d12..da3f695 100644 --- a/src/rust/core/model.rs +++ b/src/rust/core/model.rs @@ -36,8 +36,7 @@ impl Model { Ok(()) } - pub fn get_item(&self, index: i32) -> Option<&T> - { + pub fn get_item(&self, index: i32) -> Option<&T> { self.items.get(index as usize) } @@ -60,10 +59,8 @@ impl Default for Model { items: vec![], db: { let rt = tokio::runtime::Runtime::new().unwrap(); - rt.block_on(async { - get_db().await - }) - } + rt.block_on(async { get_db().await }) + }, } } } @@ -74,9 +71,7 @@ pub async fn get_db() -> SqliteConnection { data.push("library-db.sqlite3"); let mut db_url = String::from("sqlite://"); db_url.push_str(data.to_str().unwrap()); - SqliteConnection::connect(&db_url) - .await - .expect("problems") + SqliteConnection::connect(&db_url).await.expect("problems") } pub trait Modeling { diff --git a/src/rust/core/presentations.rs b/src/rust/core/presentations.rs index 8f9b33b..41768b9 100644 --- a/src/rust/core/presentations.rs +++ b/src/rust/core/presentations.rs @@ -1,12 +1,16 @@ -use std::path::PathBuf; use color_eyre::eyre::Result; use serde::{Deserialize, Serialize}; -use sqlx::{prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection}; +use sqlx::{ + prelude::FromRow, query, sqlite::SqliteRow, Row, SqliteConnection, +}; +use std::path::PathBuf; use tracing::error; use crate::model::Model; -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum PresKind { Html, #[default] @@ -14,7 +18,9 @@ pub enum PresKind { Generic, } -#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub struct Presentation { pub id: i32, pub title: String, @@ -57,7 +63,7 @@ impl Model { pub fn load_from_db(&mut self) { let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { - let result = query!(r#"SELECT id as "id: i32", title, filePath as "path", html from presentations"#).fetch_all(&mut self.db).await; + let result = query!(r#"SELECT id as "id: i32", title, file_path as "path", html from presentations"#).fetch_all(&mut self.db).await; match result { Ok(v) => { for presentation in v.into_iter() { @@ -79,8 +85,11 @@ impl Model { } } -pub async fn get_presentation_from_db(database_id: i32, db: &mut SqliteConnection) -> Result { - let row = query(r#"SELECT id as "id: i32", title, filePath as "path", html from presentations where id = $1"#).bind(database_id).fetch_one(db).await?; +pub async fn get_presentation_from_db( + database_id: i32, + db: &mut SqliteConnection, +) -> Result { + let row = query(r#"SELECT id as "id: i32", title, file_path as "path", html from presentations where id = $1"#).bind(database_id).fetch_one(db).await?; Ok(Presentation::from_row(&row)?) } @@ -111,7 +120,9 @@ mod test { let mut presentation_model: Model = Model::default(); presentation_model.load_from_db(); - if let Some(presentation) = presentation_model.find(|p| p.id == 54) { + if let Some(presentation) = + presentation_model.find(|p| p.id == 54) + { let test_presentation = test_presentation(); assert_eq!(&test_presentation, presentation); } else { diff --git a/src/rust/core/service_items.rs b/src/rust/core/service_items.rs index 222f2d6..b49c015 100644 --- a/src/rust/core/service_items.rs +++ b/src/rust/core/service_items.rs @@ -52,7 +52,9 @@ impl From<&Image> for ServiceItem { impl From<&Presentation> for ServiceItem { fn from(presentation: &Presentation) -> Self { Self { - kind: ServiceItemKind::Presentation(presentation.kind.clone()), + kind: ServiceItemKind::Presentation( + presentation.kind.clone(), + ), database_id: presentation.id, ..Default::default() } @@ -60,7 +62,10 @@ impl From<&Presentation> for ServiceItem { } impl ServiceItemModel { - fn add_item(&mut self, item: impl Into) -> Result<()> { + fn add_item( + &mut self, + item: impl Into, + ) -> Result<()> { let service_item: ServiceItem = item.into(); self.items.push(service_item); Ok(()) @@ -94,7 +99,6 @@ mod test { } } - #[test] pub fn test_service_item() { let song = test_song(); @@ -104,10 +108,16 @@ mod test { let mut service_model = ServiceItemModel::default(); match service_model.add_item(&song) { Ok(_) => { - assert_eq!(ServiceItemKind::Song, service_model.items[0].kind); - assert_eq!(ServiceItemKind::Presentation(PresKind::Html), pres_item.kind); + assert_eq!( + ServiceItemKind::Song, + service_model.items[0].kind + ); + assert_eq!( + ServiceItemKind::Presentation(PresKind::Html), + pres_item.kind + ); assert_eq!(service_item, service_model.items[0]); - }, + } Err(e) => panic!("Problem adding item: {:?}", e), } } diff --git a/src/rust/core/slides.rs b/src/rust/core/slides.rs index 726ffae..3de576a 100644 --- a/src/rust/core/slides.rs +++ b/src/rust/core/slides.rs @@ -1,4 +1,8 @@ -use std::{error::Error, fmt::Display, path::{Path, PathBuf}}; +use std::{ + error::Error, + fmt::Display, + path::{Path, PathBuf}, +}; use color_eyre::eyre::{eyre, Result}; use serde::{Deserialize, Serialize}; @@ -10,7 +14,9 @@ use crate::{ presentations::Presentation, songs::Song, videos::Video, }; -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum TextAlignment { TopLeft, TopCenter, @@ -24,7 +30,9 @@ pub enum TextAlignment { BottomRight, } -#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub struct Background { pub path: PathBuf, pub kind: BackgroundKind, @@ -36,7 +44,7 @@ impl TryFrom for Background { let value = value.trim_start_matches("file://"); let path = PathBuf::from(value); if !path.exists() { - return Err(ParseError::DoesNotExist) + return Err(ParseError::DoesNotExist); } let extension = value.rsplit_once('.').unwrap_or_default(); match extension.1 { @@ -106,11 +114,15 @@ impl DatabaseError for ParseError { todo!() } - fn as_error_mut(&mut self) -> &mut (dyn Error + Send + Sync + 'static) { + fn as_error_mut( + &mut self, + ) -> &mut (dyn Error + Send + Sync + 'static) { todo!() } - fn into_error(self: Box) -> Box { + fn into_error( + self: Box, + ) -> Box { todo!() } @@ -128,15 +140,15 @@ impl Display for ParseError { Self::NonBackgroundFile => { "The file is not a recognized image or video type" } - Self::DoesNotExist => { - "This file doesn't exist" - } + Self::DoesNotExist => "This file doesn't exist", }; write!(f, "Error: {message}") } } -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub enum BackgroundKind { #[default] Image, diff --git a/src/rust/core/songs.rs b/src/rust/core/songs.rs index d259563..b1c955f 100644 --- a/src/rust/core/songs.rs +++ b/src/rust/core/songs.rs @@ -2,7 +2,10 @@ use std::{collections::HashMap, path::PathBuf}; use color_eyre::eyre::{eyre, Context, Result}; use serde::{Deserialize, Serialize}; -use sqlx::{query, query_as, sqlite::SqliteRow, FromRow, Row, SqliteConnection}; +use sqlx::{ + query, query_as, sqlite::SqliteRow, FromRow, Row, + SqliteConnection, +}; use tracing::{debug, error}; use crate::{ @@ -10,7 +13,9 @@ use crate::{ slides::{Background, TextAlignment}, }; -#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize, +)] pub struct Song { pub id: i32, pub title: String, @@ -56,17 +61,24 @@ impl FromRow<'_, SqliteRow> for Song { text_alignment: Some({ let horizontal_alignment: String = row.try_get(3)?; let vertical_alignment: String = row.try_get(4)?; - match (horizontal_alignment.to_lowercase().as_str(), vertical_alignment.to_lowercase().as_str()) { + match ( + horizontal_alignment.to_lowercase().as_str(), + vertical_alignment.to_lowercase().as_str(), + ) { ("left", "top") => TextAlignment::TopLeft, ("left", "center") => TextAlignment::MiddleLeft, ("left", "bottom") => TextAlignment::BottomLeft, ("center", "top") => TextAlignment::TopCenter, - ("center", "center") => TextAlignment::MiddleCenter, - ("center", "bottom") => TextAlignment::BottomCenter, + ("center", "center") => { + TextAlignment::MiddleCenter + } + ("center", "bottom") => { + TextAlignment::BottomCenter + } ("right", "top") => TextAlignment::TopRight, ("right", "center") => TextAlignment::MiddleRight, ("right", "bottom") => TextAlignment::BottomRight, - _ => TextAlignment::MiddleCenter + _ => TextAlignment::MiddleCenter, } }), font: row.try_get(6)?, @@ -75,19 +87,20 @@ impl FromRow<'_, SqliteRow> for Song { } } - -pub async fn get_song_from_db(index: i32, db: &mut SqliteConnection) -> Result { - let row = query(r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#).bind(index).fetch_one(db).await?; +pub async fn get_song_from_db( + index: i32, + db: &mut SqliteConnection, +) -> Result { + let row = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs where id = $1"#).bind(index).fetch_one(db).await?; Ok(Song::from_row(&row)?) } - impl Model { pub fn load_from_db(&mut self) { // static DATABASE_URL: &str = "sqlite:///home/chris/.local/share/lumina/library-db.sqlite3"; let rt = tokio::runtime::Runtime::new().unwrap(); rt.block_on(async { - let result = query(r#"SELECT vorder as "verse_order!", fontSize as "font_size!: i32", backgroundType as "background_type!", horizontalTextAlignment as "horizontal_text_alignment!", verticalTextAlignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.db).await; + let result = query(r#"SELECT verse_order as "verse_order!", font_size as "font_size!: i32", background_type as "background_type!", horizontal_text_alignment as "horizontal_text_alignment!", vertical_text_alignment as "vertical_text_alignment!", title as "title!", font as "font!", background as "background!", lyrics as "lyrics!", ccli as "ccli!", author as "author!", audio as "audio!", id as "id: i32" from songs"#).fetch_all(&mut self.db).await; match result { Ok(s) => { for song in s.into_iter() { diff --git a/src/rust/core/videos.rs b/src/rust/core/videos.rs index c7cdb3d..0329916 100644 --- a/src/rust/core/videos.rs +++ b/src/rust/core/videos.rs @@ -5,7 +5,9 @@ use sqlx::{query_as, SqliteConnection}; use std::path::PathBuf; use tracing::error; -#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)] +#[derive( + Clone, Debug, Default, PartialEq, Serialize, Deserialize, +)] pub struct Video { pub id: i32, pub title: String, @@ -19,7 +21,7 @@ impl Model