diff --git a/src/plugins/websocket/events.rs b/src/plugins/websocket/events.rs index e00a861..19c755d 100644 --- a/src/plugins/websocket/events.rs +++ b/src/plugins/websocket/events.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use actix::prelude::*; use log::*; use serde::{Deserialize, Serialize}; +use serde_json::Value; use crate::core::{error::Error, site::models::SiteInfo}; @@ -38,6 +39,7 @@ impl Handler for WebsocketController { pub enum ServerEvent { Event { cmd: String, params: EventType }, Notification { cmd: String, params: Value }, + Confirm { cmd: String, params: Value }, } #[allow(clippy::enum_variant_names)] diff --git a/src/plugins/websocket/mod.rs b/src/plugins/websocket/mod.rs index 196bdd0..718c141 100644 --- a/src/plugins/websocket/mod.rs +++ b/src/plugins/websocket/mod.rs @@ -5,7 +5,7 @@ pub mod request; pub mod response; use futures::executor::block_on; -use serde_json::json; +use serde_json::{json, Value}; use std::collections::HashMap; @@ -100,6 +100,8 @@ pub async fn serve_websocket( site_addr: addr, address, channels: vec![], + next_message_id: 0, + waiting_callbacks: HashMap::new(), }; let (addr, res) = WsResponseBuilder::new(websocket, &req, stream) .start_with_addr() @@ -108,6 +110,8 @@ pub async fn serve_websocket( Ok(res) } +type WaitingCallback = Box ()>; + pub struct ZeruWebsocket { site_controller: Addr, user_controller: Addr, @@ -115,6 +119,8 @@ pub struct ZeruWebsocket { site_addr: actix::Addr, address: Address, channels: Vec, + next_message_id: usize, + waiting_callbacks: HashMap, } impl Actor for ZeruWebsocket { @@ -284,6 +290,33 @@ impl ZeruWebsocket { Ok(()) } + fn cmd( + &mut self, + cmd: &str, + params: Value, + callback: Option, + ) -> Result<(), Error> { + let id = self.next_message_id; + self.next_message_id += 1; + if let Some(callback) = callback { + self.waiting_callbacks.insert(id, callback); + } + match cmd { + "confirm" => { + self.confirm(params); + return Ok(()); + } + _ => unimplemented!("Command not implemented: {}", cmd), + } + } + + fn confirm(&mut self, params: Value) { + self.ws_controller.do_send(ServerEvent::Confirm { + cmd: "confirm".to_string(), + params, + }); + } + fn is_admin_site(&mut self) -> Result { let site = block_on(self.site_addr.send(SiteInfoRequest {}))??; let res = site @@ -368,6 +401,9 @@ impl ZeruWebsocket { // }); }; let mut msg = response?; + if msg.is_command() { + return Ok(()); + } self.respond(ctx, &mut msg) } diff --git a/src/plugins/websocket/request.rs b/src/plugins/websocket/request.rs index 0aef2af..919550a 100644 --- a/src/plugins/websocket/request.rs +++ b/src/plugins/websocket/request.rs @@ -137,4 +137,9 @@ impl Command { let resp = Message::inject_script(self.id, serde_json::to_value(body)?); Ok(resp) } + + pub fn command(&self) -> Result { + let resp = Message::command(); + Ok(resp) + } } diff --git a/src/plugins/websocket/response.rs b/src/plugins/websocket/response.rs index 67ef255..f92e9d9 100644 --- a/src/plugins/websocket/response.rs +++ b/src/plugins/websocket/response.rs @@ -1,4 +1,5 @@ use serde::{Deserialize, Serialize}; +use serde_json::json; use crate::utils::is_default; @@ -12,9 +13,10 @@ pub struct Message { result: serde_json::Value, } -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, PartialEq)] #[serde(rename_all = "camelCase")] pub enum MessageType { + Command, InjectScript, Response, Error, @@ -39,4 +41,17 @@ impl Message { id: 0, } } + + pub fn is_command(&self) -> bool { + self.cmd == MessageType::Command + } + + pub fn command() -> Message { + Message { + cmd: MessageType::Command, + to: 0, + result: json!(null), + id: 0, + } + } }