Migrate #4
@@ -1 +1,2 @@
|
||||
target/
|
||||
numbers.json
|
||||
|
||||
Generated
+3
-1
@@ -76,9 +76,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clean_file"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"textsender_models",
|
||||
"tokio",
|
||||
|
||||
+3
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "clean_file"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
edition = "2024"
|
||||
rust-version = "1.95"
|
||||
|
||||
@@ -8,6 +8,8 @@ rust-version = "1.95"
|
||||
[dependencies]
|
||||
tokio = { version = "1.52.2", features = ["full"] }
|
||||
futures = { version = "0.3.32" }
|
||||
serde = { version = "1.0.228", features = ["derive"] }
|
||||
serde_json = { version = "1.0.149" }
|
||||
textsender_models = { git = "ssh://git@git.kundeng.us/phoenix/textsender-models.git", tag = "v0.2.5-v0.3.0-migrate-38dbcb09f7-111" }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
+31
-2
@@ -1,3 +1,32 @@
|
||||
fn main() {
|
||||
println!("clean_file");
|
||||
pub mod parser;
|
||||
pub mod version;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
if args.len() < 2 {
|
||||
println!("Invalid arguments provided");
|
||||
std::process::exit(-1);
|
||||
}
|
||||
|
||||
if version::contains_version(&args) {
|
||||
version::print_version();
|
||||
std::process::exit(-1);
|
||||
}
|
||||
|
||||
let filepath = &args[1];
|
||||
println!("Filepath: {filepath:?}");
|
||||
let prsr = parser::NumberParser {
|
||||
filepath: filepath.clone(),
|
||||
};
|
||||
|
||||
match prsr.file_dump().await {
|
||||
Ok(contacts) => {
|
||||
prsr.print_phone_numbers(&contacts);
|
||||
prsr.save_file(contacts).await;
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("Error: {err:?}");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
use std::io::BufRead;
|
||||
|
||||
const LETTERS: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct NumberParser {
|
||||
pub filepath: String,
|
||||
}
|
||||
|
||||
impl NumberParser {
|
||||
pub async fn file_dump(
|
||||
&self,
|
||||
) -> Result<Vec<textsender_models::contact::Contact>, std::io::Error> {
|
||||
println!("Dumping files");
|
||||
let mut objs: Vec<textsender_models::contact::Contact> = Vec::new();
|
||||
|
||||
match self.read_lines(&self.filepath).await {
|
||||
Ok(lines) => {
|
||||
for line in lines {
|
||||
let contains_letters = line.chars().any(|c| LETTERS.contains(c));
|
||||
if contains_letters {
|
||||
continue;
|
||||
} else {
|
||||
let my_obj = textsender_models::contact::Contact {
|
||||
phone_number: line.clone(),
|
||||
..Default::default()
|
||||
};
|
||||
if !my_obj.phone_number.is_empty() {
|
||||
objs.push(my_obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let updated_contacts = self.update_contacts(&objs).await;
|
||||
let removed_duplicates = self.remove_dups(&updated_contacts).await;
|
||||
|
||||
Ok(removed_duplicates)
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn save_file(&self, numbers: Vec<textsender_models::contact::Contact>) {
|
||||
let filename = String::from("numbers.json");
|
||||
|
||||
match serde_json::to_string(&numbers) {
|
||||
Ok(json_string) => match std::fs::write(&filename, json_string) {
|
||||
Ok(_) => {
|
||||
println!("Saved to: {filename:?}");
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("Error: {err:?}");
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
eprintln!("Error: {err:?}");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub fn print_phone_numbers(&self, contacts: &Vec<textsender_models::contact::Contact>) {
|
||||
println!("Printing phone numbers");
|
||||
|
||||
for contact in contacts {
|
||||
println!("Phone Number: {:?}", contact.phone_number);
|
||||
}
|
||||
|
||||
println!("Total phone numbers: {:?}", contacts.len());
|
||||
}
|
||||
|
||||
async fn read_lines(&self, filename: &String) -> Result<Vec<String>, std::io::Error> {
|
||||
match std::fs::File::open(filename) {
|
||||
Ok(file) => {
|
||||
let reader = std::io::BufReader::new(file);
|
||||
reader.lines().collect()
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
async fn remove_dups(
|
||||
&self,
|
||||
contacts: &Vec<textsender_models::contact::Contact>,
|
||||
) -> Vec<textsender_models::contact::Contact> {
|
||||
let mut unique_contacts: Vec<textsender_models::contact::Contact> = Vec::new();
|
||||
let mut unique_items = std::collections::HashSet::new();
|
||||
|
||||
for val in contacts {
|
||||
unique_items.insert(val.phone_number.clone());
|
||||
}
|
||||
|
||||
for unique_item in unique_items {
|
||||
let contact = textsender_models::contact::Contact {
|
||||
phone_number: unique_item,
|
||||
..Default::default()
|
||||
};
|
||||
unique_contacts.push(contact);
|
||||
}
|
||||
|
||||
unique_contacts
|
||||
}
|
||||
|
||||
async fn update_contacts(
|
||||
&self,
|
||||
contacts: &Vec<textsender_models::contact::Contact>,
|
||||
) -> Vec<textsender_models::contact::Contact> {
|
||||
let mut updated: Vec<textsender_models::contact::Contact> = Vec::new();
|
||||
|
||||
for ct in contacts {
|
||||
let phone_number = ct.phone_number.clone();
|
||||
if phone_number.len() < 2 {
|
||||
println!("Invalid number: {phone_number:?}");
|
||||
continue;
|
||||
}
|
||||
|
||||
let pars = self.remove_some_data(&phone_number).await;
|
||||
|
||||
match self.add_prefix(&pars) {
|
||||
Ok(updated_parsed) => {
|
||||
let contact = textsender_models::contact::Contact {
|
||||
phone_number: updated_parsed,
|
||||
..Default::default()
|
||||
};
|
||||
updated.push(contact);
|
||||
}
|
||||
Err(err) => {
|
||||
eprintln!("Error: {err:?}");
|
||||
std::process::exit(-2);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
updated
|
||||
}
|
||||
|
||||
fn add_prefix(&self, raw: &String) -> Result<String, std::io::Error> {
|
||||
if raw.is_empty() {
|
||||
Err(std::io::Error::other("Empty"))
|
||||
} else {
|
||||
let mut parsed: String = String::new();
|
||||
let first_char = raw.chars().nth(0).unwrap();
|
||||
|
||||
if first_char == '1' {
|
||||
parsed = format!("+{raw}");
|
||||
} else if first_char != '+' {
|
||||
parsed = format!("+1{raw}");
|
||||
}
|
||||
|
||||
Ok(parsed)
|
||||
}
|
||||
}
|
||||
|
||||
async fn remove_some_data(&self, unparsed: &str) -> String {
|
||||
let mut parsed: String = String::new();
|
||||
|
||||
for ch in unparsed.chars() {
|
||||
if ch == ' ' {
|
||||
continue;
|
||||
} else {
|
||||
if ch.is_numeric() {
|
||||
parsed.push(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parsed
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
pub fn print_version() {
|
||||
let name = env!("CARGO_PKG_NAME");
|
||||
let version = env!("CARGO_PKG_VERSION");
|
||||
|
||||
println!("{name:?} {version:?}");
|
||||
}
|
||||
|
||||
pub fn contains_version(args: &Vec<String>) -> bool {
|
||||
let valid_flags = vec!["-v", "--version"];
|
||||
|
||||
for arg in args {
|
||||
for valid_flag in &valid_flags {
|
||||
if valid_flag == arg {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
Reference in New Issue
Block a user