Initial implementation of lua module.
This commit is contained in:
parent
41fa36cccf
commit
d9ab75a607
@ -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;
|
||||||
|
@ -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(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user