use std::fmt::Write;
use std::sync::Arc;
use color_eyre::eyre::{self, Result};
use comfy_table::modifiers::UTF8_ROUND_CORNERS;
use comfy_table::presets::UTF8_FULL;
use comfy_table::{Cell, CellAlignment, ContentArrangement, Table};
use novel_api::{Client, NovelInfo};
use crate::cmd::Convert;
use crate::utils;
pub async fn novel_info<T>(client: &Arc<T>, novel_id: u32) -> Result<NovelInfo>
where
T: Client + Send + Sync + 'static,
{
let novel_info = client.novel_info(novel_id).await?;
eyre::ensure!(
novel_info.is_some(),
"The novel does not exist: `{}`",
novel_id
);
Ok(novel_info.unwrap())
}
pub fn novel_info_to_string<T>(novel_info: &NovelInfo, converts: T) -> Result<String>
where
T: AsRef<[Convert]>,
{
let mut result = String::with_capacity(256);
let converts = converts.as_ref();
writeln!(
result,
"{}:{}",
utils::convert_str("名字", converts, false)?,
utils::convert_str(&novel_info.name, converts, false)?
)?;
writeln!(
result,
"{}:{}",
utils::convert_str("作者", converts, false)?,
utils::convert_str(&novel_info.author_name, converts, false)?
)?;
if novel_info.category.is_some() {
writeln!(
result,
"{}:{}",
utils::convert_str("类型", converts, false)?,
utils::convert_str(try_get_category(novel_info), converts, false)?
)?;
}
if novel_info.tags.is_some() {
writeln!(
result,
"{}:{}",
utils::convert_str("标签", converts, false)?,
utils::convert_str(try_get_tags(novel_info), converts, false)?
)?;
}
if novel_info.word_count.is_some() {
writeln!(
result,
"{}:{}",
utils::convert_str("字数", converts, false)?,
utils::convert_str(try_get_word_count(novel_info), converts, false)?
)?;
}
if novel_info.is_finished.is_some() {
writeln!(
result,
"{}:{}",
utils::convert_str("状态", converts, false)?,
utils::convert_str(try_get_is_finished(novel_info), converts, false)?
)?;
}
if novel_info.create_time.is_some() {
writeln!(
result,
"{}:{}",
utils::convert_str("创建时间", converts, false)?,
try_get_create_time(novel_info)
)?;
}
if novel_info.update_time.is_some() {
writeln!(
result,
"{}:{}",
utils::convert_str("更新时间", converts, false)?,
try_get_update_time(novel_info)
)?;
}
if novel_info.introduction.is_some() {
writeln!(
result,
"{}:{}",
utils::convert_str("简介", converts, false)?,
utils::convert_str(try_get_introduction(novel_info), converts, false)?
)?;
}
Ok(result)
}
pub fn print_novel_infos<T>(novel_infos: Vec<NovelInfo>, converts: T) -> Result<()>
where
T: AsRef<[Convert]>,
{
let converts = converts.as_ref();
let mut row = vec![
utils::convert_str("序号", converts, false)?,
utils::convert_str("编号", converts, false)?,
utils::convert_str("名字", converts, false)?,
utils::convert_str("作者", converts, false)?,
];
let category = novel_infos
.iter()
.any(|novel_info| novel_info.category.is_some());
if category {
row.push(utils::convert_str("类型", converts, false)?);
}
let tags = novel_infos
.iter()
.any(|novel_info| novel_info.tags.is_some());
if tags {
row.push(utils::convert_str("标签", converts, false)?);
}
let word_count = novel_infos
.iter()
.any(|novel_info| novel_info.word_count.is_some());
if word_count {
row.push(utils::convert_str("字数", converts, false)?);
}
let is_finished = novel_infos
.iter()
.any(|novel_info| novel_info.is_finished.is_some());
if is_finished {
row.push(utils::convert_str("状态", converts, false)?);
}
let create_time = novel_infos
.iter()
.any(|novel_info| novel_info.create_time.is_some());
if create_time {
row.push(utils::convert_str("创建时间", converts, false)?);
}
let update_time = novel_infos
.iter()
.any(|novel_info| novel_info.update_time.is_some());
if update_time {
row.push(utils::convert_str("更新时间", converts, false)?);
}
let mut table = Table::new();
table
.load_preset(UTF8_FULL)
.apply_modifier(UTF8_ROUND_CORNERS)
.set_content_arrangement(ContentArrangement::Dynamic)
.set_header(row);
let mut index = 1;
for novel_info in novel_infos {
let mut row = vec![
Cell::new(index.to_string()),
Cell::new(novel_info.id.to_string()),
Cell::new(utils::convert_str(&novel_info.name, converts, false)?),
Cell::new(utils::convert_str(
&novel_info.author_name,
converts,
false,
)?),
];
if category {
row.push(Cell::new(utils::convert_str(
try_get_category(&novel_info),
converts,
false,
)?));
}
if tags {
row.push(Cell::new(utils::convert_str(
try_get_tags(&novel_info),
converts,
false,
)?));
}
if word_count {
row.push(
Cell::new(utils::convert_str(
try_get_word_count(&novel_info),
converts,
false,
)?)
.set_alignment(CellAlignment::Right),
);
}
if is_finished {
row.push(Cell::new(utils::convert_str(
try_get_is_finished(&novel_info),
converts,
false,
)?));
}
if create_time {
row.push(Cell::new(try_get_create_time(&novel_info)));
}
if update_time {
row.push(Cell::new(try_get_update_time(&novel_info)));
}
table.add_row(row);
index += 1;
}
println!("{table}");
Ok(())
}
#[must_use]
fn try_get_introduction(novel_info: &NovelInfo) -> String {
if let Some(introduction) = &novel_info.introduction {
introduction.join("\n")
} else {
String::default()
}
}
#[must_use]
fn try_get_word_count(novel_info: &NovelInfo) -> String {
if let Some(word_count) = &novel_info.word_count {
if *word_count >= 10000 {
format!("{}万", word_count / 10000)
} else {
word_count.to_string()
}
} else {
String::default()
}
}
#[must_use]
fn try_get_is_finished(novel_info: &NovelInfo) -> String {
if novel_info.is_finished.is_some() {
if novel_info.is_finished.unwrap() {
String::from("已完结")
} else {
String::from("未完结")
}
} else {
String::default()
}
}
#[must_use]
fn try_get_create_time(novel_info: &NovelInfo) -> String {
if let Some(create_time) = &novel_info.create_time {
create_time.to_string()
} else {
String::default()
}
}
#[must_use]
fn try_get_update_time(novel_info: &NovelInfo) -> String {
if let Some(update_time) = novel_info.update_time {
update_time.to_string()
} else {
String::default()
}
}
#[must_use]
fn try_get_category(novel_info: &NovelInfo) -> String {
if let Some(category) = &novel_info.category {
category.name.to_string()
} else {
String::default()
}
}
#[must_use]
fn try_get_tags(novel_info: &NovelInfo) -> String {
if let Some(tags) = &novel_info.tags {
tags.iter()
.map(|tag| tag.name.to_string())
.collect::<Vec<String>>()
.join("、")
} else {
String::default()
}
}