some more docs
This commit is contained in:
parent
1314320260
commit
41206abac1
29 changed files with 119 additions and 0 deletions
|
@ -283,6 +283,7 @@ impl Calibre {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
/// Tests for the calibre module.
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Data types and functions for interacting with the calibre database.
|
||||||
pub mod author;
|
pub mod author;
|
||||||
pub mod book;
|
pub mod book;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
|
@ -24,17 +24,23 @@ pub struct MultipleAuthorsError {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching a book's author.
|
||||||
pub enum BookAuthorError {
|
pub enum BookAuthorError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareBookAuthor { source: rusqlite::Error },
|
PrepareBookAuthor { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteBookAuthor { source: rusqlite::Error },
|
ExecuteBookAuthor { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching a single author.
|
||||||
pub enum ScalarAuthorError {
|
pub enum ScalarAuthorError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareScalarAuthor { source: rusqlite::Error },
|
PrepareScalarAuthor { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteScalarAuthor { source: rusqlite::Error },
|
ExecuteScalarAuthor { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
@ -52,6 +58,7 @@ pub struct MoreAuthorsError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Author {
|
impl Author {
|
||||||
|
/// Create an author from a database row.
|
||||||
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
|
|
|
@ -39,25 +39,34 @@ pub struct AuthorBooksError {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching a series' books.
|
||||||
pub enum SeriesBookError {
|
pub enum SeriesBookError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareSeriesBook { source: rusqlite::Error },
|
PrepareSeriesBook { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteSeriesBook { source: rusqlite::Error },
|
ExecuteSeriesBook { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching recent books.
|
||||||
pub enum RecentBooksError {
|
pub enum RecentBooksError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareRecentBooks { source: rusqlite::Error },
|
PrepareRecentBooks { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteRecentBooks { source: rusqlite::Error },
|
ExecuteRecentBooks { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching a single book.
|
||||||
pub enum ScalarBookError {
|
pub enum ScalarBookError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareScalarBook { source: rusqlite::Error },
|
PrepareScalarBook { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteScalarBook { source: rusqlite::Error },
|
ExecuteScalarBook { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
@ -75,6 +84,7 @@ pub struct MoreBooksError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Book {
|
impl Book {
|
||||||
|
/// Create a book from a database row.
|
||||||
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
|
|
|
@ -24,17 +24,23 @@ pub struct MultiplSeriesError {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching a series' books.
|
||||||
pub enum SeriesBooksError {
|
pub enum SeriesBooksError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareSeriesBooks { source: rusqlite::Error },
|
PrepareSeriesBooks { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteSeriesBooks { source: rusqlite::Error },
|
ExecuteSeriesBooks { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching a single series.
|
||||||
pub enum ScalarSeriesError {
|
pub enum ScalarSeriesError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareScalarSeries { source: rusqlite::Error },
|
PrepareScalarSeries { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteScalarSeries { source: rusqlite::Error },
|
ExecuteScalarSeries { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
@ -52,6 +58,7 @@ pub struct MoreSeriesError {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Series {
|
impl Series {
|
||||||
|
/// Create a series from a database row.
|
||||||
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
fn from_row(row: &Row<'_>) -> Result<Self, rusqlite::Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id: row.get(0)?,
|
id: row.get(0)?,
|
||||||
|
|
|
@ -35,39 +35,54 @@ const SEARCH_INIT_QUERY: &str = "INSERT INTO search.fts(book_id, data)
|
||||||
GROUP BY b.id";
|
GROUP BY b.id";
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when ensuring the search database is available.
|
||||||
pub enum EnsureSearchDbError {
|
pub enum EnsureSearchDbError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareEnsureSearch { source: rusqlite::Error },
|
PrepareEnsureSearch { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteEnsureSearch { source: rusqlite::Error },
|
ExecuteEnsureSearch { source: rusqlite::Error },
|
||||||
|
/// A failure to attach the database.
|
||||||
#[snafu(display("Failed to attach database."))]
|
#[snafu(display("Failed to attach database."))]
|
||||||
Attach { source: AttachError },
|
Attach { source: AttachError },
|
||||||
|
/// A failure to initialize the database.
|
||||||
#[snafu(display("Failed to initialize database."))]
|
#[snafu(display("Failed to initialize database."))]
|
||||||
Init { source: InitError },
|
Init { source: InitError },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when attaching the search database.
|
||||||
pub enum AttachError {
|
pub enum AttachError {
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteAttach { source: rusqlite::Error },
|
ExecuteAttach { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when initializing the search database.
|
||||||
pub enum InitError {
|
pub enum InitError {
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareInit { source: rusqlite::Error },
|
PrepareInit { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteInit { source: rusqlite::Error },
|
ExecuteInit { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when searching.
|
||||||
pub enum SearchError {
|
pub enum SearchError {
|
||||||
|
/// A failure to ensure the search database is initialized.
|
||||||
#[snafu(display("Failed ensure the search db is initialized."))]
|
#[snafu(display("Failed ensure the search db is initialized."))]
|
||||||
EnsureDb { source: EnsureSearchDbError },
|
EnsureDb { source: EnsureSearchDbError },
|
||||||
|
/// A failure to get a connection from the pool.
|
||||||
#[snafu(display("Failed to get connection from pool."))]
|
#[snafu(display("Failed to get connection from pool."))]
|
||||||
Connection { source: r2d2::Error },
|
Connection { source: r2d2::Error },
|
||||||
|
/// A failure to prepare the SQL statement.
|
||||||
#[snafu(display("Failed to prepare statement."))]
|
#[snafu(display("Failed to prepare statement."))]
|
||||||
PrepareSearch { source: rusqlite::Error },
|
PrepareSearch { source: rusqlite::Error },
|
||||||
|
/// A failure to execute the SQL statement.
|
||||||
#[snafu(display("Failed to execute statement."))]
|
#[snafu(display("Failed to execute statement."))]
|
||||||
ExecuteSearch { source: rusqlite::Error },
|
ExecuteSearch { source: rusqlite::Error },
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::{
|
||||||
use ignore::Walk;
|
use ignore::Walk;
|
||||||
use zip::{CompressionMethod, write::SimpleFileOptions};
|
use zip::{CompressionMethod, write::SimpleFileOptions};
|
||||||
|
|
||||||
|
/// Create a zip archive of the source code.
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let out_dir = env::var("OUT_DIR")?;
|
let out_dir = env::var("OUT_DIR")?;
|
||||||
let src_dir = "..";
|
let src_dir = "..";
|
||||||
|
|
|
@ -30,6 +30,7 @@ pub enum SortOrder {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<SortOrder> for calibre_db::data::pagination::SortOrder {
|
impl From<SortOrder> for calibre_db::data::pagination::SortOrder {
|
||||||
|
/// Convert the API sort order to the database sort order.
|
||||||
fn from(val: SortOrder) -> Self {
|
fn from(val: SortOrder) -> Self {
|
||||||
match val {
|
match val {
|
||||||
SortOrder::ASC => calibre_db::data::pagination::SortOrder::ASC,
|
SortOrder::ASC => calibre_db::data::pagination::SortOrder::ASC,
|
||||||
|
|
|
@ -10,13 +10,17 @@ use super::SortOrder;
|
||||||
use crate::data::book::Book;
|
use crate::data::book::Book;
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving a single author.
|
||||||
pub enum SingleAuthorError {
|
pub enum SingleAuthorError {
|
||||||
|
/// A failure to fetch author data.
|
||||||
#[snafu(display("Failed to fetch author data."))]
|
#[snafu(display("Failed to fetch author data."))]
|
||||||
AuthorData { source: DataStoreError },
|
AuthorData { source: DataStoreError },
|
||||||
|
/// A failure to fetch books from the author.
|
||||||
#[snafu(display("Failed to fetch books from author."))]
|
#[snafu(display("Failed to fetch books from author."))]
|
||||||
BookData { source: DataStoreError },
|
BookData { source: DataStoreError },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve a single author and all their books.
|
||||||
pub async fn single(
|
pub async fn single(
|
||||||
id: u64,
|
id: u64,
|
||||||
calibre: &Calibre,
|
calibre: &Calibre,
|
||||||
|
|
|
@ -6,11 +6,14 @@ use snafu::{ResultExt, Snafu};
|
||||||
use crate::data::book::Book;
|
use crate::data::book::Book;
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching recent books.
|
||||||
pub enum RecentBooksError {
|
pub enum RecentBooksError {
|
||||||
|
/// A failure to fetch recent books.
|
||||||
#[snafu(display("Failed to fetch recent books."))]
|
#[snafu(display("Failed to fetch recent books."))]
|
||||||
RecentBooks { source: DataStoreError },
|
RecentBooks { source: DataStoreError },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Fetch recent books and enrich them with additional information.
|
||||||
pub async fn recent(calibre: &Calibre, library_path: &Path) -> Result<Vec<Book>, RecentBooksError> {
|
pub async fn recent(calibre: &Calibre, library_path: &Path) -> Result<Vec<Book>, RecentBooksError> {
|
||||||
let recent_books = calibre.recent_books(25).context(RecentBooksSnafu)?;
|
let recent_books = calibre.recent_books(25).context(RecentBooksSnafu)?;
|
||||||
let recent_books = recent_books
|
let recent_books = recent_books
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Handlers for HTML responses.
|
||||||
pub mod archive;
|
pub mod archive;
|
||||||
pub mod authors;
|
pub mod authors;
|
||||||
pub mod books;
|
pub mod books;
|
||||||
|
|
|
@ -14,7 +14,9 @@ use crate::{
|
||||||
const SOURCE_ARCHIVE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/archive.zip"));
|
const SOURCE_ARCHIVE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/archive.zip"));
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when downloading the source code archive.
|
||||||
pub enum ArchiveError {
|
pub enum ArchiveError {
|
||||||
|
/// A failure to stream the source code archive.
|
||||||
#[snafu(display("Failed to stream source code archive."))]
|
#[snafu(display("Failed to stream source code archive."))]
|
||||||
Download { source: DownloadError },
|
Download { source: DownloadError },
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,9 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving authors.
|
||||||
pub enum RetrieveError {
|
pub enum RetrieveError {
|
||||||
|
/// A failure to fetch pagination data.
|
||||||
#[snafu(display("Failed to fetch pagination data."))]
|
#[snafu(display("Failed to fetch pagination data."))]
|
||||||
Authors { source: AuthorError },
|
Authors { source: AuthorError },
|
||||||
}
|
}
|
||||||
|
@ -68,11 +70,14 @@ pub async fn handler(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching an author.
|
||||||
pub enum AuthorError {
|
pub enum AuthorError {
|
||||||
|
/// A failure to fetch pagination data.
|
||||||
#[snafu(display("Failed to fetch pagination data."))]
|
#[snafu(display("Failed to fetch pagination data."))]
|
||||||
Pagination { source: PaginationError },
|
Pagination { source: PaginationError },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Render a paginated list of authors.
|
||||||
async fn authors(
|
async fn authors(
|
||||||
state: &Arc<AppState>,
|
state: &Arc<AppState>,
|
||||||
cursor: Option<&str>,
|
cursor: Option<&str>,
|
||||||
|
@ -89,9 +94,12 @@ async fn authors(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving a single author.
|
||||||
pub enum SingleError {
|
pub enum SingleError {
|
||||||
|
/// A failure to fetch author data.
|
||||||
#[snafu(display("Failed to fetch author data."))]
|
#[snafu(display("Failed to fetch author data."))]
|
||||||
Data { source: SingleAuthorError },
|
Data { source: SingleAuthorError },
|
||||||
|
/// A failure to render the template.
|
||||||
#[snafu(display("Failed to render template."))]
|
#[snafu(display("Failed to render template."))]
|
||||||
Render { source: tera::Error },
|
Render { source: tera::Error },
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ impl HttpStatus for SearchError {
|
||||||
http_error!(SearchError);
|
http_error!(SearchError);
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
/// Parameters for a search request.
|
||||||
pub struct Params {
|
pub struct Params {
|
||||||
/// Query for a search request.
|
/// Query for a search request.
|
||||||
query: String,
|
query: String,
|
||||||
|
|
|
@ -21,7 +21,9 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving series.
|
||||||
pub enum RetrieveError {
|
pub enum RetrieveError {
|
||||||
|
/// A failure to fetch series data.
|
||||||
#[snafu(display("Failed to fetch series data."))]
|
#[snafu(display("Failed to fetch series data."))]
|
||||||
Series { source: SeriesError },
|
Series { source: SeriesError },
|
||||||
}
|
}
|
||||||
|
@ -68,11 +70,14 @@ pub async fn handler(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when fetching a series.
|
||||||
pub enum SeriesError {
|
pub enum SeriesError {
|
||||||
|
/// A failure to fetch pagination data.
|
||||||
#[snafu(display("Failed to fetch pagination data."))]
|
#[snafu(display("Failed to fetch pagination data."))]
|
||||||
Pagination { source: PaginationError },
|
Pagination { source: PaginationError },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Render a paginated list of series.
|
||||||
async fn series(
|
async fn series(
|
||||||
state: &Arc<AppState>,
|
state: &Arc<AppState>,
|
||||||
cursor: Option<&str>,
|
cursor: Option<&str>,
|
||||||
|
@ -89,9 +94,12 @@ async fn series(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving a single series.
|
||||||
pub enum SingleError {
|
pub enum SingleError {
|
||||||
|
/// A failure to fetch series data.
|
||||||
#[snafu(display("Failed to fetch series data."))]
|
#[snafu(display("Failed to fetch series data."))]
|
||||||
Data { source: SingleSeriesError },
|
Data { source: SingleSeriesError },
|
||||||
|
/// A failure to render the template.
|
||||||
#[snafu(display("Failed to render template."))]
|
#[snafu(display("Failed to render template."))]
|
||||||
Render { source: tera::Error },
|
Render { source: tera::Error },
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//! Handlers for OPDS feeds.
|
||||||
pub mod authors;
|
pub mod authors;
|
||||||
pub mod books;
|
pub mod books;
|
||||||
pub mod recent;
|
pub mod recent;
|
||||||
|
|
|
@ -25,9 +25,12 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving all authors.
|
||||||
pub enum AuthorsError {
|
pub enum AuthorsError {
|
||||||
|
/// A failure to fetch author data.
|
||||||
#[snafu(display("Failed to fetch author data."))]
|
#[snafu(display("Failed to fetch author data."))]
|
||||||
Data { source: DataStoreError },
|
Data { source: DataStoreError },
|
||||||
|
/// A failure to render author data.
|
||||||
#[snafu(display("Failed to render author data."))]
|
#[snafu(display("Failed to render author data."))]
|
||||||
Render { source: AsXmlError },
|
Render { source: AsXmlError },
|
||||||
}
|
}
|
||||||
|
@ -81,9 +84,12 @@ pub async fn handler(State(state): State<Arc<AppState>>) -> Result<Response, Aut
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving a single author.
|
||||||
pub enum SingleError {
|
pub enum SingleError {
|
||||||
|
/// A failure to fetch author data.
|
||||||
#[snafu(display("Failed to fetch author data."))]
|
#[snafu(display("Failed to fetch author data."))]
|
||||||
AuthorData { source: SingleAuthorError },
|
AuthorData { source: SingleAuthorError },
|
||||||
|
/// A failure to render the feed.
|
||||||
#[snafu(display("Failed to render feed."))]
|
#[snafu(display("Failed to render feed."))]
|
||||||
FeedRender { source: AsXmlError },
|
FeedRender { source: AsXmlError },
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,12 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving books for OPDS.
|
||||||
pub enum OdpsBooksError {
|
pub enum OdpsBooksError {
|
||||||
|
/// A failure to fetch book data.
|
||||||
#[snafu(display("Failed to fetch book data."))]
|
#[snafu(display("Failed to fetch book data."))]
|
||||||
Data { source: DataStoreError },
|
Data { source: DataStoreError },
|
||||||
|
/// A failure to render book data.
|
||||||
#[snafu(display("Failed to render book data."))]
|
#[snafu(display("Failed to render book data."))]
|
||||||
Render { source: RenderError },
|
Render { source: RenderError },
|
||||||
}
|
}
|
||||||
|
@ -65,7 +68,9 @@ pub async fn handler(State(state): State<Arc<AppState>>) -> Result<Response, Odp
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when rendering a feed.
|
||||||
pub enum RenderError {
|
pub enum RenderError {
|
||||||
|
/// A failure to create the OPDS feed.
|
||||||
#[snafu(display("Failed to create opds feed."))]
|
#[snafu(display("Failed to create opds feed."))]
|
||||||
Feed { source: AsXmlError },
|
Feed { source: AsXmlError },
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,12 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving recent books.
|
||||||
pub enum RecentError {
|
pub enum RecentError {
|
||||||
|
/// A failure to fetch recent books.
|
||||||
#[snafu(display("Failed to fetch recent books."))]
|
#[snafu(display("Failed to fetch recent books."))]
|
||||||
Data { source: RecentBooksError },
|
Data { source: RecentBooksError },
|
||||||
|
/// A failure to render the feed.
|
||||||
#[snafu(display("Failed to render feed."))]
|
#[snafu(display("Failed to render feed."))]
|
||||||
Render { source: AsXmlError },
|
Render { source: AsXmlError },
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,9 +25,12 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when searching for books.
|
||||||
pub enum SearchError {
|
pub enum SearchError {
|
||||||
|
/// A failure to query for books.
|
||||||
#[snafu(display("Failed to query books."))]
|
#[snafu(display("Failed to query books."))]
|
||||||
Query { source: SearchQueryError },
|
Query { source: SearchQueryError },
|
||||||
|
/// A failure to render the feed.
|
||||||
#[snafu(display("Failed to render feed."))]
|
#[snafu(display("Failed to render feed."))]
|
||||||
Render { source: RenderError },
|
Render { source: RenderError },
|
||||||
}
|
}
|
||||||
|
@ -42,6 +45,7 @@ impl HttpStatus for SearchError {
|
||||||
http_error!(SearchError);
|
http_error!(SearchError);
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
/// Parameters for a search request.
|
||||||
pub struct Params {
|
pub struct Params {
|
||||||
/// Query for a search request.
|
/// Query for a search request.
|
||||||
query: String,
|
query: String,
|
||||||
|
@ -67,7 +71,9 @@ pub async fn handler(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving search information.
|
||||||
pub enum InfoError {
|
pub enum InfoError {
|
||||||
|
/// A failure to render the feed.
|
||||||
#[snafu(display("Failed to render feed."))]
|
#[snafu(display("Failed to render feed."))]
|
||||||
FeedRender { source: AsXmlError },
|
FeedRender { source: AsXmlError },
|
||||||
}
|
}
|
||||||
|
@ -81,6 +87,7 @@ impl HttpStatus for InfoError {
|
||||||
|
|
||||||
http_error!(InfoError);
|
http_error!(InfoError);
|
||||||
|
|
||||||
|
/// Render search information as an OPDS feed.
|
||||||
#[utoipa::path(
|
#[utoipa::path(
|
||||||
get,
|
get,
|
||||||
path = "/search/info",
|
path = "/search/info",
|
||||||
|
|
|
@ -25,9 +25,12 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving all series.
|
||||||
pub enum SeriesError {
|
pub enum SeriesError {
|
||||||
|
/// A failure to fetch series data.
|
||||||
#[snafu(display("Failed to fetch series data."))]
|
#[snafu(display("Failed to fetch series data."))]
|
||||||
Data { source: DataStoreError },
|
Data { source: DataStoreError },
|
||||||
|
/// A failure to render series data.
|
||||||
#[snafu(display("Failed to render series data."))]
|
#[snafu(display("Failed to render series data."))]
|
||||||
Render { source: AsXmlError },
|
Render { source: AsXmlError },
|
||||||
}
|
}
|
||||||
|
@ -81,9 +84,12 @@ pub async fn handler(State(state): State<Arc<AppState>>) -> Result<Response, Ser
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving a single series.
|
||||||
pub enum SingleError {
|
pub enum SingleError {
|
||||||
|
/// A failure to fetch series data.
|
||||||
#[snafu(display("Failed to fetch series data."))]
|
#[snafu(display("Failed to fetch series data."))]
|
||||||
SeriesData { source: SingleSeriesError },
|
SeriesData { source: SingleSeriesError },
|
||||||
|
/// A failure to render the feed.
|
||||||
#[snafu(display("Failed to render feed."))]
|
#[snafu(display("Failed to render feed."))]
|
||||||
FeedRender { source: AsXmlError },
|
FeedRender { source: AsXmlError },
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,18 @@ use tera::Context;
|
||||||
use crate::templates::TEMPLATES;
|
use crate::templates::TEMPLATES;
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur during pagination.
|
||||||
pub enum PaginationError {
|
pub enum PaginationError {
|
||||||
|
/// A failure to fetch pagination data.
|
||||||
#[snafu(display("Failed to fetch pagination data."))]
|
#[snafu(display("Failed to fetch pagination data."))]
|
||||||
Fetch { source: DataStoreError },
|
Fetch { source: DataStoreError },
|
||||||
|
/// A failure to render the template.
|
||||||
#[snafu(display("Failed to render template."))]
|
#[snafu(display("Failed to render template."))]
|
||||||
Template { source: tera::Error },
|
Template { source: tera::Error },
|
||||||
|
/// A failure to fetch previous items.
|
||||||
#[snafu(display("Failed to fetch previous items."))]
|
#[snafu(display("Failed to fetch previous items."))]
|
||||||
Previous { source: DataStoreError },
|
Previous { source: DataStoreError },
|
||||||
|
/// A failure to fetch more items.
|
||||||
#[snafu(display("Failed to fetch more items."))]
|
#[snafu(display("Failed to fetch more items."))]
|
||||||
More { source: DataStoreError },
|
More { source: DataStoreError },
|
||||||
}
|
}
|
||||||
|
|
0
little-hesinde/src/api/recent.rs
Normal file
0
little-hesinde/src/api/recent.rs
Normal file
|
@ -6,11 +6,14 @@ use snafu::{ResultExt, Snafu};
|
||||||
use crate::data::book::Book;
|
use crate::data::book::Book;
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when querying for books.
|
||||||
pub enum SearchQueryError {
|
pub enum SearchQueryError {
|
||||||
|
/// A failure to query the database.
|
||||||
#[snafu(display("Failed to search for books."))]
|
#[snafu(display("Failed to search for books."))]
|
||||||
Db { source: DataStoreError },
|
Db { source: DataStoreError },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Query for books and enrich them with additional information.
|
||||||
pub async fn query(
|
pub async fn query(
|
||||||
query: &str,
|
query: &str,
|
||||||
calibre: &Calibre,
|
calibre: &Calibre,
|
||||||
|
|
|
@ -9,13 +9,17 @@ use snafu::{ResultExt, Snafu};
|
||||||
use crate::data::book::Book;
|
use crate::data::book::Book;
|
||||||
|
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
|
/// Errors that can occur when retrieving a single series.
|
||||||
pub enum SingleSeriesError {
|
pub enum SingleSeriesError {
|
||||||
|
/// A failure to fetch series data.
|
||||||
#[snafu(display("Failed to fetch series data."))]
|
#[snafu(display("Failed to fetch series data."))]
|
||||||
SeriesData { source: DataStoreError },
|
SeriesData { source: DataStoreError },
|
||||||
|
/// A failure to fetch books in the series.
|
||||||
#[snafu(display("Failed to fetch books in series."))]
|
#[snafu(display("Failed to fetch books in series."))]
|
||||||
BookData { source: DataStoreError },
|
BookData { source: DataStoreError },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve a single series and all its books.
|
||||||
pub async fn single(
|
pub async fn single(
|
||||||
id: u64,
|
id: u64,
|
||||||
calibre: &Calibre,
|
calibre: &Calibre,
|
||||||
|
|
|
@ -28,6 +28,7 @@ pub async fn handler(uri: Uri) -> impl IntoResponse {
|
||||||
StaticFile(path)
|
StaticFile(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A wrapper type for static files.
|
||||||
pub struct StaticFile<T>(pub T);
|
pub struct StaticFile<T>(pub T);
|
||||||
|
|
||||||
impl<T> IntoResponse for StaticFile<T>
|
impl<T> IntoResponse for StaticFile<T>
|
||||||
|
|
|
@ -14,17 +14,22 @@ use crate::cli::Cli;
|
||||||
/// Errors from loading application configuration.
|
/// Errors from loading application configuration.
|
||||||
#[derive(Debug, Snafu)]
|
#[derive(Debug, Snafu)]
|
||||||
pub enum LoadError {
|
pub enum LoadError {
|
||||||
|
/// The provided path is not a calibre library.
|
||||||
#[snafu(display("{path} is not a calibre library."))]
|
#[snafu(display("{path} is not a calibre library."))]
|
||||||
LibraryPath { path: String },
|
LibraryPath { path: String },
|
||||||
|
/// Could not find the calibre metadata database.
|
||||||
#[snafu(display("Could not find calibre metadata at {path}."))]
|
#[snafu(display("Could not find calibre metadata at {path}."))]
|
||||||
MetadataPath { path: String },
|
MetadataPath { path: String },
|
||||||
|
/// The listening address could not be parsed.
|
||||||
#[snafu(display("Invalid listening address {listen_address}."))]
|
#[snafu(display("Invalid listening address {listen_address}."))]
|
||||||
ListeningAddressParse {
|
ListeningAddressParse {
|
||||||
source: io::Error,
|
source: io::Error,
|
||||||
listen_address: String,
|
listen_address: String,
|
||||||
},
|
},
|
||||||
|
/// The listening address is invalid.
|
||||||
#[snafu(display("Invalid listening address {listen_address}."))]
|
#[snafu(display("Invalid listening address {listen_address}."))]
|
||||||
ListeningAddress { listen_address: String },
|
ListeningAddress { listen_address: String },
|
||||||
|
/// The cache directory could not be created.
|
||||||
#[snafu(display("Failed to create cach directory at {path}."))]
|
#[snafu(display("Failed to create cach directory at {path}."))]
|
||||||
CacheDir { source: io::Error, path: String },
|
CacheDir { source: io::Error, path: String },
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,2 @@
|
||||||
|
//! Data types and functions for enriching calibre data.
|
||||||
pub mod book;
|
pub mod book;
|
||||||
|
|
|
@ -17,8 +17,10 @@ use super::error::{
|
||||||
/// Url pointing to a location.
|
/// Url pointing to a location.
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
pub struct Url {
|
pub struct Url {
|
||||||
|
/// The media type of the resource.
|
||||||
#[serde(rename = "@type")]
|
#[serde(rename = "@type")]
|
||||||
pub type_name: String,
|
pub type_name: String,
|
||||||
|
/// The URL template.
|
||||||
#[serde(rename = "@template")]
|
#[serde(rename = "@template")]
|
||||||
pub template: String,
|
pub template: String,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue