diff --git a/.gitignore b/.gitignore index 4fffb2f..8eb581d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /target /Cargo.lock +/.idea diff --git a/Cargo.toml b/Cargo.toml index c683d96..7f246ed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,16 @@ [package] name = "downloader_config" -version = "0.3.0" +version = "0.3.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] log = "0.4.17" +serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0", optional = true } + + +[features] +default = [] +file = ["dep:serde_json"] diff --git a/src/lib.rs b/src/lib.rs index 56d7902..87554e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ use std::env; use std::fmt::Debug; use log::{info, trace}; +use serde::{Deserialize, Serialize}; #[derive(Clone, Debug)] pub struct Config { @@ -29,78 +30,173 @@ pub struct Config { pub download_folder_path: String, } +#[derive(Serialize, Deserialize, Default)] +struct ConfigBuilder { + pub path_auth_code: Option, + pub path_authentications: Option, + pub use_file_auth_response: Option, + pub use_local_auth_redirect: Option, + pub auth_file_read_timeout: Option, + + pub twitch_client_id: Option, + pub twitch_client_secret: Option, + pub twitch_downloader_id: Option, + pub twitch_downloader_thread_count: Option, + + pub bigquery_project_id: Option, + pub bigquery_dataset_id: Option, + pub bigquery_service_account_path: Option, + + pub youtube_client_secret_path: Option, + pub youtube_tags: Option, + pub youtube_description_template: Option, + pub youtube_video_length_minutes_soft_cap: Option, + pub youtube_video_length_minutes_hard_cap: Option, + + pub download_folder_path: Option, +} + pub fn load_config() -> Config { trace!("load_config()"); - info!("Loading config from environment variables"); - let twitch_client_id = env::var("TWITCH_CLIENT_ID").expect("TWITCH_CLIENT_ID not set"); - let twitch_client_secret = env::var("TWITCH_CLIENT_SECRET").expect("TWITCH_CLIENT_SECRET not set"); - let twitch_downloader_id = env::var("TWITCH_DOWNLOADER_ID") - .unwrap_or("kimne78kx3ncx6brgo4mv6wki5h1ko".to_string()); + let config_builder: ConfigBuilder; + let use_env; - let twitch_downloader_thread_count = env::var("TWITCH_DOWNLOADER_THREAD_COUNT") - .unwrap_or("50".to_string()) - .parse() - .expect("TWITCH_DOWNLOADER_THREAD_COUNT is not a number"); + #[cfg(not(feature = "file"))] + { + use_env = true; + } + #[cfg(feature = "file")] + let config_file_path: Option; + #[cfg(feature = "file")] + { + info!("Loading config from file"); + config_file_path = env::var("CONFIG_FILE_PATH").ok(); + if config_file_path.is_some() { + log::warn!("Failed to load config file path from environment variable. Using environment variables instead."); + use_env = true; + } else { + use_env = false; + } + } + if use_env { + info!("Loading config from environment variables"); + config_builder = ConfigBuilder { + twitch_client_id: env::var("TWITCH_CLIENT_ID").ok(), + twitch_client_secret: env::var("TWITCH_CLIENT_SECRET").ok(), + twitch_downloader_id: env::var("TWITCH_DOWNLOADER_ID").ok(), - let path_auth_code = - env::var("PATH_AUTH_CODE").unwrap_or("/tmp/twba/auth/code.txt".to_string()); - let path_authentications = - env::var("PATH_AUTHENTICATIONS").unwrap_or("/tmp/twba/auth/{user}.json".to_string()); - let use_file_auth_response = - env::var("USE_FILE_AUTH_RESPONSE").unwrap_or("1".to_string()) == "1"; - let use_local_auth_redirect = - env::var("USE_LOCAL_AUTH_REDIRECT").unwrap_or("0".to_string()) == "1"; - let auth_file_read_timeout = env::var("AUTH_FILE_READ_TIMEOUT") - .unwrap_or("5".to_string()) - .parse() - .unwrap(); + twitch_downloader_thread_count: env::var("TWITCH_DOWNLOADER_THREAD_COUNT").ok(), + path_auth_code: env::var("PATH_AUTH_CODE").ok(), + path_authentications: env::var("PATH_AUTHENTICATIONS").ok(), + use_file_auth_response: env::var("USE_FILE_AUTH_RESPONSE").ok(), + use_local_auth_redirect: env::var("USE_LOCAL_AUTH_REDIRECT").ok(), + auth_file_read_timeout: env::var("AUTH_FILE_READ_TIMEOUT").ok(), - let bigquery_project_id = - env::var("BIGQUERY_PROJECT_ID").unwrap_or("twitchbackup-v1".to_string()); - let bigquery_dataset_id = env::var("BIGQUERY_DATASET_ID").unwrap_or("backup_data".to_string()); - let bigquery_service_account_path = env::var("BIGQUERY_SERVICE_ACCOUNT_PATH") - .unwrap_or("auth/bigquery_service_account.json".to_string()); + bigquery_project_id: env::var("BIGQUERY_PROJECT_ID").ok(), + bigquery_dataset_id: env::var("BIGQUERY_DATASET_ID").ok(), + bigquery_service_account_path: env::var("BIGQUERY_SERVICE_ACCOUNT_PATH").ok(), - let youtube_client_secret_path = env::var("YOUTUBE_CLIENT_SECRET_PATH") - .unwrap_or("auth/youtube_client_secret.json".to_string()); + youtube_client_secret_path: env::var("YOUTUBE_CLIENT_SECRET_PATH").ok(), + youtube_tags: env::var("YOUTUBE_TAGS").ok(), + youtube_description_template: env::var("YOUTUBE_DESCRIPTION_TEMPLATE").ok(), + youtube_video_length_minutes_soft_cap: env::var( + "YOUTUBE_VIDEO_LENGTH_MINUTES_SOFT_CAP", + ) + .ok(), + youtube_video_length_minutes_hard_cap: env::var( + "YOUTUBE_VIDEO_LENGTH_MINUTES_HARD_CAP", + ) + .ok(), - let youtube_tags = env::var("YOUTUBE_TAGS") - .unwrap_or("".to_string()) - .split(",") - .map(|s| s.to_string()) - .collect(); + download_folder_path: env::var("DOWNLOAD_FOLDER_PATH").ok(), + }; + trace!("load_config() done loading fields"); + } else { + #[cfg(feature = "file")] + { + let config_file_path = config_file_path.expect( + "Failed to load config file path from environment variable, \ + but still ended up in the file config loading code.", + ); + let config_file = std::fs::read_to_string(&config_file_path).expect(&format!( + "Failed to read config file at path: {}", + config_file_path + )); + config_builder = + serde_json::from_str(&config_file).expect("Failed to parse config file"); + trace!("load_config() done loading fields from file"); + } + #[cfg(not(feature = "file"))] + panic!("Failed to load config from file and environment variables"); + } - let youtube_description_template = - env::var("YOUTUBE_DESCRIPTION_TEMPLATE").unwrap_or("test description for \"$$video_title$$\"".to_string()); - - let youtube_video_length_minutes_soft_cap = - env::var("YOUTUBE_VIDEO_LENGTH_MINUTES_SOFT_CAP").unwrap_or("300".to_string()).parse().unwrap_or(30i64); - let youtube_video_length_minutes_hard_cap = - env::var("YOUTUBE_VIDEO_LENGTH_MINUTES_HARD_CAP").unwrap_or("359".to_string()).parse().unwrap_or(30i64); - - - let download_folder_path = - env::var("DOWNLOAD_FOLDER_PATH").unwrap_or("/tmp/twba/videos/".to_string()); - - trace!("load_config() done loading fields"); Config { - path_auth_code, - use_file_auth_response, - path_authentications, - use_local_auth_redirect, - auth_file_read_timeout, - twitch_client_id, - twitch_client_secret, - twitch_downloader_id, - twitch_downloader_thread_count, - bigquery_project_id, - bigquery_dataset_id, - bigquery_service_account_path, - youtube_client_secret_path, - youtube_tags, - youtube_description_template, - youtube_video_length_minutes_soft_cap, - youtube_video_length_minutes_hard_cap, - download_folder_path, + path_auth_code: config_builder + .path_auth_code + .unwrap_or("/tmp/twba/auth/code.txt".to_string()), + use_file_auth_response: config_builder + .use_file_auth_response + .unwrap_or("1".to_string()) + == "1", + path_authentications: config_builder + .path_authentications + .unwrap_or("/tmp/twba/auth/{user}.json".to_string()), + use_local_auth_redirect: config_builder + .use_local_auth_redirect + .unwrap_or("0".to_string()) + == "1", + auth_file_read_timeout: config_builder + .auth_file_read_timeout + .unwrap_or("5".to_string()) + .parse() + .expect("AUTH_FILE_READ_TIMEOUT is not a number"), + twitch_client_id: config_builder + .twitch_client_id + .expect("TWITCH_CLIENT_ID not set"), + twitch_client_secret: config_builder + .twitch_client_secret + .expect("TWITCH_CLIENT_SECRET not set"), + twitch_downloader_id: config_builder + .twitch_downloader_id + .unwrap_or("kimne78kx3ncx6brgo4mv6wki5h1ko".to_string()), + twitch_downloader_thread_count: config_builder + .twitch_downloader_thread_count + .unwrap_or("50".to_string()) + .parse() + .expect("TWITCH_DOWNLOADER_THREAD_COUNT is not a number"), + bigquery_project_id: config_builder + .bigquery_project_id + .unwrap_or("twitchbackup-v1".to_string()), + bigquery_dataset_id: config_builder + .bigquery_dataset_id + .unwrap_or("backup_data".to_string()), + bigquery_service_account_path: config_builder + .bigquery_service_account_path + .unwrap_or("auth/bigquery_service_account.json".to_string()), + youtube_client_secret_path: config_builder + .youtube_client_secret_path + .unwrap_or("auth/youtube_client_secret.json".to_string()), + youtube_tags: config_builder + .youtube_tags + .unwrap_or("".to_string()) + .split(",") + .map(|s| s.to_string()) + .collect(), + youtube_description_template: config_builder + .youtube_description_template + .unwrap_or("test description for \"$$video_title$$\"".to_string()), + youtube_video_length_minutes_soft_cap: config_builder + .youtube_video_length_minutes_soft_cap + .unwrap_or("300".to_string()) + .parse() + .unwrap_or(30i64), + youtube_video_length_minutes_hard_cap: config_builder + .youtube_video_length_minutes_hard_cap + .unwrap_or("359".to_string()) + .parse() + .unwrap_or(60i64), + download_folder_path: config_builder + .download_folder_path + .unwrap_or("/tmp/twba/videos/".to_string()), } }