frontend: example: csv-import helper

* cli to import a given csv configured text file

Signed-off-by: Ralf Zerres <ralf.zerres@networkx.de>
This commit is contained in:
2020-06-26 23:01:51 +02:00
parent 60e9d307bb
commit 2b4af02db6
5 changed files with 495 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
/// Commandline program testing csv imports
use log::{info, trace, warn};
use serde::Deserialize;
use std::{
error::Error,
io,
process,
thread,
time::{Duration, Instant}};
mod parse_args;
#[derive(Debug, Deserialize)]
struct Environment {
test_lang: String,
}
#[derive(Debug, Deserialize)]
pub struct CsvImportRecord {
// dion => Allianz Dion: 1
// policy_code => Policy Typ: "AS"
// policy_number => Versicherungsscheinnummer: "1515735810"
pub dion: String,
pub policy_code: String,
pub policy_number: u32,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use parse_args::parse_args;
use std::net::ToSocketAddrs;
use std::process;
use std::sync::Arc;
use viperus::Viperus;
// initialize logger
env_logger::init();
info!("Commencing the proxy!");
// initialize viperus structure
let mut v = Viperus::new();
// parse commandline arguments
info!(target: "csv_import", "parsing commandline args");
parse_args(&mut v)?;
trace!(target: "Viperus", "Config results: {:?}", v);
// create a new NextCloudTalk client
let config = matches.value_of("config").unwrap_or("advotracker.conf");
let csv_import = matches.value_of("import").unwrap_or("allianz.txt");
//let username = matches.value_of("username").unwrap_or("nctalkbot");
//let password = matches.value_of("password").unwrap_or("botpassword");
let verbose = matches.occurrences_of("verbose");
Ok(())
}

View File

@@ -0,0 +1,94 @@
/* advotracker infrastructure.
*
* Copyright 2020 Ralf Zerres <ralf.zerres@networkx.de>
* SPDX-License-Identifier: (0BSD or MIT)
*/
// Rust nightly supports procedural macros!
//#![feature(proc_macro)]
//#![deny(rust_2018_idioms)]
use dotenv::dotenv;
use locales::t;
use serde::Deserialize;
use std::env;
use std::error::Error;
use std::io;
use std::process;
use tracing::{debug, trace, Level};
#[derive(Deserialize, Debug)]
struct Environment {
test_lang: String,
}
#[derive(Debug, Deserialize)]
pub struct CsvImportRecord {
// dion => Allianz Dion: 1
// policy_code => Policy Typ: "AS"
// policy_number => Versicherungsscheinnummer: "1515735810"
pub dion: String,
pub policy_code: String,
pub policy_number: u32,
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// the YAML file is found relative to the current file
//use clap_v3::{load_yaml, App};
use clap::{load_yaml, App};
let yaml = load_yaml!("cli.yml");
//let matches = App::from_yaml(yaml).get_matches();
let matches = App::from_yaml(yaml)
.name(clap::crate_name!())
.version(clap::crate_version!())
.author(clap::crate_authors!())
.about(clap::crate_description!())
.get_matches();
// Gets the option value if supplied by user, otherwise set defaults
let config = matches.value_of("config").unwrap_or("advotracker.conf");
let csv_import = matches.value_of("import").unwrap_or("allianz.txt");
//let username = matches.value_of("username").unwrap_or("nctalkbot");
//let password = matches.value_of("password").unwrap_or("botpassword");
let verbose = matches.occurrences_of("verbose");
if verbose > 0 {
println!("{}: runtime parameters", clap::crate_name!());
println!("config_file: '{}'", config);
println!("csv_import: '{}'", csv_import);
println!("verbosity level: {}", matches.occurrences_of("verbose"));
}
if verbose > 1 {
println!("\nEnvironment:");
for (key, value) in env::vars() {
println!("{}={}", key, value);
}
}
Ok(())
}
/// import from csv format (Standard in)
fn import() -> Result<(), Box<dyn Error>> {
// Build the CSV reader and iterate over each record.
let mut csv_reader = csv::Reader::from_reader(io::stdin());
for result in csv_reader.deserialize() {
// The iterator yields Result<StringRecord, Error>, so we check the
// error here.
let record: CsvImportRecord = result?;
println!("{:?}", record);
}
Ok(())
}
fn main() {
if let Err(err) = import() {
println!("error running CSV-Import: {}", err);
process::exit(1);
}
}

View File

@@ -0,0 +1,78 @@
{
"err.lang.not_found": {
"de_DE.UTF-8": "Konnte Sprachkode nicht auslesen",
"de": "Konnte Sprachkode nicht auslesen",
"en": "Couldn't read LANG"
},
"err.user.not_found": {
"fr": "Utilisateur introuvable: $email, $id",
"de-DE.UTF-8": "Anwender nicht gefunden: $email, $id",
"de": "Anwender nicht gefunden: $email, $id",
"en": "User not found: $email, $id"
},
"main.started": {
"de_DE.UTF-8": "Programmlogik starten",
"de": "Programmlogik starten",
"en": "Program logic started"
},
"main.finished": {
"de_DE.UTF-8": "Programmlogik beendet",
"de": "Programmlogik beendet",
"en": "Program logic finished"
},
"parse.arguments": {
"de_DE.UTF-8": "Programmargumente prüfen",
"de": "Programmargumente prüfen",
"en": "Parsing arguments"
},
"parse.environment": {
"de_DE.UTF-8": "Umgebungsvariablen prüfen",
"de": "Umgebungsvariablen prüfen",
"en": "Parsing environment"
},
"parse.results": {
"de_DE.UTF-8": "Ergebnisse der Konfigurations-Parameterprüfung",
"de": "Ergebnisse der Konfigurationsparameterprüfung",
"en": "Config parsing results"
},
"config.name": {
"de_DE.UTF-8": "Konfigurationswert für",
"de": "Konfigurationswert für",
"en": "Config Value for"
},
"config.name.lang": {
"de_DE.UTF-8": "Sprach-Code",
"de": "Sprach-Code",
"en": "Language code"
},
"config.name.verbositylevel": {
"de_DE.UTF-8": "Ausgabe-Ebene",
"de": "Ausgabe-Ebene",
"en": "verbosity level"
},
"config.name.environment": {
"de_DE.UTF-8": "Umgebungsvariablen",
"de": "Umgebungsvariablen",
"en": "environment"
},
"config.name.configfile": {
"de_DE.UTF-8": "Konfigurations-Datei",
"de": "Konfigurations-Datei",
"en": "config file"
},
"config.name.dbdriver": {
"de_DE.UTF-8": "Datenbank-Treiber",
"de": "Datenbank-Treiber",
"en": "database driver"
},
"state.started": {
"de_DE.UTF-8": "gestartet",
"de": "gestartet",
"en": "started"
},
"state.finished": {
"de_DE.UTF-8": "beendet",
"de": "beended",
"en": "finished"
}
}

View File

@@ -0,0 +1,114 @@
/// Commandline program testing csv imports
use serde::Deserialize;
use std::env;
use std::{
error::Error,
io,
// process,
// thread,
// time::{Duration, Instant}
};
use tracing::{debug, trace, Level};
mod parse_args;
#[derive(Debug, Deserialize)]
struct Environment {
test_lang: String,
}
#[derive(Debug, Deserialize)]
pub struct CsvImportRecord {
// dion => Allianz Dion: 1
// policy_code => Policy Typ: "AS"
// policy_number => Versicherungsscheinnummer: "1515735810"
pub dion: String,
pub policy_code: String,
pub policy_number: u32,
}
/// import from csv format (Standard in)
fn import() -> Result<(), Box<dyn Error>> {
// Build the CSV reader and iterate over each record.
let mut csv_reader = csv::Reader::from_reader(io::stdin());
for result in csv_reader.deserialize() {
// The iterator yields Result<StringRecord, Error>, so we check the
// error here.
let record: CsvImportRecord = result?;
println!("{:?}", record);
}
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
use dotenv::dotenv;
use parse_args::parse_args;
use locales::t;
//use std::process;
//use std::sync::Arc;
use tracing_subscriber::fmt;
use viperus::Viperus;
// initialize the tracing subsystem
// a drop in replacement for classical logging
// reference: https://tokio.rs/blog/2019-08-tracing/
let span = tracing::span!(Level::TRACE, "csv-import");
let _enter = span.enter();
let subscriber = fmt::Subscriber::builder()
.with_env_filter("csv-import=trace")
.finish();
// initialize logger
//env_logger::init();
//info!("Commencing the import Test-Run!");
tracing::subscriber::with_default(subscriber, || {
// get system environment
let mut lang = env::var("LANG").unwrap_or("en".to_string());
let mut res = t!("parse.environment", lang);
let mut state = t!("state.started", lang);
trace!(target: "csv-import", message = ?res, state = ?state);
//debug!(message = ?res, state = ?state);
trace!(target: "csv-import", environment = "system", lang = ?lang);
// get testing environment (.env)
dotenv().ok();
match envy::from_env::<Environment>() {
Ok(environment) => {
if environment.test_lang != lang { lang = environment.test_lang; }
},
Err(e) => { debug!(target: "csv-import", "{}", e); }
}
res = t!("parse.environment", lang);
trace!(target: "csv-import", environment = "envy", lang = ?lang);
state = t!("state.finished", lang);
trace!(target: "csv-import", message = ?res, state = ?state);
// initialize viperus structure
let mut v = Viperus::new();
// parse commandline arguments
res = t!("parse.arguments", lang);
state = t!("state.started", lang);
trace!(target: "csv-import", process = ?res, state = ?state);
let _ = parse_args(&mut v);
state = t!("state.finished", lang);
trace!(target: "csv-import", process = ?res, state = ?state);
//trace!(target: "Viperus", "Config results: {:?}", v);
// Starting the program logic
res = t!("main.started", lang);
state = t!("state.started", lang);
trace!(target: "csv-import", process = ?res, state = ?state);
// import the given import file
let csv_file = v.get::<String>("import_file").unwrap();
state = t!("state.finished", lang);
res = t!("main.finished", lang);
trace!(target: "csv-import", process = ?res, state = ?state);
});
Ok(())
}

View File

@@ -0,0 +1,151 @@
use viperus::Viperus;
/// The given Viperus structure will be muted according to the
/// processed default, environment and commandline arguments
pub fn parse_args(v: &mut Viperus) -> Result<(), Box<dyn std::error::Error>> {
//use log::{debug, info, trace, warn};
use log::trace;
use std::env;
if cfg!(feature = "fmt-clap") {
trace!(target: "Viperus", "Viperus feature 'fmt-clap' enabled.");
println!("Using feature fmt-clap");
}
// preset default key/value pairs (lowest priority)
v.add_default("config_file", String::from("csv_import.ron"));
v.add_default("import_file", String::from("allianz.txt"));
//v.add_default("username", String::from("nctalkbot"));
//v.add_default("password", String::from("botpassword"));
v.add_default("verbose", 0);
// parse CLI commandline arguments with clap
use clap::{crate_authors, crate_description, crate_name, crate_version, App, Arg};
// CLI arguments are defined inline
let matches = App::new("nctalkproxyd")
.name(crate_name!())
.version(crate_version!())
.author(crate_authors!())
.about(crate_description!())
.after_help("Test: Versicherungsnummern-Import Allianz DirectCall")
.template(
"\
{bin} v{version}
{about}
{all-args}
(C) 2020 {author}
{after-help}",
)
.arg(
Arg::with_name("configFile")
.short("c")
.long("configFile")
.value_name("FILE")
.help("Select a config file")
.takes_value(true),
)
.arg(
Arg::with_name("importFile")
.short("i")
.long("importFile")
//.value_name("FILE")
.help("Select source file for the csv-import")
.takes_value(true),
)
// .arg(
// Arg::with_name("username")
// .short("u")
// .long("username")
// .help("Sets username")
// .takes_value(true),
// )
// .arg(
// Arg::with_name("password")
// .short("P")
// .long("password")
// .help("Sets password")
// .takes_value(true),
// )
.arg(
Arg::with_name("verbose")
.short("v")
.long("verbose")
.help("Sets verbosity level")
.multiple(true),
)
.get_matches();
if matches.occurrences_of("verbose") > 0 {
// clap is using i64, viperus i32
let n = matches.occurrences_of("verbose") as i32;
v.add("verbose", n);
}
// preset the prefix for relevant environment variables ("ADVOTRACKER_")
let mut env_prefix: String = crate_name!().to_uppercase();
env_prefix.push_str("_");
v.set_env_prefix(&env_prefix);
// respect dotenv environment (e.g for testing)
// -> overwrites the preset default values
println!(
"RUST_LOG={}",
dotenv::var("RUST_LOG").unwrap_or_else(|_| String::from("None"))
);
// enable caching and automatic update of environment values
if cfg!(feature = "fmt-cache") {
v.cache(true);
}
if cfg!(feature = "fmt-env") {
v.automatic_env(true);
}
// load user selected call arguments
// -> overwrites values given via environment variables
v.load_clap(matches)?;
// bond the clap names to camel_case rust variable names
v.bond_clap("configFile", "config_file");
v.bond_clap("importFile", "import_file");
//v.bond_clap("username", "username");
//v.bond_clap("password", "password");
v.bond_clap("verbose", "verbose");
trace!("verbose {:?}", v.get::<i32>("verbose").unwrap());
if v.get::<i32>("verbose").unwrap() > 0 {
println!(
"config_file: {:?}",
v.get::<String>("config_file").unwrap_or_default()
);
println!(
"import_file: {:?}",
v.get::<String>("import_file").unwrap_or_default()
);
// println!(
// "username: {:?}",
// v.get::<String>("username").unwrap_or_default()
// );
// println!(
// "password: {:?}",
// v.get::<String>("password").unwrap_or_default()
// ); // only for testing now
println!(
"verbosity level: {:?}",
v.get::<i32>("verbose").unwrap_or_default()
);
}
if v.get::<i32>("verbose").unwrap() > 1 {
println!("\nEnvironment:");
for (key, value) in env::vars() {
println!("{}={}", key, value);
}
}
Ok(())
}