From 88f5752af56d9853e5606a7a2856b28177aa68e7 Mon Sep 17 00:00:00 2001 From: Alex Emmet <111742636+Alex-Emmet@users.noreply.github.com> Date: Thu, 29 Jan 2026 13:09:51 +0100 Subject: [PATCH] [Cleaned] --- src/server/api.rs | 58 +---- src/server/omikron_connection.rs | 17 +- src/server/server.rs | 37 +++- src/sql/connection_status.rs | 47 ++--- src/sql/sql.rs | 2 +- src/sql/user_online_tracker.rs | 18 +- src/util/crypto_helper.rs | 16 +- src/util/crypto_util.rs | 1 - src/util/file_util.rs | 350 ------------------------------- src/util/logger.rs | 3 +- src/util/mod.rs | 1 - 11 files changed, 86 insertions(+), 464 deletions(-) delete mode 100644 src/util/file_util.rs diff --git a/src/server/api.rs b/src/server/api.rs index a2e40ec..10be9fd 100644 --- a/src/server/api.rs +++ b/src/server/api.rs @@ -2,9 +2,7 @@ use crate::data::communication::{CommunicationType, CommunicationValue, DataType use crate::get_public_key; use crate::server::omikron_manager::get_random_omikron; use crate::sql::sql; -use crate::sql::user_online_tracker::{ - get_iota_omikron_connections, get_iota_primary_omikron_connection, -}; +use crate::sql::user_online_tracker::get_iota_primary_omikron_connection; use crate::{ sql::sql::{get_by_user_id, get_omikron_by_id}, util::crypto_helper::public_key_to_base64, @@ -19,12 +17,12 @@ use json::number::Number; pub async fn handle( path: &str, - headers: HeaderMap, + _headers: HeaderMap, body_string: Option, ) -> HttpResponse> { let path_parts: Vec<&str> = path.split("/").filter(|s| !s.is_empty()).collect(); - let body: Option = if body_string.is_some() { + let _body: Option = if body_string.is_some() { if let Ok(body_json) = json::parse(&body_string.unwrap()) { Some(body_json) } else { @@ -37,7 +35,7 @@ pub async fn handle( // get/ // omikron/ // id/ - let (status, content, body_text) = if path_parts.len() >= 2 { + let (status, body_text) = if path_parts.len() >= 2 { match path_parts[1] { "get" => match path_parts[2] { // api/get/omikron -> any omikron @@ -50,7 +48,6 @@ pub async fn handle( { ( StatusCode::OK, - "application/json", format!( "{{\"id\": {}, \"public_key\": \"{}\", \"ip_address\": \"{}\"}}", omikron_conn.get_omikron_id().await, @@ -61,14 +58,12 @@ pub async fn handle( } else { ( StatusCode::INTERNAL_SERVER_ERROR, - "text/plain", "selected an invalid omikron".to_string(), ) } } else { ( StatusCode::NOT_FOUND, - "text/plain", "couldn't find online omikron".to_string(), ) } @@ -79,7 +74,6 @@ pub async fn handle( } else if let Ok((public_key, ip_address)) = get_omikron_by_id(id).await { ( StatusCode::OK, - "application/json", format!( "{{\"id\": {}, \"public_key\": \"{}\", \"ip_address\": \"{}\"}}", id, public_key, ip_address @@ -91,7 +85,6 @@ pub async fn handle( { ( StatusCode::OK, - "application/json", format!( "{{\"id\": {}, \"public_key\": \"{}\", \"ip_address\": \"{}\"}}", omikron_id, public_key, ip_address @@ -109,7 +102,6 @@ pub async fn handle( { ( StatusCode::OK, - "application/json", format!( "{{\"id\": {}, \"public_key\": \"{}\", \"ip_address\": \"{}\"}}", omikron_id, public_key, ip_address @@ -171,11 +163,10 @@ pub async fn handle( DataTypes::sub_end, JsonValue::Number(Number::from(sub_end)), ); - (StatusCode::OK, "application/json", cv.to_json().to_string()) + (StatusCode::OK, cv.to_json().to_string()) } else { ( StatusCode::OK, - "application/json", CommunicationValue::new(CommunicationType::error_not_found) .to_json() .to_string(), @@ -184,11 +175,7 @@ pub async fn handle( } } } - "public_key" => ( - StatusCode::OK, - "application/json", - public_key_to_base64(&get_public_key()), - ), + "public_key" => (StatusCode::OK, public_key_to_base64(&get_public_key())), "user" => { if path_parts.len() != 4 { bad_request() @@ -247,11 +234,10 @@ pub async fn handle( base64::engine::general_purpose::STANDARD.encode(avatar), ); } - (StatusCode::OK, "application/json", cv.to_json().to_string()) + (StatusCode::OK, cv.to_json().to_string()) } else { ( StatusCode::OK, - "application/json", CommunicationValue::new(CommunicationType::error_not_found) .to_json() .to_string(), @@ -278,31 +264,9 @@ pub async fn handle( let body = Full::new(Bytes::from(body_text.to_string())); HttpResponse::builder().status(status).body(body).unwrap() } -pub fn bad_request() -> (StatusCode, &'static str, String) { - ( - StatusCode::BAD_REQUEST, - "text/text", - "400 Bad Request".to_string(), - ) +pub fn bad_request() -> (StatusCode, String) { + (StatusCode::BAD_REQUEST, "400 Bad Request".to_string()) } -pub fn unauthorized() -> (StatusCode, &'static str, String) { - ( - StatusCode::UNAUTHORIZED, - "text/text", - "401 Unauthorized".to_string(), - ) -} -pub fn forbidden() -> (StatusCode, &'static str, String) { - ( - StatusCode::FORBIDDEN, - "text/text", - "403 Forbidden".to_string(), - ) -} -pub fn not_found() -> (StatusCode, &'static str, String) { - ( - StatusCode::NOT_FOUND, - "text/text", - "404 Not Found".to_string(), - ) +pub fn not_found() -> (StatusCode, String) { + (StatusCode::NOT_FOUND, "404 Not Found".to_string()) } diff --git a/src/server/omikron_connection.rs b/src/server/omikron_connection.rs index 5c3d29c..f96738f 100644 --- a/src/server/omikron_connection.rs +++ b/src/server/omikron_connection.rs @@ -1,7 +1,7 @@ use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes}; use crate::server::omikron_manager; use crate::server::short_link::add_short_link; -use crate::sql::connection_status::ConnectionType; +use crate::sql::connection_status::UserStatus; use crate::sql::sql::{self, get_by_user_id, get_by_username, get_iota_by_id, get_omikron_by_id}; use crate::sql::user_online_tracker::{self}; use crate::util::crypto_helper::encrypt; @@ -12,7 +12,6 @@ use dashmap::DashMap; use futures::SinkExt; use futures::stream::SplitSink; use futures::stream::SplitStream; -use futures::task::UnsafeFutureObj; use hyper::upgrade::Upgraded; use hyper_util::rt::TokioIo; use json::JsonValue; @@ -138,7 +137,7 @@ impl OmikronConnection { let omikron_pub_key = match PublicKey::from_bytes(&pub_key_bytes) { Some(k) => k, - None => { + _ => { self.send_error_response( &cv.get_id(), CommunicationType::error_invalid_public_key, @@ -226,7 +225,7 @@ impl OmikronConnection { // ONLINE STATUS TRACKING if cv.is_type(CommunicationType::user_connected) { if let Some(user_id) = cv.get_data(DataTypes::user_id).and_then(|v| v.as_i64()) { - user_online_tracker::track_user_status(user_id, ConnectionType::Online, omikron_id); + user_online_tracker::track_user_status(user_id, UserStatus::Online, omikron_id); } return; } @@ -235,7 +234,7 @@ impl OmikronConnection { if let Some(status) = user_online_tracker::get_user_status(user_id) { user_online_tracker::track_user_status( user_id, - ConnectionType::UserOffline, + UserStatus::UserOffline, status.omikron_id, ); } @@ -253,7 +252,7 @@ impl OmikronConnection { let _ = user_ids.push(JsonValue::from(user.0)); user_online_tracker::track_user_status( user.0, - ConnectionType::UserOffline, + UserStatus::UserOffline, omikron_id, ); } @@ -292,7 +291,7 @@ impl OmikronConnection { if let Some(user_id) = user_id_json.as_i64() { user_online_tracker::track_user_status( user_id, - ConnectionType::Online, + UserStatus::Online, omikron_id, ); } @@ -388,7 +387,7 @@ impl OmikronConnection { } else { response = response.add_data( DataTypes::online_status, - JsonValue::String(ConnectionType::IotaOffline.to_string()), + JsonValue::String(UserStatus::IotaOffline.to_string()), ); } @@ -464,7 +463,7 @@ impl OmikronConnection { } else { response = response.add_data( DataTypes::online_status, - JsonValue::String(ConnectionType::IotaOffline.to_string()), + JsonValue::String(UserStatus::IotaOffline.to_string()), ); } response = response.add_data( diff --git a/src/server/server.rs b/src/server/server.rs index d4790f3..fe88e3c 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -2,7 +2,6 @@ use crate::log; use crate::server::api; use crate::server::short_link::get_short_link; use crate::server::socket; -use crate::util::file_util::load_file_buf; use base64::Engine; use base64::engine::general_purpose::STANDARD; @@ -21,12 +20,14 @@ use rustls::ServerConfig; use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use sha1::{Digest, Sha1}; use std::error::Error; -use std::io::ErrorKind; -use std::io::{self, BufReader}; +use std::fs::{self, File}; +use std::io::{self, BufReader, ErrorKind}; use std::net::SocketAddr; +use std::path::{Path, PathBuf}; use std::result::Result::Ok; use std::sync::Arc; use std::{future::Future, pin::Pin, time::Duration}; + use tokio::net::TcpListener; use tokio::sync::broadcast; use tokio_rustls::TlsAcceptor; @@ -354,6 +355,36 @@ fn calculate_accept_key(key: &str) -> String { STANDARD.encode(result) } +pub fn load_file_buf(path: &str, name: &str) -> io::Result> { + let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from(".")); + let dir = exe + .parent() + .unwrap_or(Path::new(".")) + .to_string_lossy() + .to_string(); + let dir = Path::new(&dir).join(path); + let file_path = dir.join(name); + + if !dir.exists() { + if let Err(_) = fs::create_dir_all(&dir) { + return Err(io::Error::new( + io::ErrorKind::NotFound, + "Directory creation failed", + )); + } + } + + if !file_path.exists() { + return Err(io::Error::new( + io::ErrorKind::NotFound, + "File creation failed", + )); + } + + let file = File::open(&file_path)?; + Ok(BufReader::new(file)) +} + /// Loads TLS config. Returns Ok(None) if cert files are not found, and an error if parsing fails. fn load_tls_config() -> Result>, Box> { let cert_file_res = load_file_buf("certs", "cert.pem"); diff --git a/src/sql/connection_status.rs b/src/sql/connection_status.rs index 5e7c68f..1c41491 100644 --- a/src/sql/connection_status.rs +++ b/src/sql/connection_status.rs @@ -1,38 +1,27 @@ -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum ConnectionType { +use strum::IntoEnumIterator; +use strum_macros::EnumIter; + +#[derive(Debug, Clone, PartialEq, EnumIter, Eq)] +#[allow(unused)] +pub enum UserStatus { Online, - UserOffline, - IotaOffline, + PhoneOnline, Away, DoNotDisturb, + UserOffline, + IotaOffline, } -impl ConnectionType { - pub fn to_str(&self) -> &str { - match self { - ConnectionType::Online => "online", - ConnectionType::UserOffline => "user_offline", - ConnectionType::IotaOffline => "iota_offline", - ConnectionType::Away => "away", - ConnectionType::DoNotDisturb => "do_not_disturb", - } - } +#[allow(unused)] +impl UserStatus { pub fn to_string(&self) -> String { - match self { - ConnectionType::Online => "online".to_string(), - ConnectionType::UserOffline => "user_offline".to_string(), - ConnectionType::IotaOffline => "iota_offline".to_string(), - ConnectionType::Away => "away".to_string(), - ConnectionType::DoNotDisturb => "do_not_disturb".to_string(), - } + format!("{:?}", self) } - pub fn from_str(s: &str) -> Option { - match s.to_lowercase().as_str() { - "online" => Some(ConnectionType::Online), - "user_offline" => Some(ConnectionType::UserOffline), - "iota_offline" => Some(ConnectionType::IotaOffline), - "away" => Some(ConnectionType::Away), - "do_not_disturb" => Some(ConnectionType::DoNotDisturb), - _ => None, + pub fn from_str(s: &str) -> Option { + for sel in UserStatus::iter() { + if &sel.to_string() == s { + return Some(sel); + } } + None } } diff --git a/src/sql/sql.rs b/src/sql/sql.rs index 20dd688..6a6ffc9 100644 --- a/src/sql/sql.rs +++ b/src/sql/sql.rs @@ -553,7 +553,7 @@ pub async fn get_iota_by_id(id: i64) -> Result<(i64, String), sqlx::Error> { id_u64 as i64, String::from_utf8_lossy(&public_key).to_string(), )), - None => Err(sqlx::Error::RowNotFound), + _ => Err(sqlx::Error::RowNotFound), }, Err(e) => Err(e), } diff --git a/src/sql/user_online_tracker.rs b/src/sql/user_online_tracker.rs index 3a1ab42..8cde17b 100644 --- a/src/sql/user_online_tracker.rs +++ b/src/sql/user_online_tracker.rs @@ -1,11 +1,11 @@ use crate::sql; -use crate::sql::connection_status::ConnectionType; +use crate::sql::connection_status::UserStatus; use dashmap::DashMap; use once_cell::sync::Lazy; #[derive(Debug, Clone)] -pub struct UserStatus { - pub connection_type: ConnectionType, +pub struct UserConnection { + pub connection_type: UserStatus, pub omikron_id: i64, } @@ -16,7 +16,7 @@ static IOTA_PRIMARY_OMIKRON_CONNECTION: Lazy> = Lazy::new(Dash static IOTA_OMIKRON_CONNECTIONS: Lazy>> = Lazy::new(DashMap::new); // UserID -> UserStatus -static USER_STATUS_MAP: Lazy> = Lazy::new(DashMap::new); +static USER_STATUS_MAP: Lazy> = Lazy::new(DashMap::new); pub fn track_iota_connection(iota_id: i64, omikron_id: i64, primary: bool) { let mut entry = IOTA_OMIKRON_CONNECTIONS @@ -60,24 +60,20 @@ pub fn get_iota_omikron_connections(iota_id: i64) -> Option> { IOTA_OMIKRON_CONNECTIONS.get(&iota_id).map(|v| v.clone()) } -pub fn track_user_status(user_id: i64, status: ConnectionType, omikron_id: i64) { +pub fn track_user_status(user_id: i64, status: UserStatus, omikron_id: i64) { USER_STATUS_MAP.insert( user_id, - UserStatus { + UserConnection { connection_type: status, omikron_id, }, ); } -pub fn get_user_status(user_id: i64) -> Option { +pub fn get_user_status(user_id: i64) -> Option { USER_STATUS_MAP.get(&user_id).map(|v| v.clone()) } -pub fn untrack_user(user_id: i64) { - USER_STATUS_MAP.remove(&user_id); -} - pub fn untrack_many_users(user_ids: &[i64]) { for user_id in user_ids { USER_STATUS_MAP.remove(user_id); diff --git a/src/util/crypto_helper.rs b/src/util/crypto_helper.rs index bb086b8..68e3855 100644 --- a/src/util/crypto_helper.rs +++ b/src/util/crypto_helper.rs @@ -10,31 +10,25 @@ use x448::{PublicKey, Secret, SharedSecret}; /// Errors for crypto operations #[derive(Debug)] pub enum CryptoError { - Base64Decode(base64::DecodeError), - InvalidKey, + Base64Decode, AgreementError, EncryptionError(aes_gcm::Error), DecryptionError(aes_gcm::Error), } impl From for CryptoError { - fn from(err: base64::DecodeError) -> Self { - CryptoError::Base64Decode(err) + fn from(_: base64::DecodeError) -> Self { + CryptoError::Base64Decode } } -pub struct KeyPair { - pub secret: Secret, - pub public: PublicKey, -} - -pub fn generate_keypair() -> KeyPair { +pub fn generate_keypair() -> (Secret, PublicKey) { let mut buf = [0u8; 56]; let mut rng = OsRng; rng.fill_bytes(&mut buf); let secret = Secret::from_bytes(&buf).unwrap(); let public = PublicKey::from(&secret); - KeyPair { secret, public } + (secret, public) } pub fn public_key_to_base64(pubkey: &PublicKey) -> String { diff --git a/src/util/crypto_util.rs b/src/util/crypto_util.rs index 066149a..97acab4 100644 --- a/src/util/crypto_util.rs +++ b/src/util/crypto_util.rs @@ -5,7 +5,6 @@ use aes_gcm::{ use base64::{Engine as _, engine::general_purpose::STANDARD as BASE64_STD}; use hkdf::Hkdf; use sha2::{Digest, Sha256}; -use std::fmt; use x448::{PublicKey, Secret}; // --- Custom Errors --- diff --git a/src/util/file_util.rs b/src/util/file_util.rs deleted file mode 100644 index 383ba3b..0000000 --- a/src/util/file_util.rs +++ /dev/null @@ -1,350 +0,0 @@ -use crate::log; -use std::ffi::OsStr; -use std::fs::{self, File}; -use std::io::{self, BufReader, Read}; -use std::path::{Path, PathBuf}; -use sysinfo::System; -use uuid::Uuid; -use walkdir::WalkDir; -use zip::ZipArchive; - -pub fn delete_file(path: &str, name: &str) -> bool { - let dir = Path::new(&get_directory()).join(path); - let file = dir.join(name); - if !file.exists() { - return false; - } - fs::remove_file(file).is_ok() -} - -pub fn delete_directory(path: &str) -> bool { - let dir = Path::new(&get_directory()).join(path); - delete_dir_recursive(&dir) -} - -fn delete_dir_recursive(directory: &Path) -> bool { - if !directory.exists() { - return false; - } - if let Err(e) = fs::remove_dir_all(directory) { - log!( - "[IMPORTANT] Couldn't delete directory {}: {}", - directory.display(), - e - ); - return false; - } - true -} - -pub fn load_file_buf(path: &str, name: &str) -> io::Result> { - let dir = Path::new(&get_directory()).join(path); - let file_path = dir.join(name); - - // Ensure the directory exists, create if necessary - if !dir.exists() { - if let Err(_) = fs::create_dir_all(&dir) { - return Err(io::Error::new( - io::ErrorKind::NotFound, - "Directory creation failed", - )); - } - } - - // Create the file if it doesn't exist - if !file_path.exists() { - return Err(io::Error::new( - io::ErrorKind::NotFound, - "File creation failed", - )); - } - - // Open the file and return a BufReader for efficient reading - let file = File::open(&file_path)?; - Ok(BufReader::new(file)) -} -pub fn has_file(path: &str, name: &str) -> bool { - let dir = Path::new(&get_directory()).join(path); - let file_path = dir.join(name); - - if !dir.exists() { - return false; - } - - if !file_path.exists() { - return false; - } - - true -} -pub fn has_dir(path: &str) -> bool { - let dir = Path::new(&get_directory()).join(path); - - if !dir.exists() { - return false; - } - - true -} - -pub fn load_file(path: &str, name: &str) -> String { - let dir = Path::new(&get_directory()).join(path); - let file_path = dir.join(name); - - if !dir.exists() { - if let Err(e) = fs::create_dir_all(&dir) { - log!("[IMPORTANT] Couldn't create directories: {}", e); - return String::new(); - } - return String::new(); - } - - if !file_path.exists() { - if let Err(e) = File::create(&file_path) { - log!("[IMPORTANT] Couldn't create file: {}", e); - } - return String::new(); - } - - let mut content = String::new(); - if let Ok(mut f) = File::open(&file_path) { - let _ = f.read_to_string(&mut content); - } - content -} - -pub fn load_file_vec(path: &str, name: &str) -> Vec { - let dir = Path::new(&get_directory()).join(path); - let file_path = dir.join(name); - - if !dir.exists() { - if let Err(e) = fs::create_dir_all(&dir) { - log!("[IMPORTANT] Couldn't create directories: {}", e); - return Vec::new(); - } - return Vec::new(); - } - - if !file_path.exists() { - if let Err(e) = File::create(&file_path) { - log!("[IMPORTANT] Couldn't create file: {}", e); - } - return Vec::new(); - } - - let mut content = Vec::new(); - if let Ok(mut f) = File::open(&file_path) { - let _ = f.read_to_end(&mut content); - } - content -} -pub fn save_file(path: &str, name: &str, value: &str) { - let dir = Path::new(&get_directory()).join(path); - let file_path = dir.join(name); - - if !dir.exists() { - if let Err(e) = fs::create_dir_all(&dir) { - log!("[IMPORTANT] Couldn't create directories: {}", e); - return; - } - } - - if let Err(e) = fs::write(&file_path, value) { - log!( - "[IMPORTANT] Couldn't write file {}: {}", - file_path.display(), - e - ); - } -} - -pub fn get_children(path: &str) -> Vec { - let dir = Path::new(&get_directory()).join(path); - let mut children = Vec::new(); - if let Ok(entries) = fs::read_dir(&dir) { - for entry in entries { - if let Ok(entry) = entry { - children.push(entry.file_name().to_string_lossy().to_string()); - } - } - } - children -} - -pub fn get_directory() -> String { - let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from(".")); - exe.parent() - .unwrap_or(Path::new(".")) - .to_string_lossy() - .to_string() -} - -pub fn used_space() -> u64 { - get_directory_size(&PathBuf::from(get_directory())) -} -pub fn used_dir_space(path: &str) -> u64 { - get_directory_size(&PathBuf::from(format!("{}/{}", get_directory(), path))) -} - -pub fn get_directory_size(directory: &Path) -> u64 { - let mut size = 0; - for entry in WalkDir::new(directory).into_iter().filter_map(|e| e.ok()) { - let path = entry.path(); - if path.is_file() { - if let Ok(metadata) = path.metadata() { - size += path.file_name().unwrap_or(OsStr::new("")).len() as u64; - size += metadata.len(); - } - } - } - size -} - -pub fn get_designed_storage(user_id: Uuid) -> String { - let user_dir = Path::new(&get_directory()) - .join("users") - .join(user_id.to_string()); - design_byte(get_directory_size(&user_dir)) -} - -pub fn design_byte(bytes: u64) -> String { - let mut hr_size = format!("{:.2}B", bytes as f64); - let k = bytes as f64 / 1024.0; - let m = k / 1024.0; - let g = m / 1024.0; - let t = g / 1024.0; - - if t >= 1.0 { - hr_size = format!("{:.2}TB", t); - } else if g >= 1.0 { - hr_size = format!("{:.2}GB", g); - } else if m >= 1.0 { - hr_size = format!("{:.2}MB", m); - } else if k >= 1.0 { - hr_size = format!("{:.2}KB", k); - } - hr_size -} - -pub fn get_used_ram() -> String { - let mut sys = System::new_all(); - sys.refresh_all(); - let used = sys.used_memory() * 1024; // kB to bytes - let total = sys.total_memory() * 1024; - format!("{}/{}", design_byte(used), design_byte(total)) -} - -// Helper to download the zip file content to a file on disk -async fn download_zip(url: &str, as_name: &Path) -> Result<(), Box> { - let response = reqwest::get(url).await?; - - // Check for successful response status - if !response.status().is_success() { - return Err(format!("Failed to download file: Status {}", response.status()).into()); - } - - let mut zip_file = File::create(as_name)?; - let body = response.bytes().await?; - io::copy(&mut &*body, &mut zip_file)?; - - Ok(()) -} - -fn extract_zip_contents_to_folder( - zip_path: &Path, - target_dir: &Path, -) -> Result<(), Box> { - let file = File::open(zip_path)?; - let mut archive = ZipArchive::new(file)?; - - let staging_dir = target_dir.with_extension("staging"); - - let _ = fs::remove_dir_all(&staging_dir); - fs::create_dir_all(&staging_dir)?; - - let mut first_item_name: Option = None; - - for i in 0..archive.len() { - let mut file = archive.by_index(i)?; - let entry_path = staging_dir.join(file.sanitized_name()); - - if i == 0 { - if file.name().ends_with('/') || file.sanitized_name().components().count() == 1 { - first_item_name = Some(file.sanitized_name()); - } - } - - if file.name().ends_with('/') { - fs::create_dir_all(&entry_path)?; - } else { - if let Some(parent) = entry_path.parent() { - fs::create_dir_all(parent)?; - } - let mut out_file = File::create(entry_path)?; - io::copy(&mut file, &mut out_file)?; - } - } - - if let Some(root_path) = first_item_name { - let root_dir = staging_dir.join(&root_path); - - if root_dir.is_dir() { - let root_contents_count = fs::read_dir(&staging_dir)?.count(); - - if root_contents_count == 1 - || (root_contents_count > 1 && fs::metadata(&root_dir).is_ok()) - { - let _ = fs::remove_dir_all(target_dir); - fs::create_dir_all(target_dir)?; - - for entry in fs::read_dir(root_dir)? { - let entry = entry?; - let src = entry.path(); - let dest = target_dir.join(entry.file_name()); - - if let Err(_) = fs::rename(&src, &dest) { - if src.is_file() { - fs::copy(&src, &dest)?; - } else { - if entry.path().is_dir() { - fs::rename(&src, &dest)?; - } - } - } - } - - let _ = fs::remove_dir_all(&staging_dir); - return Ok(()); - } - } - } - - log!("Extracting directly (no single root folder detected)."); - let _ = fs::remove_dir_all(target_dir); - fs::rename(&staging_dir, target_dir)?; - - Ok(()) -} - -pub async fn download_and_extract_zip(url: &str, as_name: &str) { - let base_dir = PathBuf::from(get_directory()); - let zip_filename = format!("{}.zip", Uuid::new_v4()); // Use a unique name for the downloaded ZIP file - let zip_path = base_dir.join(&zip_filename); - let target_dir = base_dir.join(as_name); - - // Step 1: Download the ZIP file - if let Err(e) = download_zip(url, &zip_path).await { - log!("Error downloading file: {}", e); - return; - } - - // Step 2: Extract and flatten the ZIP file contents into the target directory - if let Err(e) = extract_zip_contents_to_folder(&zip_path, &target_dir) { - log!("Error extracting ZIP file contents: {}", e); - } - - // Step 3: Clean up the downloaded ZIP file - if let Err(e) = fs::remove_file(&zip_path) { - log!("Error cleaning up ZIP file {}: {}", zip_path.display(), e); - } -} diff --git a/src/util/logger.rs b/src/util/logger.rs index dede826..714ee53 100644 --- a/src/util/logger.rs +++ b/src/util/logger.rs @@ -12,6 +12,7 @@ use ansi_term::Color; static LOGGER: OnceLock> = OnceLock::new(); #[derive(Clone, Copy)] +#[allow(unused)] pub enum PrintType { Call, Client, @@ -56,7 +57,7 @@ pub fn startup() { let ts = fixed_box(&msg.timestamp_ms.to_string(), 13); let sender = match msg.sender { Some(id) => fixed_box(&id.to_string(), 19), - None => fixed_box("", 19), + _ => fixed_box("", 19), }; let line = format!("{} {} {} {}", ts, sender, msg.prefix, msg.message); diff --git a/src/util/mod.rs b/src/util/mod.rs index 1897223..3472249 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,4 +1,3 @@ pub mod crypto_helper; pub mod crypto_util; -pub mod file_util; pub mod logger;