mirror of
https://github.com/neosubhamoy/neodlp.git
synced 2025-12-20 04:19:34 +05:30
(chore): initial MVP release v0.1.0
This commit is contained in:
35
src-tauri/msghost/src/config.rs
Normal file
35
src-tauri/msghost/src/config.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
use directories::ProjectDirs;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Config {
|
||||
pub port: u16,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self { port: 53511 }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_config_dir() -> Option<PathBuf> {
|
||||
ProjectDirs::from("com", "neosubhamoy", "neodlp")
|
||||
.map(|proj_dirs| proj_dirs.config_dir().to_path_buf())
|
||||
}
|
||||
|
||||
pub fn get_config_path() -> Option<PathBuf> {
|
||||
get_config_dir().map(|dir| dir.join("msghost-config.json"))
|
||||
}
|
||||
|
||||
pub fn load_config() -> Config {
|
||||
if let Some(config_path) = get_config_path() {
|
||||
if let Ok(content) = fs::read_to_string(config_path) {
|
||||
if let Ok(config) = serde_json::from_str(&content) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
}
|
||||
Config::default()
|
||||
}
|
||||
134
src-tauri/msghost/src/main.rs
Normal file
134
src-tauri/msghost/src/main.rs
Normal file
@@ -0,0 +1,134 @@
|
||||
mod config;
|
||||
use config::load_config;
|
||||
use futures_util::{SinkExt, StreamExt};
|
||||
use serde_json::Value;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::time::Duration;
|
||||
use tokio::net::TcpStream;
|
||||
use tokio::time::sleep;
|
||||
use tokio_tungstenite::{
|
||||
connect_async, tungstenite::protocol::Message, MaybeTlsStream, WebSocketStream,
|
||||
};
|
||||
|
||||
fn get_websocket_url() -> String {
|
||||
let config = load_config();
|
||||
format!("ws://localhost:{}", config.port)
|
||||
}
|
||||
|
||||
async fn connect_with_retry(
|
||||
url: &str,
|
||||
max_attempts: u32,
|
||||
) -> Result<WebSocketStream<MaybeTlsStream<TcpStream>>, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let mut attempts = 0;
|
||||
loop {
|
||||
match connect_async(url).await {
|
||||
Ok((ws_stream, _)) => {
|
||||
eprintln!("Successfully connected to Tauri app :)");
|
||||
return Ok(ws_stream);
|
||||
}
|
||||
Err(e) => {
|
||||
attempts += 1;
|
||||
if attempts >= max_attempts {
|
||||
return Err(Box::new(e));
|
||||
}
|
||||
let wait_time = Duration::from_secs(2u64.pow(attempts));
|
||||
eprintln!(
|
||||
"Connection attempt {} failed. Retrying in {:?}...",
|
||||
attempts, wait_time
|
||||
);
|
||||
sleep(wait_time).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_stdin_message() -> Result<String, Box<dyn std::error::Error>> {
|
||||
let mut stdin = io::stdin();
|
||||
let mut length_bytes = [0u8; 4];
|
||||
stdin.read_exact(&mut length_bytes)?;
|
||||
let length = u32::from_ne_bytes(length_bytes) as usize;
|
||||
|
||||
let mut buffer = vec![0u8; length];
|
||||
stdin.read_exact(&mut buffer)?;
|
||||
|
||||
let message = String::from_utf8(buffer)?;
|
||||
Ok(message)
|
||||
}
|
||||
|
||||
fn write_stdout_message(message: &str) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let message_bytes = message.as_bytes();
|
||||
let message_size = message_bytes.len();
|
||||
io::stdout().write_all(&(message_size as u32).to_ne_bytes())?;
|
||||
io::stdout().write_all(message_bytes)?;
|
||||
io::stdout().flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
eprintln!("Waiting for message from extension...");
|
||||
|
||||
let input = match read_stdin_message() {
|
||||
Ok(msg) => {
|
||||
eprintln!("Received message: {}", msg);
|
||||
msg
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading message: {:?}", e);
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Send immediate response to the extension
|
||||
write_stdout_message(
|
||||
&serde_json::json!({
|
||||
"status": "received",
|
||||
"message": "Message received by native host"
|
||||
})
|
||||
.to_string(),
|
||||
)?;
|
||||
|
||||
let parsed: Value = serde_json::from_str(&input)?;
|
||||
|
||||
let websocket_url = get_websocket_url();
|
||||
eprintln!("Attempting to connect to {}", websocket_url);
|
||||
|
||||
let mut ws_stream = match connect_with_retry(&websocket_url, 2).await {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to connect after multiple attempts: {:?}", e);
|
||||
write_stdout_message(
|
||||
&serde_json::json!({
|
||||
"status": "error",
|
||||
"message": "Failed to connect to Tauri app"
|
||||
})
|
||||
.to_string(),
|
||||
)?;
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
|
||||
// Send message to Tauri app
|
||||
ws_stream
|
||||
.send(Message::Text(parsed.to_string().into()))
|
||||
.await?;
|
||||
|
||||
// Receive response from Tauri app
|
||||
if let Some(Ok(msg)) = ws_stream.next().await {
|
||||
// Send Tauri app's response back to browser extension
|
||||
if let Message::Text(text) = msg {
|
||||
write_stdout_message(
|
||||
&serde_json::json!({
|
||||
"status": "success",
|
||||
"response": text.to_string()
|
||||
})
|
||||
.to_string(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
// Close the connection
|
||||
ws_stream.close(None).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user