extern crate structopt;
#[macro_use]
extern crate log;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
extern crate flexi_logger;
extern crate treexml;
extern crate chrono;
extern crate rfc822_sanitizer;
extern crate unidecode;
extern crate tera;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate human_panic;
extern crate kuchiki;
extern crate imap;
extern crate native_tls;
extern crate base64;
extern crate atom_syndication;
extern crate reqwest;
extern crate rss;
extern crate xhtmlchardet;
extern crate url;
extern crate tree_magic;
extern crate emailmessage;
extern crate openssl_probe;
extern crate regex;
extern crate custom_error;
extern crate async_std;
extern crate tokio;
extern crate futures;
use flexi_logger::Logger;
use std::path::PathBuf;
use structopt::StructOpt;
use std::error::Error;
mod config;
mod export;
mod feed_errors;
mod feed_reader;
mod feed_utils;
mod feed;
mod image_to_data;
mod import;
mod message;
mod settings;
mod store;
mod syndication;
#[derive(Debug, StructOpt)]
#[structopt(author=env!("CARGO_PKG_AUTHORS"))]
struct RRSS2IMAP {
#[structopt(short, long, parse(from_occurrences))]
verbose: u8,
#[structopt(subcommand)]
cmd: Command
}
#[derive(Debug, StructOpt)]
enum Command {
#[structopt(name = "new")]
New {
email: String,
},
#[structopt(name = "email")]
Email { email: String },
#[structopt(name = "run")]
Run,
#[structopt(name = "add")]
Add {
#[structopt(short = "u", long = "url")]
url:Option<String>,
#[structopt(short = "e", long = "email")]
email:Option<String>,
#[structopt(short = "d", long = "destination")]
destination:Option<String>,
#[structopt(short = "i", long = "inline-mages")]
inline_images:bool,
#[structopt(short = "x", long = "do-not-inline-mages")]
do_not_inline_images:bool,
parameters: Vec<String>,
},
#[structopt(name = "list")]
List,
#[structopt(name = "reset")]
Reset,
#[structopt(name = "delete")]
Delete {
feed: u32,
},
#[structopt(name = "export")]
Export {
#[structopt(parse(from_os_str))]
output: Option<PathBuf>,
},
#[structopt(name = "import")]
Import {
#[structopt(parse(from_os_str))]
input: Option<PathBuf>,
},
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
if !cfg!(debug_assertions) {
setup_panic!();
}
let opt = RRSS2IMAP::from_args();
Logger::try_with_env_or_str(
match opt.verbose {
0 => "warn",
1 => "warn, rrss2imap = info",
2 => "warn, rrss2imap = info",
_ => "trace", })
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e))
.format(match opt.verbose {
0 => flexi_logger::colored_default_format,
1 => flexi_logger::colored_default_format,
2 => flexi_logger::colored_detailed_format,
_ => flexi_logger::colored_with_thread, })
.start()
.unwrap_or_else(|e| panic!("Logger initialization failed with {}", e));
openssl_probe::init_ssl_cert_env_vars();
let store_path = store::find_store();
let store_result = store::Store::load(&store_path);
match store_result {
Ok(mut store) => {
match opt.cmd {
Command::New { email } => store.init_config(email),
Command::Email { email } => store.set_email(email),
Command::List => store.list(),
Command::Add { url, email, destination, inline_images, do_not_inline_images, parameters } =>
store.add(url, email, destination, store.settings.config.inline(inline_images, do_not_inline_images), parameters),
Command::Delete { feed } => store.delete(feed),
Command::Reset => store.reset(),
Command::Run => {
let handle = tokio::spawn(async move {
store.run().await
});
let _res = handle.await;
}
Command::Export { output } => store.export(output),
Command::Import { input } => store.import(input),
}
},
Err(e) => {
error!("Impossible to open store {}\n{}", store_path.to_string_lossy(), e);
}
}
Ok(())
}