Omikron Connects Data Sends Identified Users loaded

This commit is contained in:
Alex Emmet 2025-09-07 15:56:48 +02:00
commit a1d8bcbeff
10 changed files with 228 additions and 209 deletions

View file

@ -56,7 +56,7 @@ impl AuthConnector {
if !cv.is_type(CommunicationType::Success) { if !cv.is_type(CommunicationType::Success) {
return None; return None;
} }
Uuid::parse_str(cv.get_data(DataTypes::UserId).unwrap()).ok() Uuid::parse_str(&*cv.get_data(DataTypes::UserId).unwrap().to_string()).ok()
} }
pub async fn get_user(user_id: Uuid) -> Option<AuthUser> { pub async fn get_user(user_id: Uuid) -> Option<AuthUser> {
@ -90,7 +90,7 @@ impl AuthConnector {
let json = res.text().await.ok()?; let json = res.text().await.ok()?;
let mut cv = CommunicationValue::from_json(&json); let mut cv = CommunicationValue::from_json(&json);
Uuid::parse_str(cv.get_data(DataTypes::UserId).unwrap()).ok() Uuid::parse_str(&*cv.get_data(DataTypes::UserId).unwrap().to_string()).ok()
} }
pub async fn complete_register(user_profile: &UserProfile, iota_id: &str) -> bool { pub async fn complete_register(user_profile: &UserProfile, iota_id: &str) -> bool {

View file

@ -286,7 +286,7 @@ pub struct CommunicationValue {
pub log_value: Option<LogValue>, pub log_value: Option<LogValue>,
pub sender: Option<Uuid>, pub sender: Option<Uuid>,
pub receiver: Option<Uuid>, pub receiver: Option<Uuid>,
pub data: HashMap<DataTypes, String>, pub data: HashMap<DataTypes, JsonValue>,
} }
impl CommunicationValue { impl CommunicationValue {
@ -328,11 +328,15 @@ impl CommunicationValue {
pub fn get_receiver(&self) -> Option<Uuid> { pub fn get_receiver(&self) -> Option<Uuid> {
self.receiver.clone() self.receiver.clone()
} }
pub fn add_data(mut self, key: DataTypes, value: String) -> Self { pub fn add_data_str(mut self, key: DataTypes, value: String) -> Self {
self.data.insert(key, JsonValue::String(value));
self
}
pub fn add_data(mut self, key: DataTypes, value: JsonValue) -> Self {
self.data.insert(key, value); self.data.insert(key, value);
self self
} }
pub fn get_data(&mut self, key: DataTypes) -> Option<&String> { pub fn get_data(&mut self, key: DataTypes) -> Option<&JsonValue> {
self.data.get(&key) self.data.get(&key)
} }
@ -376,7 +380,7 @@ impl CommunicationValue {
if parsed["data"].is_object() { if parsed["data"].is_object() {
for (k, v) in parsed["data"].entries() { for (k, v) in parsed["data"].entries() {
if let Some(val) = v.as_str() { if let Some(val) = v.as_str() {
data.insert(DataTypes::parse(k.to_string()), val.to_string()); data.insert(DataTypes::parse(k.to_string()), v.clone());
} }
} }
} }
@ -394,12 +398,12 @@ impl CommunicationValue {
.with_id(message_id); .with_id(message_id);
if let Some(s) = sender { if let Some(s) = sender {
cv = cv.add_data(DataTypes::SenderId, s.to_string()); cv = cv.add_data(DataTypes::SenderId, JsonValue::String(s.to_string()));
} }
cv cv
} }
pub fn forward_to_other_iota(original: &mut CommunicationValue) -> CommunicationValue { pub fn forward_to_other_iota(original: &mut CommunicationValue) -> CommunicationValue {
let receiver = Uuid::from_str(original.get_data(DataTypes::ReceiverId).unwrap()).ok() let receiver = Uuid::from_str(&*original.get_data(DataTypes::ReceiverId).unwrap().to_string()).ok()
.or(Option::from(Uuid::nil())); .or(Option::from(Uuid::nil()));
let now_ms = SystemTime::now() let now_ms = SystemTime::now()
@ -410,12 +414,12 @@ impl CommunicationValue {
let mut cv = CommunicationValue::new(CommunicationType::MessageOtherIota) let mut cv = CommunicationValue::new(CommunicationType::MessageOtherIota)
.with_id(original.get_id()) .with_id(original.get_id())
.with_receiver(receiver.unwrap()) .with_receiver(receiver.unwrap())
.add_data(DataTypes::SendTime, now_ms.to_string()) .add_data(DataTypes::SendTime, JsonValue::String(now_ms.to_string()))
.add_data(DataTypes::MessageContent, original.get_data(DataTypes::MessageContent).unwrap().to_string()); .add_data(DataTypes::MessageContent, JsonValue::String(original.get_data(DataTypes::MessageContent).unwrap().to_string()));
// include sender_id if the original had one // include sender_id if the original had one
if let Some(sender) = original.get_sender() { if let Some(sender) = original.get_sender() {
cv = cv.add_data(DataTypes::SenderId, sender.to_string()); cv = cv.add_data(DataTypes::SenderId, JsonValue::String(sender.to_string()));
} }
cv cv
} }

27
src/eula/eula_checker.rs Normal file
View file

@ -0,0 +1,27 @@
use crate::util::file_util::{load_file, save_file};
pub fn check_eula() -> bool{
let eula = "By changing the value to \"true\" you agree to our end user license agreement and our terms of service!\
\nYou can find our Terms of service on https://docs.tensamin.methanium.net/legal/terms-of-service/.\
\neula=false";
let file = load_file("", "eula.txt");
if(file.is_empty()){
save_file("", "eula.txt", eula);
return false;
}
if (file.contains("eula=false")) {
false
} else if (file.contains("eula=true")) {
true
} else {
false
}
}
pub fn accept_eula(){
let eula = "By changing the value to \"true\" you agree to some shit we say on our website IDK this shouldn't be public yet!\
\nYou also give us all rights to your soul, and we own your dog now.\
\neula=true";
save_file("", "eula.txt", eula);
}

1
src/eula/mod.rs Normal file
View file

@ -0,0 +1 @@
pub mod eula_checker;

View file

@ -1,42 +1,59 @@
use tokio::runtime::Runtime;
use std::process::{Command, ExitStatus};
use futures_util::SinkExt; use futures_util::SinkExt;
use json::{self}; use json::{self, JsonValue};
use json::JsonValue::String;
use uuid::Uuid; use uuid::Uuid;
mod data; mod data;
mod omikron; mod omikron;
mod util; mod util;
mod users; mod users;
mod eula;
mod gui { mod gui {
pub mod ratatui_interface; pub mod ratatui_interface;
} }
mod auth;
mod auth;
use crate::eula::*;
use crate::omikron::omikron_connection::{OmikronConnection}; use crate::omikron::omikron_connection::{OmikronConnection};
use crate::data::communication::{CommunicationValue, CommunicationType, DataTypes}; use crate::data::communication::{CommunicationValue, CommunicationType, DataTypes};
use gui::{ratatui_interface}; use crate::users::user_manager::UserManager;
use crate::util::config_util::ConfigUtil;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
let mut omikron: OmikronConnection = OmikronConnection::new(); if(!eula_checker::check_eula()){
println!("Please accept the end user license agreement before launching!");
return;
}
let mut c_util = ConfigUtil::new();
c_util.load();
if !c_util.config.has_key("iota_id") {
c_util.change("iota_id", Uuid::new_v4());
c_util.save();
}
UserManager::load_users().await;
let mut sb = "".to_string();
for up in UserManager::get_users() {
sb = sb + "," + &*up.user_id.to_string();
}
UserManager::save_users();
let omikron: OmikronConnection = OmikronConnection::new();
omikron.connect().await; omikron.connect().await;
omikron.send_message( omikron.send_message(
CommunicationValue::new( CommunicationValue::new(
CommunicationType::Identification CommunicationType::Identification
) )
.add_data(DataTypes::UserIds, Uuid::new_v4().to_string()) .add_data(DataTypes::UserIds, String(sb.to_string()))
.add_data(DataTypes::IotaId, Uuid::new_v4().to_string()) .add_data(DataTypes::IotaId, String(c_util.config["iota_id"].to_string()))
.to_json() .to_json()
.to_string() .to_string()
.as_mut() .as_mut()
.to_string() .to_string()
); ).await;
let mut child = Command::new("sleep").arg("5").spawn().unwrap(); loop {}
let _result = child.wait().unwrap();
omikron.close().await;
println!("reached end of main");
} }

View file

@ -1,9 +1,9 @@
use futures_util::{SinkExt, StreamExt}; use futures_util::{SinkExt, StreamExt};
use std::collections::HashMap; use std::collections::HashMap;
use std::ptr::write;
use std::str::FromStr; use std::str::FromStr;
use std::sync::Arc; use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use json::JsonValue;
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tokio::net::TcpStream; use tokio::net::TcpStream;
use tokio::time::{sleep, Duration}; use tokio::time::{sleep, Duration};
@ -37,7 +37,7 @@ impl OmikronConnection {
} }
/// Connect loop with retry /// Connect loop with retry
pub async fn connect(&self) { pub async fn connect<'a>(&'a self) {
loop { loop {
match connect_async("wss://tensamin.methanium.net/ws/iota/").await { match connect_async("wss://tensamin.methanium.net/ws/iota/").await {
Ok((ws_stream, _)) => { Ok((ws_stream, _)) => {
@ -85,14 +85,6 @@ impl OmikronConnection {
println!("[Omikron] Pong received"); println!("[Omikron] Pong received");
// handle pingpong reset here // handle pingpong reset here
} }
if waiting.lock().await.contains_key(&cv.get_id()) {
if let Some(callback) = waiting.lock().await.remove(&cv.get_id()) {
callback(cv);
}
continue;
}
// ************************************************ // // ************************************************ //
// Direct messages // // Direct messages //
// ************************************************ // // ************************************************ //
@ -100,19 +92,20 @@ impl OmikronConnection {
let sender_id = &cv.get_sender(); let sender_id = &cv.get_sender();
let receiver_id = &cv.get_receiver(); let receiver_id = &cv.get_receiver();
ChatFiles::add_message( ChatFiles::add_message(
cv.get_data(DataTypes::SendTime).unwrap().parse::<i64>().unwrap_or(-1),
cv.get_data(DataTypes::SendTime).unwrap().as_i64().unwrap_or(-1),
false, false,
receiver_id.unwrap(), receiver_id.unwrap(),
sender_id.unwrap(), sender_id.unwrap(),
cv.get_data(DataTypes::MessageContent).unwrap().as_str(), cv.get_data(DataTypes::MessageContent).unwrap().as_str().unwrap(),
); );
let response = CommunicationValue::new(CommunicationType::MessageLive) let response = CommunicationValue::new(CommunicationType::MessageLive)
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(cv.get_receiver().unwrap()) .with_receiver(cv.get_receiver().unwrap())
.add_data(DataTypes::SendTime, cv.get_data(DataTypes::SendTime).unwrap().to_string()) .add_data(DataTypes::SendTime, cv.get_data(DataTypes::SendTime).unwrap().clone())
.add_data(DataTypes::Message, cv.get_data(DataTypes::MessageContent).unwrap().to_string()) .add_data(DataTypes::Message, cv.get_data(DataTypes::MessageContent).unwrap().clone())
.add_data(DataTypes::SenderId, cv.get_sender().unwrap().to_string()); .add_data(DataTypes::SenderId, JsonValue::String(cv.get_sender().unwrap().clone().to_string()));
Self::send_message_static(&writer, response.to_json().to_string()).await; Self::send_message_static(&writer.clone(), response.to_json().to_string()).await;
continue; continue;
} }
@ -129,10 +122,10 @@ impl OmikronConnection {
); );
// ack // ack
let ack = CommunicationValue::ack_message(cv.get_id(), my_id); let ack = CommunicationValue::ack_message(cv.get_id(), my_id);
Self::send_message_static(&writer, ack.to_json().to_string()).await; Self::send_message_static(&writer.clone(), ack.to_json().to_string()).await;
// forward // forward
let forward = CommunicationValue::forward_to_other_iota(&mut cv); let forward = CommunicationValue::forward_to_other_iota(&mut cv);
Self::send_message_static(&writer, forward.to_json().to_string()).await; Self::send_message_static(&writer.clone(), forward.to_json().to_string()).await;
continue; continue;
} }
@ -147,9 +140,9 @@ impl OmikronConnection {
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(my_id); .with_receiver(my_id);
if !messages.is_empty() { if !messages.is_empty() {
resp = resp.add_data(DataTypes::MessageChunk, messages.to_string()); resp = resp.add_data(DataTypes::MessageChunk, messages);
} }
Self::send_message_static(&writer, resp.to_json().to_string()).await; Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue; continue;
} }
@ -159,14 +152,14 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::GetChats) let resp = CommunicationValue::new(CommunicationType::GetChats)
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(user_id.unwrap()) .with_receiver(user_id.unwrap())
.add_data(DataTypes::UserIds, users.to_string()); .add_data(DataTypes::UserIds, users);
Self::send_message_static(&writer, resp.to_json().to_string()).await; Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue; continue;
} }
if cv.is_type(CommunicationType::AddChat) { if cv.is_type(CommunicationType::AddChat) {
let user_id = cv.get_sender(); let user_id = cv.get_sender();
let other_id = Uuid::from_str(&*cv.get_data(DataTypes::ReceiverId).unwrap().to_string()).unwrap(); let other_id = Uuid::from_str(&*cv.get_data(DataTypes::UserId).unwrap().to_string()).unwrap();
let mut contact = ChatsUtil::get_user(user_id.unwrap(), other_id).unwrap_or(Contact::new(other_id)); // needs ChatsUtil + Contact let mut contact = ChatsUtil::get_user(user_id.unwrap(), other_id).unwrap_or(Contact::new(other_id)); // needs ChatsUtil + Contact
contact.set_last_message_at(SystemTime::now() contact.set_last_message_at(SystemTime::now()
.duration_since(UNIX_EPOCH) .duration_since(UNIX_EPOCH)
@ -176,7 +169,7 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::AddChat) let resp = CommunicationValue::new(CommunicationType::AddChat)
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(user_id.unwrap()); .with_receiver(user_id.unwrap());
Self::send_message_static(&writer, resp.to_json().to_string()).await; Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue; continue;
} }
@ -189,7 +182,7 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::AddCommunity) let resp = CommunicationValue::new(CommunicationType::AddCommunity)
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(cv.get_sender().unwrap()); .with_receiver(cv.get_sender().unwrap());
Self::send_message_static(&writer, resp.to_json().to_string()).await; Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue; continue;
} }
@ -197,8 +190,8 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::GetCommunities) let resp = CommunicationValue::new(CommunicationType::GetCommunities)
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(cv.get_sender().unwrap()) .with_receiver(cv.get_sender().unwrap())
.add_data(DataTypes::Communities, UserCommunityUtil::get_communities(cv.get_sender().unwrap()).to_string()); // needs UserCommunityUtil .add_data(DataTypes::Communities, UserCommunityUtil::get_communities(cv.get_sender().unwrap())); // needs UserCommunityUtil
Self::send_message_static(&writer, resp.to_json().to_string()).await; Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue; continue;
} }
@ -207,7 +200,7 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::RemoveCommunity) let resp = CommunicationValue::new(CommunicationType::RemoveCommunity)
.with_id(cv.get_id()) .with_id(cv.get_id())
.with_receiver(cv.get_sender().unwrap()); .with_receiver(cv.get_sender().unwrap());
Self::send_message_static(&writer, resp.to_json().to_string()).await; Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue; continue;
} }
} }
@ -220,16 +213,20 @@ impl OmikronConnection {
} }
}); });
} }
pub fn send_message(&self, msg: String){ pub async fn send_message(&self, msg: String) {
OmikronConnection::send_message_static(&self.writer, msg); Self::send_message_static(&self.writer, msg).await;
} }
pub async fn send_message_static( pub async fn send_message_static(
writer: &Arc<Mutex<Option<futures_util::stream::SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>>>>, writer: &Arc<Mutex<Option<futures_util::stream::SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>>>>,
msg: String, msg: String,
) { ) -> Result<(), tokio_tungstenite::tungstenite::Error> {
let mut guard = writer.lock().await; let mut guard = writer.lock().await;
if let Some(writer) = guard.as_mut() { if let Some(writer) = guard.as_mut() {
let _ = writer.send(Message::Text(msg)).await; writer.send(Message::Text(msg)).await?;
writer.flush().await?;
Ok(())
} else {
Err(tokio_tungstenite::tungstenite::Error::ConnectionClosed)
} }
} }

View file

@ -1,6 +1,5 @@
use json::{self, JsonValue}; use json::{self, JsonValue};
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use axum::Json;
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -10,6 +10,7 @@ use json::{JsonValue};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use crate::users::user_profile::UserProfile; use crate::users::user_profile::UserProfile;
use crate::users::user_profile_full::UserProfileFull; use crate::users::user_profile_full::UserProfileFull;
use crate::util::file_util::{load_file, save_file};
pub struct UserManager; pub struct UserManager;
@ -72,20 +73,19 @@ impl UserManager {
let users = USERS.lock().unwrap(); let users = USERS.lock().unwrap();
let arr: Vec<JsonValue> = users.iter().map(|u| u.to_json()).collect(); let arr: Vec<JsonValue> = users.iter().map(|u| u.to_json()).collect();
let json_str = JsonValue::Array(arr).dump(); let json_str = JsonValue::Array(arr).dump();
fs::write("users.json", json_str)?;
save_file("", "users.json", &json_str);
Ok(()) Ok(())
} }
pub async fn load_users() -> io::Result<()> { pub async fn load_users() -> io::Result<()> {
let path = Path::new("users.json"); let content = load_file("", "users.json");
if !path.exists() {
return Ok(());
}
let content = fs::read_to_string(path)?;
if content.trim().is_empty() { if content.trim().is_empty() {
return Ok(()); return Ok(());
} }
let parsed = json::parse(&content).map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
let parsed = json::parse(&content)
.map_err(|e| io::Error::new(io::ErrorKind::Other, e.to_string()))?;
if let JsonValue::Array(arr) = parsed { if let JsonValue::Array(arr) = parsed {
let mut users = USERS.lock().unwrap(); let mut users = USERS.lock().unwrap();
for j in arr.iter() { for j in arr.iter() {

View file

@ -2,6 +2,8 @@ use json::JsonValue;
use std::fs::{self, File}; use std::fs::{self, File};
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::path::Path; use std::path::Path;
use uuid::Uuid;
use crate::util::file_util::{load_file, save_file};
pub struct ConfigUtil { pub struct ConfigUtil {
pub config: JsonValue, pub config: JsonValue,
@ -16,37 +18,15 @@ impl ConfigUtil {
} }
} }
fn load_file(path: &str) -> String {
if let Ok(mut f) = File::open(path) {
let mut content = String::new();
let _ = f.read_to_string(&mut content);
content
} else {
String::new()
}
}
fn save_file(path: &str, content: &str) -> std::io::Result<()> {
if let Some(parent) = Path::new(path).parent() {
fs::create_dir_all(parent)?;
}
let mut file = File::create(path)?;
file.write_all(content.as_bytes())
}
pub fn load(&mut self) { pub fn load(&mut self) {
let s = Self::load_file("config.json"); let s = load_file("", "config.json");
if !s.is_empty() { if !s.is_empty() {
self.config = json::parse(&s).unwrap_or(JsonValue::new_object()); self.config = json::parse(&s).unwrap_or(JsonValue::new_object());
} }
if self.config.has_key("ssl_port") {
if let Some(port) = self.config["ssl_port"].as_i32() {
}
}
} }
pub fn change(&mut self, key: &str, value: JsonValue) { pub fn change(&mut self, key: &str, value: Uuid) {
self.config[key] = value; self.config[key] = JsonValue::String(value.to_string());
self.unique = true; self.unique = true;
} }
@ -56,7 +36,7 @@ impl ConfigUtil {
} }
} }
pub fn save(&self) -> std::io::Result<()> { pub fn save(&self) {
Self::save_file("config.json", &self.config.dump()) save_file("","config.json", &self.config.to_string());
} }
} }

View file

@ -8,25 +8,21 @@ use std::process;
use walkdir::WalkDir; use walkdir::WalkDir;
use std::fmt::Write as FmtWrite; use std::fmt::Write as FmtWrite;
use uuid::Uuid; use uuid::Uuid;
pub fn delete_file(path: &str, name: &str) -> bool {
pub struct FileUtil; let dir = Path::new(&get_directory()).join(path);
impl FileUtil {
pub fn delete_file(path: &str, name: &str) -> bool {
let dir = Path::new(&Self::get_jar_directory()).join(path);
let file = dir.join(name); let file = dir.join(name);
if !file.exists() { if !file.exists() {
return false; return false;
} }
fs::remove_file(file).is_ok() fs::remove_file(file).is_ok()
} }
pub fn delete_directory(path: &str) -> bool { pub fn delete_directory(path: &str) -> bool {
let dir = Path::new(&Self::get_jar_directory()).join(path); let dir = Path::new(&get_directory()).join(path);
Self::delete_dir_recursive(&dir) delete_dir_recursive(&dir)
} }
fn delete_dir_recursive(directory: &Path) -> bool { fn delete_dir_recursive(directory: &Path) -> bool {
if !directory.exists() { if !directory.exists() {
return false; return false;
} }
@ -35,17 +31,17 @@ impl FileUtil {
return false; return false;
} }
true true
} }
pub fn delete_user_directory(user_id: Uuid) { pub fn delete_user_directory(user_id: Uuid) {
let user_dir = Path::new(&Self::get_jar_directory()) let user_dir = Path::new(&get_directory())
.join("users") .join("users")
.join(user_id.to_string()); .join(user_id.to_string());
let _ = Self::delete_dir_recursive(&user_dir); let _ = delete_dir_recursive(&user_dir);
} }
pub fn load_file(path: &str, name: &str) -> String { pub fn load_file(path: &str, name: &str) -> String {
let dir = Path::new(&Self::get_jar_directory()).join(path); let dir = Path::new(&get_directory()).join(path);
let file_path = dir.join(name); let file_path = dir.join(name);
if !dir.exists() { if !dir.exists() {
@ -68,10 +64,10 @@ impl FileUtil {
let _ = f.read_to_string(&mut content); let _ = f.read_to_string(&mut content);
} }
content content
} }
pub fn save_file(path: &str, name: &str, value: &str) { pub fn save_file(path: &str, name: &str, value: &str) {
let dir = Path::new(&Self::get_jar_directory()).join(path); let dir = Path::new(&get_directory()).join(path);
let file_path = dir.join(name); let file_path = dir.join(name);
if !dir.exists() { if !dir.exists() {
@ -84,22 +80,21 @@ impl FileUtil {
if let Err(e) = fs::write(&file_path, value) { if let Err(e) = fs::write(&file_path, value) {
println!("[IMPORTANT] Couldn't write file {}: {}", file_path.display(), e); println!("[IMPORTANT] Couldn't write file {}: {}", file_path.display(), e);
} }
} }
pub fn get_jar_directory() -> String { pub fn get_directory() -> String {
// In Rust, use current_exe as a proxy for JAR directory
let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from(".")); let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from("."));
exe.parent() exe.parent()
.unwrap_or(Path::new(".")) .unwrap_or(Path::new("."))
.to_string_lossy() .to_string_lossy()
.to_string() .to_string()
} }
pub fn used_space() -> u64 { pub fn used_space() -> u64 {
Self::get_directory_size(&PathBuf::from(Self::get_jar_directory())) get_directory_size(&PathBuf::from(get_directory()))
} }
pub fn get_directory_size(directory: &Path) -> u64 { pub fn get_directory_size(directory: &Path) -> u64 {
let mut size = 0; let mut size = 0;
for entry in WalkDir::new(directory).into_iter().filter_map(|e| e.ok()) { for entry in WalkDir::new(directory).into_iter().filter_map(|e| e.ok()) {
let path = entry.path(); let path = entry.path();
@ -114,16 +109,16 @@ impl FileUtil {
} }
} }
size size
} }
pub fn get_designed_storage(user_id: Uuid) -> String { pub fn get_designed_storage(user_id: Uuid) -> String {
let user_dir = Path::new(&Self::get_jar_directory()) let user_dir = Path::new(&get_directory())
.join("users") .join("users")
.join(user_id.to_string()); .join(user_id.to_string());
Self::design_byte(Self::get_directory_size(&user_dir)) design_byte(get_directory_size(&user_dir))
} }
pub fn design_byte(bytes: u64) -> String { pub fn design_byte(bytes: u64) -> String {
let mut hr_size = format!("{:.2}B", bytes as f64); let mut hr_size = format!("{:.2}B", bytes as f64);
let k = bytes as f64 / 1024.0; let k = bytes as f64 / 1024.0;
let m = k / 1024.0; let m = k / 1024.0;
@ -140,17 +135,16 @@ impl FileUtil {
hr_size = format!("{:.2}KB", k); hr_size = format!("{:.2}KB", k);
} }
hr_size hr_size
} }
pub fn get_used_ram() -> String { pub fn get_used_ram() -> String {
let mut sys = System::new_all(); let mut sys = System::new_all();
sys.refresh_all(); sys.refresh_all();
let used = sys.used_memory() * 1024; // kB to bytes let used = sys.used_memory() * 1024; // kB to bytes
let total = sys.total_memory() * 1024; let total = sys.total_memory() * 1024;
format!( format!(
"{}/{}", "{}/{}",
Self::design_byte(used), design_byte(used),
Self::design_byte(total) design_byte(total)
) )
}
} }