beefed up lua scripting support, the message
is now presented as a table/struct/object and lua now has access to a sender object which it can use to send messages downstream.
This commit is contained in:
parent
c6dc3f15b8
commit
b0c2928e78
@ -198,6 +198,14 @@ pub trait MessageSender : Sync + Send + std::fmt::Debug {
|
|||||||
fn send_message (&self, _: &str) {}
|
fn send_message (&self, _: &str) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct NullMessageSender {}
|
||||||
|
impl MessageSender for NullMessageSender {}
|
||||||
|
impl std::fmt::Debug for NullMessageSender {
|
||||||
|
fn fmt (&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(formatter, "NullMessageSender")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct Subscription {
|
struct Subscription {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub filters: Vec<Box<EventFilter>>
|
pub filters: Vec<Box<EventFilter>>
|
||||||
|
@ -4,10 +4,10 @@ use toml::Value;
|
|||||||
use toml::value::Table;
|
use toml::value::Table;
|
||||||
|
|
||||||
use hlua;
|
use hlua;
|
||||||
use hlua::{Lua, LuaFunction, Push};
|
use hlua::{Lua, LuaFunction, AnyHashableLuaValue, AnyLuaValue};
|
||||||
|
|
||||||
|
use {User, Message, Channel, NullMessageSender};
|
||||||
use event::{Event, Envelope};
|
use event::{Event, Envelope};
|
||||||
use Message;
|
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc::Receiver;
|
use std::sync::mpsc::Receiver;
|
||||||
@ -16,6 +16,8 @@ use transformable_channels::mpsc::ExtSender;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub struct LuaModule {
|
pub struct LuaModule {
|
||||||
code: Option<String>,
|
code: Option<String>,
|
||||||
file: Option<String>,
|
file: Option<String>,
|
||||||
@ -42,15 +44,76 @@ fn set (lua: &mut Lua, key: &str, value: &Value) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
implement_lua_read!(Message);
|
struct MessageWrapper {
|
||||||
implement_lua_push!(Message, |mut metatable| {
|
envelope: Arc<Envelope>
|
||||||
|
}
|
||||||
|
|
||||||
|
implement_lua_read!(MessageWrapper);
|
||||||
|
implement_lua_push!(MessageWrapper, |mut metatable| {
|
||||||
let mut index = metatable.empty_array("__index");
|
let mut index = metatable.empty_array("__index");
|
||||||
index.set("content", hlua::function1(|message: &mut Message| message.content.clone()));
|
index.set("content", hlua::function1(|wrapper: &MessageWrapper| {
|
||||||
index.set("reply", hlua::function2(|message: &mut Message, reply: String| message.reply(&reply)));
|
if let Event::Message { ref message } = wrapper.envelope.event {
|
||||||
|
Some(message.content.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
index.set("reply", hlua::function2(|wrapper: &MessageWrapper, reply: String| {
|
||||||
|
if let Event::Message { ref message } = wrapper.envelope.event {
|
||||||
|
message.reply(&reply);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
struct SenderWrapper {
|
||||||
|
sender: Box<ExtSender<Event>>
|
||||||
|
}
|
||||||
|
|
||||||
|
implement_lua_read!(SenderWrapper);
|
||||||
|
implement_lua_push!(SenderWrapper, |mut metatable| {
|
||||||
|
let mut index = metatable.empty_array("__index");
|
||||||
|
index.set("send", hlua::function2(|wrapper: &SenderWrapper, data: HashMap<AnyHashableLuaValue, AnyLuaValue>| {
|
||||||
|
if let Some(&AnyLuaValue::LuaString(ref event_type)) = data.get(&AnyHashableLuaValue::LuaString("type".to_owned())) {
|
||||||
|
match event_type.as_ref() {
|
||||||
|
"message" => {
|
||||||
|
wrapper.sender.send(Event::Message {
|
||||||
|
message: Message {
|
||||||
|
author: User {
|
||||||
|
name: data.get(&AnyHashableLuaValue::LuaString("username".to_owned()))
|
||||||
|
.and_then(|value| match value {
|
||||||
|
&AnyLuaValue::LuaString (ref string_value) => Some(string_value.to_owned()),
|
||||||
|
_ => None
|
||||||
|
})
|
||||||
|
.unwrap_or_else(|| "".to_owned()),
|
||||||
|
sender: Box::new(NullMessageSender {})
|
||||||
|
},
|
||||||
|
channel: data.get(&AnyHashableLuaValue::LuaString("channel".to_owned()))
|
||||||
|
.and_then(|value| match value {
|
||||||
|
&AnyLuaValue::LuaString (ref string_value) => Some(string_value.to_owned()),
|
||||||
|
_ => None
|
||||||
|
}).map(|channel| Channel {
|
||||||
|
name: channel,
|
||||||
|
description: "".to_owned(),
|
||||||
|
sender: Box::new(NullMessageSender {}),
|
||||||
|
topic: "".to_owned()
|
||||||
|
}),
|
||||||
|
content: data.get(&AnyHashableLuaValue::LuaString("message".to_owned()))
|
||||||
|
.and_then(|value| match value {
|
||||||
|
&AnyLuaValue::LuaString (ref string_value) => Some(string_value.to_owned()),
|
||||||
|
_ => None
|
||||||
|
})
|
||||||
|
.expect("Invalid message event passed in")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
impl EventLoop for LuaModule {
|
impl EventLoop for LuaModule {
|
||||||
fn run (&self, _: Box<ExtSender<Event>>, receiver: Receiver<Arc<Envelope>>) {
|
fn run (&self, sender: Box<ExtSender<Event>>, receiver: Receiver<Arc<Envelope>>) {
|
||||||
let mut lua = Lua::new();
|
let mut lua = Lua::new();
|
||||||
lua.openlibs();
|
lua.openlibs();
|
||||||
|
|
||||||
@ -58,6 +121,10 @@ impl EventLoop for LuaModule {
|
|||||||
set(&mut lua, key, value);
|
set(&mut lua, key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lua.set("sender", SenderWrapper {
|
||||||
|
sender: Box::new(sender.clone())
|
||||||
|
});
|
||||||
|
|
||||||
match self.code {
|
match self.code {
|
||||||
Some(ref code) => { lua.execute(&code).unwrap() },
|
Some(ref code) => { lua.execute(&code).unwrap() },
|
||||||
None => {
|
None => {
|
||||||
@ -81,23 +148,9 @@ impl EventLoop for LuaModule {
|
|||||||
let on_message: Option<LuaFunction<_>> = lua.get("on_message");
|
let on_message: Option<LuaFunction<_>> = lua.get("on_message");
|
||||||
match on_message {
|
match on_message {
|
||||||
Some(mut on_message) => {
|
Some(mut on_message) => {
|
||||||
/*
|
on_message.call_with_args::<(), _, _>(MessageWrapper {
|
||||||
* What this does is clone the envelope reference (an Arc - atomic refcounted)
|
envelope: envelope.clone()
|
||||||
* and pass it into the reply_callback, where it becomes owned by the closure
|
}).unwrap();
|
||||||
* (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 => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
@ -78,8 +78,8 @@ parents = ["stdin", "discord", "irc"]
|
|||||||
[lua]
|
[lua]
|
||||||
parents = ["stdin", "discord"]
|
parents = ["stdin", "discord"]
|
||||||
code = """
|
code = """
|
||||||
function on_message (message, reply)
|
function on_message (message)
|
||||||
reply("Lua says: " .. message)
|
message:reply("Lua says: " .. message:content())
|
||||||
end
|
end
|
||||||
"""
|
"""
|
||||||
foo = "bar"
|
foo = "bar"
|
||||||
@ -89,8 +89,24 @@ type = "lua"
|
|||||||
parents = ["stdin", "discord"]
|
parents = ["stdin", "discord"]
|
||||||
filters = [{ username = "David" }]
|
filters = [{ username = "David" }]
|
||||||
code = """
|
code = """
|
||||||
function on_message (message, reply)
|
function on_message (message)
|
||||||
reply("Lua2 says: " .. message)
|
message:reply("Lua2 says: " .. message:content())
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
|
||||||
|
[lua3]
|
||||||
|
type = "lua"
|
||||||
|
children = ["lua", "irc"]
|
||||||
|
code = """
|
||||||
|
local clock = os.clock
|
||||||
|
function sleep(n) -- seconds
|
||||||
|
local t0 = clock()
|
||||||
|
while clock() - t0 <= n do end
|
||||||
|
end
|
||||||
|
|
||||||
|
while true do
|
||||||
|
sender:send({type = "message", channel = "#eightbar", message = "Hello world!"})
|
||||||
|
sleep(10)
|
||||||
end
|
end
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user