summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiftob')
-rw-r--r--Swiftob/Commands.cpp9
-rw-r--r--Swiftob/LuaCommands.cpp6
-rw-r--r--Swiftob/Swiftob.cpp12
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_;