book feed
This commit is contained in:
parent
603c2fbe48
commit
12341d01a6
15 changed files with 219 additions and 41 deletions
|
@ -7,7 +7,11 @@ use poem::{
|
|||
IntoResponse,
|
||||
};
|
||||
|
||||
use crate::{app_state::AppState, data::book::Book, handlers::error::HandlerError};
|
||||
use crate::{
|
||||
app_state::AppState,
|
||||
data::book::{Book, Format},
|
||||
handlers::error::HandlerError,
|
||||
};
|
||||
|
||||
#[handler]
|
||||
pub async fn handler(
|
||||
|
@ -19,18 +23,14 @@ pub async fn handler(
|
|||
.scalar_book(id)
|
||||
.map_err(HandlerError::DataError)?;
|
||||
let book = Book::full_book(&book, &state).ok_or(NotFoundError)?;
|
||||
let format: &str = format.as_str();
|
||||
let file_name = book.formats.get(format).ok_or(NotFoundError)?;
|
||||
let format = Format(format);
|
||||
let file_name = book.formats.get(&format).ok_or(NotFoundError)?;
|
||||
let file_path = state.config.library_path.join(book.path).join(file_name);
|
||||
let mut file = File::open(file_path).map_err(|_| NotFoundError)?;
|
||||
|
||||
let mut data = Vec::new();
|
||||
file.read_to_end(&mut data).map_err(|_| NotFoundError)?;
|
||||
let content_type = match format {
|
||||
"pdf" => "application/pdf",
|
||||
"epub" => "application/epub+zip",
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let content_type = format.0;
|
||||
|
||||
Ok(data
|
||||
.with_content_type(content_type)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use calibre_db::data::pagination::SortOrder;
|
||||
use poem::{
|
||||
handler,
|
||||
web::{Data, WithContentType},
|
||||
|
@ -9,6 +10,7 @@ use time::OffsetDateTime;
|
|||
|
||||
use crate::{
|
||||
app_state::AppState,
|
||||
data::book::Book,
|
||||
handlers::error::HandlerError,
|
||||
opds::{
|
||||
author::Author, content::Content, entry::Entry, feed::Feed, link::Link,
|
||||
|
@ -16,22 +18,72 @@ use crate::{
|
|||
},
|
||||
};
|
||||
|
||||
#[handler]
|
||||
pub async fn handler(state: Data<&Arc<AppState>>) -> Result<WithContentType<String>, poem::Error> {
|
||||
let now = OffsetDateTime::now_utc();
|
||||
|
||||
fn create_feed(
|
||||
now: OffsetDateTime,
|
||||
self_link: Link,
|
||||
mut additional_links: Vec<Link>,
|
||||
entries: Vec<Entry>,
|
||||
) -> Feed {
|
||||
let author = Author {
|
||||
name: "Thallian".to_string(),
|
||||
uri: "https://code.vanwa.ch/shu/rusty-library".to_string(),
|
||||
email: None,
|
||||
};
|
||||
let home_link = Link {
|
||||
href: "/opds".to_string(),
|
||||
let mut links = vec![
|
||||
Link {
|
||||
href: "/opds".to_string(),
|
||||
media_type: MediaType::Navigation,
|
||||
rel: Relation::Start,
|
||||
title: Some("Home".to_string()),
|
||||
count: None,
|
||||
},
|
||||
self_link,
|
||||
];
|
||||
links.append(&mut additional_links);
|
||||
|
||||
Feed {
|
||||
title: "rusty-library".to_string(),
|
||||
id: "rusty:catalog".to_string(),
|
||||
updated: now,
|
||||
icon: "favicon.ico".to_string(),
|
||||
author,
|
||||
links,
|
||||
entries,
|
||||
}
|
||||
}
|
||||
|
||||
#[handler]
|
||||
pub async fn books(state: Data<&Arc<AppState>>) -> Result<WithContentType<String>, poem::Error> {
|
||||
let books: Vec<Book> = state
|
||||
.calibre
|
||||
.books(u32::MAX.into(), None, &SortOrder::ASC)
|
||||
.map(|x| {
|
||||
x.iter()
|
||||
.filter_map(|y| Book::full_book(y, &state))
|
||||
.collect()
|
||||
})
|
||||
.map_err(HandlerError::DataError)?;
|
||||
|
||||
let entries: Vec<Entry> = books.into_iter().map(Entry::from).collect();
|
||||
let now = OffsetDateTime::now_utc();
|
||||
|
||||
let self_link = Link {
|
||||
href: "/opds/books".to_string(),
|
||||
media_type: MediaType::Navigation,
|
||||
rel: Relation::Start,
|
||||
title: Some("Home".to_string()),
|
||||
rel: Relation::Myself,
|
||||
title: None,
|
||||
count: None,
|
||||
};
|
||||
let feed = create_feed(now, self_link, vec![], entries);
|
||||
let xml = feed.as_xml().map_err(HandlerError::OpdsError)?;
|
||||
|
||||
Ok(xml.with_content_type("application/atom+xml"))
|
||||
}
|
||||
|
||||
#[handler]
|
||||
pub async fn handler(state: Data<&Arc<AppState>>) -> Result<WithContentType<String>, poem::Error> {
|
||||
let now = OffsetDateTime::now_utc();
|
||||
|
||||
let self_link = Link {
|
||||
href: "/opds".to_string(),
|
||||
media_type: MediaType::Navigation,
|
||||
|
@ -47,6 +99,7 @@ pub async fn handler(state: Data<&Arc<AppState>>) -> Result<WithContentType<Stri
|
|||
media_type: MediaType::Text,
|
||||
content: "Index of all books".to_string(),
|
||||
},
|
||||
author: None,
|
||||
links: vec![Link {
|
||||
href: "/opds/books".to_string(),
|
||||
media_type: MediaType::Navigation,
|
||||
|
@ -56,15 +109,7 @@ pub async fn handler(state: Data<&Arc<AppState>>) -> Result<WithContentType<Stri
|
|||
}],
|
||||
};
|
||||
|
||||
let feed = Feed {
|
||||
title: "rusty-library".to_string(),
|
||||
id: "rusty:catalog".to_string(),
|
||||
updated: now,
|
||||
icon: "favicon.ico".to_string(),
|
||||
author,
|
||||
links: vec![home_link, self_link],
|
||||
entries: vec![books_entry],
|
||||
};
|
||||
let feed = create_feed(now, self_link, vec![], vec![books_entry]);
|
||||
let xml = feed.as_xml().map_err(HandlerError::OpdsError)?;
|
||||
|
||||
Ok(xml.with_content_type("application/atom+xml"))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue