2022-06-04 11:58:21 +00:00
|
|
|
use std::{any::Any, fs, sync::Arc};
|
|
|
|
|
2022-06-04 18:10:21 +00:00
|
|
|
use async_trait::async_trait;
|
2022-06-04 11:58:21 +00:00
|
|
|
use libloading::{Library, Symbol};
|
|
|
|
use log::{debug, trace};
|
|
|
|
|
2022-06-05 14:08:13 +00:00
|
|
|
use crate::{commands, tcp::Client};
|
2022-06-04 11:58:21 +00:00
|
|
|
|
|
|
|
/// A plugin which allows you to add extra functionality.
|
2022-06-04 18:10:21 +00:00
|
|
|
#[async_trait]
|
2022-06-04 11:58:21 +00:00
|
|
|
pub trait Plugin: Any + Send + Sync {
|
|
|
|
/// Get a name describing the `Plugin`.
|
|
|
|
fn name(&self) -> &'static str;
|
|
|
|
/// A function that runs immediately after plugin loading.
|
|
|
|
/// Usually used for initialization.
|
2022-06-04 18:10:21 +00:00
|
|
|
async fn on_plugin_load(&self);
|
2022-06-04 11:58:21 +00:00
|
|
|
/// A function that runs immediately before the plugin is unloaded.
|
|
|
|
/// Use this if you want to do any cleanup.
|
2022-06-04 18:10:21 +00:00
|
|
|
async fn on_plugin_unload(&self);
|
2022-06-04 11:58:21 +00:00
|
|
|
}
|
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Trait with function to register plugin.
|
2022-06-05 20:10:23 +00:00
|
|
|
pub trait PluginRegistrar {
|
|
|
|
/// Function to register the plugin
|
2022-06-16 17:31:09 +00:00
|
|
|
fn register(&mut self, plugin: Box<dyn Plugin>);
|
2022-06-05 20:10:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl PluginRegistrar for PluginManager {
|
2022-06-16 17:31:09 +00:00
|
|
|
fn register(&mut self, plugin: Box<dyn Plugin>) {
|
2022-06-05 20:10:23 +00:00
|
|
|
self.plugins.push(plugin)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Plugin Manager
|
2022-06-04 11:58:21 +00:00
|
|
|
pub struct PluginManager {
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Vector with all loaded plugins.
|
2022-06-04 11:58:21 +00:00
|
|
|
pub plugins: Vec<Box<dyn Plugin>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PluginManager {
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Create empty `PluginManager`.
|
2022-06-04 11:58:21 +00:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
plugins: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for PluginManager {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Plugin Manager Type
|
2022-06-05 20:10:23 +00:00
|
|
|
pub type PluginManagerType = Arc<PluginManager>;
|
2022-06-04 11:58:21 +00:00
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Trait with command functions to implement on struct.
|
2022-06-05 14:08:13 +00:00
|
|
|
#[async_trait]
|
|
|
|
pub trait Command: Any + Send + Sync {
|
|
|
|
/// Command name
|
|
|
|
fn name(&self) -> &'static str;
|
|
|
|
/// Help message of this command
|
|
|
|
fn help(&self) -> &'static str;
|
|
|
|
/// Command function
|
|
|
|
async fn execute(
|
|
|
|
&self,
|
|
|
|
client: &mut Client,
|
|
|
|
args: Vec<&str>,
|
|
|
|
command_manager: &CommandManagerType,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-06-05 20:10:23 +00:00
|
|
|
/// Command Manager
|
2022-06-05 14:08:13 +00:00
|
|
|
pub struct CommandManager {
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Vector with all commands.
|
2022-06-05 14:08:13 +00:00
|
|
|
pub commands: Vec<Box<dyn Command>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl CommandManager {
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Create empty `CommandManager`.
|
2022-06-05 14:08:13 +00:00
|
|
|
pub fn new() -> Self {
|
|
|
|
Self {
|
|
|
|
commands: Vec::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for CommandManager {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Command Manager Type
|
2022-06-05 20:10:23 +00:00
|
|
|
pub type CommandManagerType = Arc<CommandManager>;
|
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Trait with function to register command.
|
2022-06-04 18:10:21 +00:00
|
|
|
pub trait CommandRegistrar {
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Function to register the plugin and the commands in the plugin.
|
2022-06-16 17:31:09 +00:00
|
|
|
fn register(&mut self, command: Box<dyn Command>);
|
2022-06-04 18:10:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl CommandRegistrar for CommandManager {
|
2022-06-16 17:31:09 +00:00
|
|
|
fn register(&mut self, command: Box<dyn Command>) {
|
2022-06-04 18:10:21 +00:00
|
|
|
self.commands.push(command)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Trait with event functions to implement on struct.
|
2022-06-16 17:31:09 +00:00
|
|
|
#[async_trait]
|
|
|
|
pub trait Event: Any + Send + Sync {
|
|
|
|
/// Event name (onConnect, onSend)
|
|
|
|
fn name(&self) -> &'static str;
|
|
|
|
/// Event function
|
|
|
|
async fn execute(&self, client: &mut Client);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Event Manager
|
|
|
|
pub struct EventManager {
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Vector with all events loaded from plugins.
|
2022-06-16 17:31:09 +00:00
|
|
|
pub events: Vec<Box<dyn Event>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventManager {
|
|
|
|
/// Create empty `EventManager`
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self { events: Vec::new() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for EventManager {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::new()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
|
|
|
|
/// Event Manager Type
|
2022-06-16 17:31:09 +00:00
|
|
|
pub type EventManagerType = Arc<EventManager>;
|
|
|
|
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Trait with function to register event.
|
2022-06-16 17:31:09 +00:00
|
|
|
pub trait EventRegistrar {
|
2022-06-17 20:32:07 +00:00
|
|
|
/// Function to register the plugin and the commands in the plugin.
|
2022-06-16 17:31:09 +00:00
|
|
|
fn register(&mut self, command: Box<dyn Event>);
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventRegistrar for EventManager {
|
|
|
|
fn register(&mut self, command: Box<dyn Event>) {
|
|
|
|
self.events.push(command)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-05 20:10:23 +00:00
|
|
|
/// Plugins and Commands loader
|
2022-06-16 17:31:09 +00:00
|
|
|
pub fn loader() -> anyhow::Result<(CommandManagerType, PluginManagerType, EventManagerType)> {
|
2022-06-04 11:58:21 +00:00
|
|
|
// get path to .so lib from command argument
|
|
|
|
let config_dir = "./plugins";
|
|
|
|
let paths = fs::read_dir(config_dir)?;
|
|
|
|
|
|
|
|
// create a plugin manager where all loaded plugins will be located
|
|
|
|
let mut plugin_manager = PluginManager::new();
|
|
|
|
|
2022-06-04 18:10:21 +00:00
|
|
|
// create a command manager where located all commands
|
|
|
|
let mut command_manager = CommandManager::new();
|
|
|
|
|
2022-06-16 17:31:09 +00:00
|
|
|
// create a command manager where located all events from plugins
|
|
|
|
let mut event_manager = EventManager::new();
|
|
|
|
|
2022-06-04 18:10:21 +00:00
|
|
|
// register default commands
|
|
|
|
for command in commands::register_commands() {
|
|
|
|
command_manager.commands.push(command)
|
|
|
|
}
|
|
|
|
|
2022-06-04 11:58:21 +00:00
|
|
|
// for all plugin in directory
|
|
|
|
for path in paths {
|
|
|
|
// get library file path
|
|
|
|
let path = path?.path();
|
|
|
|
|
2022-06-05 14:08:13 +00:00
|
|
|
let plugin_path = path.to_str().unwrap_or("unknown");
|
|
|
|
|
|
|
|
// log debug info
|
|
|
|
debug!("Loading plugin `{}`", plugin_path);
|
|
|
|
|
2022-06-04 11:58:21 +00:00
|
|
|
// loading library with .so is unsafe
|
|
|
|
unsafe {
|
|
|
|
// load library
|
|
|
|
// Box::new and Box::leak must be there because if it isn't there it throws a segmentation fault
|
2022-06-05 14:08:13 +00:00
|
|
|
let lib = Box::leak(Box::new(Library::new(&path)?));
|
2022-06-04 11:58:21 +00:00
|
|
|
|
|
|
|
// get `plugin_entry` from library
|
2022-06-05 14:08:13 +00:00
|
|
|
trace!("Finding symbol `plugin_entry` in `{}`", plugin_path);
|
2022-06-04 18:10:21 +00:00
|
|
|
let func: Symbol<
|
2022-06-16 17:31:09 +00:00
|
|
|
unsafe extern "C" fn(
|
|
|
|
&mut dyn PluginRegistrar,
|
|
|
|
&mut dyn CommandRegistrar,
|
|
|
|
&mut dyn EventRegistrar,
|
|
|
|
) -> (),
|
2022-06-04 18:10:21 +00:00
|
|
|
> = lib.get(b"plugin_entry")?;
|
2022-06-04 11:58:21 +00:00
|
|
|
|
2022-06-05 14:08:13 +00:00
|
|
|
// execute initial plugin function
|
|
|
|
trace!("Running `plugin_entry(...)` in plugin `{}`", plugin_path);
|
2022-06-16 17:31:09 +00:00
|
|
|
func(
|
|
|
|
&mut plugin_manager,
|
|
|
|
&mut command_manager,
|
|
|
|
&mut event_manager,
|
|
|
|
);
|
2022-06-04 11:58:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-16 17:31:09 +00:00
|
|
|
// return CommandManager, PluginManager and EventManager
|
|
|
|
Ok((
|
|
|
|
Arc::new(command_manager),
|
|
|
|
Arc::new(plugin_manager),
|
|
|
|
Arc::new(event_manager),
|
|
|
|
))
|
2022-06-04 11:58:21 +00:00
|
|
|
}
|