diff options
Diffstat (limited to 'Swiftob')
-rw-r--r-- | Swiftob/Commands.cpp | 9 | ||||
-rw-r--r-- | Swiftob/LuaCommands.cpp | 6 | ||||
-rw-r--r-- | Swiftob/Swiftob.cpp | 12 |
3 files changed, 14 insertions, 13 deletions
diff --git a/Swiftob/Commands.cpp b/Swiftob/Commands.cpp index 4e31212..9212aaf 100644 --- a/Swiftob/Commands.cpp +++ b/Swiftob/Commands.cpp @@ -1,43 +1,44 @@ /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiftob/Commands.h> -#include <Swiften/Base/foreach.h> #include <iostream> -#include <boost/bind.hpp> + #include <boost/algorithm/string.hpp> +#include <boost/bind.hpp> +#include <Swiften/Base/foreach.h> #include <Swiften/Client/Client.h> typedef std::pair<std::string, Commands::Command*> NamedCommand; Commands::Commands(Users* users, Swift::Client* client, Storage* storage, MUCs* mucs) { users_ = users; client_ = client; mucs_ = mucs; storage_ = storage; resetCommands(); } Commands::~Commands() { clearCommands(); } void Commands::clearCommands() { foreach (NamedCommand command, commands_) { delete command.second; } commands_.clear(); } void Commands::resetCommands() { clearCommands(); registerCommand("quit", Owner, "Quit the bot", boost::bind(&Commands::handleQuitCommand, this, _1, _2, _3)); registerCommand("help", Anyone, "Get help", boost::bind(&Commands::handleHelpCommand, this, _1, _2, _3)); registerCommand("join", Owner, "Join a MUC", boost::bind(&Commands::handleJoinCommand, this, _1, _2, _3)); registerCommand("part", Owner, "Leave a MUC", boost::bind(&Commands::handlePartCommand, this, _1, _2, _3)); @@ -184,33 +185,33 @@ void Commands::handleHelpCommand(const std::string& /*command*/, const std::stri std::string result("Available commands:"); std::string bang = message->getType() == Swift::Message::Groupchat ? "\n!" : "\n"; foreach (NamedCommand pair, commands_) { if (roleIn(userRole, pair.second->getAllowedBy())) { result += bang + pair.first + " - " + pair.second->getDescription(); } } replyTo(message, result, true); } /** * \param outOfMUC Reply to the sender directly, don't spam MUCs with the reply */ void Commands::replyTo(Swift::Message::ref source, std::string replyBody, bool outOfMUC) { Swift::Message::ref reply(new Swift::Message()); Swift::Message::Type type = source->getType(); reply->setType(type); reply->setBody(type == Swift::Message::Groupchat ? source->getFrom().getResource() + ": " + replyBody : replyBody); Swift::JID to = source->getFrom(); if (type == Swift::Message::Groupchat) { if (outOfMUC) { reply->setType(Swift::Message::Chat); } else { to = to.toBare(); } } reply->setTo(to); if (client_->isAvailable()) { client_->sendMessage(reply); } else { - std::cout << "Dropping '" + reply->getBody() + "' -> " + reply->getTo().toString() + " on the floor due to missing connection." << std::endl; + std::cout << "Dropping '" + reply->getBody().get_value_or("") + "' -> " + reply->getTo().toString() + " on the floor due to missing connection." << std::endl; } } diff --git a/Swiftob/LuaCommands.cpp b/Swiftob/LuaCommands.cpp index 1192452..18535f3 100644 --- a/Swiftob/LuaCommands.cpp +++ b/Swiftob/LuaCommands.cpp @@ -1,32 +1,32 @@ /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiftob/LuaCommands.h> #include <boost/bind.hpp> #include <vector> #include <algorithm> #include <iostream> #include <Swiften/Base/foreach.h> #include <Swiften/Client/Client.h> #include <Swiften/Network/TimerFactory.h> #include <boost/filesystem/operations.hpp> #include <Swiften/Base/Path.h> #include <Swiftob/Commands.h> #include <Swiften/Base/BoostFilesystemVersion.h> #define LUA_COMMANDS "__Lua_Commands" #define STORAGE "__Storage" static const luaL_Reg defaultLibraries[] = { {"", luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, {LUA_TABLIBNAME, luaopen_table}, {LUA_IOLIBNAME, luaopen_io}, {LUA_OSLIBNAME, luaopen_os}, @@ -353,107 +353,107 @@ static int l_store_setting(lua_State *L) { } static int l_get_setting(lua_State *L) { return LuaCommands::commandsFromLua(L)->get_setting(L); } int LuaCommands::store_setting(lua_State *L) { if (!lua_isstring(L, 2) || !lua_isstring(L, 1)) { return luaL_error(L, "both setting and key must be strings"); } std::string value(lua_tostring(L, 2)); std::string key(lua_tostring(L, 1)); lua_pop(L, 2); storageFromLua(L)->saveSetting(key, value); return 0; } int LuaCommands::get_setting(lua_State *L) { if (!lua_isstring(L, 1)) { return luaL_error(L, "key must be a string"); } std::string key(lua_tostring(L, 1)); lua_pop(L, 1); lua_pushstring(L, storageFromLua(L)->getSetting(key).c_str()); return 1; } 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->getBody().get_value_or("").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()); lua_pushstring(L, params.c_str()); messageOntoStack(message, L); int result = lua_pcall(L, 3, 0, 0); if (result != 0) { std::string error(lua_tostring(L, -1)); lua_pop(L, 1); error = "Command '" + command + "' failed: " + error; std::cout << error << std::endl; commands_->replyTo(message, error, false); } } void LuaCommands::messageOntoStack(Swift::Message::ref message, lua_State* L) { lua_createtable(L, 0, 4); std::string typeString; switch (message->getType()) { case Message::Chat : typeString = "chat";break; case Message::Groupchat : typeString = "groupchat";break; case Message::Normal : typeString = "normal";break; case Message::Error : typeString = "error";break; case Message::Headline : typeString = "headline";break; } lua_pushstring(L, typeString.c_str()); lua_setfield(L, -2, "type"); lua_pushstring(L, message->getFrom().toString().c_str()); lua_setfield(L, -2, "from"); lua_pushstring(L, message->getFrom().toBare().toString().c_str()); lua_setfield(L, -2, "frombare"); lua_pushstring(L, message->getTo().toString().c_str()); lua_setfield(L, -2, "to"); - lua_pushstring(L, message->getBody().c_str()); + lua_pushstring(L, message->getBody().get_value_or("").c_str()); lua_setfield(L, -2, "body"); } void LuaCommands::loadScript(boost::filesystem::path filePath) { std::cout << "Trying to load file from " << filePath << std::endl; lua_State* lua = luaL_newstate(); initialize(lua); lua_pushlightuserdata(lua, this); lua_setfield(lua, LUA_REGISTRYINDEX, LUA_COMMANDS); #if BOOST_FILESYSTEM_VERSION == 2 // TODO: Delete this when boost 1.44 becomes a minimum requirement, and we no longer need v2 std::string filename = filePath.filename(); #else std::string filename = filePath.filename().string(); #endif filename += ".storage"; boost::filesystem::path storagePath(boost::filesystem::path(path_) / stringToPath(filename)); Storage* storage = new Storage(storagePath); 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); lua_register(lua, "swiftob_store_setting", &l_store_setting); lua_register(lua, "swiftob_get_setting", &l_get_setting); lua_register(lua, "swiftob_muc_kick", &l_muc_kick); int fileLoaded = luaL_dofile(lua, filePath.string().c_str()); if (fileLoaded == 0 ) { std::cout << "Loaded" << std::endl; diff --git a/Swiftob/Swiftob.cpp b/Swiftob/Swiftob.cpp index d26ea23..d534479 100644 --- a/Swiftob/Swiftob.cpp +++ b/Swiftob/Swiftob.cpp @@ -1,49 +1,49 @@ /* - * Copyright (c) 2011 Isode Limited. + * Copyright (c) 2011-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swiftob/Swiftob.h> -#include <string> #include <iostream> +#include <string> + #include <boost/bind.hpp> -#include <Swiften/JID/JID.h> #include <Swiften/Base/String.h> +#include <Swiften/JID/JID.h> #include <Swiften/Presence/PresenceSender.h> -#include <Swiftob/Users.h> #include <Swiftob/Storage.h> - +#include <Swiftob/Users.h> po::options_description Swiftob::getOptionsDescription() { po::options_description result("Options"); result.add_options() ("path", po::value<std::string>(), "Configuration folder") ("help", "produce help message") ("init", "Reset everything (Really, everything, be careful, you only want to use this on first run).") ("jid", po::value<std::string>(), "JID to use") ("password", po::value<std::string>(), "password") ("initial-owner", po::value<std::string>(), "Initial bot owner (JID)") ; return result; } Swiftob::Swiftob(const po::variables_map& options) : options_(options), networkFactories_(&eventLoop_), quitting_(false) { path_ = options["path"].as<std::string>(); client_ = new Swift::Client(Swift::JID(options["jid"].as<std::string>()), options["password"].as<std::string>(), &networkFactories_); storage_ = new Storage(boost::filesystem::path(path_) / "settings.txt"); mucs_ = NULL; users_ = NULL; commands_ = NULL; lua_ = NULL; init(); client_->onConnected.connect(boost::bind(&Swiftob::handleConnected, this)); client_->onDisconnected.connect(boost::bind(&Swiftob::handleDisconnected, this, _1)); client_->onMessageReceived.connect(boost::bind(&Swiftob::handleMessageReceived, this, _1)); if (options_.count("init") > 0) { } else if (options_.count("jid") > 0 || options_.count("password") > 0 || options_.count("initial-owner") == 0) { std::cout << "Ignoring initial config options without --initial" << std::endl; @@ -71,61 +71,61 @@ void Swiftob::handleRestartRequested() { init(); } void Swiftob::handleConnected() { std::cout << "Connected" << std::endl; if (options_.count("init") > 0) {}{ /* FIXME: Not ready for persistence yet*/ users_->clearAll(); users_->addUser(Users::User(Swift::JID(options_["initial-owner"].as<std::string>()), Users::User::Owner)); } Swift::Presence::ref presence(new Swift::Presence()); presence->setStatus("Online and botty"); client_->getPresenceSender()->sendPresence(presence); } void Swiftob::handleDisconnected(const boost::optional<Swift::ClientError>& /*error*/) { std::cout << "Disconnected" << std::endl; /* FIXME: check if last connect was more than a minute ago. If so, go ahead and connect, if not then wait a minute before connecting.*/ if (quitting_) { eventLoop_.stop(); } else { client_->connect(); } } void Swiftob::handleMessageReceived(Swift::Message::ref message) { Swift::Message::Type type = message->getType(); if (type == Swift::Message::Error || type == Swift::Message::Headline) { std::cout << "Ignoring typed message" << std::endl; return; } - std::string body = message->getBody(); + std::string body = message->getBody().get_value_or(""); std::cout << "Got message with body " << body << std::endl; if (body.size() == 0) { 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] != '!') { bangBody = "!" + body; } std::cout << "After banging, body is " << bangBody << std::endl; std::pair<std::string, std::string> split = Swift::String::getSplittedAtFirst(bangBody, ' '); std::string commandName(split.first); commandName = Swift::String::getSplittedAtFirst(commandName, '!').second; /*FIXME: remove leading bang in commandName*/ if (commands_->hasCommand(commandName)) { std::cout << "Matched command " << commandName << std::endl; commands_->runCommand(commandName, split.second, message); } } Swiftob::~Swiftob() { delete lua_; delete commands_; delete storage_; delete users_; |