gradience_lib/
store.rs

1use crate::preset::Preset;
2#[cfg(feature = "online")]
3use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
4use serde::Deserialize;
5
6#[cfg(feature = "online")]
7const GH_API_URL: &str =
8    "https://api.github.com/repos/t-dantiau/community/git/trees/main?recursive=1";
9
10#[cfg(feature = "online")]
11const GH_COMMUNITY_PRESETS_URL: &str = "https://github.com/t-dantiau/Community/raw/main";
12
13
14pub struct Store {
15    pub base_path: String,
16    presets: Vec<Preset>,
17}
18
19#[derive(Deserialize, Debug)]
20pub struct GhApiUrlResponse {
21    pub tree: Vec<Tree>,
22    pub url: String,
23    pub sha: String,
24    pub truncated: bool,
25}
26
27#[derive(Deserialize, Debug)]
28pub struct Tree {
29    pub path: String,
30    pub mode: String,
31
32    #[serde(rename(deserialize = "type"))]
33    pub type_: String,
34    pub sha: String,
35    pub size: u32,
36    pub url: String,
37}
38
39impl Store {
40    pub fn new(base_path: String) -> Store {
41        if !std::path::Path::new(&base_path).exists() {
42            std::fs::create_dir_all(&base_path).unwrap();
43        }
44
45        Store {
46            base_path,
47            presets: Vec::new(),
48        }
49    }
50
51    pub fn load(&mut self) {
52        let paths = std::fs::read_dir(&self.base_path).unwrap();
53
54        for path in paths {
55            let path = path.unwrap().path();
56            let preset = Preset::from_file(&path.to_str().unwrap());
57            self.presets.push(preset);
58        }
59    }
60
61    pub fn add_preset(&mut self, preset: Preset) {
62        self.presets.push(preset);
63    }
64
65    pub fn remove_preset(&mut self, name: String) {
66        self.presets.retain(|p| p.name != name);
67
68        let path = format!("{}/{}.json", self.base_path, name);
69        std::fs::remove_file(path).unwrap();
70    }
71
72    pub fn get_preset(&self, name: String) -> Option<&Preset> {
73        self.presets.iter().find(|p| p.name == name)
74    }
75
76    pub fn save_presets(&self) {
77        for preset in &self.presets {
78            let path = format!("{}/{}.json", self.base_path, preset.name);
79            preset.to_file(&path);
80        }
81    }
82
83    #[cfg(feature = "online")]
84    fn construct_headers() -> HeaderMap {
85        let mut headers = HeaderMap::new();
86        headers.insert(USER_AGENT, HeaderValue::from_static("reqwest"));
87        headers
88    }
89
90    #[cfg(feature = "online")]
91    pub fn list_online_presets(&self) -> Vec<String> {
92        let client = reqwest::blocking::Client::new();
93        let res: GhApiUrlResponse = client
94            .get(GH_API_URL)
95            .headers(Store::construct_headers())
96            .send()
97            .unwrap()
98            .json()
99            .unwrap();
100
101        let mut online_presets = Vec::new();
102
103        for tree in res.tree {
104            let url = format!(
105                "{}/{}",
106                GH_COMMUNITY_PRESETS_URL, tree.path
107            );
108            online_presets.push(url);
109        }
110        online_presets
111    }
112
113    #[cfg(feature = "online")]
114    pub fn download_online_preset(&self, name: String) -> Result<Preset, reqwest::Error> {
115        let client = reqwest::blocking::Client::new();
116
117        let url = format!(
118            "{}/{}.json",
119            GH_COMMUNITY_PRESETS_URL, name
120        );
121
122        let resp = client
123            .get(&url)
124            .headers(Store::construct_headers())
125            .send()
126            .unwrap();
127        let content: Preset = resp.json().unwrap();
128        Ok(content)
129    }
130
131    pub fn list_local_presets(&self) -> Vec<String> {
132        let mut local_presets = Vec::new();
133        for preset in &self.presets {
134            local_presets.push(format!("{}/{}.json", self.base_path, preset.name));
135        }
136        local_presets
137    }
138}