main.rs (3233B)
1 use std::path::absolute; 2 use std::path::PathBuf; 3 use std::process; 4 use std::io::stdout; 5 use std::str::from_utf8; 6 7 use uuid::Uuid; 8 9 use clap::Arg; 10 use clap::App; 11 12 use log::debug; 13 use log::info; 14 use env_logger; 15 16 use crier::Sequencer; 17 use crier::io::FeedGet; 18 use crier::mem::MemCache; 19 use crier::io::fs::FsFeed; 20 use crier::Error; 21 22 struct Config { 23 urls: Vec<String>, 24 author: String, 25 title: String, 26 id: String, 27 } 28 29 impl Config { 30 fn new(id: String, title: String, author: String, urls: Vec<String>) -> Config { 31 Config { 32 urls: urls, 33 title: title, 34 author: author, 35 id: id, 36 } 37 } 38 } 39 40 fn parse() -> Config { 41 let mut o = App::new("crier") 42 .version(env!("CARGO_PKG_VERSION")) 43 .author(env!("CARGO_PKG_AUTHORS")); 44 45 o = o.arg( 46 Arg::with_name("title") 47 .long("title") 48 .short("t") 49 .value_name("Aggregated feed title") 50 .takes_value(true) 51 .required(true) 52 ); 53 54 o = o.arg( 55 Arg::with_name("author") 56 .long("author") 57 .short("a") 58 .value_name("Aggregated feed author") 59 .takes_value(true) 60 .required(true) 61 ); 62 63 // TODO: implement auto generate id when missing 64 o = o.arg( 65 Arg::with_name("id") 66 .long("id") 67 .short("i") 68 .value_name("Aggregated feed id uuid value") 69 .takes_value(true) 70 .required(true) 71 ); 72 73 o = o.arg(Arg::with_name("URLS") 74 .multiple(true) 75 .help("list of uris to merge")); 76 77 let m = o.get_matches(); 78 79 Config::new( 80 String::from(m.value_of("id").unwrap()), 81 String::from(m.value_of("title").unwrap()), 82 String::from(m.value_of("author").unwrap()), 83 m.values_of("URLS").unwrap().map(|v| String::from(v)).collect()) 84 } 85 86 fn add_feed(seq: &mut Sequencer, getter: impl FeedGet, uri: String) -> Result<i64, Error> { 87 match getter.get(uri.as_str(), None) { 88 Ok(v) => { 89 let r = seq.add_from(v); 90 info!("got {} results from {}", r, uri); 91 return Ok(r); 92 }, 93 Err(e) => { 94 return Err(Error::ParseError); 95 }, 96 }; 97 } 98 99 fn process_entry(seq: &mut Sequencer, uri: String) -> Result<(), Error> { 100 let v: PathBuf; 101 let fp: String; 102 let fs = FsFeed{}; 103 104 debug!("processing {}", uri); 105 match absolute(uri) { 106 Ok(r) => { 107 fp = String::from(r.to_str().unwrap()); 108 }, 109 Err(e) => { 110 return Err(Error::ParseError); 111 } 112 }; 113 114 match add_feed(seq, fs, fp) { 115 Ok(r) => { 116 return Ok(()); 117 }, 118 Err(e) => { 119 return Err(e); 120 }, 121 } 122 } 123 124 fn main() { 125 let cfg = parse(); 126 let mut cache = MemCache::new(); 127 128 let id: Vec<u8> = cfg.id.into(); 129 let mut seq = Sequencer::new(id).with_cache(&mut cache); 130 131 seq.set_title(cfg.title.as_str()); 132 seq.set_author(cfg.author.as_str()); 133 134 env_logger::init(); 135 136 debug!("config has {} uris", cfg.urls.len()); 137 138 for v in cfg.urls { 139 process_entry(&mut seq, v).unwrap_or_else(|e| process::exit(1)); 140 } 141 142 seq.write_to(stdout()).unwrap(); 143 }