Skip to content

Commit

Permalink
feat: list fav
Browse files Browse the repository at this point in the history
  • Loading branch information
Thaumy committed Sep 26, 2023
1 parent f756117 commit 57680ea
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 0 deletions.
63 changes: 63 additions & 0 deletions src/api/fav/get_list.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use crate::api::fav::Fav;
use crate::infra::http::{body_or_err, RequestBuilderExt, VecExt as HttpVecExt};
use crate::infra::iter::IntoIteratorExt;
use crate::infra::json;
use crate::infra::result::IntoResult;
use crate::infra::vec::VecExt;
use crate::openapi;
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::ops::ControlFlow;

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FavEntry {
#[serde(rename = "Title")]
pub title: String,
#[serde(rename = "LinkUrl")]
pub url: String,
#[serde(rename = "Summary")]
pub summary: String,
#[serde(rename = "Tags")]
pub tags: Vec<String>,
#[serde(rename = "DateAdded")]
pub create_time: String,
}

impl Fav {
pub async fn get_list(&self, skip: usize, take: usize) -> Result<Vec<FavEntry>> {
let client = &reqwest::Client::new();

let range = (skip + 1)..=(skip + take);
let cf = range
.map(|i| async move {
let req = {
let query = vec![("pageIndex", i), ("pageSize", 1)].into_query_string();
let url = openapi!("/Bookmarks?{}", query);
client.get(url).pat_auth(&self.pat)
};

let resp = req.send().await?;

let body = body_or_err(resp).await?;

json::deserialize::<Vec<FavEntry>>(&body)?
.pop()
.into_ok::<anyhow::Error>()
})
.join_all()
.await
.into_iter()
.try_fold(vec![], |acc, it| match it {
Ok(maybe) => match maybe {
Some(entry) => ControlFlow::Continue(acc.chain_push(entry)),
None => ControlFlow::Break(Ok(acc)),
},
Err(e) => ControlFlow::Break(Err(e)),
});

match cf {
ControlFlow::Continue(vec) => Ok(vec),
ControlFlow::Break(result) => result,
}
}
}
12 changes: 12 additions & 0 deletions src/api/fav/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
pub mod get_list;

// Aka cnblogs wz
pub struct Fav {
pat: String,
}

impl Fav {
pub const fn new(pat: String) -> Self {
Self { pat }
}
}
1 change: 1 addition & 0 deletions src/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
pub mod auth;
pub mod fav;
pub mod ing;
pub mod news;
pub mod post;
Expand Down
11 changes: 11 additions & 0 deletions src/args/cmd/fav.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use clap::Parser;

#[derive(Parser, Debug)]
pub struct Opt {
#[arg(verbatim_doc_comment)]
/// Show favorite list, order by time in DESC
/// Example: cnb fav --list
#[arg(long)]
#[arg(short = 'l')]
pub list: bool,
}
4 changes: 4 additions & 0 deletions src/args/cmd/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod fav;
pub mod ing;
pub mod news;
pub mod post;
Expand All @@ -19,4 +20,7 @@ pub enum Cmd {
/// News operations
#[clap(visible_alias = "n")]
News(news::Opt),
/// Favorite operations
#[clap(visible_alias = "f")]
Fav(fav::Opt),
}
1 change: 1 addition & 0 deletions src/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum TimeStyle {
Normal,
}

// TODO: flatten options in struct?
#[derive(Debug, Parser)]
#[command(author, about, long_about = None, version)]
pub struct Args {
Expand Down
24 changes: 24 additions & 0 deletions src/args/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,3 +457,27 @@ pub fn list_news(args: &Args) -> Option<(usize, usize)> {
}
.into_some()
}

pub fn list_fav(args: &Args) -> Option<(usize, usize)> {
match args {
Args {
cmd: Some(Cmd::Fav(cmd::fav::Opt { list: true })),
id: None,
with_pat: _,
rev: _,
skip,
take,
debug: _,
style: _,
time_style: _,
fail_on_error: _,
quiet: _,
} => {
let skip = get_skip(skip);
let take = get_take(take);
(skip, take)
}
_ => return None,
}
.into_some()
}
46 changes: 46 additions & 0 deletions src/display/colorful.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::api::fav::get_list::FavEntry;
use crate::api::ing::get_comment_list::IngCommentEntry;
use crate::api::ing::get_list::IngEntry;
use crate::api::ing::{
Expand Down Expand Up @@ -348,3 +349,48 @@ pub fn list_news(
acc
})
}

// TODO: lift out rev option
pub fn list_fav(
time_style: &TimeStyle,
fav_list: &Result<Vec<FavEntry>>,
rev: bool,
) -> Result<String> {
let fav_list = match fav_list {
Ok(o) => o,
Err(e) => return fmt_err(e).into_ok(),
};

fav_list
.iter()
.dyn_rev(rev)
.map(|fav| try {
let mut buf = String::new();
{
let buf = &mut buf;
let create_time = display_cnb_time(&fav.create_time, time_style);
writeln!(buf, "{} {}", create_time.dimmed(), fav.url.dimmed())?;
writeln!(buf, " {}", fav.title)?;

let summary = {
fav.summary.width_split(get_term_width() - 4).map_or_else(
|| fav.summary.clone(),
|vec| {
vec.into_iter()
.map(|line| format!(" {}", line))
.collect::<Vec<_>>()
.join("\n")
},
)
};
if summary.is_empty().not() {
writeln!(buf, "{}", summary.dimmed())?;
}
}
buf
})
.try_fold(String::new(), |mut acc, buf: Result<String>| try {
write!(&mut acc, "\n{}", buf?)?;
acc
})
}
12 changes: 12 additions & 0 deletions src/display/json.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::api::fav::get_list::FavEntry;
use crate::api::ing::get_comment_list::IngCommentEntry;
use crate::api::ing::get_list::IngEntry;
use crate::api::news::get_list::NewsEntry;
Expand Down Expand Up @@ -139,3 +140,14 @@ pub fn list_news(news_list: &Result<Vec<NewsEntry>>, rev: bool) -> Result<String

json::serialize(vec.clone())
}

pub fn list_fav(news_list: &Result<Vec<FavEntry>>, rev: bool) -> Result<String> {
let news_list = match news_list {
Ok(o) => o,
Err(e) => return fmt_err(e).into_ok(),
};

let vec = news_list.iter().dyn_rev(rev).collect::<Vec<_>>();

json::serialize(vec.clone())
}
14 changes: 14 additions & 0 deletions src/display/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::api::fav::get_list::FavEntry;
use crate::api::ing::get_comment_list::IngCommentEntry;
use crate::api::ing::get_list::IngEntry;
use crate::api::news::get_list::NewsEntry;
Expand Down Expand Up @@ -160,3 +161,16 @@ pub fn list_news(
Style::Json => json::list_news(news_list, rev),
}
}

pub fn list_fav(
style: &Style,
time_style: &TimeStyle,
fav_list: &Result<Vec<FavEntry>>,
rev: bool,
) -> Result<String> {
match style {
Style::Colorful => colorful::list_fav(time_style, fav_list, rev),
Style::Normal => normal::list_fav(time_style, fav_list, rev),
Style::Json => json::list_fav(fav_list, rev),
}
}
45 changes: 45 additions & 0 deletions src/display/normal.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::api::fav::get_list::FavEntry;
use crate::api::ing::get_comment_list::IngCommentEntry;
use crate::api::ing::get_list::IngEntry;
use crate::api::ing::{
Expand Down Expand Up @@ -340,3 +341,47 @@ pub fn list_news(
acc
})
}

pub fn list_fav(
time_style: &TimeStyle,
fav_list: &Result<Vec<FavEntry>>,
rev: bool,
) -> Result<String> {
let fav_list = match fav_list {
Ok(o) => o,
Err(e) => return fmt_err(e).into_ok(),
};

fav_list
.iter()
.dyn_rev(rev)
.map(|fav| try {
let mut buf = String::new();
{
let buf = &mut buf;
let create_time = display_cnb_time(&fav.create_time, time_style);
writeln!(buf, "{} {}", create_time, fav.url)?;
writeln!(buf, " {}", fav.title)?;

let summary = {
fav.summary.width_split(get_term_width() - 4).map_or_else(
|| fav.summary.clone(),
|vec| {
vec.into_iter()
.map(|line| format!(" {}", line))
.collect::<Vec<_>>()
.join("\n")
},
)
};
if summary.is_empty().not() {
writeln!(buf, "{}", summary)?;
}
}
buf
})
.try_fold(String::new(), |mut acc, buf: Result<String>| try {
write!(&mut acc, "\n{}", buf?)?;
acc
})
}
6 changes: 6 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#![warn(clippy::all, clippy::nursery, clippy::cargo_common_metadata)]

use crate::api::auth::session;
use crate::api::fav::Fav;
use crate::api::ing::Ing;
use crate::api::news::News;
use crate::api::post::Post;
Expand Down Expand Up @@ -164,6 +165,11 @@ async fn main() -> Result<()> {
foe.then(|| panic_if_err(&news_vec));
display::list_news(style, time_style, &news_vec, rev)?
}
_ if let Some((skip, take)) = parser::list_fav(&args) => {
let fav_vec = Fav::new(pat?).get_list(skip, take).await;
foe.then(|| panic_if_err(&fav_vec));
display::list_fav(style, time_style, &fav_vec, rev)?
}

_ if no_operation(&args) =>
infer::<Command>(Args::command()).render_help().to_string(),
Expand Down

0 comments on commit 57680ea

Please sign in to comment.