Initial implementation of lua module.

This commit is contained in:
Adrian Malacoda 2017-02-26 02:10:28 -06:00
parent 41fa36cccf
commit d9ab75a607
3 changed files with 104 additions and 7 deletions

View File

@ -6,6 +6,9 @@ extern crate pvn;
extern crate echobox; extern crate echobox;
extern crate transformable_channels; extern crate transformable_channels;
#[macro_use]
extern crate hlua;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use toml::Table; use toml::Table;
@ -20,6 +23,7 @@ use std::sync::Arc;
use std::sync::mpsc; use std::sync::mpsc;
use std::sync::mpsc::Sender; use std::sync::mpsc::Sender;
use std::rc::Rc;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
use transformable_channels::mpsc::TransformableSender; use transformable_channels::mpsc::TransformableSender;

View File

@ -6,6 +6,7 @@ use modules::Module;
use toml::Table; use toml::Table;
use event; use event;
use event::Envelope;
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
@ -72,7 +73,7 @@ impl Module for DiscordModule {
for channel in server.channels { for channel in server.channels {
info!(" - Joined channel: {}", channel.name); info!(" - Joined channel: {}", channel.name);
match sender.send(event::Envelope::new(event::Event::SelfJoin { match sender.send(Envelope::new(event::Event::SelfJoin {
channel: Channel { channel: Channel {
name: channel.name, name: channel.name,
description: String::from(""), description: String::from(""),
@ -116,7 +117,7 @@ impl Module for DiscordModule {
channel: Some(channel) channel: Some(channel)
}; };
match sender.send(event::Envelope::new(event::Event::Message { message: message })) { match sender.send(Envelope::new(event::Event::Message { message: message })) {
Err(err) => error!("Error sending message event: {:?}", err), Err(err) => error!("Error sending message event: {:?}", err),
Ok(_) => {} Ok(_) => {}
} }

View File

@ -1,14 +1,106 @@
use modules::Module; use modules::Module;
use toml::Table;
use toml::{Table, Value};
use hlua;
use hlua::{Lua, LuaFunction, Push};
use event::{Event, Envelope};
use Message;
use std::sync::Arc;
use std::sync::mpsc::Receiver;
use transformable_channels::mpsc::ExtSender;
use std::path::Path;
use std::fs::File;
pub struct LuaModule { pub struct LuaModule {
code: Option<String>,
file: Option<String>,
variables: Table
} }
impl LuaModule { impl LuaModule {
pub fn new (_: &Table) -> Box<Module> { pub fn new (config: &Table) -> Box<Module> {
Box::new(LuaModule {}) Box::new(LuaModule {
code: config.get("code").and_then(|value| value.as_str()).map(String::from),
file: config.get("file").and_then(|value| value.as_str()).map(String::from),
variables: config.clone()
})
} }
} }
impl Module for LuaModule {} fn set (lua: &mut Lua, key: &str, value: &Value) {
match value.clone() {
Value::String(string) => lua.set(key, string),
Value::Integer(integer) => lua.set(key, integer as i32),
Value::Float(float) => lua.set(key, float),
Value::Boolean(boolean) => lua.set(key, boolean),
_ => {}
}
}
implement_lua_read!(Message);
implement_lua_push!(Message, |mut metatable| {
let mut index = metatable.empty_array("__index");
index.set("content", hlua::function1(|message: &mut Message| message.content.clone()));
index.set("reply", hlua::function2(|message: &mut Message, reply: String| message.reply(&reply)));
});
impl Module for LuaModule {
fn run (&self, _: Box<ExtSender<Envelope>>, receiver: Receiver<Arc<Envelope>>) {
let mut lua = Lua::new();
lua.openlibs();
for (key, value) in &self.variables {
set(&mut lua, key, value);
}
match self.code {
Some(ref code) => { lua.execute(&code).unwrap() },
None => {
match self.file {
Some(ref file) => { lua.execute_from_reader::<(), _>(File::open(&Path::new(file)).unwrap()).unwrap(); }
None => {}
}
}
}
loop {
match receiver.recv() {
Ok(envelope) => {
match envelope.event {
Event::Message { ref message } => {
let on_message: Option<LuaFunction<_>> = lua.get("on_message");
match on_message {
Some(mut on_message) => {
/*
* What this does is clone the envelope reference (an Arc - atomic refcounted)
* and pass it into the reply_callback, where it becomes owned by the closure
* (since it's a move closure). We then pass this callback into the lua code,
* where it can be used to send a reply.
*
* TODO: Replace this with a table (struct/class) which has a
* reply() method.
*/
let envelope_clone = envelope.clone();
let reply_callback = hlua::function1(move |reply: String| {
match envelope_clone.event {
Event::Message { ref message } => message.reply(&reply),
_ => {}
}
});
on_message.call_with_args::<(), _, _>((message.content.clone(), reply_callback)).unwrap();
},
None => {}
}
}
_ => ()
}
}
Err(error) => { error!("Error {:?}", error) }
}
}
}
}