fancier error handling for config
This commit is contained in:
parent
e4be6d9588
commit
9a90b18caf
|
@ -1,11 +1,14 @@
|
|||
use std::{
|
||||
env::{self, VarError},
|
||||
error::Error,
|
||||
fmt::Debug,
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use anyhow::{anyhow, Context};
|
||||
|
||||
pub struct Config {
|
||||
pub capture_images: bool,
|
||||
pub capture_audio_duration: Option<f64>,
|
||||
|
@ -22,37 +25,62 @@ pub struct Config {
|
|||
|
||||
const VAR_PREFIX: &str = "SCREENCAP_BOT_";
|
||||
|
||||
fn get_var(name: &str) -> Result<String, VarError> {
|
||||
env::var(VAR_PREFIX.to_string() + name)
|
||||
}
|
||||
|
||||
fn parse_var<E: Debug, T: FromStr<Err = E>>(name: &str) -> Result<T, VarError> {
|
||||
get_var(name).map(|s| {
|
||||
s.parse()
|
||||
.unwrap_or_else(|e| panic!("Failed to parse {}{}: {:?}", VAR_PREFIX, name, e))
|
||||
})
|
||||
}
|
||||
|
||||
fn expect_var(name: &str) -> String {
|
||||
get_var(name).unwrap_or_else(|_| panic!("{}{} must be set", VAR_PREFIX, name))
|
||||
}
|
||||
|
||||
pub fn load() -> Config {
|
||||
let capture_images = parse_var("CAPTURE_IMAGES").unwrap_or(true);
|
||||
|
||||
Config {
|
||||
capture_images,
|
||||
capture_audio_duration: parse_var("CAPTURE_AUDIO_DURATION").ok(),
|
||||
shows_file: parse_var("SHOWS_FILE").unwrap_or(PathBuf::from("./shows.yaml")),
|
||||
global_tags: get_var("GLOBAL_TAGS")
|
||||
.map(|s| s.split(',').map(String::from).collect())
|
||||
.unwrap_or_default(),
|
||||
post_interval: Duration::from_secs(parse_var("POST_INTERVAL").unwrap_or_default()),
|
||||
cohost_email: expect_var("COHOST_EMAIL"),
|
||||
cohost_password: expect_var("COHOST_PASSWORD"),
|
||||
cohost_page: expect_var("COHOST_PAGE"),
|
||||
cohost_draft: parse_var("COHOST_DRAFT").unwrap_or(false),
|
||||
cohost_cw: parse_var("COHOST_CW").unwrap_or(capture_images),
|
||||
eighteen_plus: parse_var("18PLUS").unwrap_or(false),
|
||||
fn get_var(name: &str) -> anyhow::Result<Option<String>> {
|
||||
let var_name = VAR_PREFIX.to_string() + name;
|
||||
match env::var(&var_name) {
|
||||
Ok(v) => Ok(Some(v)),
|
||||
Err(VarError::NotPresent) => Ok(None),
|
||||
Err(e) => Err(e).with_context(|| format!("Failed to read variable {}", var_name)),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_var<E: Debug + Send + Sync + Error + 'static, T: FromStr<Err = E>>(
|
||||
name: &str,
|
||||
) -> anyhow::Result<Option<T>> {
|
||||
get_var(name)?
|
||||
.map(|s| {
|
||||
s.parse()
|
||||
.with_context(|| format!("Failed to parse variable {}{}", VAR_PREFIX, name))
|
||||
})
|
||||
.transpose()
|
||||
}
|
||||
|
||||
fn require_var(name: &str) -> anyhow::Result<String> {
|
||||
get_var(name)?.ok_or_else(|| anyhow!("{}{} must be set", VAR_PREFIX, name))
|
||||
}
|
||||
|
||||
pub fn load() -> anyhow::Result<Config> {
|
||||
let capture_images = parse_var("CAPTURE_IMAGES")?.unwrap_or(true);
|
||||
|
||||
let capture_audio_duration = parse_var("CAPTURE_AUDIO_DURATION")?;
|
||||
if let Some(d) = capture_audio_duration {
|
||||
if d <= 0.0 {
|
||||
return Err(anyhow!(
|
||||
"{}CAPTURE_AUDIO_DURATION cannot be <= 0",
|
||||
VAR_PREFIX
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
if let (false, None) = (capture_images, capture_audio_duration) {
|
||||
return Err(anyhow!(
|
||||
"At least one of image capture and audio capture must be enabled!"
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Config {
|
||||
capture_images,
|
||||
capture_audio_duration,
|
||||
shows_file: parse_var("SHOWS_FILE")?.unwrap_or_else(|| PathBuf::from("./shows.yaml")),
|
||||
global_tags: get_var("GLOBAL_TAGS")?
|
||||
.map(|s| s.split(',').map(String::from).collect())
|
||||
.unwrap_or_default(),
|
||||
post_interval: Duration::from_secs(parse_var("POST_INTERVAL")?.unwrap_or_default()),
|
||||
cohost_email: require_var("COHOST_EMAIL")?,
|
||||
cohost_password: require_var("COHOST_PASSWORD")?,
|
||||
cohost_page: require_var("COHOST_PAGE")?,
|
||||
cohost_draft: parse_var("COHOST_DRAFT")?.unwrap_or(false),
|
||||
cohost_cw: parse_var("COHOST_CW")?.unwrap_or(capture_images),
|
||||
eighteen_plus: parse_var("18PLUS")?.unwrap_or(false),
|
||||
})
|
||||
}
|
||||
|
|
14
src/main.rs
14
src/main.rs
|
@ -27,13 +27,7 @@ async fn main() -> anyhow::Result<()> {
|
|||
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let conf = config::load();
|
||||
|
||||
if let (false, None) = (conf.capture_images, conf.capture_audio_duration) {
|
||||
return Err(anyhow!(
|
||||
"At least one of image capture and audio capture must be enabled!"
|
||||
));
|
||||
}
|
||||
let conf = config::load()?;
|
||||
|
||||
info!("Loading shows from {}", conf.shows_file.display());
|
||||
let shows = shows::load(&conf.shows_file).with_context(|| {
|
||||
|
@ -110,6 +104,12 @@ async fn post_random_capture<R: Rng>(
|
|||
Some(d) => media_info.duration_secs - d,
|
||||
None => media_info.duration_secs,
|
||||
};
|
||||
if max_timestamp < 0.0 {
|
||||
return Err(anyhow!(
|
||||
"Media file {} is too short to take audio clip!",
|
||||
file.display()
|
||||
));
|
||||
}
|
||||
let timestamp = max_timestamp * rng.sample::<f64, _>(Standard);
|
||||
let formatted_timestamp = format_timestamp(timestamp, Some(media_info.duration_secs));
|
||||
info!("Taking capture at {}", formatted_timestamp);
|
||||
|
|
Loading…
Reference in a new issue