leetcode_cli/config/
mod.rs

1//! Soft-link with `config.toml`
2//!
3//! leetcode-cli will generate a `leetcode.toml` by default,
4//! if you wanna change to it, you can:
5//!
6//! + Edit leetcode.toml at `~/.leetcode/leetcode.toml` directly
7//! + Use `leetcode config` to update it
8use crate::{
9    config::{code::Code, cookies::Cookies, storage::Storage, sys::Sys},
10    Error, Result,
11};
12use serde::{Deserialize, Serialize};
13use std::{fs, path::Path};
14
15mod code;
16mod cookies;
17mod storage;
18mod sys;
19
20pub use cookies::LeetcodeSite;
21
22/// Sync with `~/.leetcode/leetcode.toml`
23#[derive(Clone, Debug, Default, Deserialize, Serialize)]
24pub struct Config {
25    #[serde(default, skip_serializing)]
26    pub sys: Sys,
27    pub code: Code,
28    pub cookies: Cookies,
29    pub storage: Storage,
30}
31
32impl Config {
33    fn write_default(p: impl AsRef<Path>) -> Result<()> {
34        fs::write(p.as_ref(), toml::ser::to_string_pretty(&Self::default())?)?;
35
36        Ok(())
37    }
38
39    /// Locate lc's config file
40    pub fn locate() -> Result<Config> {
41        let conf = Self::root()?.join("leetcode.toml");
42
43        if !conf.is_file() {
44            Self::write_default(&conf)?;
45        }
46
47        let s = fs::read_to_string(&conf)?;
48        match toml::from_str::<Config>(&s) {
49            Ok(mut config) => {
50                // Override config.cookies with environment variables
51                config.cookies = config.cookies.with_env_override();
52
53                match config.cookies.site {
54                    cookies::LeetcodeSite::LeetcodeCom => Ok(config),
55                    cookies::LeetcodeSite::LeetcodeCn => {
56                        let mut config = config;
57                        config.sys.urls = sys::Urls::new_with_leetcode_cn();
58                        Ok(config)
59                    }
60                }
61            }
62            Err(e) => {
63                let tmp = Self::root()?.join("leetcode.tmp.toml");
64                Self::write_default(tmp)?;
65                Err(e.into())
66            }
67        }
68    }
69
70    /// Get root path of leetcode-cli
71    pub fn root() -> Result<std::path::PathBuf> {
72        let dir = dirs::home_dir().ok_or(Error::NoneError)?.join(".leetcode");
73        if !dir.is_dir() {
74            info!("Generate root dir at {:?}.", &dir);
75            fs::DirBuilder::new().recursive(true).create(&dir)?;
76        }
77
78        Ok(dir)
79    }
80
81    /// Sync new config to config.toml
82    pub fn sync(&self) -> Result<()> {
83        let home = dirs::home_dir().ok_or(Error::NoneError)?;
84        let conf = home.join(".leetcode/leetcode.toml");
85        fs::write(conf, toml::ser::to_string_pretty(&self)?)?;
86
87        Ok(())
88    }
89}