summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiftob')
-rw-r--r--Swiftob/Commands.cpp54
-rw-r--r--Swiftob/Commands.h10
-rw-r--r--Swiftob/LuaCommands.cpp63
-rw-r--r--Swiftob/LuaCommands.h8
-rw-r--r--Swiftob/MUCs.cpp17
-rw-r--r--Swiftob/MUCs.h22
-rw-r--r--Swiftob/SConscript16
-rw-r--r--Swiftob/Storage.cpp4
-rw-r--r--Swiftob/Swiftob.cpp35
-rw-r--r--Swiftob/Swiftob.h3
-rw-r--r--Swiftob/Users.cpp2
-rw-r--r--Swiftob/Users.h10
-rw-r--r--Swiftob/linit.cpp (renamed from Swiftob/linit.c)0
-rw-r--r--Swiftob/scripts/badWords.lua15
-rw-r--r--Swiftob/scripts/irssiLogs.lua23
-rw-r--r--Swiftob/scripts/logAllMessages.lua6
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)