From 54ef43a07207429f64449b24817265b7ed51c502 Mon Sep 17 00:00:00 2001 From: Thaumy Date: Thu, 28 Sep 2023 16:13:42 +0800 Subject: [PATCH] feat(post option)!: rename search to search-self --- src/api/post/mod.rs | 2 +- src/api/post/search_self.rs | 94 ++++++++++++++++++++++++++++++++++++ src/args/cmd/post.rs | 10 ++-- src/args/parser/post.rs | 18 +++---- src/display/colorful/post.rs | 2 +- src/display/json/post.rs | 2 +- src/display/mod.rs | 8 +-- src/display/normal/post.rs | 2 +- src/main.rs | 6 +-- 9 files changed, 119 insertions(+), 25 deletions(-) create mode 100644 src/api/post/search_self.rs diff --git a/src/api/post/mod.rs b/src/api/post/mod.rs index 81a80b9..6a2bea7 100644 --- a/src/api/post/mod.rs +++ b/src/api/post/mod.rs @@ -5,7 +5,7 @@ pub mod get_count; pub mod get_meta_list; pub mod get_one; pub mod get_one_raw; -pub mod search; +pub mod search_self; pub mod update; pub struct Post { diff --git a/src/api/post/search_self.rs b/src/api/post/search_self.rs new file mode 100644 index 0000000..b48bb59 --- /dev/null +++ b/src/api/post/search_self.rs @@ -0,0 +1,94 @@ +use crate::api::post::Post; +use crate::blog_backend; +use crate::infra::http::{body_or_err, RequestBuilderExt}; +use crate::infra::iter::IntoIteratorExt; +use crate::infra::json; +use crate::infra::result::WrapResult; +use anyhow::Result; +use serde_json::Value; +use std::collections::HashSet; +use std::iter; + +impl Post { + pub async fn search_self( + &self, + skip: usize, + take: usize, + keyword: &str, + ) -> Result<(Vec, usize)> { + let client = &reqwest::Client::new(); + + // total_count is used for patch the buggy blog backend API + // If index is greater than the max page index, API will still return the last page + let total_count = { + let req = { + let url = blog_backend!("/posts/list"); + let query = [ + ("t", 1.to_string()), + ("p", 1.to_string()), + ("s", 1.to_string()), + ("search", keyword.to_string()), + ]; + client.get(url).query(&query).pat_auth(&self.pat) + }; + let resp = req.send().await?; + + // total_count + { + let body = body_or_err(resp).await?; + let json = json::deserialize::(&body)?; + json["postsCount"] + .as_u64() + .expect("as_u64 failed for `postsCount`") as usize + } + }; + + let range = (skip + 1)..=(skip + take).min(total_count); + let id_list = range + .map(|i| async move { + let req = { + let url = blog_backend!("/posts/list"); + let query = [ + ("t", 1.to_string()), + ("p", i.to_string()), + ("s", 1.to_string()), + ("search", keyword.to_string()), + ]; + client.get(url).query(&query).pat_auth(&self.pat) + }; + let resp = req.send().await?; + + let id_list = { + let body = body_or_err(resp).await?; + let mut json = json::deserialize::(&body)?; + let post_id = { + let json = json["postList"].take(); + let [post, ..] = serde_json::from_value::<[Value; 1]>(json)?; + post["id"].as_u64().expect("as_u64 failed for `id`") as usize + }; + let zzk_post_id_list = { + let json = json["zzkSearchResult"]["postIds"].take(); + serde_json::from_value::>(json) + }?; + + zzk_post_id_list + .into_iter() + .chain(iter::once(post_id)) + .collect::>() + }; + + id_list.wrap_ok::() + }) + .join_all() + .await + .into_iter() + .collect::>>()? + .into_iter() + .flatten() + .collect::>() + .into_iter() + .collect::>(); + + (id_list, total_count).wrap_ok() + } +} diff --git a/src/args/cmd/post.rs b/src/args/cmd/post.rs index a4e9a7e..cc677d8 100644 --- a/src/args/cmd/post.rs +++ b/src/args/cmd/post.rs @@ -47,14 +47,14 @@ pub struct Opt { pub delete: bool, #[arg(verbatim_doc_comment)] - /// Search post by keyword and output the post id list that matches - /// Example: cnb post --search 'Hello world' + /// Search self post by keyword and output the post id list that matches + /// Example: cnb post --search-self 'Hello world' /// * #[arg(long)] - #[arg(short = 'f')] - #[arg(visible_alias = "find")] + #[arg(visible_alias = "f-self")] + #[arg(visible_alias = "find-self")] #[arg(value_name = "KEYWORD")] - pub search: Option, + pub search_self: Option, #[command(subcommand)] pub cmd: Option, diff --git a/src/args/parser/post.rs b/src/args/parser/post.rs index d6b7c03..958a780 100644 --- a/src/args/parser/post.rs +++ b/src/args/parser/post.rs @@ -13,7 +13,7 @@ pub fn list_post(args: &Args) -> Option<(usize, usize)> { show_comment: false, list: true, delete: false, - search: None, + search_self: None, cmd: None, })), id: None, @@ -41,7 +41,7 @@ pub fn show_post(args: &Args) -> Option { show_comment: false, list: false, delete: false, - search: None, + search_self: None, cmd: None, })), id: Some(id), @@ -65,7 +65,7 @@ pub fn show_post_meta(args: &Args) -> Option { show_comment: false, list: false, delete: false, - search: None, + search_self: None, cmd: None, })), id: Some(id), @@ -89,7 +89,7 @@ pub fn show_post_comment(args: &Args) -> Option { show_comment: true, list: false, delete: false, - search: None, + search_self: None, cmd: None, })), id: Some(id), @@ -103,7 +103,7 @@ pub fn show_post_comment(args: &Args) -> Option { .wrap_some() } -pub fn search_post(args: &Args) -> Option<(&String, usize, usize)> { +pub fn search_self_post(args: &Args) -> Option<(&String, usize, usize)> { match args { Args { cmd: @@ -113,7 +113,7 @@ pub fn search_post(args: &Args) -> Option<(&String, usize, usize)> { show_comment: false, list: false, delete: false, - search: Some(keyword), + search_self: Some(keyword), cmd: None, })), id: None, @@ -141,7 +141,7 @@ pub fn delete_post(args: &Args) -> Option { show_comment: false, list: false, delete: true, - search: None, + search_self: None, cmd: None, })), id: Some(id), @@ -165,7 +165,7 @@ pub fn create_post(args: &Args) -> Option<&CreateCmd> { show_comment: false, list: false, delete: false, - search: None, + search_self: None, cmd: Some(cmd::post::Cmd::Create(cmd)), })), id: None, @@ -189,7 +189,7 @@ pub fn update_post(args: &Args) -> Option<(usize, &UpdateCmd)> { show_comment: false, list: false, delete: false, - search: None, + search_self: None, cmd: Some(cmd::post::Cmd::Update(cmd)), })), id: Some(id), diff --git a/src/display/colorful/post.rs b/src/display/colorful/post.rs index 94530fa..8b549da 100644 --- a/src/display/colorful/post.rs +++ b/src/display/colorful/post.rs @@ -120,7 +120,7 @@ pub fn show_post_comment( }) } -pub fn search_post( +pub fn search_self_post( result: Result<(impl ExactSizeIterator, usize)>, ) -> Result { let (mut id_iter, total_count) = match result { diff --git a/src/display/json/post.rs b/src/display/json/post.rs index 35afa6e..4310191 100644 --- a/src/display/json/post.rs +++ b/src/display/json/post.rs @@ -45,7 +45,7 @@ pub fn show_post_comment( fmt_ok(comment_vec) } -pub fn search_post(result: Result<(impl ExactSizeIterator, usize)>) -> String { +pub fn search_self_post(result: Result<(impl ExactSizeIterator, usize)>) -> String { let (id_iter, total_count) = match result { Ok(o) => o, Err(e) => return fmt_err(&e), diff --git a/src/display/mod.rs b/src/display/mod.rs index f22eaf2..bfb50c8 100644 --- a/src/display/mod.rs +++ b/src/display/mod.rs @@ -118,14 +118,14 @@ pub fn delete_post(style: &Style, result: &Result) -> String { } } -pub fn search_post( +pub fn search_self_post( style: &Style, result: Result<(impl ExactSizeIterator, usize)>, ) -> Result { match style { - Style::Colorful => colorful::post::search_post(result), - Style::Normal => normal::post::search_post(result), - Style::Json => json::post::search_post(result).wrap_ok(), + Style::Colorful => colorful::post::search_self_post(result), + Style::Normal => normal::post::search_self_post(result), + Style::Json => json::post::search_self_post(result).wrap_ok(), } } diff --git a/src/display/normal/post.rs b/src/display/normal/post.rs index e3fa28b..70dae93 100644 --- a/src/display/normal/post.rs +++ b/src/display/normal/post.rs @@ -118,7 +118,7 @@ pub fn show_post_comment( }) } -pub fn search_post( +pub fn search_self_post( result: Result<(impl ExactSizeIterator, usize)>, ) -> Result { let (mut id_iter, total_count) = match result { diff --git a/src/main.rs b/src/main.rs index d316821..afd410f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -152,13 +152,13 @@ async fn main() -> Result<()> { foe.then(|| panic_if_err(&id)); display::delete_post(style, &id) } - _ if let Some((kw, skip, take)) = parser::post::search_post(&args) => { + _ if let Some((kw, skip, take)) = parser::post::search_self_post(&args) => { let result = Post::new(pat?) - .search(skip, take, kw) + .search_self(skip, take, kw) .await .map(|(vec, count)| (vec.into_iter().dyn_rev(rev), count)); foe.then(|| panic_if_err(&result)); - display::search_post(style, result)? + display::search_self_post(style, result)? } _ if let Some(create_cmd) = parser::post::create_post(&args) => { let CreateCmd { title, body, publish } = create_cmd;