From 04ca15e97e9bb64a31f39edf3d00b6f5d1267efd Mon Sep 17 00:00:00 2001
From: Roc Sun <710989028@qq.com>
Date: Thu, 18 Jan 2024 18:15:37 +0800
Subject: [PATCH] refact:ing add query operate

---
 Cargo.toml             |   1 +
 README.zh-CN.md        |  13 +++++
 src/apis/ing/mod.rs    |  52 ++++++++++++-----
 src/args/cmd/ing.rs    | 127 ++++++++++++++++++++++++++++++++++++++++-
 src/args/parser/ing.rs |  35 ++++++++++++
 src/bin/cnb.rs         |   8 +++
 src/lib.rs             |   1 +
 src/logic/ing.rs       |  43 ++++++++++++++
 src/logic/mod.rs       |   6 ++
 9 files changed, 270 insertions(+), 16 deletions(-)
 create mode 100644 src/logic/ing.rs
 create mode 100644 src/logic/mod.rs

diff --git a/Cargo.toml b/Cargo.toml
index 481b8a3..02684e4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ license = "MIT"
 repository = "https://github.com/cnblogs/cli"
 keywords = ["cli", "cnblogs", "blog"]
 categories = ["command-line-utilities"]
+default-run = "cnb"
 
 [profile.dev]
 lto = true
diff --git a/README.zh-CN.md b/README.zh-CN.md
index 197dea1..89a95e9 100644
--- a/README.zh-CN.md
+++ b/README.zh-CN.md
@@ -50,3 +50,16 @@ cnb user --info
 ```shell
 cnb posts [comment] [list,create,query,delete,update] --[id/file/quertset] --[pagesize,pagecount] 
 ```
+
+## 闪存cli
+
+闪存cli设计如下:
+
+```sh
+cnb ing query   # 默认10条
+cnb ing query --id 123456
+cnb ing query --page 1 --count 10
+cnb ing query --type All --page 1 --count 10 --tag Linux
+cnb ing create --conent hello --private false --lucky false
+cnb ing delete --id 123456
+```
diff --git a/src/apis/ing/mod.rs b/src/apis/ing/mod.rs
index 7f76ffe..ad17840 100644
--- a/src/apis/ing/mod.rs
+++ b/src/apis/ing/mod.rs
@@ -15,21 +15,34 @@
 pub mod comment;
 
 use anyhow::{Ok, Result};
+use clap::{ValueEnum, Parser};
 use reqwest::{Client, Response};
 use serde::{Deserialize, Serialize};
 use serde_repr::{Deserialize_repr, Serialize_repr};
 
 use crate::{infra::http::RequestBuilderExt, openapi};
 
-#[derive(Debug, Default, Serialize, Deserialize)]
+#[derive(Debug, Serialize, Deserialize)]
 #[serde(rename_all = "PascalCase")]
 #[serde(default)]
 pub struct IngContent {
     pub content: String,
     pub is_private: bool,
+    pub lucky: bool,
     pub client_type: IngSendFrom,
 }
 
+impl Default for IngContent {
+    fn default() -> Self {
+        IngContent {
+            content: "".to_string(),
+            is_private: true,
+            lucky: false,
+            client_type: IngSendFrom::default(),
+        }
+    }
+}
+
 #[derive(Clone, Debug, Serialize_repr, Deserialize_repr)]
 #[repr(u8)]
 pub enum IngSendFrom {
@@ -56,7 +69,7 @@ impl Default for IngSendFrom {
 #[serde(default)]
 pub struct QeurySet {
     #[serde(skip)]
-    pub types: QueryIngType,
+    pub r#type: QueryIngType,
     pub page_index: u64,
     pub page_size: u64,
     #[serde(skip_serializing_if = "String::is_empty")]
@@ -66,9 +79,9 @@ pub struct QeurySet {
 impl Default for QeurySet {
     fn default() -> Self {
         return Self {
-            types: QueryIngType::default(),
+            r#type: QueryIngType::default(),
             page_index: 1,
-            page_size: 30,
+            page_size: 10,
             tag: "".to_string(),
         };
     }
@@ -83,15 +96,16 @@ impl Default for QeurySet {
 /// Tag = 10,  tag 必填
 /// Comment = 13 回复我
 /// Mention = 14,
-#[derive(Debug)]
+#[derive(Debug, Clone, ValueEnum, Parser)]
 pub enum QueryIngType {
-    Following,
-    My,
-    MyComment,
-    RecentComment,
-    Mention,
-    Comment,
-    All,
+    Following = 1,
+    My = 4,
+    All = 5,
+    RecentComment = 6,
+    MyComment = 7,
+    Tag = 10,
+    Comment = 13,
+    Mention = 14,
 }
 
 impl Default for QueryIngType {
@@ -100,6 +114,15 @@ impl Default for QueryIngType {
     }
 }
 
+impl From<u8> for QueryIngType {
+    fn from(value: u8) -> Self {
+        match value {
+            1 => Self::Following,
+            _ => Self::All,
+        }
+    }
+}
+
 impl QueryIngType {
     fn as_u8(&self) -> u8 {
         match self {
@@ -108,6 +131,7 @@ impl QueryIngType {
             QueryIngType::All => 5,
             QueryIngType::RecentComment => 6,
             QueryIngType::MyComment => 7,
+            QueryIngType::Tag => 10,
             QueryIngType::Mention => 14,
             QueryIngType::Comment => 13,
         }
@@ -151,7 +175,7 @@ pub async fn lastest(token: &str) -> Result<Response> {
 /// 页数是从1开始的
 pub async fn query(token: &str, q: &QeurySet) -> Result<Vec<IngEntry>> {
     let r = Client::new()
-        .get(openapi!("/statuses/@{}", q.types.as_u8()))
+        .get(openapi!("/statuses/@{}", q.r#type.as_u8()))
         .pat_auth(token)
         .query(&q)
         .send()
@@ -163,7 +187,7 @@ pub async fn query(token: &str, q: &QeurySet) -> Result<Vec<IngEntry>> {
 }
 
 /// 根据ID查询
-pub async fn query_by_id(token: &str, id: &str) -> Result<IngEntry> {
+pub async fn query_by_id(token: &str, id: &u64) -> Result<IngEntry> {
     let r = Client::new()
         .get(openapi!("/statuses/{}", id))
         .pat_auth(token)
diff --git a/src/args/cmd/ing.rs b/src/args/cmd/ing.rs
index 974c6bc..fe96460 100644
--- a/src/args/cmd/ing.rs
+++ b/src/args/cmd/ing.rs
@@ -1,5 +1,8 @@
-use crate::api::ing::IngType;
-use clap::{Parser, Subcommand};
+use crate::{
+    api::ing::IngType,
+    apis::{self, ing::QeurySet},
+};
+use clap::{Args, Parser, Subcommand, ValueEnum};
 
 #[derive(Parser, Debug)]
 #[non_exhaustive]
@@ -54,4 +57,124 @@ pub enum Cmd {
         #[arg(default_value_t = true)]
         align: bool,
     },
+
+    /// 根据条件查询闪存。
+    Query(QueryIng),
+
+    /// 创建闪存
+    Create(CreateIng),
+
+    /// 根据ID删除闪存
+    Delete {
+        #[arg(long)]
+        id: Vec<u64>,
+    },
+}
+
+#[derive(Debug, Args)]
+pub struct CreateIng {
+    /// 闪存内容
+    // #[arg(short, long)]
+    content: Option<String>,
+    #[arg(short, long, default_value_t = true)]
+    private: bool,
+
+    #[arg(short, long, default_value_t = false)]
+    lucky: bool,
+
+    #[arg(short, long)]
+    tag: Option<String>,
+}
+
+#[derive(Args, Debug)]
+struct Create {
+    /// 闪存内容
+    content: String,
+
+    /// 是否私有,默认是全站
+    #[arg(short, long, default_value_t = true)]
+    private: bool,
+
+    /// 是否发布为幸运
+    #[arg(short, long, default_value_t = false)]
+    lucky: bool,
+
+    /// 是否发布在某个标签下,默认不发布标签。
+    #[arg(short, long, default_value = "")]
+    tag: String,
+}
+
+/// 查询参数
+/// 当使用type为
+#[derive(Debug, Args, Clone)]
+pub struct QueryIng {
+    /// 查询类型
+    #[arg(
+        short,
+        long,
+        value_name = "TYPE",
+        default_value_t = QueryType::F,
+        default_missing_value = "f",
+        value_enum
+    )]
+    pub r#type: QueryType,
+    /// 分页查询,起始索引是1
+    #[arg(short('n'), long, default_value_t = 1)]
+    pub page_index: u64,
+    /// 分页查询数量, 默认是10
+    #[arg(short('s'), long, default_value_t = 10)]
+    pub page_size: u64,
+    /// 按照标签查询
+    #[arg(short('g'), long)]
+    pub tag: Option<String>,
+    /// 根据ID查询
+    #[arg(short, long)]
+    pub id: Option<Vec<u64>>,
+}
+
+impl From<&QueryIng> for QeurySet {
+    fn from(value: &QueryIng) -> Self {
+        Self {
+            r#type: value.r#type.clone().into(),
+            page_index: value.page_index,
+            page_size: value.page_size,
+            tag: value.tag.clone().unwrap_or_default(),
+        }
+    }
+}
+
+/// 过滤的类型
+#[derive(Debug, Clone, ValueEnum, Parser)]
+pub enum QueryType {
+    /// 关注
+    F = 1,
+    /// 我的
+    My = 4,
+    /// 全站
+    P = 5,
+    /// 新回应
+    Rc = 6,
+    /// 我回应
+    Mc = 7,
+    /// 按照Tag过滤,使用T时,如果没有Query::tag或者站点不存在,则不会有结果。
+    T = 10,
+    /// 回复我
+    C = 13,
+    /// 提到我
+    M = 14,
+}
+
+impl From<QueryType> for apis::ing::QueryIngType {
+    fn from(value: QueryType) -> Self {
+        match value {
+            QueryType::F => Self::Following,
+            QueryType::My => Self::My,
+            QueryType::P => Self::All,
+            QueryType::Rc => Self::RecentComment,
+            QueryType::Mc => Self::MyComment,
+            QueryType::T => Self::Tag,
+            QueryType::C => Self::Comment,
+            QueryType::M => Self::Mention,
+        }
+    }
 }
diff --git a/src/args/parser/ing.rs b/src/args/parser/ing.rs
index 62ed32b..2c8e42c 100644
--- a/src/args/parser/ing.rs
+++ b/src/args/parser/ing.rs
@@ -1,4 +1,5 @@
 use crate::api::ing::IngType;
+use crate::args::cmd::ing::QueryIng;
 use crate::args::parser::{get_skip, get_take};
 use crate::args::{cmd, Args, Cmd};
 use crate::infra::option::WrapOption;
@@ -67,3 +68,37 @@ pub fn comment_ing(args: &Args) -> Option<(&String, usize)> {
     }
     .wrap_some()
 }
+
+#[allow(unused)]
+pub fn query(args: &Args) -> Option<QueryIng> {
+    match args {
+        Args {
+            cmd:
+                Some(Cmd::Ing(cmd::ing::Opt {
+                    cmd:
+                        Some(cmd::ing::Cmd::Query(QueryIng {
+                            r#type,
+                            page_index,
+                            page_size,
+                            tag,
+                            id,
+                        })),
+                    publish: None,
+                    comment: None,
+                })),
+            id: None,
+            rev: _,
+            skip,
+            take,
+            global_opt: _,
+        } => QueryIng {
+            r#type: r#type.clone(),
+            page_index: page_index.clone(),
+            page_size: page_size.clone(),
+            tag: tag.clone(),
+            id: id.clone(),
+        },
+        _ => return None,
+    }
+    .wrap_some()
+}
diff --git a/src/bin/cnb.rs b/src/bin/cnb.rs
index 64fe301..0a5c1ae 100644
--- a/src/bin/cnb.rs
+++ b/src/bin/cnb.rs
@@ -25,6 +25,7 @@ use cnblogs_lib::infra::infer::infer;
 use cnblogs_lib::infra::iter::{ExactSizeIteratorExt, IntoIteratorExt};
 use cnblogs_lib::infra::option::OptionExt;
 use cnblogs_lib::infra::result::WrapResult;
+use cnblogs_lib::logic::ing::get_ings_and_comments;
 use colored::Colorize;
 use std::env;
 
@@ -84,6 +85,13 @@ async fn main() -> Result<()> {
             foe.then(|| panic_if_err(&user_info));
             display::user_info(style, &user_info)?
         }
+
+        _ if let Some(q) = parser::ing::query(&args) => {
+
+            get_ings_and_comments(pat.unwrap().as_str(), &q).await;
+            "".to_string()
+        }
+
         _ if let Some((skip, take, r#type, align)) = parser::ing::list_ing(&args) => {
             let ing_with_comment_iter = infer::<Result<_, _>>(
                 try {
diff --git a/src/lib.rs b/src/lib.rs
index 984f7bc..4c7b191 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -10,3 +10,4 @@ pub mod apis;
 pub mod args;
 pub mod display;
 pub mod infra;
+pub mod logic;
diff --git a/src/logic/ing.rs b/src/logic/ing.rs
new file mode 100644
index 0000000..a79f2f7
--- /dev/null
+++ b/src/logic/ing.rs
@@ -0,0 +1,43 @@
+//! 闪存相关逻辑
+//!
+
+use crate::{
+    apis::ing::{query_by_id, query as iq},
+    args::cmd::ing::QueryIng,
+    infra::iter::IntoIteratorExt,
+};
+
+pub async fn get_ings_and_comments(t: &str, q: &QueryIng) {
+    println!("{:?}", q);
+    if let Some(ids) = &q.id {
+        let a = ids
+            .iter()
+            .map(|id| async move { query_by_id(t, id).await })
+            .join_all()
+            .await
+            ;
+
+        a.iter().for_each(|i| {
+            match i {
+                Ok(e) => {
+                    println!("{:?}", e);
+                }
+                Err(e) => {
+                    eprintln!("{:?}", e);
+                }
+            }
+        })
+        
+    }
+    
+    let a: Result<Vec<crate::apis::ing::IngEntry>, anyhow::Error> = iq(t, &q.into()).await;
+    match a {
+        Ok(e) => {
+            println!("{:?}", e);
+        }
+        Err(e) => {
+            eprintln!("{:?}", e);
+        }
+    }
+
+}
diff --git a/src/logic/mod.rs b/src/logic/mod.rs
new file mode 100644
index 0000000..b9ab01d
--- /dev/null
+++ b/src/logic/mod.rs
@@ -0,0 +1,6 @@
+//! cli操作逻辑
+//! 
+//! 此模块暂定封装操作逻辑,比如是闪存的curd,闪存评论的curd。
+//! 
+
+pub mod ing;
\ No newline at end of file