diff options
Diffstat (limited to 'Swiftob')
-rw-r--r-- | Swiftob/Commands.cpp | 54 | ||||
-rw-r--r-- | Swiftob/Commands.h | 10 | ||||
-rw-r--r-- | Swiftob/LuaCommands.cpp | 63 | ||||
-rw-r--r-- | Swiftob/LuaCommands.h | 8 | ||||
-rw-r--r-- | Swiftob/MUCs.cpp | 17 | ||||
-rw-r--r-- | Swiftob/MUCs.h | 22 | ||||
-rw-r--r-- | Swiftob/SConscript | 16 | ||||
-rw-r--r-- | Swiftob/Storage.cpp | 4 | ||||
-rw-r--r-- | Swiftob/Swiftob.cpp | 35 | ||||
-rw-r--r-- | Swiftob/Swiftob.h | 3 | ||||
-rw-r--r-- | Swiftob/Users.cpp | 2 | ||||
-rw-r--r-- | Swiftob/Users.h | 10 | ||||
-rw-r--r-- | Swiftob/linit.cpp (renamed from Swiftob/linit.c) | 0 | ||||
-rw-r--r-- | Swiftob/scripts/badWords.lua | 15 | ||||
-rw-r--r-- | Swiftob/scripts/irssiLogs.lua | 23 | ||||
-rw-r--r-- | Swiftob/scripts/logAllMessages.lua | 6 |
16 files changed, 37 insertions, 251 deletions
diff --git a/Swiftob/Commands.cpp b/Swiftob/Commands.cpp index 38e5f57..cf24196 100644 --- a/Swiftob/Commands.cpp +++ b/Swiftob/Commands.cpp @@ -1,180 +1,128 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiftob/Commands.h> #include <Swiften/Base/foreach.h> #include <iostream> #include <boost/bind.hpp> -#include <boost/algorithm/string.hpp> #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() { +void Commands::resetCommands() { 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)); registerCommand("rehash", Owner, "Reload scripts", boost::bind(&Commands::handleRehashCommand, this, _1, _2, _3)); - registerCommand("restart", Owner, "Restart bot", boost::bind(&Commands::handleRestartCommand, this, _1, _2, _3)); - registerCommand("nick", Owner, "Change nick (requires restart)", boost::bind(&Commands::handleChangeNick, this, _1, _2, _3)); - //registerCommand("owner", Owner, "Change owner settinsg", boost::bind(&Commands::handleChangeOwner, this, _1, _2, _3)); onReset(); } void Commands::registerCommand(const std::string& name, RoleList roles, const std::string& description, boost::function<void(const std::string& /*command*/, const std::string& /*params*/, Swift::Message::ref)> callback) { Command* command = new Command(roles, description); commands_[name] = command; 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(); } bool Commands::runCommand(const std::string& name, const std::string& params, Swift::Message::ref message) { Users::User::Role userRole = users_->getRoleForSender(message); Command* command = commands_[name]; if (roleIn(userRole, command->getAllowedBy())) { command->onReceived(name, params, message); return true; } else { replyTo(message, "You may not run this command", true); } 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; case Anyone : return true; } std::cerr << "Unrecognised role list" << std::endl; return false; } -void Commands::handleChangeNick(const std::string& /*command*/, const std::string& params, Swift::Message::ref message) { - std::string nick(params); - boost::algorithm::trim(nick); - if (nick.empty()) { - replyTo(message, "Current nick is '" + mucs_->getDefaultNick() + "'. Run the command with a new nick to change it."); - } - else { - if (mucs_->setDefaultNick(params)) { - replyTo(message, "Default nick now set to '" + nick + "' - restart the bot for this to take effect."); - } - else { - replyTo(message, "Can't set invalid nick '" + nick + "'."); - } - } -} - -void Commands::handleChangeOwner(const std::string& /*command*/, const std::string& /*params*/, Swift::Message::ref /*message*/) { - /* Oh, right. I don't have user persistence coded yet. - * Probably not worth doing this until I have.*/ -} - void Commands::handleQuitCommand(const std::string& /*command*/, const std::string& /*params*/, Swift::Message::ref message) { replyTo(message, "Shutting down"); std::cout << "Quitting at the behest of " << message->getFrom().toString() << std::endl; exit(0); } void Commands::setRehashError(const std::string& error) { if (!rehashError_.empty()) { rehashError_ += "; "; } rehashError_ += error; } void Commands::handleRehashCommand(const std::string& /*command*/, const std::string& /*params*/, Swift::Message::ref message) { rehashError_ = ""; 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 { replyTo(message, "I have suffered a tremendous failure: " + rehashError_); } } -void Commands::handleRestartCommand(const std::string& /*command*/, const std::string& /*params*/, Swift::Message::ref message) { - rehashError_ = ""; - replyTo(message, "Restarting now."); - std::cout << "Restarting at the behest of " << message->getFrom().toString() << std::endl; - onRestartRequested(); -} - void Commands::handleJoinCommand(const std::string& /*command*/, const std::string& params, Swift::Message::ref message) { Swift::JID room(params); if (!room.isValid() || !room.getResource().empty() || room.getNode().empty()) { replyTo(message, "Can't join " + room.toString() + ", not a valid room JID."); return; } if (mucs_->contains(room)) { replyTo(message, "I'm already (trying to be?) in " + room.toString() + "."); return; } replyTo(message, "Trying to join " + room.toString() + "."); mucs_->join(room, boost::bind(&Commands::handleJoinCommandSuccess, this, room, message), boost::bind(&Commands::handleJoinCommandFailure, this, room, _1, message)); } void Commands::handlePartCommand(const std::string& /*command*/, const std::string& params, Swift::Message::ref message) { Swift::JID room(params); if (!room.isValid() || !room.getResource().empty() || room.getNode().empty()) { replyTo(message, "Can't leave " + room.toString() + ", not a valid room JID."); return; } if (mucs_->contains(room)) { replyTo(message, "I'm not in " + room.toString() + "."); return; } replyTo(message, "Leaving " + room.toString() + "."); mucs_->part(room); } void Commands::handleJoinCommandSuccess(const Swift::JID& room, Swift::Message::ref message) { replyTo(message, "Joined " + room.toString()); } void Commands::handleJoinCommandFailure(const Swift::JID& room, const std::string& error, Swift::Message::ref message) { replyTo(message, "Join to " + room.toString() + "failed. " + error); } diff --git a/Swiftob/Commands.h b/Swiftob/Commands.h index d5aac2c..8423252 100644 --- a/Swiftob/Commands.h +++ b/Swiftob/Commands.h @@ -1,81 +1,71 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <map> #include <string> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Elements/Message.h> #include <Swiftob/Users.h> #include <Swiftob/MUCs.h> namespace Swift { class Client; } class Storage; class Commands { - typedef boost::function<void(Swift::Message::ref)> ListenerCallback; public: enum RoleList {Anyone, Owner}; public: class Command { public: Command(RoleList allowedBy, const std::string& description) : allowedBy_(allowedBy), description_(description) { } virtual ~Command() {}; boost::signal<void (const std::string&, const std::string&, Swift::Message::ref)> onReceived; RoleList getAllowedBy() {return allowedBy_;} std::string getDescription() {return description_;} private: RoleList allowedBy_; std::string description_; }; public: Commands(Users* users, Swift::Client* client, Storage* storage, MUCs* mucs); - ~Commands(); 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<void(const std::string& /*command*/, const std::string& /*params*/, Swift::Message::ref)> callback); - void registerListener(ListenerCallback); void resetCommands(); void setRehashError(const std::string& error); public: boost::signal<void ()> onReset; - boost::signal<void ()> onRestartRequested; private: - void clearCommands(); bool roleIn(const Users::User::Role userRole, RoleList roles); void handleQuitCommand(const std::string& command, const std::string& params, Swift::Message::ref message); void handleHelpCommand(const std::string& command, const std::string& params, Swift::Message::ref message); void handleJoinCommand(const std::string& /*command*/, const std::string& params, Swift::Message::ref message); void handleJoinCommandSuccess(const Swift::JID& room, Swift::Message::ref message); void handleJoinCommandFailure(const Swift::JID& room, const std::string& error, Swift::Message::ref message); void handlePartCommand(const std::string& /*command*/, const std::string& params, Swift::Message::ref message); void handleRehashCommand(const std::string& command, const std::string& params, Swift::Message::ref message); - void handleRestartCommand(const std::string& command, const std::string& params, Swift::Message::ref message); - void handleChangeNick(const std::string& command, const std::string& params, Swift::Message::ref message); - void handleChangeOwner(const std::string& command, const std::string& params, Swift::Message::ref message); private: std::map<std::string, Command*> commands_; - std::vector<ListenerCallback> listeners_; Users* users_; Swift::Client* client_; Storage* storage_; MUCs* mucs_; std::string rehashError_; }; diff --git a/Swiftob/LuaCommands.cpp b/Swiftob/LuaCommands.cpp index c2478cd..9f99d82 100644 --- a/Swiftob/LuaCommands.cpp +++ b/Swiftob/LuaCommands.cpp @@ -1,98 +1,79 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt 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" LuaCommands::LuaCommands(Commands* commands, const std::string& path, Client* client, TimerFactory* timerFactory, MUCs* mucs) : path_(path), scriptsPath_(boost::filesystem::path(path_) / "scripts") { commands_ = commands; client_ = client; timerFactory_ = timerFactory; mucs_ = mucs; commands_->onReset.connect(boost::bind(&LuaCommands::registerCommands, this)); registerCommands(); } void LuaCommands::registerCommands() { std::cout << "Trying to load all scripts in " << scriptsPath_ << std::endl; if (boost::filesystem::exists(scriptsPath_) && boost::filesystem::is_directory(scriptsPath_)) { std::vector<boost::filesystem::path> files; copy(boost::filesystem::directory_iterator(scriptsPath_), boost::filesystem::directory_iterator(), std::back_inserter(files)); foreach (boost::filesystem::path file, files) { if (boost::filesystem::is_regular_file(file) && file.extension() == ".lua") { loadScript(file); } } } } -static int l_register_listener(lua_State *L) { - LuaCommands* commands = NULL; - lua_getfield(L, LUA_REGISTRYINDEX, LUA_COMMANDS); - commands = static_cast<LuaCommands*>(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); commands = static_cast<LuaCommands*>(lua_touserdata(L, -1)); lua_pop(L, 1); if (!lua_isfunction(L, 4)) { return luaL_error(L, "register_command callback parameter must be a function"); } //luaL_ref callback(lua_to(L, 4)); lua_pushvalue(L, 4); int callbackIndex = luaL_ref(L, LUA_REGISTRYINDEX); lua_pop(L, 1); if (!lua_isstring(L, 3)) { return luaL_error(L, "register_command description parameter must be a string"); } std::string description(lua_tostring(L, 3)); lua_pop(L, 1); if (!lua_isstring(L, 2)) { return luaL_error(L, "register_command allowed roles parameter must be a string"); } std::string roleString(lua_tostring(L, 2)); lua_pop(L, 1); Commands::RoleList roleList = Commands::Owner; if (roleString == "Owner") { roleList = Commands::Owner; } else if (roleString == "Anyone") { roleList = Commands::Anyone; } else { return luaL_error(L, "register_command allowed roles parameter has illegal value"); } if (!lua_isstring(L, 1)) { return luaL_error(L, "register_command command name parameter must be a string"); } @@ -270,169 +251,129 @@ void LuaCommands::handleSoftwareVersionResponse(boost::shared_ptr<SoftwareVersio static int l_get_software_version(lua_State *L) { LuaCommands* commands = LuaCommands::commandsFromLua(L); return commands->get_software_version(L); } int LuaCommands::get_software_version(lua_State *L) { if (!lua_istable(L, 1)) { return luaL_error(L, "get_software_version requires a table parameter."); } lua_pushvalue(L, 1); JID to(luatable_asstring(L, "to")); if (!to.isValid()) { return luaL_error(L, "invalid JID."); } int timeout = luatable_asint(L, "timeout"); if (timeout == 0) { return luaL_error(L, "invalid timeout."); } int successCallback = luatable_asfunction(L, "success_callback"); int failureCallback = luatable_asfunction(L, "failure_callback"); int timeoutCallback = luatable_asfunction(L, "timeout_callback"); GetSoftwareVersionRequest::ref request = GetSoftwareVersionRequest::create(to, client_->getIQRouter()); Timer::ref timer = timerFactory_->createTimer(timeout * 1000); Callbacks callbacks(successCallback, failureCallback, timeoutCallback); request->onResponse.connect(boost::bind(&LuaCommands::handleSoftwareVersionResponse, this, _1, _2, false, request, timer, L, callbacks)); boost::shared_ptr<SoftwareVersion> fakePayload; ErrorPayload::ref fakeError; timer->onTick.connect(boost::bind(&LuaCommands::handleSoftwareVersionResponse, this, fakePayload, fakeError, true, request, timer, L, callbacks)); timer->start(); request->send(); return 1; } -int LuaCommands::muc_kick(lua_State *L) { - if (!lua_isstring(L, 2)) { - return luaL_error(L, "muc_kick requires a nick to kick"); - } - std::string nick = lua_tostring(L, 2); - if (!lua_isstring(L, 1)) { - return luaL_error(L, "muc_kick requires a muc to kick from"); - } - JID mucJID(lua_tostring(L, 1)); - MUC::ref muc = mucs_->getMUC(mucJID); - muc->kickOccupant(JID(mucJID.getNode(), mucJID.getDomain(), nick)); - return 0; -} - -static int l_muc_kick(lua_State *L) { - LuaCommands* commands = LuaCommands::commandsFromLua(L); - return commands->muc_kick(L); -} - static int l_store_setting(lua_State *L) { return LuaCommands::commandsFromLua(L)->store_setting(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->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_setfield(L, -2, "body"); } void LuaCommands::loadScript(boost::filesystem::path filePath) { std::cout << "Trying to load file from " << filePath << std::endl; lua_State* lua = lua_open(); luaL_openlibs(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 + std::string filename(filePath.filename()); filename += ".storage"; - boost::filesystem::path storagePath(boost::filesystem::path(path_) / stringToPath(filename)); + boost::filesystem::path storagePath(boost::filesystem::path(path_) / 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; } else { const char* error = lua_tostring(lua, -1); std::cout << "Error: " << error << std::endl; lua_pop(lua, -1); } } diff --git a/Swiftob/LuaCommands.h b/Swiftob/LuaCommands.h index c5f959d..fc743ca 100644 --- a/Swiftob/LuaCommands.h +++ b/Swiftob/LuaCommands.h @@ -1,90 +1,90 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <string> #include <vector> -#include <lua.hpp> +#include <lua.h> +#include <lauxlib.h> +#include <lualib.h> #include <boost/filesystem/fstream.hpp> #include <boost/noncopyable.hpp> #include <Swiften/Network/NetworkFactories.h> #include <Swiften/Elements/SoftwareVersion.h> #include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h> #include <Swiften/Network/Timer.h> #include <Swiftob/Commands.h> #include <Swiftob/Storage.h> using namespace Swift; /** * Yes, there's an odd naming scheme going on here for methods. * normalCamelCase methods are methods called from C++ * lower_case_methods are exposed to Lua through wrappers and * l_lower_case_functions are functions directly exposed (often calling the lower_case_methods). */ class LuaCommands { public: class LuaCommand : public Commands::Command, boost::noncopyable { public: /** Takes ownership of lua and storage.*/ LuaCommand(Commands::RoleList allowedBy, const std::string& description, lua_State* lua, Storage* storage) : Command(allowedBy, description), lua_(lua), storage_(storage) { } virtual ~LuaCommand() { lua_close(lua_); delete storage_; }; private: lua_State* lua_; Storage* storage_; }; class Callbacks { public: Callbacks(int success, int failure, int timeout) : success(success), failure(failure), timeout(timeout) {}; int success; int failure; int timeout; void erase(lua_State *L) { lua_pushnil(L); lua_rawseti(L, LUA_REGISTRYINDEX, success); lua_pushnil(L); lua_rawseti(L, LUA_REGISTRYINDEX, failure); lua_pushnil(L); lua_rawseti(L, LUA_REGISTRYINDEX, timeout); } }; LuaCommands(Commands* commands, const std::string& path, Client* client, TimerFactory* timerFactory, MUCs* mucs); - /* Public but aren't really part of the API */ + /* Public but isn'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); int store_setting(lua_State *L); int get_setting(lua_State *L); - int muc_kick(lua_State *L); static LuaCommands* commandsFromLua(lua_State *L); static Storage* storageFromLua(lua_State *L); private: void registerCommands(); void loadScript(boost::filesystem::path filePath); void messageOntoStack(Message::ref message, lua_State* L); void handleSoftwareVersionResponse(boost::shared_ptr<SoftwareVersion> version, ErrorPayload::ref error, bool timeout, GetSoftwareVersionRequest::ref request, Timer::ref timer, lua_State* L, Callbacks callbacks); private: std::string path_; boost::filesystem::path scriptsPath_; Commands* commands_; MUCs* mucs_; Client* client_; TimerFactory* timerFactory_; }; diff --git a/Swiftob/MUCs.cpp b/Swiftob/MUCs.cpp index aec821a..695cbd9 100644 --- a/Swiftob/MUCs.cpp +++ b/Swiftob/MUCs.cpp @@ -1,68 +1,61 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiftob/MUCs.h> #include <boost/bind.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <Swiften/Base/foreach.h> #include <Swiften/Client/Client.h> #include <Swiften/MUC/MUC.h> #include <Swiften/MUC/MUCManager.h> #include <Swiften/Base/String.h> #include <Swiftob/Storage.h> -using namespace Swift; - #define MUC_LIST_SETTING "muc_list" -#define NICK "default_nick" typedef std::pair<JID, MUC::ref> JIDMUCPair; MUCs::MUCs(Client* client, Storage* storage) : defaultNick_("Kanchil+") { client_ = client; storage_ = storage; - std::string storedNick = storage_->getSetting(NICK); - if (!storedNick.empty()) { - defaultNick_ = storedNick; - } client_->onConnected.connect(boost::bind(&MUCs::handleConnected, this)); } void MUCs::handleConnected() { foreach (std::string room, String::split(storage_->getSetting(MUC_LIST_SETTING), ' ')) { join(JID(room), boost::bind(&MUCs::handleInitialJoinSuccess, this), boost::bind(&MUCs::handleInitialJoinFailure, this, _1)); } } void MUCs::handleInitialJoinSuccess() { } void MUCs::handleInitialJoinFailure(const std::string&) { } void MUCs::join(const JID& room, boost::signal<void (const std::string&)>::slot_type successCallback, boost::function<void(const std::string& /*reason*/)> failureCallback) { if (contains(room)) { failureCallback("Already in room"); } mucs_[room] = client_->getMUCManager()->createMUC(room); mucs_[room]->onJoinComplete.connect(successCallback); mucs_[room]->onJoinFailed.connect(boost::bind(&MUCs::handleJoinFailed, this, room, _1, failureCallback)); mucs_[room]->joinWithContextSince(defaultNick_, boost::posix_time::microsec_clock::universal_time()); save(); } void MUCs::part(const JID& room) { if (!contains(room)) { return; } mucs_[room]->part(); } @@ -93,45 +86,35 @@ void MUCs::handleJoinFailed(const JID& muc, ErrorPayload::ref error, boost::func break; case ErrorPayload::Forbidden: errorMessage += ": "; errorMessage += "You are banned from the room"; break; case ErrorPayload::ServiceUnavailable: errorMessage += ": "; errorMessage += "The room is full"; break; case ErrorPayload::ItemNotFound: errorMessage += ": "; errorMessage += "The room does not exist"; break; default: break; } if (!error->getText().empty()) { errorMessage += " - " + error->getText(); } } mucs_.erase(muc); failureCallback(errorMessage); } void MUCs::save() { std::string concat; foreach (JIDMUCPair pair, mucs_) { concat += pair.first.toString() + " "; } storage_->saveSetting(MUC_LIST_SETTING, concat); } MUC::ref MUCs::getMUC(const JID& room) { return (mucs_.find(room) != mucs_.end()) ? mucs_[room] : MUC::ref(); } - -bool MUCs::setDefaultNick(const std::string& nick) { - JID testJID("alice", "wonderland.lit", nick); - if (testJID.isValid()) { - defaultNick_ = testJID.getResource(); - storage_->saveSetting(NICK, defaultNick_); - return true; - } - return false; -} diff --git a/Swiftob/MUCs.h b/Swiftob/MUCs.h index ecbb7a6..e727ec2 100644 --- a/Swiftob/MUCs.h +++ b/Swiftob/MUCs.h @@ -1,47 +1,47 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <vector> #include <string> #include <Swiften/JID/JID.h> #include <Swiften/Elements/Message.h> #include <Swiften/MUC/MUC.h> #include <Swiften/MUC/MUCRegistry.h> namespace Swift { class Client; class MUC; } class Storage; +using namespace Swift; + class MUCs { public: - MUCs(Swift::Client* client, Storage* storage); - void join(const Swift::JID& room, boost::signal<void (const std::string&)>::slot_type successCallback, boost::function<void(const std::string& /*reason*/)> failureCallback); - void part(const Swift::JID& room); - bool contains(const Swift::JID& room); - Swift::MUC::ref getMUC(const Swift::JID& room); - const std::string& getDefaultNick() const {return defaultNick_;} - bool setDefaultNick(const std::string& nick); + MUCs(Client* client, Storage* storage); + void join(const JID& room, boost::signal<void (const std::string&)>::slot_type successCallback, boost::function<void(const std::string& /*reason*/)> failureCallback); + void part(const JID& room); + bool contains(const JID& room); + MUC::ref getMUC(const JID& room); private: void handleConnected(); - void handleJoinFailed(const Swift::JID& room, Swift::ErrorPayload::ref error, boost::function<void(const std::string& /*reason*/)> failureCallback); + void handleJoinFailed(const JID& room, ErrorPayload::ref error, boost::function<void(const std::string& /*reason*/)> failureCallback); void handleInitialJoinSuccess(); void handleInitialJoinFailure(const std::string&); void save(); private: - Swift::MUCRegistry registry_; - std::map<Swift::JID, Swift::MUC::ref> mucs_; - Swift::Client* client_; + MUCRegistry registry_; + std::map<JID, MUC::ref> mucs_; + Client* client_; Storage* storage_; std::string defaultNick_; }; diff --git a/Swiftob/SConscript b/Swiftob/SConscript index a830b84..bb056bb 100644 --- a/Swiftob/SConscript +++ b/Swiftob/SConscript @@ -1,25 +1,19 @@ Import("env") -if env["SCONS_STAGE"] == "build" and not GetOption("help") and not env.get("HAVE_LUA", 0) : - print "Warning: Lua was not found. Swiftob will not be built." - if "Sluift" in env["PROJECTS"] : - env["PROJECTS"].remove("Sluift") -elif env["SCONS_STAGE"] == "build": +if env["SCONS_STAGE"] == "build": myenv = env.Clone() - # Too many compile warnings here at the moment - myenv.Replace(CXXFLAGS = [flag for flag in env["CXXFLAGS"] if flag != "-Weverything"]) - myenv.UseFlags(myenv.get("LUA_FLAGS", {})) - myenv.UseFlags(myenv["SWIFTEN_FLAGS"]) - myenv.UseFlags(myenv["SWIFTEN_DEP_FLAGS"]) + myenv.MergeFlags(myenv.get("LUA_FLAGS", {})) + myenv.MergeFlags(myenv["SWIFTEN_FLAGS"]) + myenv.MergeFlags(myenv["SWIFTEN_DEP_FLAGS"]) sources = [ - "linit.c", + "linit.cpp", "Swiftob.cpp", "Users.cpp", "Commands.cpp", "MUCs.cpp", "Storage.cpp", "LuaCommands.cpp", "main.cpp" ] swiftob = myenv.Program("swiftob", sources) diff --git a/Swiftob/Storage.cpp b/Swiftob/Storage.cpp index 5311d82..47d0619 100644 --- a/Swiftob/Storage.cpp +++ b/Swiftob/Storage.cpp @@ -1,49 +1,47 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiftob/Storage.h> -#include <boost/filesystem/operations.hpp> - #include <Swiften/Base/String.h> #include <Swiften/Base/ByteArray.h> #include <Swiften/Base/foreach.h> typedef std::pair<std::string, std::string> Strings; Storage::Storage(const std::string& path) : settingsPath_(boost::filesystem::path(path)) { load(); } Storage::Storage(const boost::filesystem::path& path) : settingsPath_(path) { load(); } void Storage::load() { if (boost::filesystem::exists(settingsPath_)) { Swift::ByteArray data; - Swift::readByteArrayFromFile(data, settingsPath_); + Swift::readByteArrayFromFile(data, settingsPath_.string()); foreach (std::string line, Swift::String::split(Swift::byteArrayToString(data), '\n')) { std::pair<std::string, std::string> pair = Swift::String::getSplittedAtFirst(line, '\t'); settings_[pair.first] = pair.second; } } } void Storage::saveSetting(const std::string& setting, const std::string& value) { settings_[setting] = value; std::string settingsString; foreach(Strings pair, settings_) { settingsString += pair.first + '\t' + pair.second + '\n'; } boost::filesystem::ofstream file(settingsPath_); file << settingsString; file.close(); } std::string Storage::getSetting(const std::string& setting) { return settings_[setting]; } diff --git a/Swiftob/Swiftob.cpp b/Swiftob/Swiftob.cpp index 1578e34..331e55e 100644 --- a/Swiftob/Swiftob.cpp +++ b/Swiftob/Swiftob.cpp @@ -1,139 +1,118 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiftob/Swiftob.h> #include <string> #include <iostream> #include <boost/bind.hpp> #include <Swiften/JID/JID.h> #include <Swiften/Base/String.h> #include <Swiften/Presence/PresenceSender.h> #include <Swiftob/Users.h> #include <Swiftob/Storage.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>(); + std::string path; + 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(); + storage_ = new Storage(boost::filesystem::path(path) / "settings.txt"); + mucs_ = new MUCs(client_, storage_); + users_ = new Users(client_, mucs_); + commands_ = new Commands(users_, client_, storage_, mucs_); + lua_ = new LuaCommands(commands_, path, client_, networkFactories_.getTimerFactory(), mucs_); 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; } client_->setAlwaysTrustCertificates(); client_->setSoftwareVersion("Swiftob", "pregit", ""); client_->connect(); eventLoop_.run(); } -void Swiftob::init() { - delete mucs_; - mucs_ = new MUCs(client_, storage_); - delete users_; - users_ = new Users(client_, mucs_); - delete commands_; - commands_ = new Commands(users_, client_, storage_, mucs_); - commands_->onRestartRequested.connect(boost::bind(&Swiftob::handleRestartRequested, this)); - delete lua_; - lua_ = new LuaCommands(commands_, path_, client_, networkFactories_.getTimerFactory(), mucs_); -} - -void Swiftob::handleRestartRequested() { - client_->disconnect(); - 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::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_; delete mucs_; delete client_; } int Swiftob::exec() { return 0; } diff --git a/Swiftob/Swiftob.h b/Swiftob/Swiftob.h index 36091e4..ad4e9b8 100644 --- a/Swiftob/Swiftob.h +++ b/Swiftob/Swiftob.h @@ -1,52 +1,49 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <boost/program_options/variables_map.hpp> #include <boost/program_options/options_description.hpp> #include <boost/shared_ptr.hpp> #include <string> #include <Swiften/Base/Platform.h> #include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/Base/boost_bsignals.h> #include <Swiften/Client/Client.h> #include <Swiften/Network/BoostNetworkFactories.h> #include <Swiftob/Commands.h> #include <Swiftob/LuaCommands.h> namespace po = boost::program_options; class Users; class Storage; class Swiftob { public: Swiftob(const po::variables_map& options); static po::options_description getOptionsDescription(); int exec(); ~Swiftob(); private: - void init(); - void handleRestartRequested(); void handleConnected(); void handleDisconnected(const boost::optional<Swift::ClientError>&); void handleMessageReceived(Swift::Message::ref); private: const po::variables_map options_; Swift::SimpleEventLoop eventLoop_; Swift::BoostNetworkFactories networkFactories_; Commands* commands_; LuaCommands* lua_; Storage* storage_; MUCs* mucs_; bool quitting_; Users* users_; - std::string path_; Swift::Client* client_; }; diff --git a/Swiftob/Users.cpp b/Swiftob/Users.cpp index 868efb0..09173cc 100644 --- a/Swiftob/Users.cpp +++ b/Swiftob/Users.cpp @@ -1,48 +1,46 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #include <Swiftob/Users.h> #include <iostream> #include <Swiften/Base/foreach.h> #include <Swiften/Client/Client.h> #include <Swiftob/MUCs.h> -using namespace Swift; - Users::Users(Client* client, MUCs* mucs) { client_ = client; mucs_ = mucs; } /* TODO: Store in roster */ void Users::clearAll() { users_.clear(); } void Users::addUser(const User& user) { users_.push_back(user); } Users::User::Role Users::getRoleForSender(Message::ref message) { JID jid = message->getFrom(); MUC::ref muc = mucs_->getMUC(message->getFrom().toBare()); if (muc && muc->hasOccupant(message->getFrom().getResource())) { MUCOccupant occupant = muc->getOccupant(message->getFrom().getResource()); if (occupant.getRealJID()) { jid = occupant.getRealJID().get(); } } foreach (User user, users_) { if (user.getJID().equals(jid.toBare(), JID::WithoutResource)) { return user.getRole(); } } return User::Unknown; } diff --git a/Swiftob/Users.h b/Swiftob/Users.h index a78beed..0acc330 100644 --- a/Swiftob/Users.h +++ b/Swiftob/Users.h @@ -1,47 +1,49 @@ /* * Copyright (c) 2011 Kevin Smith * Licensed under the GNU General Public License v3. * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <vector> #include <string> #include <Swiften/JID/JID.h> #include <Swiften/Elements/Message.h> namespace Swift { class Client; } class MUCs; +using namespace Swift; + class Users { public: class User { public: /* If you add a role here, edit the role lists in Commands.cpp*/ enum Role {Unknown, Owner}; - User(const Swift::JID& jid, Role role) : jid_(jid), role_(role) {} + User(const JID& jid, Role role) : jid_(jid), role_(role) {} Role getRole() {return role_;} Swift::JID getJID() {return jid_;} private: Swift::JID jid_; Role role_; }; public: - Users(Swift::Client* client, MUCs* mucs); + Users(Client* client, MUCs* mucs); void clearAll(); void addUser(const User& user); - User::Role getRoleForSender(Swift::Message::ref message); + User::Role getRoleForSender(Message::ref message); private: std::vector<User> users_; - Swift::Client* client_; + Client* client_; MUCs* mucs_; }; diff --git a/Swiftob/linit.c b/Swiftob/linit.cpp index 13c5b09..13c5b09 100644 --- a/Swiftob/linit.c +++ b/Swiftob/linit.cpp diff --git a/Swiftob/scripts/badWords.lua b/Swiftob/scripts/badWords.lua deleted file mode 100644 index 2c16214..0000000 --- a/Swiftob/scripts/badWords.lua +++ /dev/null @@ -1,15 +0,0 @@ -function bad_words(body, muc, nick, message) - words = {"sbwriel"} - print("Received line from '" .. nick .. "' in '" .. muc .. "':") - print(body) - - for _, word in pairs(words) do - if string.len(string.match(body, word)) > 0 then - --swiftob_reply_to(message, "Kicking "..nick.." for bad word "..word) - swiftob_muc_kick(muc, nick) - end - end -end - -swiftob_register_listener(bad_words) - diff --git a/Swiftob/scripts/irssiLogs.lua b/Swiftob/scripts/irssiLogs.lua deleted file mode 100644 index 3cecd9d..0000000 --- a/Swiftob/scripts/irssiLogs.lua +++ /dev/null @@ -1,23 +0,0 @@ -function irssi_log_to_file(muc, line) - filename = muc:gsub("@", "_at_") - filename = filename:gsub("%.%.", "_") - filename = filename:gsub("/", "_") - filename = filename:gsub("\\", "_") - file = io.open(filename, "a+") - if file == nil then - io.close() - else - file:write(line) - file:write("\n") - file:close() - end - -end - -function irssi_log_message(body, muc, nick, message) - time = os.date("%H:%M") - irssi_log_to_file(muc, time.." <"..nick.."> "..body) -end - -swiftob_register_listener(irssi_log_message) - diff --git a/Swiftob/scripts/logAllMessages.lua b/Swiftob/scripts/logAllMessages.lua deleted file mode 100644 index a14c0f3..0000000 --- a/Swiftob/scripts/logAllMessages.lua +++ /dev/null @@ -1,6 +0,0 @@ -function log_a_message(body, muc, nick, message) - print("Received line from '" .. nick .. "' in '" .. muc .. "':") - print(body) -end - -swiftob_register_listener(log_a_message) |