diff --git a/include/transport/Frontend.h b/include/transport/Frontend.h index a5f7acfb..fa3d0b7a 100644 --- a/include/transport/Frontend.h +++ b/include/transport/Frontend.h @@ -94,6 +94,7 @@ class Frontend { virtual std::string setOAuth2Code(const std::string &code, const std::string &state) { return "OAuth2 code is not needed for this frontend."; } virtual std::string getOAuth2URL(const std::vector &args) { return ""; } virtual std::string getRegistrationFields() { return "Jabber ID\n3rd-party network username\n3rd-party network password"; } + virtual bool handleAdminMessage(Swift::Message::ref /*message*/) { return false; } boost::signal onVCardRequired; boost::signal vcard)> onVCardUpdated; diff --git a/libtransport/AdminInterface.cpp b/libtransport/AdminInterface.cpp index 03a82a7c..d0b7c95f 100644 --- a/libtransport/AdminInterface.cpp +++ b/libtransport/AdminInterface.cpp @@ -324,6 +324,9 @@ void AdminInterface::handleQuery(Swift::Message::ref message) { std::string fields = m_component->getFrontend()->getRegistrationFields(); message->setBody(fields); } + else if (m_component->getFrontend()->handleAdminMessage(message)) { + LOG4CXX_INFO(logger, "Message handled by frontend"); + } else if (message->getBody().find("help") == 0) { std::string help; help += "General:\n"; diff --git a/spectrum/src/frontends/slack/SlackAPI.cpp b/spectrum/src/frontends/slack/SlackAPI.cpp index f5625c57..8f970f61 100644 --- a/spectrum/src/frontends/slack/SlackAPI.cpp +++ b/spectrum/src/frontends/slack/SlackAPI.cpp @@ -141,6 +141,12 @@ std::string SlackAPI::getChannelId(HTTPRequest *req, bool ok, rapidjson::Documen return id.GetString(); } +void SlackAPI::channelsList( HTTPRequest::Callback callback) { + std::string url = "https://slack.com/api/channels.list?token=" + Util::urlencode(m_token); + HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url, callback); + queueRequest(req); +} + void SlackAPI::channelsCreate(const std::string &name, HTTPRequest::Callback callback) { std::string url = "https://slack.com/api/channels.create?name=" + Util::urlencode(name) + "&token=" + Util::urlencode(m_token); HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url, callback); diff --git a/spectrum/src/frontends/slack/SlackAPI.h b/spectrum/src/frontends/slack/SlackAPI.h index 97c5e7f7..32e6b9f3 100644 --- a/spectrum/src/frontends/slack/SlackAPI.h +++ b/spectrum/src/frontends/slack/SlackAPI.h @@ -76,6 +76,8 @@ class SlackAPI : public HTTPRequestQueue { std::string getOwnerId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data); void channelsCreate(const std::string &name, HTTPRequest::Callback callback); + void channelsList(HTTPRequest::Callback callback); + void imOpen(const std::string &uid, HTTPRequest::Callback callback); std::string getChannelId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data); diff --git a/spectrum/src/frontends/slack/SlackFrontend.cpp b/spectrum/src/frontends/slack/SlackFrontend.cpp index 06cf45d0..7d07bbe6 100644 --- a/spectrum/src/frontends/slack/SlackFrontend.cpp +++ b/spectrum/src/frontends/slack/SlackFrontend.cpp @@ -126,6 +126,10 @@ std::string SlackFrontend::getRegistrationFields() { return "Slack team name\n3rd-party network username\n3rd-party network password"; } +bool SlackFrontend::handleAdminMessage(Swift::Message::ref message) { + return static_cast(m_userManager)->handleAdminMessage(message); +} + void SlackFrontend::disconnectFromServer() { } diff --git a/spectrum/src/frontends/slack/SlackFrontend.h b/spectrum/src/frontends/slack/SlackFrontend.h index 622047a2..f0f4f30f 100644 --- a/spectrum/src/frontends/slack/SlackFrontend.h +++ b/spectrum/src/frontends/slack/SlackFrontend.h @@ -68,6 +68,7 @@ namespace Transport { virtual std::string setOAuth2Code(const std::string &code, const std::string &state); virtual std::string getOAuth2URL(const std::vector &args); virtual std::string getRegistrationFields(); + virtual bool handleAdminMessage(Swift::Message::ref message); void handleMessage(boost::shared_ptr message); diff --git a/spectrum/src/frontends/slack/SlackSession.cpp b/spectrum/src/frontends/slack/SlackSession.cpp index a6874ee7..35dccaf4 100644 --- a/spectrum/src/frontends/slack/SlackSession.cpp +++ b/spectrum/src/frontends/slack/SlackSession.cpp @@ -56,10 +56,16 @@ SlackSession::SlackSession(Component *component, StorageBackend *storageBackend, m_onlineBuddiesTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(20000); m_onlineBuddiesTimer->onTick.connect(boost::bind(&SlackSession::sendOnlineBuddies, this)); + + int type = (int) TYPE_STRING; + std::string token; + m_storageBackend->getUserSetting(m_uinfo.id, "access_token", type, token); + m_api = new SlackAPI(m_component, token); } SlackSession::~SlackSession() { delete m_rtm; + delete m_api; m_onlineBuddiesTimer->stop(); } @@ -150,12 +156,11 @@ void SlackSession::setPurpose(const std::string &purpose, const std::string &cha m_rtm->getAPI()->setPurpose(ch, purpose); } -void SlackSession::handleJoinMessage(const std::string &message, std::vector &args, bool quiet) { - // .spectrum2 join.room BotName #room irc.freenode.net channel +void SlackSession::joinRoom(std::vector args) { 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 = args[3]; + std::string &legacyServer = args[4]; + std::string &slackChannel = args[5]; std::string to = legacyRoom + "%" + legacyServer + "@" + m_component->getJID().toString(); if (!CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true)) { @@ -169,16 +174,6 @@ void SlackSession::handleJoinMessage(const std::string &message, std::vectorgetUserSetting(m_uinfo.id, "rooms", type, rooms); - rooms += message + "\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 + "/" + name)); @@ -187,12 +182,37 @@ void SlackSession::handleJoinMessage(const std::string &message, std::vectorgetFrontend()->onPresenceReceived(presence); m_onlineBuddiesTimer->start(); +} - 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); +void SlackSession::handleJoinRoomCreate(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::vector args) { + std::string channelId = m_api->getChannelId(req, ok, resp, data); + if (channelId.empty()) { + LOG4CXX_INFO(logger, args[1] << ": Error creating channel " << args[5] << "."); + return; } + + args[5] = channelId; + joinRoom(args); +} + +void SlackSession::handleJoinRoomList(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::vector args) { + std::map channels; + SlackAPI::getSlackChannelInfo(req, ok, resp, data, channels); + + if (channels.find(args[5]) != channels.end()) { + LOG4CXX_INFO(logger, args[1] << ": Channel " << args[5] << " already exists. Joining the room."); + args[5] = channels[args[5]].id; + joinRoom(args); + } + else { + LOG4CXX_INFO(logger, args[1] << ": Channel " << args[5] << " does not exit. Creating it."); + m_api->channelsCreate(args[5], boost::bind(&SlackSession::handleJoinRoomCreate, this, _1, _2, _3, _4, args)); + } +} + +void SlackSession::handleJoinMessage(const std::string &message, std::vector &args, bool quiet) { + LOG4CXX_INFO(logger, args[1] << ": Going to join the room, checking the ID of channel " << args[5]); + m_api->channelsList(boost::bind(&SlackSession::handleJoinRoomList, this, _1, _2, _3, _4, args)); } void SlackSession::handleLeaveMessage(const std::string &message, std::vector &args, bool quiet) { diff --git a/spectrum/src/frontends/slack/SlackSession.h b/spectrum/src/frontends/slack/SlackSession.h index 608d2939..fd08468d 100644 --- a/spectrum/src/frontends/slack/SlackSession.h +++ b/spectrum/src/frontends/slack/SlackSession.h @@ -60,14 +60,18 @@ class SlackSession { void handleDisconnected(); void handleConnected(); + void handleJoinMessage(const std::string &message, std::vector &args, bool quiet = false); + void handleLeaveMessage(const std::string &message, std::vector &args, bool quiet = false); + void handleRegisterMessage(const std::string &message, std::vector &args, bool quiet = false); + private: void handleRTMStarted(); void handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message, const std::string &ts, bool quiet); void handleImOpen(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data); - void handleJoinMessage(const std::string &message, std::vector &args, bool quiet = false); - void handleLeaveMessage(const std::string &message, std::vector &args, bool quiet = false); - void handleRegisterMessage(const std::string &message, std::vector &args, bool quiet = false); + void joinRoom(std::vector args); + void handleJoinRoomCreate(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::vector args); + void handleJoinRoomList(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::vector args); void sendOnlineBuddies(); @@ -86,6 +90,7 @@ class SlackSession { std::map m_onlineBuddies; bool m_disconnected; std::string m_ownerId; + SlackAPI *m_api; }; } diff --git a/spectrum/src/frontends/slack/SlackUserManager.cpp b/spectrum/src/frontends/slack/SlackUserManager.cpp index 414668a9..83106edb 100644 --- a/spectrum/src/frontends/slack/SlackUserManager.cpp +++ b/spectrum/src/frontends/slack/SlackUserManager.cpp @@ -29,6 +29,8 @@ #include "transport/StorageBackend.h" #include "transport/Logging.h" +#include + namespace Transport { DEFINE_LOGGER(logger, "SlackUserManager"); @@ -102,5 +104,52 @@ void SlackUserManager::handleUserCreated(User *user) { static_cast(user)->getSession()->handleConnected(); } +bool SlackUserManager::handleAdminMessage(Swift::Message::ref message) { + if (message->getBody().find("get_user_configuration") == 0) { +// std::string body = message->getBody(); +// std::vector args; +// boost::split(args, body, boost::is_any_of(" ")); +// if (args.size() == 2) { +// UserInfo uinfo; +// if (!m_storageBackend->getUser(args[1], uinfo)) { +// message->setBody("Error: Unknown user"); +// return true; +// } +// +// std::string rooms = ""; +// int type = (int) TYPE_STRING; +// m_storageBackend->getUserSetting(uinfo.id, "rooms", type, rooms); +// +// m_storageBackend->getUserSetting(uinfo.id, "slack_channel", type, m_slackChannel); +// } + } + else if (message->getBody().find("join_room ") == 0) { + std::string body = message->getBody(); + std::vector args; + boost::split(args, body, boost::is_any_of(" ")); + if (args.size() == 6) { + UserInfo uinfo; + if (!m_storageBackend->getUser(args[1], uinfo)) { + message->setBody("Error: Unknown user"); + return true; + } + + std::string rooms = ""; + int type = (int) TYPE_STRING; + m_storageBackend->getUserSetting(uinfo.id, "rooms", type, rooms); + rooms += message->getBody() + "\n"; + m_storageBackend->updateUserSetting(uinfo.id, "rooms", rooms); + + SlackUser *user = static_cast(getUser(args[1])); + if (user) { + user->getSession()->handleJoinMessage("", args, true); + } + message->setBody("Joined the room"); + return true; + } + } + return false; +} + } diff --git a/spectrum/src/frontends/slack/SlackUserManager.h b/spectrum/src/frontends/slack/SlackUserManager.h index 103ae802..2a928eda 100644 --- a/spectrum/src/frontends/slack/SlackUserManager.h +++ b/spectrum/src/frontends/slack/SlackUserManager.h @@ -62,6 +62,8 @@ class SlackUserManager : public UserManager { SlackSession *moveTempSession(const std::string &user); void moveTempSession(const std::string &user, SlackSession *session); + bool handleAdminMessage(Swift::Message::ref message); + private: void handleUserCreated(User *user); diff --git a/spectrum/src/frontends/slack/SlackUserRegistration.cpp b/spectrum/src/frontends/slack/SlackUserRegistration.cpp index 432a2830..95854924 100644 --- a/spectrum/src/frontends/slack/SlackUserRegistration.cpp +++ b/spectrum/src/frontends/slack/SlackUserRegistration.cpp @@ -175,7 +175,7 @@ std::string SlackUserRegistration::handleOAuth2Code(const std::string &code, con m_component->getFrontend()->reconnectUser(user.jid); - return ""; + return "Registered as " + domain; } bool SlackUserRegistration::doUserRegistration(const UserInfo &row) { diff --git a/spectrum_manager/src/server.cpp b/spectrum_manager/src/server.cpp index 8e6aed28..b8993d2d 100644 --- a/spectrum_manager/src/server.cpp +++ b/spectrum_manager/src/server.cpp @@ -396,7 +396,20 @@ void Server::serve_oauth2(struct mg_connection *conn, struct http_message *hm) { std::string code = get_http_var(hm, "code"); std::string state = get_http_var(hm, "state"); - send_command(instance, "set_oauth2_code " + code + " " + state); + std::string response = send_command(instance, "set_oauth2_code " + code + " " + state); + if (response.find("Registered as ") == 0) { + std::vector args; + boost::split(args, response, boost::is_any_of(" ")); + if (args.size() == 3) { + Server:session *session = get_session(hm); + UserInfo info; + m_storage->getUser(session->user, info); + std::string username = ""; + int type = (int) TYPE_STRING; + m_storage->getUserSetting(info.id, instance, type, username); + m_storage->updateUserSetting(info.id, instance, args[2]); + } + } redirect_to(conn, hm, "/instances/"); } diff --git a/tests/start.py b/tests/start.py index 7fb3e211..6cd66c05 100644 --- a/tests/start.py +++ b/tests/start.py @@ -195,7 +195,7 @@ configurations = [] configurations.append(LibcommuniServerModeSingleServerConf()) configurations.append(LibcommuniServerModeConf()) configurations.append(JabberServerModeConf()) -configurations.append(JabberSlackServerModeConf()) +#configurations.append(JabberSlackServerModeConf()) configurations.append(TwitterServerModeConf()) exitcode = 0