diff --git a/src/cli.rs b/src/cli.rs index 6dc7cfe..71ab4c6 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,6 +1,6 @@ use clap::Parser; -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Clone)] #[clap(author, version, about, long_about = None)] pub struct Cli { /// Discord token (if not used will be taken from DISCORD_TOKEN) diff --git a/src/main.rs b/src/main.rs index 6e61f7f..7508da2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use clap::{error::ErrorKind, CommandFactory, Parser}; -use dsc_tg_forwarder::{cli::Cli, config::parse_config, handler::Handler}; +use dsc_tg_forwarder::{cli::Cli, config::parse_config, handler::Handler, Config}; use serenity::prelude::*; -use std::env; +use std::{env, error::Error, fmt::Display}; use teloxide::prelude::*; #[tokio::main] @@ -9,53 +9,17 @@ async fn main() { let args = Cli::parse(); let mut cmd = Cli::command(); - let config_path = args.config_path.unwrap_or_else(|| { + let config_path = args.config_path.clone().unwrap_or_else(|| { format!( "{}/.config/dsc-tg-forwarder/config.yml", home::home_dir().unwrap().display() ) }); + let config = parse_config(&config_path.into()) .unwrap_or_else(|err| cmd.error(ErrorKind::InvalidValue, err).exit()); - - let discord_token = match ( - args.discord_token, - config.discord_token, - env::var("DISCORD_TOKEN"), - ) { - (Some(discord_token), _, _) => discord_token, - (_, Some(discord_token), _) => discord_token, - (_, _, Ok(discord_token)) => discord_token, - (None, None, Err(_)) => cmd - .error(ErrorKind::InvalidValue, "Discord token wasn't supplied") - .exit(), - }; - - let telegram_token = match ( - args.telegram_token, - config.telegram_token, - env::var("TELEGRAM_TOKEN"), - ) { - (Some(telegram_token), _, _) => telegram_token, - (_, Some(telegram_token), _) => telegram_token, - (_, _, Ok(telegram_token)) => telegram_token, - (None, None, Err(_)) => cmd - .error(ErrorKind::InvalidValue, "Telegram token wasn't supplied") - .exit(), - }; - - let output_chat_id = match ( - args.output_chat_id, - config.output_chat_id, - env::var("OUTPUT_CHAT_ID"), - ) { - (Some(output_chat_id), _, _) => output_chat_id, - (_, Some(output_chat_id), _) => output_chat_id, - (_, _, Ok(output_chat_id)) => output_chat_id, - (None, None, Err(_)) => cmd - .error(ErrorKind::InvalidValue, "Output chat id wasn't supplied") - .exit(), - }; + let (discord_token, telegram_token, output_chat_id) = get_tokens(&args.clone(), &config) + .unwrap_or_else(|err| cmd.error(ErrorKind::InvalidValue, err).exit()); // Login with a bot token from the environment let mut client = Client::builder(discord_token) @@ -77,3 +41,68 @@ async fn main() { cmd.error(ErrorKind::InvalidValue, err).exit() } } + +// Todo: Return struct instead of tuple +fn get_tokens(args: &Cli, config: &Config) -> anyhow::Result<(String, String, String)> { + let discord_token = get_discord_token(args, config)?; + let telegram_token = get_telegram_token(args, config)?; + let output_channel = get_output_channel(args, config)?; + + Ok((discord_token, telegram_token, output_channel)) +} + +fn get_telegram_token(args: &Cli, config: &Config) -> anyhow::Result { + let telegram_token = match ( + args.telegram_token.clone(), + config.telegram_token.clone(), + env::var("TELEGRAM_TOKEN"), + ) { + (Some(telegram_token), _, _) => telegram_token, + (_, Some(telegram_token), _) => telegram_token, + (_, _, Ok(telegram_token)) => telegram_token, + (None, None, Err(_)) => return Err(ConfigTokenError("Telegram token".to_owned()).into()), + }; + + Ok(telegram_token) +} + +fn get_discord_token(args: &Cli, config: &Config) -> anyhow::Result { + let discord_token = match ( + args.discord_token.clone(), + config.discord_token.clone(), + env::var("DISCORD_TOKEN"), + ) { + (Some(discord_token), _, _) => discord_token, + (_, Some(discord_token), _) => discord_token, + (_, _, Ok(discord_token)) => discord_token, + (None, None, Err(_)) => return Err(ConfigTokenError("Discord token".to_owned()).into()), + }; + + Ok(discord_token) +} + +fn get_output_channel(args: &Cli, config: &Config) -> anyhow::Result { + let output_chat_id = match ( + args.output_chat_id.clone(), + config.output_chat_id.clone(), + env::var("OUTPUT_CHAT_ID"), + ) { + (Some(output_chat_id), _, _) => output_chat_id, + (_, Some(output_chat_id), _) => output_chat_id, + (_, _, Ok(output_chat_id)) => output_chat_id, + (None, None, Err(_)) => return Err(ConfigTokenError("Output channel".to_owned()).into()), + }; + + Ok(output_chat_id) +} + +#[derive(Clone, Debug)] +struct ConfigTokenError(String); + +impl Display for ConfigTokenError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} not found!", self.0) + } +} + +impl Error for ConfigTokenError {}