Testing indicators
This commit is contained in:
@@ -0,0 +1,30 @@
|
|||||||
|
use crate::{server::Server, types::message::ServerMessage, utils::client::Client};
|
||||||
|
use anyhow::Context;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
#[serde(tag = "type", content = "params", rename_all = "snake_case")]
|
||||||
|
pub enum Indicator {
|
||||||
|
Typing { user_id: String, channel_id: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct IndicatorContext {
|
||||||
|
pub indicator: Indicator,
|
||||||
|
pub expires: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::logger!(LOGGER "Typing Indicator");
|
||||||
|
|
||||||
|
pub fn start_typing(server: &Arc<Server>, client: &Client, channel_id: &str) -> crate::Result<()> {
|
||||||
|
server.broadcast(ServerMessage::Indicator(IndicatorContext {
|
||||||
|
indicator: Indicator::Typing {
|
||||||
|
user_id: client.get_uuid().context("Failed to get uuid")?,
|
||||||
|
channel_id: channel_id.to_string(),
|
||||||
|
},
|
||||||
|
expires: 5, // 5 secs
|
||||||
|
}));
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
+5
-2
@@ -1,5 +1,6 @@
|
|||||||
pub mod chunk;
|
pub mod chunk;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
pub mod indicator;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
@@ -36,8 +37,10 @@ impl Server {
|
|||||||
ClientMessage::LoadChunk {
|
ClientMessage::LoadChunk {
|
||||||
chunk_id,
|
chunk_id,
|
||||||
channel_id,
|
channel_id,
|
||||||
} => {
|
} => chunk::load_chunk(self, client, channel_id, *chunk_id)?,
|
||||||
chunk::load_chunk(self, client, channel_id, *chunk_id)?;
|
|
||||||
|
ClientMessage::Typing { channel_id } => {
|
||||||
|
indicator::start_typing(self, client, channel_id)?
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -44,6 +44,7 @@ pub struct Server {
|
|||||||
pub plugins: Mutex<Vec<Plugin>>,
|
pub plugins: Mutex<Vec<Plugin>>,
|
||||||
pub db: utils::database::Database,
|
pub db: utils::database::Database,
|
||||||
pub shutting_down: AtomicBool,
|
pub shutting_down: AtomicBool,
|
||||||
|
pub indicators: Mutex<Vec<crate::requests::indicator::IndicatorContext>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ServerConfig {
|
impl Default for ServerConfig {
|
||||||
@@ -79,6 +80,7 @@ impl Server {
|
|||||||
clients: Mutex::new(HashSet::new()),
|
clients: Mutex::new(HashSet::new()),
|
||||||
plugins: Mutex::new(Vec::new()),
|
plugins: Mutex::new(Vec::new()),
|
||||||
shutting_down: AtomicBool::new(false),
|
shutting_down: AtomicBool::new(false),
|
||||||
|
indicators: Mutex::new(Vec::new()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +166,10 @@ impl Server {
|
|||||||
let uuid = self.wrap_err(&client, auth_res)?;
|
let uuid = self.wrap_err(&client, auth_res)?;
|
||||||
self.wrap_err(
|
self.wrap_err(
|
||||||
&client,
|
&client,
|
||||||
client.send(types::message::ServerMessage::Authenticated { uuid }),
|
client.send(types::message::ServerMessage::Authenticated {
|
||||||
|
uuid,
|
||||||
|
indicators: self.indicators.lock().unwrap().clone(),
|
||||||
|
}),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
|
|||||||
+13
-8
@@ -55,9 +55,12 @@ pub mod handshake {
|
|||||||
pub mod message {
|
pub mod message {
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::types::{
|
use crate::{
|
||||||
Author,
|
requests::indicator::IndicatorContext,
|
||||||
data::{self, Message},
|
types::{
|
||||||
|
Author,
|
||||||
|
data::{self, Message},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Messages sent *from the client* (user’s app) to the server
|
/// Messages sent *from the client* (user’s app) to the server
|
||||||
@@ -85,6 +88,10 @@ pub mod message {
|
|||||||
channel_id: String,
|
channel_id: String,
|
||||||
chunk_id: usize,
|
chunk_id: usize,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
Typing {
|
||||||
|
channel_id: String,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Messages sent *from the server* to the client
|
/// Messages sent *from the server* to the client
|
||||||
@@ -94,6 +101,7 @@ pub mod message {
|
|||||||
/// Successful authentication
|
/// Successful authentication
|
||||||
Authenticated {
|
Authenticated {
|
||||||
uuid: Author,
|
uuid: Author,
|
||||||
|
indicators: Vec<IndicatorContext>,
|
||||||
},
|
},
|
||||||
|
|
||||||
TempMessage {
|
TempMessage {
|
||||||
@@ -120,11 +128,8 @@ pub mod message {
|
|||||||
status: String,
|
status: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Typing indicator
|
/// Indicator
|
||||||
Typing {
|
Indicator(IndicatorContext),
|
||||||
user_id: Author,
|
|
||||||
channel_id: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
Shutdown {
|
Shutdown {
|
||||||
message: String,
|
message: String,
|
||||||
|
|||||||
+9
-9
@@ -33,13 +33,13 @@ impl Logger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract_panic<T, E: Display, D: Display>(&self, v: Result<T, E>, m: D) -> T {
|
// pub fn extract_panic<T, E: Display, D: Display>(&self, v: Result<T, E>, m: D) -> T {
|
||||||
match v {
|
// match v {
|
||||||
Ok(a) => a,
|
// Ok(a) => a,
|
||||||
Err(e) => {
|
// Err(e) => {
|
||||||
self.error(format!("{m}: {e}"));
|
// self.error(format!("{m}: {e}"));
|
||||||
panic!()
|
// panic!()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
+36
-36
@@ -16,29 +16,29 @@ pub fn dir(path: &Path) -> crate::Result<()> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(path: &Path, default_content: &str) -> crate::Result<String> {
|
// pub fn read(path: &Path, default_content: &str) -> crate::Result<String> {
|
||||||
if !path.exists() {
|
// if !path.exists() {
|
||||||
LOGGER.info(format!(
|
// LOGGER.info(format!(
|
||||||
"File {path:?} does not exist, creating it with default contents"
|
// "File {path:?} does not exist, creating it with default contents"
|
||||||
));
|
// ));
|
||||||
write(path, default_content)?;
|
// write(path, default_content)?;
|
||||||
return Ok(default_content.to_string());
|
// return Ok(default_content.to_string());
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(fs::read_to_string(path)?)
|
// Ok(fs::read_to_string(path)?)
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn read_bytes<'a>(path: &Path, default_content: Vec<u8>) -> crate::Result<Vec<u8>> {
|
// pub fn read_bytes<'a>(path: &Path, default_content: Vec<u8>) -> crate::Result<Vec<u8>> {
|
||||||
if !path.exists() {
|
// if !path.exists() {
|
||||||
LOGGER.info(format!(
|
// LOGGER.info(format!(
|
||||||
"File {path:?} does not exist, creating it with default contents"
|
// "File {path:?} does not exist, creating it with default contents"
|
||||||
));
|
// ));
|
||||||
write_bytes(path, &default_content)?;
|
// write_bytes(path, &default_content)?;
|
||||||
return Ok(default_content);
|
// return Ok(default_content);
|
||||||
}
|
// }
|
||||||
|
|
||||||
Ok(fs::read(path)?)
|
// Ok(fs::read(path)?)
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn read_config<T: Default + Serialize + for<'de> Deserialize<'de>>(
|
pub fn read_config<T: Default + Serialize + for<'de> Deserialize<'de>>(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
@@ -56,23 +56,23 @@ pub fn read_config<T: Default + Serialize + for<'de> Deserialize<'de>>(
|
|||||||
Ok(serde_json::from_str::<T>(&read)?)
|
Ok(serde_json::from_str::<T>(&read)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(path: &Path, content: &str) -> crate::Result<()> {
|
// pub fn write(path: &Path, content: &str) -> crate::Result<()> {
|
||||||
dir(path.parent().ok_or(std::io::Error::new(
|
// dir(path.parent().ok_or(std::io::Error::new(
|
||||||
std::io::ErrorKind::InvalidFilename,
|
// std::io::ErrorKind::InvalidFilename,
|
||||||
"File doesn't have a parent assigned, example: `config/config.json`",
|
// "File doesn't have a parent assigned, example: `config/config.json`",
|
||||||
))?)?;
|
// ))?)?;
|
||||||
fs::write(path, content)?;
|
// fs::write(path, content)?;
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn write_bytes(path: &Path, content: &[u8]) -> crate::Result<()> {
|
// pub fn write_bytes(path: &Path, content: &[u8]) -> crate::Result<()> {
|
||||||
dir(path.parent().ok_or(std::io::Error::new(
|
// dir(path.parent().ok_or(std::io::Error::new(
|
||||||
std::io::ErrorKind::InvalidFilename,
|
// std::io::ErrorKind::InvalidFilename,
|
||||||
"File doesn't have a parent assigned, example: `config/config.json`",
|
// "File doesn't have a parent assigned, example: `config/config.json`",
|
||||||
))?)?;
|
// ))?)?;
|
||||||
fs::write(path, content)?;
|
// fs::write(path, content)?;
|
||||||
Ok(())
|
// Ok(())
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub fn write_config<T: Serialize>(path: &Path, content: &T) -> crate::Result<()> {
|
pub fn write_config<T: Serialize>(path: &Path, content: &T) -> crate::Result<()> {
|
||||||
dir(path.parent().ok_or(std::io::Error::new(
|
dir(path.parent().ok_or(std::io::Error::new(
|
||||||
|
|||||||
Reference in New Issue
Block a user