Skip to content

Commit b3254f9

Browse files
committed
feat!: update post
1 parent b363871 commit b3254f9

File tree

13 files changed

+309
-191
lines changed

13 files changed

+309
-191
lines changed

src/api/post/get_one.rs

Lines changed: 1 addition & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,7 @@ use crate::infra::result::IntoResult;
66
use anyhow::Result;
77
use serde::{Deserialize, Serialize};
88

9-
/*
10-
Fields only available over blog_backend!("/posts/{}", id):
11-
postBody: string
12-
categoryIds: []
13-
collectionIds: []
14-
inSiteCandidate: boolean
15-
inSiteHome: boolean
16-
siteCategoryId: null
17-
blogTeamIds: []
18-
displayOnHomePage: boolean
19-
isAllowComments: boolean
20-
includeInMainSyndication: boolean
21-
isOnlyForRegisterUser: boolean
22-
isUpdateDateAdded: boolean
23-
description: string
24-
featuredImage: null
25-
tags: []
26-
password: null
27-
autoDesc: string
28-
changePostType: boolean
29-
blogId: number
30-
author: string
31-
removeScript: boolean
32-
clientInfo: null
33-
changeCreatedTime: boolean
34-
canChangeCreatedTime: boolean
35-
isContributeToImpressiveBugActivity: boolean
36-
usingEditorId: null
37-
sourceUrl: null
38-
39-
Fields available over blog_backend!("/posts/{}", id) and blog_backend!("/posts/list?{}", query):
40-
id: number
41-
postType: PostType
42-
accessPermission: AccessPermission
43-
title: string
44-
url: string
45-
entryName: null
46-
datePublished: string
47-
dateUpdated: string
48-
isMarkdown: boolean
49-
isDraft: boolean
50-
isPinned: boolean
51-
isPublished: boolean
52-
*/
53-
9+
// TODO: not elegant
5410
#[derive(Serialize, Deserialize, Debug)]
5511
pub struct PostEntry {
5612
pub id: usize,

src/api/post/get_one_raw.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use crate::api::post::Post;
2+
use crate::blog_backend;
3+
use crate::infra::http::{body_or_err, setup_auth};
4+
use crate::infra::result::IntoResult;
5+
use anyhow::Result;
6+
use serde_json::Value;
7+
8+
/*
9+
Fields only available over blog_backend!("/posts/{}", id):
10+
postBody: string
11+
categoryIds: []
12+
collectionIds: []
13+
inSiteCandidate: boolean
14+
inSiteHome: boolean
15+
siteCategoryId: null
16+
blogTeamIds: []
17+
displayOnHomePage: boolean
18+
isAllowComments: boolean
19+
includeInMainSyndication: boolean
20+
isOnlyForRegisterUser: boolean
21+
isUpdateDateAdded: boolean
22+
description: string
23+
featuredImage: null
24+
tags: []
25+
password: null
26+
autoDesc: string
27+
changePostType: boolean
28+
blogId: number
29+
author: string
30+
removeScript: boolean
31+
clientInfo: null
32+
changeCreatedTime: boolean
33+
canChangeCreatedTime: boolean
34+
isContributeToImpressiveBugActivity: boolean
35+
usingEditorId: null
36+
sourceUrl: null
37+
38+
Fields available over blog_backend!("/posts/{}", id) and blog_backend!("/posts/list?{}", query):
39+
id: number
40+
postType: PostType
41+
accessPermission: AccessPermission
42+
title: string
43+
url: string
44+
entryName: null
45+
datePublished: string
46+
dateUpdated: string
47+
isMarkdown: boolean
48+
isDraft: boolean
49+
isPinned: boolean
50+
isPublished: boolean
51+
*/
52+
53+
impl Post {
54+
/**
55+
Get raw json from remote
56+
57+
Use this while it's hard to deserialize to struct
58+
**/
59+
pub async fn get_one_raw(&self, id: usize) -> Result<Value> {
60+
let client = reqwest::Client::new();
61+
62+
let req = {
63+
let url = blog_backend!("/posts/{}", id);
64+
let req = client.get(url);
65+
setup_auth(req, &self.pat)
66+
};
67+
68+
let resp = req.send().await?;
69+
70+
let mut json = {
71+
let body = body_or_err(resp).await?;
72+
serde_json::from_str::<Value>(&body)
73+
}?;
74+
75+
json["blogPost"].take().into_ok()
76+
}
77+
}

src/api/post/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ pub mod del_one;
33
pub mod get_count;
44
pub mod get_meta_list;
55
pub mod get_one;
6+
pub mod get_one_raw;
67
pub mod search;
8+
pub mod update;
79

810
pub struct Post {
911
pat: String,

src/api/post/update.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use crate::api::post::Post;
2+
use crate::blog_backend;
3+
use crate::infra::http::{body_or_err, setup_auth};
4+
use crate::infra::json;
5+
use crate::infra::result::IntoResult;
6+
use anyhow::Result;
7+
use serde::{Deserialize, Serialize};
8+
use serde_json::json;
9+
10+
impl Post {
11+
pub async fn update(
12+
&self,
13+
id: usize,
14+
title: &Option<String>,
15+
body: &Option<String>,
16+
publish: &Option<bool>,
17+
) -> Result<usize> {
18+
let client = reqwest::Client::new();
19+
20+
let req = {
21+
let url = blog_backend!("/posts");
22+
23+
let json = {
24+
let mut json = self.get_one_raw(id).await?;
25+
if let Some(title) = title {
26+
json["title"] = json!(title)
27+
}
28+
if let Some(body) = body {
29+
json["postBody"] = json!(body)
30+
}
31+
if let Some(publish) = publish {
32+
json["isPublished"] = json!(publish)
33+
}
34+
json
35+
};
36+
37+
let req = client.post(url).json(&json);
38+
setup_auth(req, &self.pat)
39+
};
40+
41+
let resp = req.send().await?;
42+
43+
let id = {
44+
let json = body_or_err(resp).await?;
45+
#[derive(Serialize, Deserialize, Debug)]
46+
struct Body {
47+
pub id: usize,
48+
}
49+
let body = json::deserialize::<Body>(&json)?;
50+
body.id
51+
};
52+
53+
id.into_ok()
54+
}
55+
}

src/args/cmd/ing.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct Opt {
2222
#[arg(verbatim_doc_comment)]
2323
/// Comment ing with specific content
2424
/// Example: cnb --id 114514 ing --comment 'Hello world'
25-
/// You should also specify the id of ing via option --id
25+
/// You should also specify the id of the ing via --id
2626
#[arg(long)]
2727
#[arg(short = 'c')]
2828
#[arg(value_name = "CONTENT")]

src/args/cmd/post.rs

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
use clap::Parser;
1+
use clap::{Parser, Subcommand};
22

33
#[derive(Parser, Debug)]
44
pub struct Opt {
55
#[arg(verbatim_doc_comment)]
66
/// Show title and content of a specific post
77
/// Example: cnb --id 114514 post --show
8-
/// You should also specify the id of post via option --id
8+
/// You should also specify the id of the post via --id
99
#[arg(long)]
1010
#[arg(short = 's')]
1111
pub show: bool,
1212

1313
#[arg(verbatim_doc_comment)]
1414
/// Show metadata of a specific post
1515
/// Example: cnb --id 114514 post --show-meta
16-
/// You should also specify the id of post via option --id
16+
/// You should also specify the id of the post via --id
1717
#[arg(long)]
1818
#[arg(short = 'm')]
1919
pub show_meta: bool,
@@ -30,7 +30,7 @@ pub struct Opt {
3030
#[arg(verbatim_doc_comment)]
3131
/// Delete post
3232
/// Example: cnb --id 114514 post --delete
33-
/// You should also specify the id of post via option --id
33+
/// You should also specify the id of the post via --id
3434
#[arg(long)]
3535
#[arg(visible_alias = "del")]
3636
pub delete: bool,
@@ -39,14 +39,66 @@ pub struct Opt {
3939
/// Search post by keyword and output the post id list that matches
4040
/// Example: cnb post --search 'Hello world'
4141
#[arg(long)]
42+
#[arg(short = 'f')]
43+
#[arg(visible_alias = "find")]
4244
#[arg(value_name = "KEYWORD")]
4345
pub search: Option<String>,
4446

45-
#[arg(verbatim_doc_comment)]
46-
/// Create a post
47-
/// Example: cnb post --create 'Title' 'Body'
48-
/// The status of post is draft
49-
#[arg(long)]
50-
#[arg(value_names = ["TITLE","BODY"])]
51-
pub create: Option<Vec<String>>,
47+
#[command(subcommand)]
48+
pub cmd: Option<Cmd>,
49+
}
50+
51+
#[derive(Debug, Subcommand)]
52+
pub enum Cmd {
53+
/// Create post
54+
/// Example: cnb post create --title 'Title' --body 'Body'
55+
#[clap(visible_alias = "c")]
56+
Create {
57+
#[arg(verbatim_doc_comment)]
58+
/// Set post title
59+
/// Example: cnb post create --title 'Title' --body 'Body'
60+
#[arg(long)]
61+
#[arg(value_name = "TITLE")]
62+
title: String,
63+
64+
#[arg(verbatim_doc_comment)]
65+
/// Set post body
66+
/// Example: cnb post create --title 'Title' --body 'Body'
67+
#[arg(long)]
68+
#[arg(value_name = "BODY")]
69+
body: String,
70+
71+
#[arg(verbatim_doc_comment)]
72+
/// Set post status to publish
73+
/// Example: cnb post create --title 'Title' --body 'Body' --publish
74+
#[arg(long)]
75+
#[arg(visible_alias = "pub")]
76+
publish: bool,
77+
},
78+
/// Update post
79+
/// Example: cnb --id 114514 post update --title 'Title'
80+
/// You should also specify the id of the post via --id
81+
#[clap(visible_alias = "u")]
82+
Update {
83+
#[arg(verbatim_doc_comment)]
84+
/// Set post title
85+
/// Example: cnb --id 114514 post update --title 'Title'
86+
#[arg(long)]
87+
#[arg(value_name = "TITLE")]
88+
title: Option<String>,
89+
90+
#[arg(verbatim_doc_comment)]
91+
/// Set post body
92+
/// Example: cnb --id 114514 post update --body 'Body'
93+
#[arg(long)]
94+
#[arg(value_name = "BODY")]
95+
body: Option<String>,
96+
97+
#[arg(verbatim_doc_comment)]
98+
/// Set post publish state
99+
/// Example: cnb --id 114514 post update --publish true
100+
#[arg(long)]
101+
#[arg(visible_alias = "pub")]
102+
publish: Option<bool>,
103+
},
52104
}

src/args/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub enum Style {
1515
#[command(author, about, long_about = None, version)]
1616
pub struct Args {
1717
#[command(subcommand)]
18-
command: Option<Cmd>,
18+
cmd: Option<Cmd>,
1919

2020
#[arg(verbatim_doc_comment)]
2121
/// Provide ID required by other options

0 commit comments

Comments
 (0)