diff --git a/src/bots/approved_bot/modules/book.rs b/src/bots/approved_bot/modules/book.rs index 50cd394..2f08a0b 100644 --- a/src/bots/approved_bot/modules/book.rs +++ b/src/bots/approved_bot/modules/book.rs @@ -7,7 +7,7 @@ use teloxide::{dispatching::UpdateFilterExt, dptree, prelude::*, adaptors::{Thro use crate::{bots::approved_bot::{ services::{ book_library::{ - formaters::Format, get_author_books, get_sequence_books, get_translator_books, + formaters::{Format, FormatTitle}, get_author_books, get_sequence_books, get_translator_books, types::Page, }, user_settings::get_user_or_default_lang_codes, @@ -113,7 +113,7 @@ impl GetPaginationCallbackData for BookCallbackData { } } -async fn send_book_handler( +async fn send_book_handler( message: Message, bot: CacheMe>, command: BookCommand, @@ -122,7 +122,8 @@ async fn send_book_handler( ) -> crate::bots::BotHandlerInternal where T: Format + Clone, - Fut: std::future::Future, Box>>, + P: FormatTitle + Clone, + Fut: std::future::Future, Box>>, { let id = match command { BookCommand::Author { id } => id, @@ -189,7 +190,7 @@ where Ok(()) } -async fn send_pagination_book_handler( +async fn send_pagination_book_handler( cq: CallbackQuery, bot: CacheMe>, callback_data: BookCallbackData, @@ -198,7 +199,8 @@ async fn send_pagination_book_handler( ) -> crate::bots::BotHandlerInternal where T: Format + Clone, - Fut: std::future::Future, Box>>, + P: FormatTitle + Clone, + Fut: std::future::Future, Box>>, { let (id, page) = match callback_data { BookCallbackData::Author { id, page } => (id, page), diff --git a/src/bots/approved_bot/modules/search.rs b/src/bots/approved_bot/modules/search.rs index 139db11..d645677 100644 --- a/src/bots/approved_bot/modules/search.rs +++ b/src/bots/approved_bot/modules/search.rs @@ -12,7 +12,7 @@ use crate::{bots::{ approved_bot::{ services::{ book_library::{ - formaters::Format, search_author, search_book, search_sequence, search_translator, + formaters::{Format, FormatTitle}, search_author, search_book, search_sequence, search_translator, types::Page, }, user_settings::get_user_or_default_lang_codes, @@ -106,7 +106,7 @@ fn get_query(cq: CallbackQuery) -> Option { .unwrap_or(None) } -async fn generic_search_pagination_handler( +async fn generic_search_pagination_handler( cq: CallbackQuery, bot: CacheMe>, search_data: SearchCallbackData, @@ -115,7 +115,8 @@ async fn generic_search_pagination_handler( ) -> BotHandlerInternal where T: Format + Clone, - Fut: std::future::Future, Box>>, + P: FormatTitle + Clone, + Fut: std::future::Future, Box>>, { let chat_id = cq.chat_id(); let user_id = cq.from.id; diff --git a/src/bots/approved_bot/services/book_library/formaters.rs b/src/bots/approved_bot/services/book_library/formaters.rs index fff63c7..b0f6010 100644 --- a/src/bots/approved_bot/services/book_library/formaters.rs +++ b/src/bots/approved_bot/services/book_library/formaters.rs @@ -4,7 +4,7 @@ use crate::bots::approved_bot::modules::download::StartDownloadData; use super::types::{ Author, AuthorBook, Book, BookAuthor, BookGenre, SearchBook, Sequence, Translator, - TranslatorBook, SequenceBook, BookTranslator, + TranslatorBook, SequenceBook, BookTranslator, Empty, }; const NO_LIMIT: usize = 4096; @@ -25,6 +25,62 @@ pub trait FormatInline { fn format_inline(&self) -> String; } +pub trait FormatTitle { + fn format_title(&self) -> String; +} + +impl FormatTitle for Empty { + fn format_title(&self) -> String { + "".to_string() + } +} + +impl FormatTitle for BookAuthor { + fn format_title(&self) -> String { + let BookAuthor { + id, + last_name, + first_name, + middle_name, + } = self; + + if *id == 0 { + return "".to_string() + } + + format!("👤 {last_name} {first_name} {middle_name}") + } +} + +impl FormatTitle for BookTranslator { + fn format_title(&self) -> String { + let BookTranslator { + id, + first_name, + last_name, + middle_name, + } = self; + + if *id == 0 { + return "".to_string() + } + + format!("👤 {last_name} {first_name} {middle_name}") + } +} + +impl FormatTitle for Sequence { + fn format_title(&self) -> String { + let Sequence { id, name } = self; + + if *id == 0 { + return "".to_string() + } + + format!("📚 {name}") + } +} + impl FormatInline for BookAuthor { fn format_inline(&self) -> String { let BookAuthor { diff --git a/src/bots/approved_bot/services/book_library/mod.rs b/src/bots/approved_bot/services/book_library/mod.rs index 4488964..951fe44 100644 --- a/src/bots/approved_bot/services/book_library/mod.rs +++ b/src/bots/approved_bot/services/book_library/mod.rs @@ -5,6 +5,8 @@ use serde::de::DeserializeOwned; use crate::config; +use self::types::Empty; + fn get_allowed_langs_params(allowed_langs: Vec) -> Vec<(&'static str, String)> { allowed_langs .into_iter() @@ -83,7 +85,7 @@ pub async fn get_genre_metas() -> Result, Box Result, Box> { +) -> Result, Box> { let params = vec![("meta", meta)]; _make_request("/api/v1/genres/", params).await @@ -95,7 +97,7 @@ pub async fn search_book( query: String, page: u32, allowed_langs: Vec, -) -> Result, Box> { +) -> Result, Box> { let mut params = get_allowed_langs_params(allowed_langs); params.push(("page", page.to_string())); @@ -108,7 +110,7 @@ pub async fn search_author( query: String, page: u32, allowed_langs: Vec, -) -> Result, Box> { +) -> Result, Box> { let mut params = get_allowed_langs_params(allowed_langs); params.push(("page", page.to_string())); @@ -121,7 +123,7 @@ pub async fn search_sequence( query: String, page: u32, allowed_langs: Vec, -) -> Result, Box> { +) -> Result, Box> { let mut params = get_allowed_langs_params(allowed_langs); params.push(("page", page.to_string())); @@ -134,7 +136,7 @@ pub async fn search_translator( query: String, page: u32, allowed_langs: Vec, -) -> Result, Box> { +) -> Result, Box> { let mut params = get_allowed_langs_params(allowed_langs); params.push(("page", page.to_string())); @@ -163,7 +165,7 @@ pub async fn get_author_books( id: u32, page: u32, allowed_langs: Vec, -) -> Result, Box> { +) -> Result, Box> { let mut params = get_allowed_langs_params(allowed_langs); params.push(("page", page.to_string())); @@ -176,7 +178,7 @@ pub async fn get_translator_books( id: u32, page: u32, allowed_langs: Vec, -) -> Result, Box> { +) -> Result, Box> { let mut params = get_allowed_langs_params(allowed_langs); params.push(("page", page.to_string())); @@ -189,7 +191,7 @@ pub async fn get_sequence_books( id: u32, page: u32, allowed_langs: Vec, -) -> Result, Box> { +) -> Result, Box> { let mut params = get_allowed_langs_params(allowed_langs); params.push(("page", page.to_string())); @@ -202,7 +204,7 @@ pub async fn get_uploaded_books( page: u32, uploaded_gte: String, uploaded_lte: String, -) -> Result, Box> { +) -> Result, Box> { let params = vec![ ("page", page.to_string()), ("size", PAGE_SIZE.to_string()), diff --git a/src/bots/approved_bot/services/book_library/types.rs b/src/bots/approved_bot/services/book_library/types.rs index 248b68e..9f712e9 100644 --- a/src/bots/approved_bot/services/book_library/types.rs +++ b/src/bots/approved_bot/services/book_library/types.rs @@ -1,9 +1,9 @@ use serde::Deserialize; -use super::formaters::{Format, FormatResult}; +use super::formaters::{Format, FormatResult, FormatTitle}; -#[derive(Deserialize, Debug, Clone)] +#[derive(Default, Deserialize, Debug, Clone)] pub struct BookAuthor { pub id: u32, pub first_name: String, @@ -11,7 +11,7 @@ pub struct BookAuthor { pub middle_name: String, } -#[derive(Deserialize, Debug, Clone)] +#[derive(Default, Deserialize, Debug, Clone)] pub struct BookTranslator { pub id: u32, pub first_name: String, @@ -55,7 +55,7 @@ pub struct Translator { pub annotation_exists: bool, } -#[derive(Deserialize, Debug, Clone)] +#[derive(Default, Deserialize, Debug, Clone)] pub struct Sequence { pub id: u32, pub name: String, @@ -71,8 +71,11 @@ pub struct Genre { pub meta: String, } +#[derive(Default, Deserialize, Debug, Clone)] +pub struct Empty {} + #[derive(Deserialize, Debug, Clone)] -pub struct Page { +pub struct Page { pub items: Vec, pub total: u32, @@ -80,18 +83,36 @@ pub struct Page { pub size: u32, pub pages: u32, + + #[serde(default)] + pub parent_item: Option

} -impl Page +impl Page where T: Format + Clone, + P: FormatTitle + Clone { pub fn format_items(&self, max_size: usize) -> String { + let title: String = match &self.parent_item { + Some(parent_item) => { + let item_title = parent_item.format_title(); + + if item_title.is_empty() { + return "".to_string(); + } + + format!("{item_title}\n\n\n") + }, + None => "".to_string(), + }; + let title_len: usize = title.len(); + let separator = "\n\n\n"; let separator_len: usize = separator.len(); let items_count: usize = self.items.len(); - let item_size: usize = (max_size - separator_len * items_count) / items_count; + let item_size: usize = (max_size - title_len - separator_len * items_count) / items_count; let format_result: Vec = self.items .iter() @@ -118,7 +139,7 @@ where .map(|item| item_size - item.current_size) .sum(); - self.items + let items_string = self.items .iter() .enumerate() .map(|(index, item)| { @@ -136,7 +157,9 @@ where } }) .collect::>() - .join(separator) + .join(separator); + + format!("{title}{items_string}") } }