Add title to page formating

This commit is contained in:
2023-06-06 22:21:39 +02:00
parent 5dc946cec0
commit b902e5f488
5 changed files with 111 additions and 27 deletions

View File

@@ -7,7 +7,7 @@ use teloxide::{dispatching::UpdateFilterExt, dptree, prelude::*, adaptors::{Thro
use crate::{bots::approved_bot::{ use crate::{bots::approved_bot::{
services::{ services::{
book_library::{ 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, types::Page,
}, },
user_settings::get_user_or_default_lang_codes, user_settings::get_user_or_default_lang_codes,
@@ -113,7 +113,7 @@ impl GetPaginationCallbackData for BookCallbackData {
} }
} }
async fn send_book_handler<T, Fut>( async fn send_book_handler<T, P, Fut>(
message: Message, message: Message,
bot: CacheMe<Throttle<Bot>>, bot: CacheMe<Throttle<Bot>>,
command: BookCommand, command: BookCommand,
@@ -122,7 +122,8 @@ async fn send_book_handler<T, Fut>(
) -> crate::bots::BotHandlerInternal ) -> crate::bots::BotHandlerInternal
where where
T: Format + Clone, T: Format + Clone,
Fut: std::future::Future<Output = Result<Page<T>, Box<dyn std::error::Error + Send + Sync>>>, P: FormatTitle + Clone,
Fut: std::future::Future<Output = Result<Page<T, P>, Box<dyn std::error::Error + Send + Sync>>>,
{ {
let id = match command { let id = match command {
BookCommand::Author { id } => id, BookCommand::Author { id } => id,
@@ -189,7 +190,7 @@ where
Ok(()) Ok(())
} }
async fn send_pagination_book_handler<T, Fut>( async fn send_pagination_book_handler<T, P, Fut>(
cq: CallbackQuery, cq: CallbackQuery,
bot: CacheMe<Throttle<Bot>>, bot: CacheMe<Throttle<Bot>>,
callback_data: BookCallbackData, callback_data: BookCallbackData,
@@ -198,7 +199,8 @@ async fn send_pagination_book_handler<T, Fut>(
) -> crate::bots::BotHandlerInternal ) -> crate::bots::BotHandlerInternal
where where
T: Format + Clone, T: Format + Clone,
Fut: std::future::Future<Output = Result<Page<T>, Box<dyn std::error::Error + Send + Sync>>>, P: FormatTitle + Clone,
Fut: std::future::Future<Output = Result<Page<T, P>, Box<dyn std::error::Error + Send + Sync>>>,
{ {
let (id, page) = match callback_data { let (id, page) = match callback_data {
BookCallbackData::Author { id, page } => (id, page), BookCallbackData::Author { id, page } => (id, page),

View File

@@ -12,7 +12,7 @@ use crate::{bots::{
approved_bot::{ approved_bot::{
services::{ services::{
book_library::{ 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, types::Page,
}, },
user_settings::get_user_or_default_lang_codes, user_settings::get_user_or_default_lang_codes,
@@ -106,7 +106,7 @@ fn get_query(cq: CallbackQuery) -> Option<String> {
.unwrap_or(None) .unwrap_or(None)
} }
async fn generic_search_pagination_handler<T, Fut>( async fn generic_search_pagination_handler<T, P, Fut>(
cq: CallbackQuery, cq: CallbackQuery,
bot: CacheMe<Throttle<Bot>>, bot: CacheMe<Throttle<Bot>>,
search_data: SearchCallbackData, search_data: SearchCallbackData,
@@ -115,7 +115,8 @@ async fn generic_search_pagination_handler<T, Fut>(
) -> BotHandlerInternal ) -> BotHandlerInternal
where where
T: Format + Clone, T: Format + Clone,
Fut: std::future::Future<Output = Result<Page<T>, Box<dyn std::error::Error + Send + Sync>>>, P: FormatTitle + Clone,
Fut: std::future::Future<Output = Result<Page<T, P>, Box<dyn std::error::Error + Send + Sync>>>,
{ {
let chat_id = cq.chat_id(); let chat_id = cq.chat_id();
let user_id = cq.from.id; let user_id = cq.from.id;

View File

@@ -4,7 +4,7 @@ use crate::bots::approved_bot::modules::download::StartDownloadData;
use super::types::{ use super::types::{
Author, AuthorBook, Book, BookAuthor, BookGenre, SearchBook, Sequence, Translator, Author, AuthorBook, Book, BookAuthor, BookGenre, SearchBook, Sequence, Translator,
TranslatorBook, SequenceBook, BookTranslator, TranslatorBook, SequenceBook, BookTranslator, Empty,
}; };
const NO_LIMIT: usize = 4096; const NO_LIMIT: usize = 4096;
@@ -25,6 +25,62 @@ pub trait FormatInline {
fn format_inline(&self) -> String; 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 { impl FormatInline for BookAuthor {
fn format_inline(&self) -> String { fn format_inline(&self) -> String {
let BookAuthor { let BookAuthor {

View File

@@ -5,6 +5,8 @@ use serde::de::DeserializeOwned;
use crate::config; use crate::config;
use self::types::Empty;
fn get_allowed_langs_params(allowed_langs: Vec<String>) -> Vec<(&'static str, String)> { fn get_allowed_langs_params(allowed_langs: Vec<String>) -> Vec<(&'static str, String)> {
allowed_langs allowed_langs
.into_iter() .into_iter()
@@ -83,7 +85,7 @@ pub async fn get_genre_metas() -> Result<Vec<String>, Box<dyn std::error::Error
pub async fn get_genres( pub async fn get_genres(
meta: String, meta: String,
) -> Result<types::Page<types::Genre>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::Genre, Empty>, Box<dyn std::error::Error + Send + Sync>> {
let params = vec![("meta", meta)]; let params = vec![("meta", meta)];
_make_request("/api/v1/genres/", params).await _make_request("/api/v1/genres/", params).await
@@ -95,7 +97,7 @@ pub async fn search_book(
query: String, query: String,
page: u32, page: u32,
allowed_langs: Vec<String>, allowed_langs: Vec<String>,
) -> Result<types::Page<types::SearchBook>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::SearchBook, Empty>, Box<dyn std::error::Error + Send + Sync>> {
let mut params = get_allowed_langs_params(allowed_langs); let mut params = get_allowed_langs_params(allowed_langs);
params.push(("page", page.to_string())); params.push(("page", page.to_string()));
@@ -108,7 +110,7 @@ pub async fn search_author(
query: String, query: String,
page: u32, page: u32,
allowed_langs: Vec<String>, allowed_langs: Vec<String>,
) -> Result<types::Page<types::Author>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::Author, Empty>, Box<dyn std::error::Error + Send + Sync>> {
let mut params = get_allowed_langs_params(allowed_langs); let mut params = get_allowed_langs_params(allowed_langs);
params.push(("page", page.to_string())); params.push(("page", page.to_string()));
@@ -121,7 +123,7 @@ pub async fn search_sequence(
query: String, query: String,
page: u32, page: u32,
allowed_langs: Vec<String>, allowed_langs: Vec<String>,
) -> Result<types::Page<types::Sequence>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::Sequence, Empty>, Box<dyn std::error::Error + Send + Sync>> {
let mut params = get_allowed_langs_params(allowed_langs); let mut params = get_allowed_langs_params(allowed_langs);
params.push(("page", page.to_string())); params.push(("page", page.to_string()));
@@ -134,7 +136,7 @@ pub async fn search_translator(
query: String, query: String,
page: u32, page: u32,
allowed_langs: Vec<String>, allowed_langs: Vec<String>,
) -> Result<types::Page<types::Translator>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::Translator, Empty>, Box<dyn std::error::Error + Send + Sync>> {
let mut params = get_allowed_langs_params(allowed_langs); let mut params = get_allowed_langs_params(allowed_langs);
params.push(("page", page.to_string())); params.push(("page", page.to_string()));
@@ -163,7 +165,7 @@ pub async fn get_author_books(
id: u32, id: u32,
page: u32, page: u32,
allowed_langs: Vec<String>, allowed_langs: Vec<String>,
) -> Result<types::Page<types::AuthorBook>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::AuthorBook, types::BookAuthor>, Box<dyn std::error::Error + Send + Sync>> {
let mut params = get_allowed_langs_params(allowed_langs); let mut params = get_allowed_langs_params(allowed_langs);
params.push(("page", page.to_string())); params.push(("page", page.to_string()));
@@ -176,7 +178,7 @@ pub async fn get_translator_books(
id: u32, id: u32,
page: u32, page: u32,
allowed_langs: Vec<String>, allowed_langs: Vec<String>,
) -> Result<types::Page<types::TranslatorBook>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::TranslatorBook, types::BookTranslator>, Box<dyn std::error::Error + Send + Sync>> {
let mut params = get_allowed_langs_params(allowed_langs); let mut params = get_allowed_langs_params(allowed_langs);
params.push(("page", page.to_string())); params.push(("page", page.to_string()));
@@ -189,7 +191,7 @@ pub async fn get_sequence_books(
id: u32, id: u32,
page: u32, page: u32,
allowed_langs: Vec<String>, allowed_langs: Vec<String>,
) -> Result<types::Page<types::SequenceBook>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::SequenceBook, types::Sequence>, Box<dyn std::error::Error + Send + Sync>> {
let mut params = get_allowed_langs_params(allowed_langs); let mut params = get_allowed_langs_params(allowed_langs);
params.push(("page", page.to_string())); params.push(("page", page.to_string()));
@@ -202,7 +204,7 @@ pub async fn get_uploaded_books(
page: u32, page: u32,
uploaded_gte: String, uploaded_gte: String,
uploaded_lte: String, uploaded_lte: String,
) -> Result<types::Page<types::SearchBook>, Box<dyn std::error::Error + Send + Sync>> { ) -> Result<types::Page<types::SearchBook, Empty>, Box<dyn std::error::Error + Send + Sync>> {
let params = vec![ let params = vec![
("page", page.to_string()), ("page", page.to_string()),
("size", PAGE_SIZE.to_string()), ("size", PAGE_SIZE.to_string()),

View File

@@ -1,9 +1,9 @@
use serde::Deserialize; 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 struct BookAuthor {
pub id: u32, pub id: u32,
pub first_name: String, pub first_name: String,
@@ -11,7 +11,7 @@ pub struct BookAuthor {
pub middle_name: String, pub middle_name: String,
} }
#[derive(Deserialize, Debug, Clone)] #[derive(Default, Deserialize, Debug, Clone)]
pub struct BookTranslator { pub struct BookTranslator {
pub id: u32, pub id: u32,
pub first_name: String, pub first_name: String,
@@ -55,7 +55,7 @@ pub struct Translator {
pub annotation_exists: bool, pub annotation_exists: bool,
} }
#[derive(Deserialize, Debug, Clone)] #[derive(Default, Deserialize, Debug, Clone)]
pub struct Sequence { pub struct Sequence {
pub id: u32, pub id: u32,
pub name: String, pub name: String,
@@ -71,8 +71,11 @@ pub struct Genre {
pub meta: String, pub meta: String,
} }
#[derive(Default, Deserialize, Debug, Clone)]
pub struct Empty {}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct Page<T> { pub struct Page<T, P> {
pub items: Vec<T>, pub items: Vec<T>,
pub total: u32, pub total: u32,
@@ -80,18 +83,36 @@ pub struct Page<T> {
pub size: u32, pub size: u32,
pub pages: u32, pub pages: u32,
#[serde(default)]
pub parent_item: Option<P>
} }
impl<T> Page<T> impl<T, P> Page<T, P>
where where
T: Format + Clone, T: Format + Clone,
P: FormatTitle + Clone
{ {
pub fn format_items(&self, max_size: usize) -> String { 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 = "\n\n\n";
let separator_len: usize = separator.len(); let separator_len: usize = separator.len();
let items_count: usize = self.items.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<FormatResult> = self.items let format_result: Vec<FormatResult> = self.items
.iter() .iter()
@@ -118,7 +139,7 @@ where
.map(|item| item_size - item.current_size) .map(|item| item_size - item.current_size)
.sum(); .sum();
self.items let items_string = self.items
.iter() .iter()
.enumerate() .enumerate()
.map(|(index, item)| { .map(|(index, item)| {
@@ -136,7 +157,9 @@ where
} }
}) })
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join(separator) .join(separator);
format!("{title}{items_string}")
} }
} }