Migrate (#4)
Reviewed-on: #4
This commit was merged in pull request #4.
This commit is contained in:
@@ -1 +1,2 @@
|
|||||||
target/
|
target/
|
||||||
|
numbers.json
|
||||||
|
|||||||
Generated
+3
-1
@@ -76,9 +76,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clean_file"
|
name = "clean_file"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"textsender_models",
|
"textsender_models",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|||||||
+3
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "clean_file"
|
name = "clean_file"
|
||||||
version = "0.8.2"
|
version = "0.8.3"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
rust-version = "1.95"
|
rust-version = "1.95"
|
||||||
|
|
||||||
@@ -8,6 +8,8 @@ rust-version = "1.95"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
tokio = { version = "1.52.2", features = ["full"] }
|
tokio = { version = "1.52.2", features = ["full"] }
|
||||||
futures = { version = "0.3.32" }
|
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" }
|
textsender_models = { git = "ssh://git@git.kundeng.us/phoenix/textsender-models.git", tag = "v0.2.5-v0.3.0-migrate-38dbcb09f7-111" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|||||||
+31
-2
@@ -1,3 +1,32 @@
|
|||||||
fn main() {
|
pub mod parser;
|
||||||
println!("clean_file");
|
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