From 12024c66fe21c62b158552abe26b1bcfa142ffe8 Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Sat, 21 Jul 2012 19:15:37 +0100 Subject: Allowing generic message listeners for Swiftob bots diff --git a/Swiftob/Commands.cpp b/Swiftob/Commands.cpp index cf24196..18f9fb0 100644 --- a/Swiftob/Commands.cpp +++ b/Swiftob/Commands.cpp @@ -41,6 +41,10 @@ void Commands::registerCommand(const std::string& name, RoleList roles, const st command->onReceived.connect(callback); } +void Commands::registerListener(ListenerCallback listener) { + listeners_.push_back(listener); +} + bool Commands::hasCommand(const std::string& name) { return commands_.find(name) != commands_.end(); } @@ -57,6 +61,12 @@ bool Commands::runCommand(const std::string& name, const std::string& params, Sw return false; } +void Commands::runListeners(Swift::Message::ref message) { + foreach (ListenerCallback listener, listeners_) { + listener(message); + } +} + bool Commands::roleIn(const Users::User::Role userRole, RoleList roleList) { switch (roleList) { case Owner : return userRole == Users::User::Owner; @@ -84,6 +94,7 @@ void Commands::handleRehashCommand(const std::string& /*command*/, const std::st replyTo(message, "Rehashing now."); std::cout << "Rehashing at the behest of " << message->getFrom().toString() << std::endl; resetCommands(); + listeners_.clear(); if (rehashError_.empty()) { replyTo(message, "Rehash complete"); } else { diff --git a/Swiftob/Commands.h b/Swiftob/Commands.h index 8423252..5c55f39 100644 --- a/Swiftob/Commands.h +++ b/Swiftob/Commands.h @@ -21,6 +21,7 @@ namespace Swift { class Storage; class Commands { + typedef boost::function ListenerCallback; public: enum RoleList {Anyone, Owner}; public: @@ -43,8 +44,10 @@ class Commands { Commands(Users* users, Swift::Client* client, Storage* storage, MUCs* mucs); bool hasCommand(const std::string&); bool runCommand(const std::string& command, const std::string& params, Swift::Message::ref message); + void runListeners(Swift::Message::ref message); void replyTo(Swift::Message::ref source, std::string replyBody, bool outOfMUC = false); void registerCommand(const std::string& name, RoleList roles, const std::string& description, boost::function callback); + void registerListener(ListenerCallback); void resetCommands(); void setRehashError(const std::string& error); @@ -61,6 +64,7 @@ class Commands { void handleRehashCommand(const std::string& command, const std::string& params, Swift::Message::ref message); private: std::map commands_; + std::vector listeners_; Users* users_; Swift::Client* client_; Storage* storage_; diff --git a/Swiftob/LuaCommands.cpp b/Swiftob/LuaCommands.cpp index 9f99d82..8cc614d 100644 --- a/Swiftob/LuaCommands.cpp +++ b/Swiftob/LuaCommands.cpp @@ -42,6 +42,21 @@ void LuaCommands::registerCommands() { } } +static int l_register_listener(lua_State *L) { + LuaCommands* commands = NULL; + lua_getfield(L, LUA_REGISTRYINDEX, LUA_COMMANDS); + commands = static_cast(lua_touserdata(L, -1)); + lua_pop(L, 1); + if (!lua_isfunction(L, 1)) { + return luaL_error(L, "register_listener parameter must be a callback function"); + } + lua_pushvalue(L, 1); + int callbackIndex = luaL_ref(L, LUA_REGISTRYINDEX); + lua_pop(L, 1); + commands->getCommands()->registerListener(boost::bind(&LuaCommands::handleLuaListener, commands, callbackIndex, L, _1)); + return 0; +} + static int l_register_command(lua_State *L) { LuaCommands* commands = NULL; lua_getfield(L, LUA_REGISTRYINDEX, LUA_COMMANDS); @@ -313,6 +328,21 @@ int LuaCommands::get_setting(lua_State *L) { } +void LuaCommands::handleLuaListener(int callbackIndex, lua_State* L, Swift::Message::ref message) { + lua_rawgeti(L, LUA_REGISTRYINDEX, callbackIndex); + lua_pushstring(L, message->getBody().c_str()); + lua_pushstring(L, message->getFrom().toBare().toString().c_str()); + lua_pushstring(L, message->getFrom().getResource().c_str()); + messageOntoStack(message, L); + int result = lua_pcall(L, 4, 0, 0); + if (result != 0) { + std::string error(lua_tostring(L, -1)); + lua_pop(L, 1); + error = "Listener failed: " + error; + std::cout << error << std::endl; + } +} + void LuaCommands::handleLuaCommand(int callbackIndex, lua_State* L, const std::string& command, const std::string& params, Swift::Message::ref message) { lua_rawgeti(L, LUA_REGISTRYINDEX, callbackIndex); lua_pushstring(L, command.c_str()); @@ -363,6 +393,7 @@ void LuaCommands::loadScript(boost::filesystem::path filePath) { lua_pushlightuserdata(lua, storage); lua_setfield(lua, LUA_REGISTRYINDEX, STORAGE); lua_register(lua, "swiftob_register_command", &l_register_command); + lua_register(lua, "swiftob_register_listener", &l_register_listener); lua_register(lua, "swiftob_reply_to", &l_reply_to); lua_register(lua, "swiftob_get_software_version", &l_get_software_version); lua_register(lua, "swiftob_muc_input_to_jid", &l_muc_input_to_jid); diff --git a/Swiftob/LuaCommands.h b/Swiftob/LuaCommands.h index fc743ca..b82959e 100644 --- a/Swiftob/LuaCommands.h +++ b/Swiftob/LuaCommands.h @@ -64,8 +64,9 @@ class LuaCommands { }; LuaCommands(Commands* commands, const std::string& path, Client* client, TimerFactory* timerFactory, MUCs* mucs); - /* Public but isn't really part of the API */ + /* Public but aren't really part of the API */ void handleLuaCommand(int callbackIndex, lua_State* L, const std::string& command, const std::string& params, Message::ref message); + void handleLuaListener(int callbackIndex, lua_State* L, Message::ref message); Commands* getCommands() {return commands_;} int get_software_version(lua_State *L); int muc_input_to_jid(lua_State *L); diff --git a/Swiftob/Swiftob.cpp b/Swiftob/Swiftob.cpp index 331e55e..6f36b3d 100644 --- a/Swiftob/Swiftob.cpp +++ b/Swiftob/Swiftob.cpp @@ -87,6 +87,10 @@ void Swiftob::handleMessageReceived(Swift::Message::ref message) { std::cout << "Not handling empty body" << std::endl; return; } + + /* Run through any full-message listeners */ + commands_->runListeners(message); + /*Convert body into !command if it's not a MUC, and it misses the bang*/ std::string bangBody(body); if (type != Swift::Message::Groupchat && body[0] != '!') { diff --git a/Swiftob/scripts/logAllMessages.lua b/Swiftob/scripts/logAllMessages.lua new file mode 100644 index 0000000..a14c0f3 --- /dev/null +++ b/Swiftob/scripts/logAllMessages.lua @@ -0,0 +1,6 @@ +function log_a_message(body, muc, nick, message) + print("Received line from '" .. nick .. "' in '" .. muc .. "':") + print(body) +end + +swiftob_register_listener(log_a_message) -- cgit v0.10.2-6-g49f6