rename plugin -> module

This commit is contained in:
Adrian Malacoda
2017-02-16 01:05:33 -06:00
parent bdee07143b
commit 0a51c7294f
10 changed files with 135 additions and 135 deletions

80
src/modules/discord.rs Normal file
View File

@@ -0,0 +1,80 @@
use discord;
use discord::Discord;
use discord::model::Event;
use modules::Module;
use toml::Table;
use event;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use MessageSender;
use User;
use Channel;
pub struct DiscordModule {
token: String
}
impl DiscordModule {
pub fn new (configuration: &Table) -> Box<Module> {
let token = configuration.get("token")
.and_then(|value| value.as_str())
.unwrap_or("");
Box::new(DiscordModule {
token: String::from(token)
})
}
}
pub struct DiscordMessageSender {
discord: Arc<Discord>,
channel_id: discord::model::ChannelId
}
impl MessageSender for DiscordMessageSender {
fn send_message (&self, message: &str) {
self.discord.send_message(&self.channel_id, message, "", false);
}
}
impl Module for DiscordModule {
fn produce_events<'a>(&'a self, sender: Sender<event::Event>) {
let discord = Arc::new(Discord::from_bot_token(&self.token[..]).expect("Login failed"));
let (mut connection, _) = discord.connect().expect("Connection failed");
loop {
match connection.recv_event() {
Ok(Event::MessageCreate(message)) => {
let author = User {
name: message.author.name.clone(),
sender: Arc::new(DiscordMessageSender {
discord: discord.clone(),
channel_id: message.channel_id
})
};
let channel = Channel {
name: String::from("channel"),
description: String::from(""),
topic: String::from(""),
sender: Arc::new(DiscordMessageSender {
discord: discord.clone(),
channel_id: message.channel_id
})
};
sender.send(event::Event::Message { sender: author, content: message.content, channel: Option::Some(channel) });
}
Ok(_) => {}
Err(discord::Error::Closed(code, body)) => {
println!("Gateway closed on us with code {:?}: {}", code, body);
break
}
Err(err) => println!("Receive error: {:?}", err)
}
}
}
}

45
src/modules/echo.rs Normal file
View File

@@ -0,0 +1,45 @@
use modules::Module;
use toml::Table;
use std::sync::mpsc::Receiver;
use event::Event;
pub struct EchoModule {
prefix: String
}
impl EchoModule {
pub fn new (configuration: &Table) -> Box<Module> {
let prefix = configuration.get("prefix")
.and_then(|value| value.as_str())
.unwrap_or("!echo ");
Box::new(EchoModule {
prefix: String::from(prefix)
})
}
}
impl Module for EchoModule {
fn consume_events (&self, receiver: Receiver<Event>) {
loop {
match receiver.recv() {
Ok(event) => {
match event {
Event::Message { content: message, channel, sender } => {
if message.starts_with(self.prefix.as_str()) {
let substring = &message[self.prefix.chars().count()..];
match channel {
Some(channel) => channel.send(substring),
None => sender.send(substring)
}
}
}
_ => ()
}
}
Err(error) => { }
}
}
}
}

26
src/modules/hello.rs Normal file
View File

@@ -0,0 +1,26 @@
use modules::Module;
use toml::Table;
use Tenquestionmarks;
pub struct Hello {
name: String
}
impl Hello {
pub fn new (configuration: &Table) -> Box<Module> {
let name = configuration.get("name")
.and_then(|value| value.as_str())
.unwrap_or("world");
Box::new(Hello {
name: String::from(name)
})
}
}
impl Module for Hello {
fn register (&self, tenquestionmarks: &Tenquestionmarks) {
println!("Hello, {}!", self.name);
}
}

74
src/modules/loader.rs Normal file
View File

@@ -0,0 +1,74 @@
use std::collections::BTreeMap;
use std::error::Error;
use std::fmt;
use toml::Table;
use modules::Module;
use modules::hello::Hello;
use modules::discord::DiscordModule;
use modules::lua::LuaModule;
use modules::stdin::StdinModule;
use modules::echo::EchoModule;
pub struct ModuleLoader {
types: BTreeMap<&'static str, fn(&Table) -> Box<Module>>
}
impl ModuleLoader {
pub fn new () -> ModuleLoader {
let mut types = BTreeMap::new();
types.insert("hello", Hello::new as fn(&Table) -> Box<Module>);
types.insert("discord", DiscordModule::new as fn(&Table) -> Box<Module>);
types.insert("lua", LuaModule::new as fn(&Table) -> Box<Module>);
types.insert("stdin", StdinModule::new as fn(&Table) -> Box<Module>);
types.insert("echo", EchoModule::new as fn(&Table) -> Box<Module>);
ModuleLoader {
types: types
}
}
pub fn load_from_configuration (&self, configuration: Table) -> Result<BTreeMap<String, Box<Module>>, ModuleLoaderError> {
configuration.into_iter().map(|(key, value)| {
match value.as_table() {
Some(table) => {
let module = self.load_single_module(&key, table)?;
Result::Ok((key, module))
},
None => Result::Err(ModuleLoaderError { message: format!("Bad configuration parameters for module instance: {}. Configuration for a Module must be a table.", key) })
}
}).collect()
}
pub fn load_single_module (&self, name: &str, configuration: &Table) -> Result<Box<Module>, ModuleLoaderError> {
/*
* The Module type defaults to the instance name (in the tenquestionmarks configuration)
* but can explicitly be set by using the special "type" parameter.
*/
let module_type: &str = configuration.get("type")
.and_then(|value| value.as_str())
.unwrap_or(name);
match self.types.get(module_type) {
Some(constructor) => Result::Ok(constructor(configuration)),
None => Result::Err(ModuleLoaderError { message: format!("No such module type: {}", module_type) })
}
}
}
#[derive(Debug)]
pub struct ModuleLoaderError {
message: String
}
impl Error for ModuleLoaderError {
fn description(&self) -> &str {
&self.message[..]
}
}
impl fmt::Display for ModuleLoaderError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ModuleLoaderError: {}", self.message)
}
}

14
src/modules/lua.rs Normal file
View File

@@ -0,0 +1,14 @@
use modules::Module;
use toml::Table;
pub struct LuaModule {
}
impl LuaModule {
pub fn new (configuration: &Table) -> Box<Module> {
Box::new(LuaModule {})
}
}
impl Module for LuaModule {}

18
src/modules/mod.rs Normal file
View File

@@ -0,0 +1,18 @@
pub mod hello;
pub mod lua;
pub mod discord;
pub mod stdin;
pub mod echo;
pub mod loader;
use Tenquestionmarks;
use event::Event;
use std::sync::mpsc::{Sender, Receiver};
pub trait Module : Sync {
fn register (&self, tenquestionmarks: &Tenquestionmarks) {}
fn consume_events (&self, receiver: Receiver<Event>) {}
fn produce_events<'a>(&'a self, sender: Sender<Event>) {}
}

51
src/modules/stdin.rs Normal file
View File

@@ -0,0 +1,51 @@
use std::io;
use modules::Module;
use toml::Table;
use User;
use MessageSender;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use event::Event;
pub struct StdinModule {}
pub struct StdinMessageSender {
name: String
}
impl MessageSender for StdinMessageSender {
fn send_message (&self, message: &str) {
println!("send to {:?}: {:?}", self.name, message);
}
}
impl StdinModule {
pub fn new (configuration: &Table) -> Box<Module> {
Box::new(StdinModule {})
}
}
impl Module for StdinModule {
fn produce_events<'a>(&'a self, sender: Sender<Event>) {
let user = User {
name: String::from("Dave"),
sender: Arc::new(StdinMessageSender {
name: String::from("Dave")
})
};
loop {
let mut input = String::new();
match io::stdin().read_line(&mut input) {
Ok(n) => {
let message = Event::Message { sender: user.clone(), content: input, channel: None };
sender.send(message);
}
Err(error) => println!("error: {}", error),
}
}
}
}