canvas_grading/
config.rs

1use anyhow::{anyhow, Context, Result};
2use reqwest::Client;
3use serde::Deserialize;
4use std::{fs::File, io::Read, path::PathBuf};
5use tracing::info;
6
7use crate::{create_client, AccessToken, CLI};
8
9#[derive(Debug, Clone)]
10pub struct Config {
11    pub access_token: AccessToken,
12    pub course_id: u64,
13    pub base_url: String,
14    pub client: Client,
15}
16
17#[derive(Debug, Clone, Deserialize)]
18struct ConfigFile {
19    pub access_token: Option<AccessToken>,
20    pub course_id: Option<u64>,
21    pub base_url: Option<String>,
22}
23
24impl Config {
25    pub fn get(command_line_options: &CLI) -> Result<Self> {
26        let config_file_path = dirs::config_dir()
27            .context("Unable to get config dir for system")?
28            .join("grading")
29            .join("config.toml");
30
31        let config_contents = ConfigFile::read_from_file(&config_file_path)?;
32        info!("Config File: {:#?}", config_contents);
33
34        let access_token = command_line_options
35            .access_token
36            .clone()
37            .map(AccessToken)
38            .or(config_contents.access_token)
39            .ok_or(anyhow!("Access token not configured!"))?;
40        Ok(Self {
41            access_token: access_token.to_owned(),
42            course_id: command_line_options
43                .course_id
44                .or(config_contents.course_id)
45                .ok_or(anyhow!("Course id not configured!"))?,
46            base_url: command_line_options
47                .base_url
48                .clone()
49                .or(config_contents.base_url)
50                .ok_or(anyhow!("Base URL not configured!"))?,
51            client: create_client(access_token)?,
52        })
53    }
54}
55
56impl ConfigFile {
57    pub fn read_from_file(path: &PathBuf) -> Result<Self> {
58        let config_file = File::open(path);
59
60        let mut buffer = String::new();
61        if let Ok(mut file) = config_file {
62            file.read_to_string(&mut buffer)
63                .context("Unable to read file contents.")?;
64        }
65
66        toml::from_str(&buffer).context("Unable to parse config as TOML")
67    }
68}