#![feature(str_strip)] extern crate fern; #[macro_use] extern crate log; extern crate clap; #[macro_use] extern crate diesel_migrations; use chrono::Utc; use clap::App; use clap::Arg; use clap::SubCommand; use diesel::connection::Connection; use diesel::pg::PgConnection; use pjournal::db; use pjournal::importer; use pjournal::models; use serde_json::to_value; embed_migrations!(); fn setup_logger() -> Result<(), fern::InitError> { use fern::colors::{Color, ColoredLevelConfig}; let colors = ColoredLevelConfig::new(); fern::Dispatch::new() .format(move |out, message, record| { let thread = std::thread::current(); let thread_id = &format!("{:?}", thread.id())[..]; let prefix = "ThreadId("; let thread_id = if thread_id.find(prefix).is_some() { &thread_id[prefix.len()..thread_id.len() - 1] } else { thread_id }; let thread_colors = [ Color::Red, Color::Green, Color::Magenta, Color::Cyan, Color::White, Color::Yellow, Color::BrightRed, Color::BrightGreen, Color::BrightMagenta, Color::BrightCyan, Color::BrightBlue, Color::BrightWhite, ]; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; let mut hasher = DefaultHasher::new(); thread_id.hash(&mut hasher); let thread_color = thread_colors[hasher.finish() as usize % thread_colors.len()]; // if thread_id.find("ThreadId(") { // } // TODO: Make a random color based on the thread name. out.finish(format_args!( "[{}] \x1B[{}m{}@{}\x1B[0m {}", colors.color(record.level()), thread_color.to_fg_str(), thread.name().unwrap_or(""), thread_id, message )) }) .level(log::LevelFilter::Info) .chain(std::io::stdout()) .apply()?; Ok(()) } fn main() { let matches = App::new("pjournal") .version("0.1") .author("KJ Ørbekk ") .about("Practice Journaling") .arg( Arg::with_name("database_url") .long("database_url") .required(true) .takes_value(true) .help("URL to postgresql database"), ) .arg( Arg::with_name("base_url") .long("base_url") .takes_value(true) .help("Endpoint for this web server"), ) .arg( Arg::with_name("static_path") .long("static_path") .takes_value(true) .help("Directory containing static files"), ) .subcommand( SubCommand::with_name("init") .about("initialize database config") .arg( Arg::with_name("rocket_secret_key") .long("rocket_secret_key") .takes_value(true) .required(true) .help("Secret passed to rocket for encrypted cookies"), ) .arg( Arg::with_name("strava_client_secret") .long("strava_client_secret") .takes_value(true) .required(true) .help("Client secret for strava authentication"), ) .arg( Arg::with_name("strava_client_id") .long("strava_client_id") .takes_value(true) .required(true) .help("Client id for strava authentication"), ), ) .subcommand( SubCommand::with_name("adduser") .about("add a user account") .arg(Arg::with_name("USERNAME").required(true).index(1)) .arg(Arg::with_name("PASSWORD").required(true).index(2)), ) .subcommand( SubCommand::with_name("process_all_data").about("create a ProcessAllRawData task"), ) .get_matches(); setup_logger().expect("logger"); let base_url = matches .value_of("base_url") .unwrap_or("http://localhost:8000"); let static_path = matches.value_of("static_path").unwrap_or("./static"); let db_url = matches.value_of("database_url").unwrap(); let conn = PgConnection::establish(db_url).unwrap(); embedded_migrations::run(&conn).unwrap(); if let Some(matches) = matches.subcommand_matches("init") { let config = models::Config { strava_client_id: matches.value_of("strava_client_id").unwrap().to_string(), strava_client_secret: matches .value_of("strava_client_secret") .unwrap() .to_string(), rocket_secret_key: matches.value_of("rocket_secret_key").unwrap().to_string(), singleton: true, }; db::create_config(&conn, &config).unwrap(); } else if let Some(matches) = matches.subcommand_matches("adduser") { let user = matches.value_of("USERNAME").unwrap(); let password = matches.value_of("PASSWORD").unwrap(); db::adduser(&conn, user, password).unwrap(); } else if let Some(_matches) = matches.subcommand_matches("process_all_data") { let command = importer::Command::ProcessAllRawData; db::insert_task( &conn, &models::NewTask { start_at: Utc::now(), state: models::TaskState::NEW, username: "system", payload: &to_value(command).unwrap(), }, ) .expect("insert"); } else { info!("Start server"); pjournal::server::start(conn, db_url, base_url, static_path); } }