#![forbid(unsafe_code)]
mod bot;
mod cli;
mod config;
mod error;
mod limits;
mod names;
mod run;
mod session;
mod shepherd;
mod stop;
mod stream;
#[cfg(test)]
mod test_support;
mod wiring;
use std::{path::PathBuf, process::ExitCode};
use shep_client::shep_core::paths::ShepPaths;
use crate::{cli::Action, run::Identity};
const NO_SHEP_HOME_MESSAGE: &str = "shep-discord: neither $HOME nor $SHEP_HOME is set, so there \
is no shep home to find a socket in.";
fn cannot_start_runtime_message(err: &std::io::Error) -> String {
format!("shep-discord: cannot start a runtime: {err}")
}
fn main() -> ExitCode {
shep_client::dogs::probe::<config::Section>(env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
let args: Vec<String> = std::env::args().skip(1).collect();
let action = match Action::parse(args.iter().map(String::as_str)) {
Ok(action) => action,
Err(usage) => {
eprintln!("{usage}");
return ExitCode::FAILURE;
}
};
if action == Action::PrintConfig {
println!("{}", config::PRINT_CONFIG);
return ExitCode::SUCCESS;
}
let env = |key: &str| std::env::var(key).ok();
let home_dir = match (std::env::var_os("HOME"), env("SHEP_HOME")) {
(Some(dir), _) => PathBuf::from(dir),
(None, Some(_)) => PathBuf::new(),
(None, None) => {
eprintln!("{NO_SHEP_HOME_MESSAGE}");
return ExitCode::FAILURE;
}
};
let paths = ShepPaths::resolve(&env, &home_dir);
let identity = Identity::from_env(env);
let runtime = match tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
{
Ok(runtime) => runtime,
Err(err) => {
eprintln!("{}", cannot_start_runtime_message(&err));
return ExitCode::FAILURE;
}
};
let code = runtime.block_on(run::run(&paths.socket, &identity));
runtime.shutdown_background();
code
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_support::assert_no_dashes;
#[test]
fn nothing_printed_for_a_person_carries_a_dash() {
assert_no_dashes(config::PRINT_CONFIG);
assert_no_dashes(NO_SHEP_HOME_MESSAGE);
assert_no_dashes(&cannot_start_runtime_message(&std::io::Error::other(
"no more file descriptors",
)));
}
}