every-day-things / citadel Goto Github PK
View Code? Open in Web Editor NEWManage your ebook library without frustrations. Calibre compatible.
License: MIT License
Manage your ebook library without frustrations. Calibre compatible.
License: MIT License
Add CRUD operations for external IDs attached to books. These are not entities, they are value objects.
Add support for reading from arbitrary custom columns.
The compile-time location of the build is embedded into the binary.
In my case, I am building citadel in the folder /tmp/makepkg/citadel-git
.
This particular path is embedded in the final binary, as seen here with src-tauri/libcalibre/src/application/services/library/service.rs
:
This seems to be the only occurrence.
If you need more context:
0xa0f0dc: 0x4e 0x6f 0x74 0x46 0x6f 0x75 0x6e 0x64 0x42 0x6f NotFoundBo
0xa0f0e6: 0x6f 0x6b 0x46 0x69 0x6c 0x65 0x73 0x4e 0x6f 0x74 okFilesNot
0xa0f0f0: 0x46 0x6f 0x75 0x6e 0x64 0x42 0x6f 0x6f 0x6b 0x4e FoundBookN
0xa0f0fa: 0x6f 0x74 0x46 0x6f 0x75 0x6e 0x64 0x41 0x75 0x74 otFoundAut
0xa0f104: 0x68 0x6f 0x72 0x63 0x61 0x6c 0x6c 0x65 0x64 0x20 horcalled
0xa0f10e: 0x60 0x4f 0x70 0x74 0x69 0x6f 0x6e 0x3a 0x3a 0x75 `Option::u
0xa0f118: 0x6e 0x77 0x72 0x61 0x70 0x28 0x29 0x60 0x20 0x6f nwrap()` o
0xa0f122: 0x6e 0x20 0x61 0x20 0x60 0x4e 0x6f 0x6e 0x65 0x60 n a `None`
0xa0f12c: 0x20 0x76 0x61 0x6c 0x75 0x65 0x2f 0x62 0x75 0x69 value/bui
0xa0f136: 0x6c 0x64 0x2f 0x72 0x75 0x73 0x74 0x2f 0x73 0x72 ld/rust/sr
0xa0f140: 0x63 0x2f 0x72 0x75 0x73 0x74 0x63 0x2d 0x31 0x2e c/rustc-1.
0xa0f14a: 0x37 0x35 0x2e 0x30 0x2d 0x73 0x72 0x63 0x2f 0x6c 75.0-src/l
0xa0f154: 0x69 0x62 0x72 0x61 0x72 0x79 0x2f 0x61 0x6c 0x6c ibrary/all
0xa0f15e: 0x6f 0x63 0x2f 0x73 0x72 0x63 0x2f 0x63 0x6f 0x6c oc/src/col
0xa0f168: 0x6c 0x65 0x63 0x74 0x69 0x6f 0x6e 0x73 0x2f 0x62 lections/b
0xa0f172: 0x74 0x72 0x65 0x65 0x2f 0x6e 0x61 0x76 0x69 0x67 tree/navig
0xa0f17c: 0x61 0x74 0x65 0x2e 0x72 0x73 0x2f 0x74 0x6d 0x70 ate.rs/tmp
0xa0f186: 0x2f 0x6d 0x61 0x6b 0x65 0x70 0x6b 0x67 0x2f 0x63 /makepkg/c
0xa0f190: 0x69 0x74 0x61 0x64 0x65 0x6c 0x2d 0x67 0x69 0x74 itadel-git
0xa0f19a: 0x2f 0x73 0x72 0x63 0x2f 0x63 0x69 0x74 0x61 0x64 /src/citad
0xa0f1a4: 0x65 0x6c 0x2f 0x73 0x72 0x63 0x2d 0x74 0x61 0x75 el/src-tau
0xa0f1ae: 0x72 0x69 0x2f 0x6c 0x69 0x62 0x63 0x61 0x6c 0x69 ri/libcali
0xa0f1b8: 0x62 0x72 0x65 0x2f 0x73 0x72 0x63 0x2f 0x61 0x70 bre/src/ap
0xa0f1c2: 0x70 0x6c 0x69 0x63 0x61 0x74 0x69 0x6f 0x6e 0x2f plication/
0xa0f1cc: 0x73 0x65 0x72 0x76 0x69 0x63 0x65 0x73 0x2f 0x6c services/l
0xa0f1d6: 0x69 0x62 0x72 0x61 0x72 0x79 0x2f 0x73 0x65 0x72 ibrary/ser
0xa0f1e0: 0x76 0x69 0x63 0x65 0x2e 0x72 0x73 0x3c 0x64 0x63 vice.rs<dc
0xa0f1ea: 0x3a 0x63 0x72 0x65 0x61 0x74 0x6f 0x72 0x20 0x6f :creator o
0xa0f1f4: 0x70 0x66 0x3a 0x66 0x69 0x6c 0x65 0x2d 0x61 0x73 pf:file-as
0xa0f1fe: 0x3d 0x22 0x22 0x20 0x6f 0x70 0x66 0x3a 0x72 0x6f ="" opf:ro
0xa0f208: 0x6c 0x65 0x3d 0x22 0x61 0x75 0x74 0x22 0x3e 0x3c le="aut"><
0xa0f212: 0x2f 0x64 0x63 0x3a 0x63 0x72 0x65 0x61 0x74 0x6f /dc:creato
0xa0f21c: 0x72 0x3e 0x3c 0x3f 0x78 0x6d 0x6c 0x20 0x76 0x65 r><?xml ve
0xa0f226: 0x72 0x73 0x69 0x6f 0x6e 0x3d 0x27 0x31 0x2e 0x30 rsion='1.0
0xa0f230: 0x27 0x20 0x65 0x6e 0x63 0x6f 0x64 0x69 0x6e 0x67 ' encoding
0xa0f23a: 0x3d 0x27 0x75 0x74 0x66 0x2d 0x38 0x27 0x3f 0x3e ='utf-8'?>
0xa0f244: 0x0a 0x20 0x20 0x20 0x20 0x3c 0x70 0x61 0x63 0x6b . <pack
0xa0f24e: 0x61 0x67 0x65 0x20 0x78 0x6d 0x6c 0x6e 0x73 0x3d age xmlns=
0xa0f258: 0x22 0x68 0x74 0x74 0x70 0x3a 0x2f 0x2f 0x77 0x77 "http://ww
0xa0f262: 0x77 0x2e 0x69 0x64 0x70 0x66 0x2e 0x6f 0x72 0x67 w.idpf.org
0xa0f26c: 0x2f 0x32 0x30 0x30 0x37 0x2f 0x6f 0x70 0x66 0x22 /2007/opf"
0xa0f276: 0x20 0x75 0x6e 0x69 0x71 0x75 0x65 0x2d 0x69 0x64 unique-id
0xa0f280: 0x65 0x6e 0x74 0x69 0x66 0x69 0x65 0x72 0x3d 0x22 entifier="
0xa0f28a: 0x75 0x75 0x69 0x64 0x5f 0x69 0x64 0x22 0x20 0x76 uuid_id" v
0xa0f294: 0x65 0x72 0x73 0x69 0x6f 0x6e 0x3d 0x22 0x32 0x2e ersion="2.
0xa0f29e: 0x30 0x22 0x3e 0x0a 0x20 0x20 0x20 0x20 0x20 0x20 0">.
0xa0f2a8: 0x3c 0x6d 0x65 0x74 0x61 0x64 0x61 0x74 0x61 0x20 <metadata
To make it easier to try Citadel, and ensure that new changes don't prevent the app from working for long, add a CI pipeline using GitHub Actions to build main
anytime it's updated, and run any tests.
The build should be a matrix supporting
In the future, if there is appeal, we can add Windows builds + non-appimage/.deb builds.
Add a CI pipeline that, on PR open or updated, runs static checks like linting & formatting checks (ensure code is correctly formatted). I haven't run these in a while, so there are likely to be some errors. The first step is to open a PR that resolves any lint/format issues without adding CI.
Add CRUD operations for book tags.
You said on hacknews that "When I add books, I need to grab metadata for the book like title, ISBN, etc." It would thus be nice if citadel could do precisely this, since it's also my main usecase for Calibre: adding books to it, and having it figure out fancy rich metadata :)
I'd like to use a subset of DDD's language in libcalibre
that should make it easier to extend & maintain. With a better understanding of how libcalibre
works (now that I've written (part of) it) comes the ability to write a better version.
Book
, Author
, LibraryFile
(any file within the lib. root)citadel-rs
– creating (and destroying) 3-4 repos & 3-4 services is wild and mostly annoying. It 100% doesn't not need to do that, it can store the services.mut
self's for services. It seems unnecessary.clone()
callsbook_${id}
=> id)search(phrase, fields: &str[])
or similar pattern)Book
aggregate (? or "entity"?) allows for CRUD-ing ("managing")
update_links
which diffs, adds & removes)as well as
find_by_id/1
find_by_author/1
list_all/0
create/1
, which accepts a minimal DTO
Author
entity supports CRUD operations for
libcalibre
.in #1, i saw some mention of appimage, has the idea of publishing this as a flatpak crossed your mind? right now it's what keeping me from trying the app, which otherwise looks pretty fantastic!
warning: unused import: dto::UpdateBookDto
--> src/main.rs:7:43
|
7 | application::services::domain::book::{dto::UpdateBookDto, service::BookService},
| ^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_imports)]
on by default
warning: unused import: format::StrftimeItems
--> src/book.rs:3:25
|
3 | use chrono::{NaiveDate, format::StrftimeItems};
| ^^^^^^^^^^^^^^^^^^^^^
warning: unused variable: book_list
--> src/main.rs:63:9
|
63 | let book_list = book_service.all();
| ^^^^^^^^^ help: if this is intentional, prefix it with an underscore: _book_list
|
= note: #[warn(unused_variables)]
on by default
warning: citadel-rs
(bin "citadel-rs") generated 3 warnings (run cargo fix --bin "citadel-rs"
to apply 3 suggestions)
Finished release [optimized] target(s) in 1m 36s
Bundling citadel_0.1.0_amd64.deb (/home/demor/programs/citadel/src-tauri/target/release/bundle/deb/citadel_0.1.0_amd64.deb)
Bundling citadel_0.1.0_amd64.AppImage (/home/demor/programs/citadel/src-tauri/target/release/bundle/appimage/citadel_0.1.0_amd64.AppImage)
Error failed to bundle project: error running appimage.sh
error: script "build:app" exited with code 1
error: script "build" exited with code 1
Tauri supports autoupdates out-of-the-box. When is Citadel ready for auto updates? How early is too early?
My biggest concern with adding auto updates is that I don't want folks to be frustrated with Citadel's updates the same way that (some) are with Calibre's. Citadel is early software and it's going to be updated a lot.
Since we're using Bun, Node should not need to be installed, but tauri dev
doesn't work without it. It doesn't seem like a Svelte issue — running bun dev:web
without Node will start the Vite web server with no problems.
So something with tauri dev
requires Node. I want to find it, and I want to fix it. Node should not be required for citadel
.
Re-written by @phildenhoff. Original issue desc. below.
When a user selects a folder for their library that is not a pre-existing Calibre library (e.g. no metadata.db file),
If Citadel cannot operate without a Calibre library already in place, can it check for the Calibre database at the folder selection step?
Otherwise, adding a book to an empty folder crashes the app:
RUST_BACKTRACE=full /usr/bin/citadel
thread 'main' panicked at src/libs/calibre/mod.rs:187:17:
Could not find database at /home/jack/Citadel/
stack backtrace:
0: 0x5639e2268c9c - std::backtrace_rs::backtrace::libunwind::trace::he0644f4189ae2429
at /build/rust/src/rustc-1.75.0-src/library/std/src/../../backtrace/src/backtrace/libunwind.rs:104:5
1: 0x5639e2268c9c - std::backtrace_rs::backtrace::trace_unsynchronized::h9d17fc782d3b981a
at /build/rust/src/rustc-1.75.0-src/library/std/src/../../backtrace/src/backtrace/mod.rs:66:5
2: 0x5639e2268c9c - std::sys_common::backtrace::_print_fmt::hb438557330fe04dd
at /build/rust/src/rustc-1.75.0-src/library/std/src/sys_common/backtrace.rs:67:5
3: 0x5639e2268c9c - <std::sys_common::backtrace::_print::DisplayBacktrace as core::fmt::Display>::fmt::hfbaa40019107bf73
at /build/rust/src/rustc-1.75.0-src/library/std/src/sys_common/backtrace.rs:44:22
4: 0x5639e2299230 - core::fmt::rt::Argument::fmt::hb051b4144eaf7ba9
at /build/rust/src/rustc-1.75.0-src/library/core/src/fmt/rt.rs:142:9
5: 0x5639e2299230 - core::fmt::write::h09ae4ee704823005
at /build/rust/src/rustc-1.75.0-src/library/core/src/fmt/mod.rs:1120:17
6: 0x5639e226507d - std::io::Write::write_fmt::h2f754c40a62d69e7
at /build/rust/src/rustc-1.75.0-src/library/std/src/io/mod.rs:1762:15
7: 0x5639e2268a85 - std::sys_common::backtrace::_print::h5aa33cefb716154f
at /build/rust/src/rustc-1.75.0-src/library/std/src/sys_common/backtrace.rs:47:5
8: 0x5639e2268a85 - std::sys_common::backtrace::print::hba7db713d2ca6e46
at /build/rust/src/rustc-1.75.0-src/library/std/src/sys_common/backtrace.rs:34:9
9: 0x5639e226a2d3 - std::panicking::default_hook::{{closure}}::hdecc168c96eda73a
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:272:22
10: 0x5639e226a00a - std::panicking::default_hook::h094baec9e5d8cab2
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:292:9
11: 0x5639e226a805 - std::panicking::rust_panic_with_hook::h1d7664437b07c6b2
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:779:13
12: 0x5639e226a6ee - std::panicking::begin_panic_handler::{{closure}}::hcf3241a5a930cf68
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:657:13
13: 0x5639e2269156 - std::sys_common::backtrace::__rust_end_short_backtrace::h5bffafd462cab801
at /build/rust/src/rustc-1.75.0-src/library/std/src/sys_common/backtrace.rs:170:18
14: 0x5639e226a472 - rust_begin_unwind
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:645:5
15: 0x5639e19f6ab5 - core::panicking::panic_fmt::h45860aff82e9ff99
at /build/rust/src/rustc-1.75.0-src/library/core/src/panicking.rs:72:14
16: 0x5639e1ad9521 - citadel_rs::libs::calibre::add_book_to_db_by_metadata::h091d8d1888d3ca69
17: 0x5639e1b64983 - citadel_rs::run_tauri_backend::{{closure}}::h3bb29e5111b22700
18: 0x5639e1b631c1 - <tauri::plugin::TauriPlugin<R,C> as tauri::plugin::Plugin<R>>::extend_api::h39fc29458d96579b
19: 0x5639e1b514ed - tauri::plugin::PluginStore<R>::extend_api::h9168bad0d72111a2
20: 0x5639e1a6fb8c - tauri::manager::WindowManager<R>::extend_api::h244fd2d23d749935
21: 0x5639e1b56250 - tauri::window::Window<R>::on_message::hd9491f566b821a6b
22: 0x5639e1a724a7 - tauri::manager::WindowManager<R>::prepare_ipc_handler::{{closure}}::h01dfecb7134b3895
23: 0x5639e1b2cf2a - tauri_runtime_wry::create_ipc_handler::{{closure}}::h7bde2fd2d1179594
24: 0x5639e1a78420 - <alloc::boxed::Box<F,A> as core::ops::function::Fn<Args>>::call::h20407a0158c08f3a
25: 0x5639e1eb4353 - <O as webkit2gtk::auto::user_content_manager::UserContentManagerExt>::connect_script_message_received::script_message_received_trampoline::h72b90c7c1777d1b2
26: 0x7f7e4fbb26c0 - g_closure_invoke
27: 0x7f7e4fbe0a36 - <unknown>
28: 0x7f7e4fbd1a42 - <unknown>
29: 0x7f7e4fbd1c77 - g_signal_emit_valist
30: 0x7f7e4fbd1d34 - g_signal_emit
31: 0x7f7e540e5d88 - <unknown>
32: 0x7f7e53caf98e - <unknown>
33: 0x7f7e53f916f5 - <unknown>
34: 0x7f7e54070dce - <unknown>
35: 0x7f7e53f86a8e - <unknown>
36: 0x7f7e53f8abb2 - <unknown>
37: 0x7f7e51ad2aab - <unknown>
38: 0x7f7e51ad2b91 - <unknown>
39: 0x7f7e4faabf69 - <unknown>
40: 0x7f7e4fb0a367 - <unknown>
41: 0x7f7e4faaa162 - g_main_context_iteration
42: 0x7f7e521ed3c7 - gtk_main_iteration_do
43: 0x5639e1eeee3d - gtk::auto::functions::main_iteration_do::hf7f1f4b33400a7c3
44: 0x5639e1b7b1ad - glib::main_context::<impl glib::auto::main_context::MainContext>::with_thread_default::h451a5aa60667354f
45: 0x5639e1b3de52 - tao::platform_impl::platform::event_loop::EventLoop<T>::run::hc1de31bbe5167cca
46: 0x5639e1b6256d - <tauri_runtime_wry::Wry<T> as tauri_runtime::Runtime<T>>::run::h948abacff27924ed
47: 0x5639e1a7cbb8 - citadel_rs::run_tauri_backend::hfba7896320e1d756
48: 0x5639e1bc352f - <tokio::task::local::RunUntil<T> as core::future::future::Future>::poll::ha5cedacb30465c30
49: 0x5639e1bdd11c - <core::pin::Pin<P> as core::future::future::Future>::poll::h5b4f109d65dda040
50: 0x5639e1bc227c - tokio::runtime::scheduler::current_thread::Context::enter::hcd1680d270807e31
51: 0x5639e1a4e0fc - tokio::runtime::context::set_scheduler::hbb6d62a0de494b81
52: 0x5639e1bc186f - tokio::runtime::scheduler::current_thread::CurrentThread::block_on::h1ef579b3b0127ac9
53: 0x5639e1bdcf8d - tokio::runtime::runtime::Runtime::block_on::h1417fa88ebfcd082
54: 0x5639e1a7d895 - citadel_rs::main::h5204abaf2ee96bfb
55: 0x5639e1b10493 - std::sys_common::backtrace::__rust_begin_short_backtrace::hce4b60bab80bff90
56: 0x5639e1b912b9 - std::rt::lang_start::{{closure}}::hf4fd96fb54286a84
57: 0x5639e225dbed - core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once::h6e58cd4b3aa0cedc
at /build/rust/src/rustc-1.75.0-src/library/core/src/ops/function.rs:284:13
58: 0x5639e225dbed - std::panicking::try::do_call::h1d63a6ddcddbf3d7
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:552:40
59: 0x5639e225dbed - std::panicking::try::ha98263394816949f
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:516:19
60: 0x5639e225dbed - std::panic::catch_unwind::hc08a17c58416f4cc
at /build/rust/src/rustc-1.75.0-src/library/std/src/panic.rs:142:14
61: 0x5639e225dbed - std::rt::lang_start_internal::{{closure}}::h8a6385fe0d26a9d5
at /build/rust/src/rustc-1.75.0-src/library/std/src/rt.rs:148:48
62: 0x5639e225dbed - std::panicking::try::do_call::h6b4548ddcceb66f1
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:552:40
63: 0x5639e225dbed - std::panicking::try::ha4d76d1974f7f45a
at /build/rust/src/rustc-1.75.0-src/library/std/src/panicking.rs:516:19
64: 0x5639e225dbed - std::panic::catch_unwind::h691bb3d050a579da
at /build/rust/src/rustc-1.75.0-src/library/std/src/panic.rs:142:14
65: 0x5639e225dbed - std::rt::lang_start_internal::h1630c9ed041f86ee
at /build/rust/src/rustc-1.75.0-src/library/std/src/rt.rs:148:20
66: 0x5639e1b912ae - std::rt::lang_start::h81cf3f1050ed8f71
67: 0x7f7e4f158cd0 - <unknown>
68: 0x7f7e4f158d8a - __libc_start_main
69: 0x5639e19f7495 - _start
70: 0x0 - <unknown>
We only support EPUB rn because they are very common and there was an easy-to-use crate to get data from EPUBs.
Add support for getting the same data for other core file types, specifically:
I'd like to do enforce the mimetype enum a bit better: we should look at the file extension for clues to the mimetype, validate it, and (if valid) pass around a filepath/mimetype pair (a "validated file"). Supporting incorrect file extensions is not necessary, e.g. .epub is actually a PDF? invalid & unimportable.
Calibre has a wide range of import formats, not all of which are a good fit for Citadel. Citadel is specifically focused on managing ebook libraries, and (while it may support conversion in the future) not directed at editing ebook content or ebook publishing. To that end, it makes sense to focus on commonly used end formats. Specifically, we're not planning to add these formats. Please let me know if you use these!
See also, this list of ebook file formats
Calibre seems to support adding whatever files you want to your library. I tried adding a PNG (image) and a GPX (GPS coordinates) file to my library, and both worked. While Calibre may be forgiving, Citadel is not. We won't support arbitrary files.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.