2021-02-12 13:44:08 +00:00
|
|
|
use std::fs::File;
|
|
|
|
use std::io::Read;
|
2021-02-12 13:47:36 +00:00
|
|
|
use std::path::PathBuf;
|
2021-02-12 13:44:08 +00:00
|
|
|
|
2021-02-12 08:12:43 +00:00
|
|
|
use anyhow::Result;
|
2021-02-12 12:32:17 +00:00
|
|
|
use futures::future::TryFutureExt;
|
2021-02-12 13:47:36 +00:00
|
|
|
use structopt::StructOpt;
|
2021-02-12 13:44:08 +00:00
|
|
|
use tokio::sync::{mpsc, oneshot};
|
2021-02-14 12:11:17 +00:00
|
|
|
use xdg::BaseDirectories;
|
2021-02-14 12:27:13 +00:00
|
|
|
use panorama::config::{spawn_config_watcher, MailConfig};
|
2021-02-12 08:12:43 +00:00
|
|
|
|
2021-02-12 13:47:36 +00:00
|
|
|
#[derive(Debug, StructOpt)]
|
2021-02-12 13:52:46 +00:00
|
|
|
#[structopt(author, about)]
|
2021-02-12 13:47:36 +00:00
|
|
|
struct Opt {
|
2021-02-12 16:04:41 +00:00
|
|
|
/// Config file
|
|
|
|
#[structopt(long = "config-file", short = "c")]
|
|
|
|
config_path: Option<PathBuf>,
|
|
|
|
|
2021-02-12 13:47:36 +00:00
|
|
|
/// The path to the log file. By default, does not log.
|
|
|
|
#[structopt(long = "log-file")]
|
|
|
|
log_file: Option<PathBuf>,
|
|
|
|
}
|
|
|
|
|
2021-02-12 08:54:19 +00:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<()> {
|
2021-02-14 12:11:17 +00:00
|
|
|
// parse command line arguments into options struct
|
2021-02-12 13:47:36 +00:00
|
|
|
let opt = Opt::from_args();
|
|
|
|
|
2021-02-14 12:11:17 +00:00
|
|
|
// print logs to file as directed by command line options
|
2021-02-12 13:47:36 +00:00
|
|
|
setup_logger(&opt)?;
|
2021-02-12 08:12:43 +00:00
|
|
|
|
2021-02-14 12:11:17 +00:00
|
|
|
let xdg = BaseDirectories::new()?;
|
|
|
|
let config_update = spawn_config_watcher()?;
|
|
|
|
|
|
|
|
// let config: MailConfig = {
|
|
|
|
// let config_path = opt
|
|
|
|
// .config_path
|
|
|
|
// .clone()
|
|
|
|
// .unwrap_or_else(|| "config.toml".into());
|
|
|
|
// let mut config_file = File::open(config_path)?;
|
|
|
|
// let mut contents = Vec::new();
|
|
|
|
// config_file.read_to_end(&mut contents)?;
|
|
|
|
// toml::from_slice(&contents)?
|
|
|
|
// };
|
|
|
|
|
|
|
|
// used to notify the runtime that the process should exit
|
2021-02-12 08:54:19 +00:00
|
|
|
let (exit_tx, exit_rx) = oneshot::channel::<()>();
|
2021-02-14 12:11:17 +00:00
|
|
|
|
|
|
|
// used to send commands to the mail service
|
2021-02-12 13:44:08 +00:00
|
|
|
let (mail_tx, mail_rx) = mpsc::unbounded_channel();
|
2021-02-12 08:12:43 +00:00
|
|
|
|
2021-02-14 12:11:17 +00:00
|
|
|
tokio::spawn(mail::run_mail(config_update.clone(), mail_rx).unwrap_or_else(report_err));
|
|
|
|
let stdout = std::io::stdout();
|
2021-02-12 12:32:17 +00:00
|
|
|
tokio::spawn(ui::run_ui(stdout, exit_tx).unwrap_or_else(report_err));
|
2021-02-12 08:12:43 +00:00
|
|
|
|
2021-02-12 08:54:19 +00:00
|
|
|
exit_rx.await?;
|
2021-02-12 08:12:43 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-02-12 12:32:17 +00:00
|
|
|
|
2021-02-12 13:47:36 +00:00
|
|
|
fn setup_logger(opt: &Opt) -> Result<()> {
|
|
|
|
let mut fern = fern::Dispatch::new()
|
2021-02-12 12:32:17 +00:00
|
|
|
.format(|out, message, record| {
|
|
|
|
out.finish(format_args!(
|
|
|
|
"{}[{}][{}] {}",
|
|
|
|
chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
|
|
|
|
record.target(),
|
|
|
|
record.level(),
|
|
|
|
message
|
|
|
|
))
|
|
|
|
})
|
2021-02-12 13:47:36 +00:00
|
|
|
.level(log::LevelFilter::Debug);
|
|
|
|
|
|
|
|
if let Some(path) = &opt.log_file {
|
|
|
|
fern = fern.chain(fern::log_file(path)?);
|
|
|
|
}
|
|
|
|
|
|
|
|
fern.apply()?;
|
2021-02-12 12:32:17 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2021-02-14 12:27:13 +00:00
|
|
|
|
|
|
|
fn report_err(err: anyhow::Error) {
|
|
|
|
log::error!("error: {:?}", err);
|
|
|
|
}
|