1use anyhow::anyhow;
2use serde_json::json;
3
4pub mod analyzer;
5pub mod book;
6pub mod book_source;
7pub mod error;
8pub mod http_client;
9pub mod utils;
10pub use analyzer::*;
11pub use book::*;
12pub use book_source::*;
13pub use error::*;
14pub use http_client::*;
15
16#[derive(Debug, Clone)]
17pub struct BookSourceParser {
18 pub book_source: BookSource,
19 pub http_client: HttpClient,
20 pub analyzer: AnalyzerManager,
21 pub temp: Option<String>,
22}
23
24unsafe impl Send for BookSourceParser {}
25unsafe impl Sync for BookSourceParser {}
26
27impl TryFrom<BookSource> for BookSourceParser {
28 type Error = ParseError;
29
30 fn try_from(book_source: BookSource) -> Result<Self> {
31 let mut http_config = book_source.http_config.clone();
32 if let Some(ref header) = book_source.header {
33 http_config.header = Some(serde_json::from_str(header)?);
34 }
35
36 if let Some(ref response_time) = book_source.respond_time {
37 http_config.timeout = Some(*response_time);
38 }
39
40 Ok(Self {
41 http_client: HttpClient::new(&book_source.book_source_url, &http_config)?,
42 book_source,
43 analyzer: AnalyzerManager::new()?,
44 temp: None,
45 })
46 }
47}
48
49impl BookSourceParser {
50 pub fn new(book_source: BookSource) -> Result<Self> {
51 Self::try_from(book_source)
52 }
53
54 pub async fn get_explores(&mut self) -> Result<ExploreList> {
56 if let Some(ref explore_url) = self.book_source.explore_url {
57 if let Some(ref rule_explore_item) = self.book_source.rule_explore_item {
58 let res = self
59 .http_client
60 .get(&self.book_source.book_source_url)
61 .await?
62 .text()
63 .await?;
64
65 let list = self.analyzer.get_element(explore_url, &res)?;
66
67 let res = list
68 .into_iter()
69 .flat_map(|item| {
70 rule_explore_item.parse_to_explore_item(&mut self.analyzer, &item)
71 })
72 .collect::<Vec<_>>();
73 return Ok(res);
74 } else {
75 return Ok(serde_json::from_str(explore_url)?);
76 }
77 }
78
79 Ok(vec![])
80 }
81
82 pub async fn search_books(&mut self, key: &str, page: u32, page_size: u32) -> Result<BookList> {
84 let url = self.analyzer.get_string(
85 &self.book_source.search_url,
86 "",
87 Some(json!({
88 "key": key,
89 "page": page,
90 "page_size": page_size,
91 })),
92 )?;
93
94 let mut res = String::new();
95
96 for i in url.split(",") {
97 res = self.http_client.get(i).await?.text().await?;
98 }
99
100 let list = self
101 .analyzer
102 .get_element(&self.book_source.rule_search.book_list, &res)?;
103
104 let res = list
105 .into_iter()
106 .flat_map(|item| {
107 self.book_source
108 .rule_search
109 .parse_to_book_list_item(&mut self.analyzer, &item)
110 })
111 .collect::<Vec<_>>();
112
113 Ok(res)
114 }
115
116 pub async fn explore_books(
118 &mut self,
119 url: &str,
120 page: u32,
121 page_size: u32,
122 ) -> Result<BookList> {
123 if self.book_source.rule_explore.is_none() {
124 return Err(anyhow!("explore rule is none").into());
125 }
126 let url = self.analyzer.get_string(
127 url,
128 "",
129 Some(json!({
130 "page": page,
131 "page_size": page_size,
132 })),
133 )?;
134
135 let res = self.http_client.get(url.as_str()).await?.text().await?;
136
137 let list = self.analyzer.get_element(
138 &self.book_source.rule_explore.as_ref().unwrap().book_list,
139 &res,
140 )?;
141
142 let res = list
143 .into_iter()
144 .flat_map(|item| {
145 self.book_source
146 .rule_explore
147 .as_ref()
148 .unwrap()
149 .parse_to_book_list_item(&mut self.analyzer, &item)
150 })
151 .collect::<Vec<_>>();
152
153 Ok(res)
154 }
155
156 pub async fn get_book_info(&mut self, book_url: &str) -> Result<BookInfo> {
158 let res = self.http_client.get(book_url).await?.text().await?;
159
160 let book_info = self
161 .book_source
162 .rule_book_info
163 .parse_to_book_info(&mut self.analyzer, &res);
164
165 self.temp = Some(res);
166
167 book_info
168 }
169
170 pub async fn get_chapters(&mut self, toc_url: &str) -> Result<Vec<Chapter>> {
171 let res = if toc_url.starts_with("/") || toc_url.starts_with("http") {
173 self.http_client.get(toc_url).await?.text().await?
174 } else {
175 self.temp.clone().ok_or(anyhow!("temp is none"))?
176 };
177
178 let list = self
179 .analyzer
180 .get_element(&self.book_source.rule_toc.chapter_list, &res)?;
181
182 let res = list
183 .into_iter()
184 .flat_map(|item| {
185 self.book_source
186 .rule_toc
187 .parse_to_chapter(&mut self.analyzer, &item)
188 })
189 .collect::<Vec<_>>();
190
191 Ok(res)
192 }
193
194 pub async fn get_content(&mut self, chapter_url: &str) -> Result<String> {
195 let mut res = self.http_client.get(chapter_url).await?.text().await?;
196
197 match &self.book_source.rule_content {
198 RuleContent::One { content } => self.analyzer.get_string(content, &res, None),
199
200 RuleContent::More {
201 content,
202 next_content_url,
203 start,
204 end,
205 } => {
206 let end = self
207 .analyzer
208 .get_string(end, &res, None)?
209 .parse::<usize>()?;
210 let mut contents = vec![];
211 let mut start = *start;
212
213 loop {
214 let content = self.analyzer.get_string(content, &res, None)?;
215 contents.push(content);
216
217 if start > end {
218 break;
219 }
220
221 let next_url = self.analyzer.get_string(
222 next_content_url,
223 &res,
224 Some(json!({
225 "index": start,
226 })),
227 )?;
228 res = self
229 .http_client
230 .get(next_url.as_str())
231 .await?
232 .text()
233 .await?;
234 start += 1;
235 }
236
237 Ok(contents.join(" "))
238 }
239 }
240 }
241}