parse_book_source/book_source/
mod.rs1use crate::Result;
2use anyhow::anyhow;
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::path::Path;
6
7pub mod http_config;
8pub use http_config::*;
9pub mod rule;
10pub use rule::*;
11
12#[derive(Debug, Serialize, Deserialize, Clone)]
13#[serde(rename_all = "camelCase")]
14pub struct BookSource {
15 pub book_source_group: String,
16 pub book_source_name: String,
17 pub book_source_url: String,
18 pub last_update_time: u64,
19
20 pub search_url: String,
21 pub explore_url: Option<String>,
22 pub rule_explore_item: Option<RuleExploreItem>,
23
24 pub header: Option<String>,
25 pub respond_time: Option<u64>,
26
27 #[serde(default)]
28 pub http_config: HttpConfig,
29
30 pub rule_book_info: RuleBookInfo,
32 pub rule_content: RuleContent,
33 pub rule_explore: Option<RuleSearch>,
34 pub rule_search: RuleSearch,
35 pub rule_toc: RuleToc,
36}
37
38impl BookSource {
39 pub async fn from_url(url: &str) -> Result<Vec<Self>> {
40 let res: Value = reqwest::get(url).await?.json().await?;
41 Self::from_json(res)
42 }
43
44 pub fn from_path<T: AsRef<Path>>(path: T) -> Result<Vec<Self>> {
45 let file = std::fs::File::open(path)?;
46 let res: Value = serde_json::from_reader(file)?;
47 Self::from_json(res)
48 }
49
50 pub fn from_json(value: Value) -> Result<Vec<Self>> {
51 if value.is_object() {
52 Ok(vec![serde_json::from_value(value)?])
53 } else if value.is_array() {
54 Ok(value
55 .as_array()
56 .unwrap()
57 .iter()
58 .filter_map(|item| serde_json::from_value(item.clone()).ok())
59 .collect())
60 } else {
61 Err(anyhow!("value is not object or array").into())
62 }
63 }
64}