Code refactor

This commit is contained in:
2023-05-27 22:27:45 +02:00
parent ccf7152111
commit c11780ba30
6 changed files with 252 additions and 307 deletions

View File

@@ -165,10 +165,11 @@ where
return Ok(()); return Ok(());
}; };
let formated_items = items_page.format_items();
let total_pages = items_page.total_pages; let total_pages = items_page.total_pages;
let footer = format!("\n\nСтраница 1/{total_pages}"); let footer = format!("\n\nСтраница 1/{total_pages}");
let formated_items = items_page.format_items((4096 - footer.len()).try_into().unwrap());
let message_text = format!("{formated_items}{footer}"); let message_text = format!("{formated_items}{footer}");
let callback_data = match command { let callback_data = match command {
@@ -256,11 +257,11 @@ where
}; };
} }
let formated_items = items_page.format_items();
let total_pages = items_page.total_pages; let total_pages = items_page.total_pages;
let footer = format!("\n\nСтраница {page}/{total_pages}"); let footer = format!("\n\nСтраница {page}/{total_pages}");
let formated_items = items_page.format_items((4096 - footer.len()).try_into().unwrap());
let message_text = format!("{formated_items}{footer}"); let message_text = format!("{formated_items}{footer}");
let keyboard = generic_get_pagination_keyboard(page, total_pages, callback_data, true); let keyboard = generic_get_pagination_keyboard(page, total_pages, callback_data, true);

View File

@@ -137,7 +137,7 @@ where
}, },
}; };
let item_message = item.format(); let item_message = item.format(4096);
bot.send_message(cq.from.id, item_message) bot.send_message(cq.from.id, item_message)
.reply_markup(InlineKeyboardMarkup { .reply_markup(InlineKeyboardMarkup {

View File

@@ -188,11 +188,11 @@ where
}; };
} }
let formated_items = items_page.format_items();
let total_pages = items_page.total_pages; let total_pages = items_page.total_pages;
let footer = format!("\n\nСтраница {page}/{total_pages}"); let footer = format!("\n\nСтраница {page}/{total_pages}");
let formated_items = items_page.format_items((4096 - footer.len()).try_into().unwrap());
let message_text = format!("{formated_items}{footer}"); let message_text = format!("{formated_items}{footer}");
let keyboard = generic_get_pagination_keyboard(page, total_pages, search_data, true); let keyboard = generic_get_pagination_keyboard(page, total_pages, search_data, true);

View File

@@ -173,12 +173,12 @@ async fn update_log_pagination_handler(
).await?; ).await?;
} }
let formated_items = items_page.format_items();
let page = update_callback_data.page; let page = update_callback_data.page;
let total_pages = items_page.total_pages; let total_pages = items_page.total_pages;
let footer = format!("\n\nСтраница {page}/{total_pages}"); let footer = format!("\n\nСтраница {page}/{total_pages}");
let formated_items = items_page.format_items((4096 - footer.len()).try_into().unwrap());
let message_text = format!("{header}{formated_items}{footer}"); let message_text = format!("{header}{formated_items}{footer}");
let keyboard = generic_get_pagination_keyboard(page, total_pages, update_callback_data, true); let keyboard = generic_get_pagination_keyboard(page, total_pages, update_callback_data, true);

View File

@@ -2,97 +2,116 @@ use std::cmp::min;
use crate::bots::approved_bot::modules::download::StartDownloadData; use crate::bots::approved_bot::modules::download::StartDownloadData;
use super::types::{Author, AuthorBook, Book, SearchBook, Sequence, Translator, TranslatorBook}; use super::types::{Author, AuthorBook, Book, SearchBook, Sequence, Translator, TranslatorBook, BookAuthor, BookGenre, AsBook};
const NO_LIMIT: u32 = 4096;
pub trait Format { pub trait Format {
fn format(&self) -> String; fn format(&self, max_size: u32) -> String;
} }
impl Format for Book {
fn format(&self) -> String {
let book_title = {
let Book { title, lang, .. } = self;
format!("📖 {title} | {lang}\n")
};
let pages_count = match self.pages { pub trait FormatInline {
Some(1) | None => "".to_string(), fn format_inline(&self) -> String;
Some(v) => format!("[ {v}с. ]\n\n"), }
};
let annotations = match self.annotation_exists {
true => {
let Book { id, .. } = self;
format!("📝 Аннотация: /b_an_{id}\n\n")
}
false => "".to_string(),
};
let authors = match !self.authors.is_empty() { impl FormatInline for BookAuthor {
true => { fn format_inline(&self) -> String {
let formated_authors = self let BookAuthor {
.authors id,
.clone() last_name,
.into_iter() first_name,
.map(|author| author.format_author()) middle_name,
.collect::<Vec<String>>() } = self;
.join("\n");
format!("Авторы:\n{formated_authors}\n\n")
}
false => "".to_string(),
};
let translators = match !self.translators.is_empty() { format!("👤 {last_name} {first_name} {middle_name} /a_{id}")
true => {
let formated_translators = self
.translators
.clone()
.into_iter()
.map(|translator| translator.format_translator())
.collect::<Vec<String>>()
.join("\n");
format!("Переводчики:\n{formated_translators}\n\n")
}
false => "".to_string(),
};
let sequences = match !self.sequences.is_empty() {
true => {
let formated_sequences: String = self
.sequences
.clone()
.into_iter()
.map(|sequence| sequence.format())
.collect::<Vec<String>>()
.join("\n");
format!("Серии:\n{formated_sequences}\n\n")
}
false => "".to_string(),
};
let genres = match !self.genres.is_empty() {
true => {
let formated_genres: String = self
.genres
.clone()
.into_iter()
.map(|genre| genre.format())
.collect::<Vec<String>>()
.join("\n");
format!("Жанры:\n{formated_genres}\n\n")
}
false => "".to_string(),
};
let download_command = (StartDownloadData { id: self.id }).to_string();
let download_links = format!("Скачать:\n📥{download_command}");
format!("{book_title}{pages_count}{annotations}{authors}{translators}{sequences}{genres}{download_links}")
} }
} }
impl FormatInline for Translator {
fn format_inline(&self) -> String {
let Translator {
id,
first_name,
last_name,
middle_name,
..
} = self;
format!("👤 {last_name} {first_name} {middle_name} /t_{id}")
}
}
fn format_authors(authors: Vec<BookAuthor>, count: usize) -> String {
match !authors.is_empty() {
true => {
let formated_authors = authors
.clone()[..min(count, authors.len())]
.into_iter()
.map(|author| author.format_inline())
.collect::<Vec<String>>()
.join("\n");
format!("Авторы:\n{formated_authors}\n\n")
}
false => "".to_string(),
}
}
fn format_translators(translators: Vec<Translator>, count: usize) -> String {
match !translators.is_empty() {
true => {
let formated_translators = translators
.clone()[..min(count, translators.len())]
.into_iter()
.map(|translator| translator.format_inline())
.collect::<Vec<String>>()
.join("\n");
format!("Переводчики:\n{formated_translators}\n\n")
}
false => "".to_string(),
}
}
fn format_sequences(sequences: Vec<Sequence>, count: usize) -> String {
match !sequences.is_empty() {
true => {
let formated_sequences: String = sequences
.clone()[..min(count, sequences.len())]
.into_iter()
.map(|sequence| sequence.format(NO_LIMIT))
.collect::<Vec<String>>()
.join("\n");
format!("Серии:\n{formated_sequences}\n\n")
}
false => "".to_string(),
}
}
fn format_genres(genres: Vec<BookGenre>, count: usize) -> String {
match !genres.is_empty() {
true => {
let formated_genres: String = genres
.clone()[..min(count, genres.len())]
.into_iter()
.map(|genre| genre.format())
.collect::<Vec<String>>()
.join("\n");
format!("Жанры:\n{formated_genres}\n\n")
}
false => "".to_string(),
}
}
impl Format for Author { impl Format for Author {
fn format(&self) -> String { fn format(&self, _max_size: u32) -> String {
let Author { let Author {
id, id,
last_name, last_name,
@@ -112,8 +131,9 @@ impl Format for Author {
} }
} }
impl Format for Sequence { impl Format for Sequence {
fn format(&self) -> String { fn format(&self, _max_size: u32) -> String {
let Sequence { id, name, .. } = self; let Sequence { id, name, .. } = self;
let title = format!("📚 {name}"); let title = format!("📚 {name}");
@@ -123,76 +143,9 @@ impl Format for Sequence {
} }
} }
impl Format for SearchBook {
fn format(&self) -> String {
let book_title = {
let SearchBook { title, lang, .. } = self;
format!("📖 {title} | {lang}\n")
};
let annotations = match self.annotation_exists {
true => {
let SearchBook { id, .. } = self;
format!("📝 Аннотация: /b_an_{id}\n")
}
false => "".to_string(),
};
let authors = if !self.authors.is_empty() {
let formated_authors = self
.authors
.clone()[..min(5, self.authors.len())]
.iter()
.map(|author| author.format_author())
.collect::<Vec<String>>()
.join("\n");
let post_fix = if self.authors.len() > 5 { "\nи др." } else { "" };
format!("Авторы:\n{formated_authors}{post_fix}\n")
} else {
"".to_string()
};
let sequences = match !self.sequences.is_empty() {
true => {
let formated_sequences: String = self
.sequences
.clone()[..min(5, self.sequences.len())]
.into_iter()
.map(|sequence| sequence.format())
.collect::<Vec<String>>()
.join("\n");
let post_fix = if self.sequences.len() > 5 { "\nи др." } else { "" };
format!("Серии:\n{formated_sequences}{post_fix}\n")
}
false => "".to_string(),
};
let translators = if !self.translators.is_empty() {
let formated_translators = self
.translators
.clone()[..min(5, self.translators.len())]
.iter()
.map(|translator| translator.format_translator())
.collect::<Vec<String>>()
.join("\n");
let post_fix = if self.translators.len() > 5 { "\nи др." } else { "" };
format!("Переводчики:\n{formated_translators}{post_fix}\n")
} else {
"".to_string()
};
let download_command = (StartDownloadData { id: self.id }).to_string();
let download_links = format!("Скачать:\n📥{download_command}");
format!("{book_title}{annotations}{authors}{translators}{sequences}{download_links}")
}
}
impl Format for Translator { impl Format for Translator {
fn format(&self) -> String { fn format(&self, _max_size: u32) -> String {
let Translator { let Translator {
id, id,
last_name, last_name,
@@ -212,47 +165,23 @@ impl Format for Translator {
} }
} }
impl Format for AuthorBook {
fn format(&self) -> String { impl Format for Book {
fn format(&self, max_size: u32) -> String {
let book_title = { let book_title = {
let AuthorBook { title, lang, .. } = self; let Book { title, lang, .. } = self;
format!("📖 {title} | {lang}\n") format!("📖 {title} | {lang}\n")
}; };
let pages_count = match self.pages {
Some(1) | None => "".to_string(),
Some(v) => format!("[ {v}с. ]\n\n"),
};
let annotations = match self.annotation_exists { let annotations = match self.annotation_exists {
true => { true => {
let AuthorBook { id, .. } = self; let Book { id, .. } = self;
format!("📝 Аннотация: /b_an_{id}\n") format!("📝 Аннотация: /b_an_{id}\n\n")
}
false => "".to_string(),
};
let translators = match !self.translators.is_empty() {
true => {
let formated_translators = self
.translators
.clone()
.into_iter()
.map(|translator| translator.format_translator())
.collect::<Vec<String>>()
.join("\n");
format!("Переводчики:\n{formated_translators}\n")
}
false => "".to_string(),
};
let sequences = match !self.sequences.is_empty() {
true => {
let formated_sequences: String = self
.sequences
.clone()[..min(5, self.sequences.len())]
.into_iter()
.map(|sequence| sequence.format())
.collect::<Vec<String>>()
.join("\n");
let post_fix = if self.sequences.len() > 5 { "\nи др." } else { "" };
format!("Серии:\n{formated_sequences}{post_fix}\n")
} }
false => "".to_string(), false => "".to_string(),
}; };
@@ -260,58 +189,32 @@ impl Format for AuthorBook {
let download_command = (StartDownloadData { id: self.id }).to_string(); let download_command = (StartDownloadData { id: self.id }).to_string();
let download_links = format!("Скачать:\n📥{download_command}"); let download_links = format!("Скачать:\n📥{download_command}");
format!("{book_title}{annotations}{translators}{sequences}{download_links}") let authors = format_authors(self.authors.clone(), self.authors.len());
let translators = format_translators(self.translators.clone(), self.translators.len());
let sequences = format_sequences(self.sequences.clone(), self.sequences.len());
let genres = format_genres(self.genres.clone(), self.genres.len());
format!("{book_title}{pages_count}{annotations}{authors}{translators}{sequences}{genres}{download_links}")
} }
} }
impl Format for SearchBook {
fn format(&self, max_size: u32) -> String {
self.clone().as_book().format(max_size)
}
}
impl Format for AuthorBook {
fn format(&self, max_size: u32) -> String {
self.clone().as_book().format(max_size)
}
}
impl Format for TranslatorBook { impl Format for TranslatorBook {
fn format(&self) -> String { fn format(&self, max_size: u32) -> String {
let book_title = { self.clone().as_book().format(max_size)
let TranslatorBook { title, lang, .. } = self;
format!("📖 {title} | {lang}\n")
};
let annotations = match self.annotation_exists {
true => {
let TranslatorBook { id, .. } = self;
format!("📝 Аннотация: /b_an_{id}\n")
}
false => "".to_string(),
};
let authors = match !self.authors.is_empty() {
true => {
let formated_authors = self
.authors
.clone()
.into_iter()
.map(|author| author.format_author())
.collect::<Vec<String>>()
.join("\n");
format!("Авторы:\n{formated_authors}\n")
}
false => "".to_string(),
};
let sequences = match !self.sequences.is_empty() {
true => {
let formated_sequences: String = self
.sequences
.clone()[..min(5, self.sequences.len())]
.into_iter()
.map(|sequence| sequence.format())
.collect::<Vec<String>>()
.join("\n");
let post_fix = if self.sequences.len() > 5 { "\nи др." } else { "" };
format!("Серии:\n{formated_sequences}{post_fix}\n")
}
false => "".to_string(),
};
let download_command = (StartDownloadData { id: self.id }).to_string();
let download_links = format!("Скачать:\n📥{download_command}");
format!("{book_title}{annotations}{authors}{sequences}{download_links}")
} }
} }

View File

@@ -2,36 +2,13 @@ use serde::Deserialize;
use super::formaters::Format; use super::formaters::Format;
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct BookAuthor { pub struct BookAuthor {
id: u32, pub id: u32,
first_name: String, pub first_name: String,
last_name: String, pub last_name: String,
middle_name: String, pub middle_name: String,
}
impl BookAuthor {
pub fn format_author(&self) -> String {
let BookAuthor {
id,
last_name,
first_name,
middle_name,
} = self;
format!("👤 {last_name} {first_name} {middle_name} /a_{id}")
}
pub fn format_translator(&self) -> String {
let BookAuthor {
id,
first_name,
last_name,
middle_name,
} = self;
format!("👤 {last_name} {first_name} {middle_name} /t_{id}")
}
} }
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
@@ -52,25 +29,6 @@ pub struct Source {
// name: String // name: String
} }
#[derive(Deserialize, Debug, Clone)]
pub struct Book {
pub id: u32,
pub title: String,
pub lang: String,
// file_type: String,
pub available_types: Vec<String>,
// uploaded: String,
pub annotation_exists: bool,
pub authors: Vec<BookAuthor>,
pub translators: Vec<BookAuthor>,
pub sequences: Vec<Sequence>,
pub genres: Vec<BookGenre>,
// source: Source,
// remote_id: u32,
// id_deleted: bool,
pub pages: Option<u32>,
}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct Author { pub struct Author {
pub id: u32, pub id: u32,
@@ -118,30 +76,19 @@ impl<T> Page<T>
where where
T: Format + Clone, T: Format + Clone,
{ {
pub fn format_items(&self) -> String { pub fn format_items(&self, max_size: u32) -> String {
let items_count: u32 = self.items.len().try_into().unwrap();
let item_size: u32 = max_size / items_count;
self.items self.items
.clone() .clone()
.into_iter() .into_iter()
.map(|book| book.format()) .map(|item| item.format(item_size))
.collect::<Vec<String>>() .collect::<Vec<String>>()
.join("\n\n\n") .join("\n\n\n")
} }
} }
#[derive(Deserialize, Debug, Clone)]
pub struct SearchBook {
pub id: u32,
pub title: String,
pub lang: String,
// file_type: String,
pub available_types: Vec<String>,
// uploaded: String,
pub annotation_exists: bool,
pub authors: Vec<BookAuthor>,
pub translators: Vec<BookAuthor>,
pub sequences: Vec<Sequence>,
}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct BookAnnotation { pub struct BookAnnotation {
pub id: u32, pub id: u32,
@@ -158,6 +105,66 @@ pub struct AuthorAnnotation {
pub file: Option<String>, pub file: Option<String>,
} }
pub trait AsBook<T> {
fn as_book(self) -> T;
}
#[derive(Deserialize, Debug, Clone)]
pub struct Book {
pub id: u32,
pub title: String,
pub lang: String,
// file_type: String,
pub available_types: Vec<String>,
// uploaded: String,
pub annotation_exists: bool,
pub authors: Vec<BookAuthor>,
pub translators: Vec<Translator>,
pub sequences: Vec<Sequence>,
pub genres: Vec<BookGenre>,
// source: Source,
// remote_id: u32,
// id_deleted: bool,
pub pages: Option<u32>,
}
impl AsBook<Book> for Book {
fn as_book(self) -> Book {
self
}
}
#[derive(Deserialize, Debug, Clone)]
pub struct SearchBook {
pub id: u32,
pub title: String,
pub lang: String,
// file_type: String,
pub available_types: Vec<String>,
// uploaded: String,
pub annotation_exists: bool,
pub authors: Vec<BookAuthor>,
pub translators: Vec<Translator>,
pub sequences: Vec<Sequence>,
}
impl AsBook<Book> for SearchBook {
fn as_book(self) -> Book {
Book {
id: self.id,
title: self.title,
lang: self.lang,
available_types: self.available_types,
annotation_exists: self.annotation_exists,
authors: self.authors,
translators: self.translators,
sequences: self.sequences,
genres: vec![],
pages: None
}
}
}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct AuthorBook { pub struct AuthorBook {
pub id: u32, pub id: u32,
@@ -167,10 +174,27 @@ pub struct AuthorBook {
pub available_types: Vec<String>, pub available_types: Vec<String>,
// uploaded: String, // uploaded: String,
pub annotation_exists: bool, pub annotation_exists: bool,
pub translators: Vec<BookAuthor>, pub translators: Vec<Translator>,
pub sequences: Vec<Sequence>, pub sequences: Vec<Sequence>,
} }
impl AsBook<Book> for AuthorBook {
fn as_book(self) -> Book {
Book {
id: self.id,
title: self.title,
lang: self.lang,
available_types: self.available_types,
annotation_exists: self.annotation_exists,
authors: vec![],
translators: self.translators,
sequences: self.sequences,
genres: vec![],
pages: None
}
}
}
#[derive(Deserialize, Debug, Clone)] #[derive(Deserialize, Debug, Clone)]
pub struct TranslatorBook { pub struct TranslatorBook {
pub id: u32, pub id: u32,
@@ -183,3 +207,20 @@ pub struct TranslatorBook {
pub authors: Vec<BookAuthor>, pub authors: Vec<BookAuthor>,
pub sequences: Vec<Sequence>, pub sequences: Vec<Sequence>,
} }
impl AsBook<Book> for TranslatorBook {
fn as_book(self) -> Book {
Book {
id: self.id,
title: self.title,
lang: self.lang,
available_types: self.available_types,
annotation_exists: self.annotation_exists,
authors: self.authors,
translators: vec![],
sequences: self.sequences,
genres: vec![],
pages: None
}
}
}