parse_book_source/book_source/
mod.rs

1use 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    // 解析规则
31    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}