mirror of https://github.com/MedzikUser/servers
feat(server): add `onCommand` event and handle errors in message processing
Added `OnCommand` event e.g. to disable command for client. (BREAKING CHANGES IN EVENT PLUGINS) Added function for error handling in message process.
This commit is contained in:
parent
56e16145f6
commit
67fb1a0a3c
|
@ -42,7 +42,7 @@ impl Event for PluginTest {
|
||||||
EventType::OnConnect
|
EventType::OnConnect
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn execute(&self, client: &Client) -> anyhow::Result<()> {
|
async fn execute(&self, client: &Client, _data: EventData) -> anyhow::Result<()> {
|
||||||
client.send("Hello!")
|
client.send("Hello!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,12 +29,23 @@ pub trait Command: Any + Send + Sync {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All possible to run events.
|
/// All possible to run events.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub enum EventType {
|
pub enum EventType {
|
||||||
/// On client connected.
|
/// On client connected.
|
||||||
OnConnect,
|
OnConnect,
|
||||||
/// On client sent message.
|
/// On client sent message.
|
||||||
OnSend,
|
OnSend,
|
||||||
|
/// Event executed before command execute (e.g. for disable command).
|
||||||
|
OnCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All possible to run events.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum EventData {
|
||||||
|
/// for `onCommand` event
|
||||||
|
Command(String),
|
||||||
|
/// No data
|
||||||
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a event to the plugin.
|
/// Add a event to the plugin.
|
||||||
|
@ -43,7 +54,7 @@ pub trait Event: Any + Send + Sync {
|
||||||
/// Type of the event.
|
/// Type of the event.
|
||||||
fn event(&self) -> EventType;
|
fn event(&self) -> EventType;
|
||||||
/// Event function.
|
/// Event function.
|
||||||
async fn execute(&self, client: &Client) -> anyhow::Result<()>;
|
async fn execute(&self, client: &Client, data: EventData) -> anyhow::Result<()>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Registrar {
|
pub trait Registrar {
|
||||||
|
|
|
@ -9,7 +9,10 @@ use std::{
|
||||||
use tungstenite::{accept, Message, WebSocket};
|
use tungstenite::{accept, Message, WebSocket};
|
||||||
|
|
||||||
use super::run::PLUGINS_MANAGER;
|
use super::run::PLUGINS_MANAGER;
|
||||||
use crate::plugins::{manager::PluginsManagerType, prelude::EventType};
|
use crate::plugins::{
|
||||||
|
manager::PluginsManagerType,
|
||||||
|
prelude::{EventData, EventType},
|
||||||
|
};
|
||||||
|
|
||||||
/// Max length of a TCP and UDP packet
|
/// Max length of a TCP and UDP packet
|
||||||
pub const MAX_PACKET_LEN: usize = 65536;
|
pub const MAX_PACKET_LEN: usize = 65536;
|
||||||
|
@ -208,10 +211,14 @@ impl Client {
|
||||||
self.map.lock().unwrap().remove(&key.to_string())
|
self.map.lock().unwrap().remove(&key.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn run_events(&self, event_type: EventType) -> anyhow::Result<()> {
|
pub async fn run_events(
|
||||||
|
&self,
|
||||||
|
event_type: EventType,
|
||||||
|
event_data: EventData,
|
||||||
|
) -> anyhow::Result<()> {
|
||||||
for event in self.plugins_manager.events.iter() {
|
for event in self.plugins_manager.events.iter() {
|
||||||
if event.event() == event_type {
|
if event.event() == event_type {
|
||||||
event.execute(self).await?;
|
event.execute(self, event_data.clone()).await?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,11 @@ use lazy_static::lazy_static;
|
||||||
use tracing::{error, info, span, Level};
|
use tracing::{error, info, span, Level};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
plugins::{self, manager::PluginsManagerType, prelude::EventType},
|
plugins::{
|
||||||
|
self,
|
||||||
|
manager::PluginsManagerType,
|
||||||
|
prelude::{EventData, EventType},
|
||||||
|
},
|
||||||
server::Client,
|
server::Client,
|
||||||
CLIENTS, CLIENT_NEXT,
|
CLIENTS, CLIENT_NEXT,
|
||||||
};
|
};
|
||||||
|
@ -47,40 +51,66 @@ async fn process(client: Client) -> anyhow::Result<()> {
|
||||||
info!("Processing client connection: {}", client_addr);
|
info!("Processing client connection: {}", client_addr);
|
||||||
|
|
||||||
// run `onConnect` events
|
// run `onConnect` events
|
||||||
client.run_events(EventType::OnConnect).await?;
|
client
|
||||||
|
.run_events(EventType::OnConnect, EventData::None)
|
||||||
|
.await?;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let buf = client.read()?;
|
let buf = client.read()?;
|
||||||
|
|
||||||
// run `onSend` events
|
// functions for error handling see `if` below function
|
||||||
client.run_events(EventType::OnSend).await?;
|
async fn handle(client: &Client, buf: String) -> anyhow::Result<()> {
|
||||||
|
// run `onSend` events
|
||||||
|
client
|
||||||
|
.run_events(EventType::OnSend, EventData::None)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut args: Vec<&str> = buf.split_ascii_whitespace().collect();
|
let mut args: Vec<&str> = buf.split_ascii_whitespace().collect();
|
||||||
|
|
||||||
// if client sent an empty buffer
|
// if client sent an empty buffer
|
||||||
if args.is_empty() {
|
if args.is_empty() {
|
||||||
client.send("empty buffer")?;
|
client.send("empty buffer")?;
|
||||||
continue;
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let cmd = args[0];
|
||||||
|
|
||||||
|
// remove command name from args
|
||||||
|
args = args[1..args.len()].to_vec();
|
||||||
|
|
||||||
|
// find command
|
||||||
|
let command = client
|
||||||
|
.plugins_manager
|
||||||
|
.commands
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|&(_i, command)| command.name() == cmd || command.aliases().contains(&cmd));
|
||||||
|
|
||||||
|
// execute command, if command isn't blocked
|
||||||
|
// to block a command return error in the `onCommand` event
|
||||||
|
if let Some((_i, cmd)) = command {
|
||||||
|
// run `onCommand` events
|
||||||
|
if let Ok(_) = client
|
||||||
|
.run_events(
|
||||||
|
EventType::OnCommand,
|
||||||
|
EventData::Command(cmd.name().to_string()),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
// execute command
|
||||||
|
cmd.execute(&client, args).await?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
client.send("unknown command")?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
let cmd = args[0];
|
// handle errors from message processing
|
||||||
|
if let Err(err) = handle(&client, buf).await {
|
||||||
// remove command name from args
|
error!("Unexpected error in message handler: {}", err);
|
||||||
args = args[1..args.len()].to_vec();
|
client.send("Unexpected error")?;
|
||||||
|
|
||||||
// find command
|
|
||||||
let command = client
|
|
||||||
.plugins_manager
|
|
||||||
.commands
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.find(|&(_i, command)| command.name() == cmd || command.aliases().contains(&cmd));
|
|
||||||
|
|
||||||
// execute command
|
|
||||||
if let Some((_i, cmd)) = command {
|
|
||||||
cmd.execute(&client, args).await?;
|
|
||||||
} else {
|
|
||||||
client.send("unknown command")?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client.flush()?;
|
client.flush()?;
|
||||||
|
|
Loading…
Reference in New Issue