Removed submodule classification in git
This commit is contained in:
@@ -0,0 +1,170 @@
|
||||
use chrono::{Datelike, Duration, NaiveDate, Utc};
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
use std::collections::HashMap;
|
||||
use std::fs::{self, File};
|
||||
use std::io::{Read, Write};
|
||||
use std::path::Path;
|
||||
|
||||
// Example API response type
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
struct HistoryItem {
|
||||
checkpoint: Option<String>,
|
||||
datetime: String,
|
||||
sha256: Option<String>,
|
||||
filename: Option<String>,
|
||||
hostname: Option<String>,
|
||||
// other fields...
|
||||
}
|
||||
|
||||
// JSON file structure
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct JsonFile {
|
||||
error: String,
|
||||
response: ResponseData,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct ResponseData {
|
||||
exechistories: Vec<HistoryItem>,
|
||||
}
|
||||
|
||||
// Mock API function
|
||||
fn history_logging(_type: &str, checkpoint: &str, _policy: &[&str]) -> Vec<HistoryItem> {
|
||||
// Replace with actual API call
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let file_path = Path::new("data/example.json");
|
||||
let mut checkpoint = "initial_checkpoint".to_string();
|
||||
let policy_name = "policy1".to_string();
|
||||
let days = 7;
|
||||
|
||||
// Initialize JSON output
|
||||
let mut json_output = JsonFile {
|
||||
error: "Success".to_string(),
|
||||
response: ResponseData {
|
||||
exechistories: vec![],
|
||||
},
|
||||
};
|
||||
|
||||
// Outer progress bar (filebar)
|
||||
let filebar = ProgressBar::new(10_000);
|
||||
filebar.set_style(
|
||||
ProgressStyle::default_bar()
|
||||
.template("Checkpoint Progress: {msg} [{bar:40.cyan/blue}] {pos}/{len}")
|
||||
.unwrap(),
|
||||
);
|
||||
filebar.set_message(&checkpoint);
|
||||
|
||||
// Inner progress bar (total progress)
|
||||
let pbar = ProgressBar::new(100);
|
||||
pbar.set_style(
|
||||
ProgressStyle::default_bar()
|
||||
.template("Total of {msg} Complete: [{bar:40.cyan/blue}] {pos}/{len}")
|
||||
.unwrap(),
|
||||
);
|
||||
pbar.set_message(&policy_name);
|
||||
|
||||
loop {
|
||||
let histories = history_logging("type", &checkpoint, &[&policy_name]);
|
||||
|
||||
if !histories.iter().all(|h| h.datetime.len() > 0) {
|
||||
eprintln!("Unexpected response format from API.");
|
||||
break;
|
||||
}
|
||||
|
||||
filebar.set_length(histories.len() as u64);
|
||||
|
||||
if histories.is_empty() {
|
||||
break;
|
||||
}
|
||||
|
||||
for (index, history_item) in histories.iter().enumerate() {
|
||||
if history_item.checkpoint.is_none() || history_item.datetime.is_empty() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if index == histories.len() - 1 {
|
||||
checkpoint = history_item.checkpoint.clone().unwrap();
|
||||
filebar.set_message(&checkpoint);
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse date
|
||||
let history_date = match NaiveDate::parse_from_str(
|
||||
&history_item.datetime.replace(" +0000 UTC", ""),
|
||||
"%Y-%m-%dT%H:%M:%SZ",
|
||||
) {
|
||||
Ok(date) => date,
|
||||
Err(_) => continue,
|
||||
};
|
||||
|
||||
let cutoff = Utc::today().naive_utc() - Duration::days(days);
|
||||
if history_date >= cutoff {
|
||||
json_output.response.exechistories.push(history_item.clone());
|
||||
}
|
||||
|
||||
filebar.inc(1);
|
||||
filebar.tick();
|
||||
}
|
||||
|
||||
// Deduplicate
|
||||
let mut seen: HashMap<(Option<String>, Option<String>, Option<String>), HistoryItem> =
|
||||
HashMap::new();
|
||||
|
||||
let combined = if file_path.exists() {
|
||||
let mut f = File::open(file_path).unwrap();
|
||||
let mut contents = String::new();
|
||||
f.read_to_string(&mut contents).unwrap();
|
||||
let existing_data: JsonFile = serde_json::from_str(&contents).unwrap_or(JsonFile {
|
||||
error: "Success".to_string(),
|
||||
response: ResponseData {
|
||||
exechistories: vec![],
|
||||
},
|
||||
});
|
||||
[existing_data.response.exechistories, json_output.response.exechistories.clone()]
|
||||
.concat()
|
||||
} else {
|
||||
json_output.response.exechistories.clone()
|
||||
};
|
||||
|
||||
for entry in combined {
|
||||
let key = (entry.sha256.clone(), entry.filename.clone(), entry.hostname.clone());
|
||||
seen.insert(key, entry);
|
||||
}
|
||||
|
||||
let deduplicated: Vec<HistoryItem> = seen.into_values().collect();
|
||||
|
||||
// Write to file
|
||||
let output_file = File::create(file_path).unwrap();
|
||||
serde_json::to_writer_pretty(&output_file, &json!({
|
||||
"error": "Success",
|
||||
"response": { "exechistories": deduplicated }
|
||||
}))
|
||||
.unwrap();
|
||||
|
||||
json_output.response.exechistories.clear();
|
||||
|
||||
// Update inner progress bar (percentage based on last valid item)
|
||||
if let Some(last_item) = histories.last() {
|
||||
if let Ok(last_date) = NaiveDate::parse_from_str(
|
||||
&last_item.datetime.replace(" +0000 UTC", ""),
|
||||
"%Y-%m-%dT%H:%M:%SZ",
|
||||
) {
|
||||
let date_diff = Utc::today().naive_utc() - last_date;
|
||||
let percentage_diff = ((days + 10) - date_diff.num_days()) as f64 / (days + 10) as f64 * 100.0;
|
||||
pbar.set_position(percentage_diff.round() as u64);
|
||||
pbar.set_message(&policy_name);
|
||||
pbar.tick();
|
||||
}
|
||||
}
|
||||
|
||||
filebar.set_position(1);
|
||||
}
|
||||
|
||||
filebar.finish();
|
||||
pbar.finish();
|
||||
}
|
||||
Reference in New Issue
Block a user