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) {
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> {
@ -90,7 +90,7 @@ impl AuthConnector {
let json = res.text().await.ok()?;
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 {

View file

@ -286,7 +286,7 @@ pub struct CommunicationValue {
pub log_value: Option<LogValue>,
pub sender: Option<Uuid>,
pub receiver: Option<Uuid>,
pub data: HashMap<DataTypes, String>,
pub data: HashMap<DataTypes, JsonValue>,
}
impl CommunicationValue {
@ -328,11 +328,15 @@ impl CommunicationValue {
pub fn get_receiver(&self) -> Option<Uuid> {
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
}
pub fn get_data(&mut self, key: DataTypes) -> Option<&String> {
pub fn get_data(&mut self, key: DataTypes) -> Option<&JsonValue> {
self.data.get(&key)
}
@ -376,7 +380,7 @@ impl CommunicationValue {
if parsed["data"].is_object() {
for (k, v) in parsed["data"].entries() {
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);
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
}
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()));
let now_ms = SystemTime::now()
@ -410,12 +414,12 @@ impl CommunicationValue {
let mut cv = CommunicationValue::new(CommunicationType::MessageOtherIota)
.with_id(original.get_id())
.with_receiver(receiver.unwrap())
.add_data(DataTypes::SendTime, now_ms.to_string())
.add_data(DataTypes::MessageContent, original.get_data(DataTypes::MessageContent).unwrap().to_string());
.add_data(DataTypes::SendTime, JsonValue::String(now_ms.to_string()))
.add_data(DataTypes::MessageContent, JsonValue::String(original.get_data(DataTypes::MessageContent).unwrap().to_string()));
// include sender_id if the original had one
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
}

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 json::{self};
use json::{self, JsonValue};
use json::JsonValue::String;
use uuid::Uuid;
mod data;
mod omikron;
mod util;
mod users;
mod eula;
mod gui {
pub mod ratatui_interface;
}
mod auth;
mod auth;
use crate::eula::*;
use crate::omikron::omikron_connection::{OmikronConnection};
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]
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.send_message(
CommunicationValue::new(
CommunicationType::Identification
)
.add_data(DataTypes::UserIds, Uuid::new_v4().to_string())
.add_data(DataTypes::IotaId, Uuid::new_v4().to_string())
.add_data(DataTypes::UserIds, String(sb.to_string()))
.add_data(DataTypes::IotaId, String(c_util.config["iota_id"].to_string()))
.to_json()
.to_string()
.as_mut()
.to_string()
);
).await;
let mut child = Command::new("sleep").arg("5").spawn().unwrap();
let _result = child.wait().unwrap();
omikron.close().await;
println!("reached end of main");
loop {}
}

View file

@ -1,9 +1,9 @@
use futures_util::{SinkExt, StreamExt};
use std::collections::HashMap;
use std::ptr::write;
use std::str::FromStr;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use json::JsonValue;
use tokio::sync::Mutex;
use tokio::net::TcpStream;
use tokio::time::{sleep, Duration};
@ -37,7 +37,7 @@ impl OmikronConnection {
}
/// Connect loop with retry
pub async fn connect(&self) {
pub async fn connect<'a>(&'a self) {
loop {
match connect_async("wss://tensamin.methanium.net/ws/iota/").await {
Ok((ws_stream, _)) => {
@ -85,14 +85,6 @@ impl OmikronConnection {
println!("[Omikron] Pong received");
// 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 //
// ************************************************ //
@ -100,19 +92,20 @@ impl OmikronConnection {
let sender_id = &cv.get_sender();
let receiver_id = &cv.get_receiver();
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,
receiver_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)
.with_id(cv.get_id())
.with_receiver(cv.get_receiver().unwrap())
.add_data(DataTypes::SendTime, cv.get_data(DataTypes::SendTime).unwrap().to_string())
.add_data(DataTypes::Message, cv.get_data(DataTypes::MessageContent).unwrap().to_string())
.add_data(DataTypes::SenderId, cv.get_sender().unwrap().to_string());
Self::send_message_static(&writer, response.to_json().to_string()).await;
.add_data(DataTypes::SendTime, cv.get_data(DataTypes::SendTime).unwrap().clone())
.add_data(DataTypes::Message, cv.get_data(DataTypes::MessageContent).unwrap().clone())
.add_data(DataTypes::SenderId, JsonValue::String(cv.get_sender().unwrap().clone().to_string()));
Self::send_message_static(&writer.clone(), response.to_json().to_string()).await;
continue;
}
@ -129,10 +122,10 @@ impl OmikronConnection {
);
// ack
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
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;
}
@ -147,9 +140,9 @@ impl OmikronConnection {
.with_id(cv.get_id())
.with_receiver(my_id);
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;
}
@ -159,14 +152,14 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::GetChats)
.with_id(cv.get_id())
.with_receiver(user_id.unwrap())
.add_data(DataTypes::UserIds, users.to_string());
Self::send_message_static(&writer, resp.to_json().to_string()).await;
.add_data(DataTypes::UserIds, users);
Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue;
}
if cv.is_type(CommunicationType::AddChat) {
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
contact.set_last_message_at(SystemTime::now()
.duration_since(UNIX_EPOCH)
@ -176,7 +169,7 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::AddChat)
.with_id(cv.get_id())
.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;
}
@ -189,7 +182,7 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::AddCommunity)
.with_id(cv.get_id())
.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;
}
@ -197,8 +190,8 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::GetCommunities)
.with_id(cv.get_id())
.with_receiver(cv.get_sender().unwrap())
.add_data(DataTypes::Communities, UserCommunityUtil::get_communities(cv.get_sender().unwrap()).to_string()); // needs UserCommunityUtil
Self::send_message_static(&writer, resp.to_json().to_string()).await;
.add_data(DataTypes::Communities, UserCommunityUtil::get_communities(cv.get_sender().unwrap())); // needs UserCommunityUtil
Self::send_message_static(&writer.clone(), resp.to_json().to_string()).await;
continue;
}
@ -207,7 +200,7 @@ impl OmikronConnection {
let resp = CommunicationValue::new(CommunicationType::RemoveCommunity)
.with_id(cv.get_id())
.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;
}
}
@ -220,16 +213,20 @@ impl OmikronConnection {
}
});
}
pub fn send_message(&self, msg: String){
OmikronConnection::send_message_static(&self.writer, msg);
pub async fn send_message(&self, msg: String) {
Self::send_message_static(&self.writer, msg).await;
}
pub async fn send_message_static(
writer: &Arc<Mutex<Option<futures_util::stream::SplitSink<WebSocketStream<MaybeTlsStream<TcpStream>>, Message>>>>,
msg: String,
) {
) -> Result<(), tokio_tungstenite::tungstenite::Error> {
let mut guard = writer.lock().await;
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 std::time::{SystemTime, UNIX_EPOCH};
use axum::Json;
use uuid::Uuid;
#[derive(Debug, Clone)]

View file

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

View file

@ -2,6 +2,8 @@ use json::JsonValue;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::path::Path;
use uuid::Uuid;
use crate::util::file_util::{load_file, save_file};
pub struct ConfigUtil {
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) {
let s = Self::load_file("config.json");
let s = load_file("", "config.json");
if !s.is_empty() {
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) {
self.config[key] = value;
pub fn change(&mut self, key: &str, value: Uuid) {
self.config[key] = JsonValue::String(value.to_string());
self.unique = true;
}
@ -56,7 +36,7 @@ impl ConfigUtil {
}
}
pub fn save(&self) -> std::io::Result<()> {
Self::save_file("config.json", &self.config.dump())
pub fn save(&self) {
save_file("","config.json", &self.config.to_string());
}
}

View file

@ -8,12 +8,8 @@ use std::process;
use walkdir::WalkDir;
use std::fmt::Write as FmtWrite;
use uuid::Uuid;
pub struct FileUtil;
impl FileUtil {
pub fn delete_file(path: &str, name: &str) -> bool {
let dir = Path::new(&Self::get_jar_directory()).join(path);
let dir = Path::new(&get_directory()).join(path);
let file = dir.join(name);
if !file.exists() {
return false;
@ -22,8 +18,8 @@ impl FileUtil {
}
pub fn delete_directory(path: &str) -> bool {
let dir = Path::new(&Self::get_jar_directory()).join(path);
Self::delete_dir_recursive(&dir)
let dir = Path::new(&get_directory()).join(path);
delete_dir_recursive(&dir)
}
fn delete_dir_recursive(directory: &Path) -> bool {
@ -38,14 +34,14 @@ impl FileUtil {
}
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(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 {
let dir = Path::new(&Self::get_jar_directory()).join(path);
let dir = Path::new(&get_directory()).join(path);
let file_path = dir.join(name);
if !dir.exists() {
@ -71,7 +67,7 @@ impl FileUtil {
}
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);
if !dir.exists() {
@ -86,8 +82,7 @@ impl FileUtil {
}
}
pub fn get_jar_directory() -> String {
// In Rust, use current_exe as a proxy for JAR directory
pub fn get_directory() -> String {
let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from("."));
exe.parent()
.unwrap_or(Path::new("."))
@ -96,7 +91,7 @@ impl FileUtil {
}
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 {
@ -117,10 +112,10 @@ impl FileUtil {
}
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(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 {
@ -149,8 +144,7 @@ impl FileUtil {
let total = sys.total_memory() * 1024;
format!(
"{}/{}",
Self::design_byte(used),
Self::design_byte(total)
design_byte(used),
design_byte(total)
)
}
}