From ab8a950661d42bc9fd381d7eca027a14b96e10a7 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 25 Nov 2015 21:52:29 +0100 Subject: [PATCH] Fix various small Slack bugs --- spectrum/src/frontends/slack/SlackAPI.cpp | 20 +++-- spectrum/src/frontends/slack/SlackAPI.h | 2 +- spectrum/src/frontends/slack/SlackSession.cpp | 76 ++++++++++++++++--- spectrum/src/frontends/slack/SlackSession.h | 2 +- src/SQLite3Backend.cpp | 13 ++-- 5 files changed, 89 insertions(+), 24 deletions(-) diff --git a/spectrum/src/frontends/slack/SlackAPI.cpp b/spectrum/src/frontends/slack/SlackAPI.cpp index 36d0456c..8977faf2 100644 --- a/spectrum/src/frontends/slack/SlackAPI.cpp +++ b/spectrum/src/frontends/slack/SlackAPI.cpp @@ -254,19 +254,25 @@ void SlackAPI::getSlackUserInfo(HTTPRequest *req, bool ok, rapidjson::Document & return; } -std::string &SlackAPI::SlackObjectToPlainText(std::string &object, bool isChannel) { +std::string SlackAPI::SlackObjectToPlainText(const std::string &object, bool isChannel, bool returnName) { + std::string ret = object; if (isChannel) { - if (object[0] == '<') { - object = object.substr(2, object.size() - 3); + if (ret[0] == '<') { + ret = ret.substr(2, ret.size() - 3); } } else { - if (object[0] == '<') { - object = object.substr(1, object.size() - 2); - object = object.substr(object.find("|") + 1); + if (ret[0] == '<') { + ret = ret.substr(1, ret.size() - 2); + if (returnName) { + ret = ret.substr(0, ret.find("|")); + } + else { + ret = ret.substr(ret.find("|") + 1); + } } } - return object; + return ret; } diff --git a/spectrum/src/frontends/slack/SlackAPI.h b/spectrum/src/frontends/slack/SlackAPI.h index c71d1c54..d7cf3600 100644 --- a/spectrum/src/frontends/slack/SlackAPI.h +++ b/spectrum/src/frontends/slack/SlackAPI.h @@ -84,7 +84,7 @@ class SlackAPI : public HTTPRequestQueue { static void getSlackChannelInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map &channels); static void getSlackImInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map &ims); static void getSlackUserInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map &users); - static std::string &SlackObjectToPlainText(std::string &object, bool isChannel = false); + static std::string SlackObjectToPlainText(const std::string &object, bool isChannel = false, bool returnName = false); private: void handleSendMessage(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data); diff --git a/spectrum/src/frontends/slack/SlackSession.cpp b/spectrum/src/frontends/slack/SlackSession.cpp index da51ca79..82a35067 100644 --- a/spectrum/src/frontends/slack/SlackSession.cpp +++ b/spectrum/src/frontends/slack/SlackSession.cpp @@ -48,7 +48,7 @@ SlackSession::SlackSession(Component *component, StorageBackend *storageBackend, m_rtm = new SlackRTM(component, storageBackend, uinfo); m_rtm->onRTMStarted.connect(boost::bind(&SlackSession::handleRTMStarted, this)); - m_rtm->onMessageReceived.connect(boost::bind(&SlackSession::handleMessageReceived, this, _1, _2, _3)); + m_rtm->onMessageReceived.connect(boost::bind(&SlackSession::handleMessageReceived, this, _1, _2, _3, false)); } @@ -70,7 +70,7 @@ void SlackSession::sendMessage(boost::shared_ptr message) { m_rtm->getAPI()->sendMessage(message->getFrom().getResource(), channel, message->getBody()); } -void SlackSession::handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message) { +void SlackSession::handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message, bool quiet) { if (m_ownerChannel != channel) { std::string to = m_channel2jid[channel]; if (!to.empty()) { @@ -96,9 +96,9 @@ void SlackSession::handleMessageReceived(const std::string &channel, const std:: // .spectrum2 join.room BotName #room irc.freenode.net channel if (args.size() == 6) { std::string &name = args[2]; - std::string &legacyRoom = SlackAPI::SlackObjectToPlainText(args[3], true); - std::string &legacyServer = SlackAPI::SlackObjectToPlainText(args[4]); - std::string &slackChannel = SlackAPI::SlackObjectToPlainText(args[5], true); + std::string legacyRoom = SlackAPI::SlackObjectToPlainText(args[3], true); + std::string legacyServer = SlackAPI::SlackObjectToPlainText(args[4]); + std::string slackChannel = SlackAPI::SlackObjectToPlainText(args[5], true); m_uinfo.uin = name; m_storageBackend->setUser(m_uinfo); @@ -122,8 +122,62 @@ void SlackSession::handleMessageReceived(const std::string &channel, const std:: presence->addPayload(boost::shared_ptr(new Swift::MUCPayload())); m_component->getFrontend()->onPresenceReceived(presence); - std::string msg; - msg += "Spectrum 2 is now joining the room. To leave the room later to disable transporting, you can use `.spectrum2 leave.room #SlackChannel`."; + if (!quiet) { + std::string msg; + msg += "Spectrum 2 is now joining the room. To leave the room later to disable transporting, you can use `.spectrum2 leave.room #" + SlackAPI::SlackObjectToPlainText(args[5], true, true) + "`."; + m_rtm->sendMessage(m_ownerChannel, msg); + } + } + } + else if (args[1] == "leave.room") { + // .spectrum2 leave.room channel + if (args.size() == 3) { + std::string slackChannel = SlackAPI::SlackObjectToPlainText(args[2], true); + std::string to = m_channel2jid[slackChannel]; + if (to.empty()) { + m_rtm->sendMessage(m_ownerChannel, "Spectrum 2 is not configured to transport this Slack channel."); + return; + } + + std::string rooms = ""; + int type = (int) TYPE_STRING; + m_storageBackend->getUserSetting(m_uinfo.id, "rooms", type, rooms); + + std::vector commands; + boost::split(commands, rooms, boost::is_any_of("\n")); + rooms = ""; + + BOOST_FOREACH(const std::string &command, commands) { + if (command.size() > 5) { + std::vector args2; + boost::split(args2, command, boost::is_any_of(" ")); + if (args2.size() == 6) { + if (slackChannel != SlackAPI::SlackObjectToPlainText(args2[5], true)) { + rooms += command + "\n"; + } + } + } + } + + m_storageBackend->updateUserSetting(m_uinfo.id, "rooms", rooms); + + Swift::Presence::ref presence = Swift::Presence::create(); + presence->setFrom(Swift::JID("", m_uinfo.jid, "default")); + presence->setTo(Swift::JID(to + "/" + m_uinfo.uin)); + presence->setType(Swift::Presence::Unavailable); + presence->addPayload(boost::shared_ptr(new Swift::MUCPayload())); + m_component->getFrontend()->onPresenceReceived(presence); + } + } + else if (args[1] == "list.rooms") { + // .spectrum2 list.rooms + if (args.size() == 2) { + std::string rooms = ""; + int type = (int) TYPE_STRING; + m_storageBackend->getUserSetting(m_uinfo.id, "rooms", type, rooms); + + std::string msg = "Spectrum 2 is configured for following channels:\\n"; + msg += "```" + rooms + "```"; m_rtm->sendMessage(m_ownerChannel, msg); } } @@ -132,6 +186,8 @@ void SlackSession::handleMessageReceived(const std::string &channel, const std:: msg = "Following commands are supported:\\n"; msg += "```.spectrum2 help``` Shows this help message.\\n"; msg += "```.spectrum2 join.room <3rdPartyBotName> <#3rdPartyRoom> <3rdPartyServer> <#SlackChannel>``` Starts transport between 3rd-party room and Slack channel."; + msg += "```.spectrum2 leave.room <#SlackChannel>``` Leaves the 3rd-party room connected with the given Slack channel."; + msg += "```.spectrum2 list.rooms``` List all the transported rooms."; m_rtm->sendMessage(m_ownerChannel, msg); } else { @@ -164,8 +220,10 @@ void SlackSession::handleImOpen(HTTPRequest *req, bool ok, rapidjson::Document & boost::split(commands, rooms, boost::is_any_of("\n")); BOOST_FOREACH(const std::string &command, commands) { - LOG4CXX_INFO(logger, m_uinfo.jid << ": Sending command from storage: " << command); - handleMessageReceived(m_ownerChannel, "owner", command); + if (command.size() > 5) { + LOG4CXX_INFO(logger, m_uinfo.jid << ": Sending command from storage: " << command); + handleMessageReceived(m_ownerChannel, "owner", command, true); + } } } } diff --git a/spectrum/src/frontends/slack/SlackSession.h b/spectrum/src/frontends/slack/SlackSession.h index 98dc86d0..46c2c771 100644 --- a/spectrum/src/frontends/slack/SlackSession.h +++ b/spectrum/src/frontends/slack/SlackSession.h @@ -51,7 +51,7 @@ class SlackSession { private: void handleRTMStarted(); - void handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message); + void handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message, bool quiet); void handleImOpen(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data); private: diff --git a/src/SQLite3Backend.cpp b/src/SQLite3Backend.cpp index 6a1b907e..a8edc1e4 100644 --- a/src/SQLite3Backend.cpp +++ b/src/SQLite3Backend.cpp @@ -120,7 +120,7 @@ bool SQLite3Backend::connect() { if (createDatabase() == false) return false; - PREP_STMT(m_setUser, "INSERT OR REPLACE INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES (?, ?, ?, ?, ?, DATETIME('NOW'), ?)"); + PREP_STMT(m_setUser, "INSERT OR REPLACE INTO " + m_prefix + "users (id, jid, uin, password, language, encoding, last_login, vip) VALUES ((SELECT id FROM " + m_prefix + "users WHERE jid = ?), ?, ?, ?, ?, ?, DATETIME('NOW'), ?)"); PREP_STMT(m_getUser, "SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid=?"); PREP_STMT(m_removeUser, "DELETE FROM " + m_prefix + "users WHERE id=?"); @@ -224,11 +224,12 @@ bool SQLite3Backend::exec(const std::string &query) { void SQLite3Backend::setUser(const UserInfo &user) { sqlite3_reset(m_setUser); sqlite3_bind_text(m_setUser, 1, user.jid.c_str(), -1, SQLITE_STATIC); - sqlite3_bind_text(m_setUser, 2, user.uin.c_str(), -1, SQLITE_STATIC); - sqlite3_bind_text(m_setUser, 3, user.password.c_str(), -1, SQLITE_STATIC); - sqlite3_bind_text(m_setUser, 4, user.language.c_str(), -1, SQLITE_STATIC); - sqlite3_bind_text(m_setUser, 5, user.encoding.c_str(), -1, SQLITE_STATIC); - sqlite3_bind_int (m_setUser, 6, user.vip); + sqlite3_bind_text(m_setUser, 2, user.jid.c_str(), -1, SQLITE_STATIC); + sqlite3_bind_text(m_setUser, 3, user.uin.c_str(), -1, SQLITE_STATIC); + sqlite3_bind_text(m_setUser, 4, user.password.c_str(), -1, SQLITE_STATIC); + sqlite3_bind_text(m_setUser, 5, user.language.c_str(), -1, SQLITE_STATIC); + sqlite3_bind_text(m_setUser, 6, user.encoding.c_str(), -1, SQLITE_STATIC); + sqlite3_bind_int (m_setUser, 7, user.vip); if(sqlite3_step(m_setUser) != SQLITE_DONE) { LOG4CXX_ERROR(logger, "setUser query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));