Skip to content

Commit 72f3cef

Browse files
committed
feat: search site post api
1 parent 6bec167 commit 72f3cef

File tree

2 files changed

+146
-0
lines changed

2 files changed

+146
-0
lines changed

src/api/post/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ pub mod get_meta_list;
66
pub mod get_one;
77
pub mod get_one_raw;
88
pub mod search_self;
9+
pub mod search_site;
910
pub mod update;
1011

1112
pub struct Post {

src/api/post/search_site.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use crate::api::post::Post;
2+
use crate::infra::http::{body_or_err, RequestBuilderExt};
3+
use crate::infra::iter::IntoIteratorExt;
4+
use crate::infra::json;
5+
use crate::infra::result::WrapResult;
6+
use crate::openapi;
7+
use anyhow::Result;
8+
use serde::{Deserialize, Serialize};
9+
use std::ops::Range;
10+
11+
// HACK:
12+
// Convert skip and take to page index range while page size is 10
13+
fn get_page_index_range(skip: usize, take: usize) -> Range<usize> {
14+
let page_size = 10;
15+
let start_index = skip / page_size + 1;
16+
let end_index = if take == 0 {
17+
0
18+
} else {
19+
((take + skip) as f64 / page_size as f64).ceil() as usize
20+
};
21+
start_index..end_index + 1
22+
}
23+
24+
// HACK:
25+
// Convert skip and take to a range to slice the vec while page size is 10
26+
const fn get_slice_range(skip: usize, take: usize) -> Range<usize> {
27+
let skip_left = skip - (skip / 10) * 10;
28+
skip_left..skip_left + take
29+
}
30+
31+
#[test]
32+
fn test_get_page_index_range_and_get_slice_range() {
33+
fn f(skip: usize, take: usize) -> (Range<usize>, Range<usize>) {
34+
(
35+
get_page_index_range(skip, take),
36+
get_slice_range(skip, take),
37+
)
38+
}
39+
40+
assert_eq!(f(0, 00), (1..1, 0..00));
41+
assert_eq!(f(0, 01), (1..2, 0..01));
42+
assert_eq!(f(0, 09), (1..2, 0..09));
43+
assert_eq!(f(0, 10), (1..2, 0..10));
44+
assert_eq!(f(0, 11), (1..3, 0..11));
45+
assert_eq!(f(0, 19), (1..3, 0..19));
46+
assert_eq!(f(0, 20), (1..3, 0..20));
47+
assert_eq!(f(0, 21), (1..4, 0..21));
48+
49+
assert_eq!(f(1, 00), (1..1, 1..01));
50+
assert_eq!(f(1, 01), (1..2, 1..02));
51+
assert_eq!(f(1, 09), (1..2, 1..10));
52+
assert_eq!(f(1, 10), (1..3, 1..11));
53+
assert_eq!(f(1, 11), (1..3, 1..12));
54+
assert_eq!(f(1, 19), (1..3, 1..20));
55+
assert_eq!(f(1, 20), (1..4, 1..21));
56+
assert_eq!(f(1, 21), (1..4, 1..22));
57+
assert_eq!(f(1, 29), (1..4, 1..30));
58+
59+
assert_eq!(f(9, 00), (1..1, 9..09));
60+
assert_eq!(f(9, 01), (1..2, 9..10));
61+
assert_eq!(f(9, 09), (1..3, 9..18));
62+
assert_eq!(f(9, 10), (1..3, 9..19));
63+
assert_eq!(f(9, 11), (1..3, 9..20));
64+
assert_eq!(f(9, 19), (1..4, 9..28));
65+
assert_eq!(f(9, 20), (1..4, 9..29));
66+
assert_eq!(f(9, 21), (1..4, 9..30));
67+
assert_eq!(f(9, 29), (1..5, 9..38));
68+
69+
assert_eq!(f(10, 00), (2..1, 0..00));
70+
assert_eq!(f(10, 01), (2..3, 0..01));
71+
assert_eq!(f(10, 09), (2..3, 0..09));
72+
assert_eq!(f(10, 10), (2..3, 0..10));
73+
assert_eq!(f(10, 11), (2..4, 0..11));
74+
assert_eq!(f(10, 19), (2..4, 0..19));
75+
assert_eq!(f(10, 20), (2..4, 0..20));
76+
assert_eq!(f(10, 21), (2..5, 0..21));
77+
}
78+
79+
#[derive(Clone, Debug, Serialize, Deserialize)]
80+
pub struct SearchResultEntry {
81+
#[serde(rename = "Title")]
82+
pub title: String,
83+
#[serde(rename = "Content")]
84+
pub summary: String,
85+
86+
#[serde(rename = "UserName")]
87+
pub user_name: String,
88+
89+
#[serde(rename = "VoteTimes")]
90+
pub vote_count: usize,
91+
#[serde(rename = "ViewTimes")]
92+
pub view_count: usize,
93+
#[serde(rename = "CommentTimes")]
94+
pub comment_count: usize,
95+
96+
#[serde(rename = "PublishTime")]
97+
pub create_time: String,
98+
#[serde(rename = "Uri")]
99+
pub url: String,
100+
}
101+
102+
impl Post {
103+
pub async fn search_site(
104+
&self,
105+
skip: usize,
106+
take: usize,
107+
keyword: &str,
108+
) -> Result<Vec<SearchResultEntry>> {
109+
let client = &reqwest::Client::new();
110+
111+
let slice_range = get_slice_range(skip, take);
112+
113+
let entry_vec = {
114+
let entry_vec = get_page_index_range(skip, take)
115+
.map(|i| async move {
116+
let req = {
117+
let url = openapi!("/zzkdocuments/blog");
118+
let query = [
119+
("pageIndex", i.to_string()),
120+
("keyWords", keyword.to_string()),
121+
];
122+
client.get(url).query(&query).pat_auth(&self.pat)
123+
};
124+
let resp = req.send().await?;
125+
126+
let body = body_or_err(resp).await?;
127+
json::deserialize::<Vec<SearchResultEntry>>(&body)
128+
})
129+
.join_all()
130+
.await
131+
.into_iter()
132+
.collect::<Result<Vec<Vec<SearchResultEntry>>>>()?
133+
.concat();
134+
135+
entry_vec
136+
.into_iter()
137+
.enumerate()
138+
.filter(|(i, _)| slice_range.contains(i))
139+
.map(|(_, entry)| entry)
140+
.collect::<Vec<SearchResultEntry>>()
141+
};
142+
143+
entry_vec.wrap_ok()
144+
}
145+
}

0 commit comments

Comments
 (0)