| use serde::{Deserialize, Serialize}; |
| use tokio::sync::mpsc; |
| use zeromq::{Socket, SocketRecv, SocketSend}; |
|
|
| #[derive(Clone, Debug, Serialize)] |
| pub struct HistoryRequest { |
| #[serde(rename = "type")] |
| pub req_type: String, |
| pub symbol: String, |
| pub timeframe: String, |
| pub start: String, |
| pub end: String, |
| pub mode: String, |
| } |
|
|
| #[derive(Clone, Debug, Deserialize)] |
| pub struct HistoryResponse { |
| pub success: bool, |
| pub error: Option<String>, |
| pub message: Option<String>, |
| } |
|
|
| pub struct Mt5Client { |
| pub rep_address: String, |
| } |
|
|
| impl Mt5Client { |
| pub fn new(rep_address: &str) -> Self { |
| Self { |
| rep_address: rep_address.to_string(), |
| } |
| } |
|
|
| pub async fn download_history(&self, request: HistoryRequest) -> Result<String, String> { |
| let mut socket = zeromq::ReqSocket::new(); |
| socket.connect(&self.rep_address).await.map_err(|e| format!("Failed to connect: {}", e))?; |
|
|
| let json_request = serde_json::to_string(&request).map_err(|e| format!("Serialization error: {}", e))?; |
| |
| socket.send(json_request.into()).await.map_err(|e| format!("Send error: {}", e))?; |
|
|
| let msg = socket.recv().await.map_err(|e| format!("Receive error: {}", e))?; |
| let payload = msg.get(0).ok_or("Empty response")?; |
| let json_str = std::str::from_utf8(payload).map_err(|e| format!("UTF8 error: {}", e))?; |
| |
| let response: HistoryResponse = serde_json::from_str(json_str).map_err(|e| format!("JSON Parse error: {}", e))?; |
|
|
| if response.success { |
| if let Some(msg) = response.message { |
| if msg.contains("||CSV_DATA||") { |
| let parts: Vec<&str> = msg.splitn(2, "||CSV_DATA||").collect(); |
| if parts.len() == 2 { |
| let csv_content = parts[1].replace("|NL|", "\n"); |
| return Ok(csv_content); |
| } |
| } |
| return Ok(msg); |
| } |
| Ok("Success".to_string()) |
| } else { |
| Err(response.error.unwrap_or_else(|| "Unknown error".to_string())) |
| } |
| } |
| } |
|
|