Slack: Send real team name chosen by user to Web interface, create channel chosen by the user when joining the room if it does not exists

This commit is contained in:
Jan Kaluza 2016-01-26 18:55:22 +01:00
parent f231cf1a61
commit fd9c9af71b
13 changed files with 131 additions and 25 deletions

View file

@ -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<std::string> &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<void (User *, const std::string &name, unsigned int id)> onVCardRequired;
boost::signal<void (User *, boost::shared_ptr<Swift::VCard> vcard)> onVCardUpdated;

View file

@ -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";

View file

@ -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);

View file

@ -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);

View file

@ -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<SlackUserManager *>(m_userManager)->handleAdminMessage(message);
}
void SlackFrontend::disconnectFromServer() {
}

View file

@ -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<std::string> &args);
virtual std::string getRegistrationFields();
virtual bool handleAdminMessage(Swift::Message::ref message);
void handleMessage(boost::shared_ptr<Swift::Message> message);

View file

@ -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<std::string> &args, bool quiet) {
// .spectrum2 join.room BotName #room irc.freenode.net channel
void SlackSession::joinRoom(std::vector<std::string> 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::vector<std
m_jid2channel[to] = slackChannel;
m_channel2jid[slackChannel] = to;
LOG4CXX_INFO(logger, "Setting transport between " << to << " and " << slackChannel);
if (!quiet) {
std::string rooms = "";
int type = (int) TYPE_STRING;
m_storageBackend->getUserSetting(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::vector<std
m_component->getFrontend()->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<std::string> 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<std::string> args) {
std::map<std::string, SlackChannelInfo> 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<std::string> &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<std::string> &args, bool quiet) {

View file

@ -60,14 +60,18 @@ class SlackSession {
void handleDisconnected();
void handleConnected();
void handleJoinMessage(const std::string &message, std::vector<std::string> &args, bool quiet = false);
void handleLeaveMessage(const std::string &message, std::vector<std::string> &args, bool quiet = false);
void handleRegisterMessage(const std::string &message, std::vector<std::string> &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<std::string> &args, bool quiet = false);
void handleLeaveMessage(const std::string &message, std::vector<std::string> &args, bool quiet = false);
void handleRegisterMessage(const std::string &message, std::vector<std::string> &args, bool quiet = false);
void joinRoom(std::vector<std::string> args);
void handleJoinRoomCreate(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::vector<std::string> args);
void handleJoinRoomList(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::vector<std::string> args);
void sendOnlineBuddies();
@ -86,6 +90,7 @@ class SlackSession {
std::map<std::string, std::string> m_onlineBuddies;
bool m_disconnected;
std::string m_ownerId;
SlackAPI *m_api;
};
}

View file

@ -29,6 +29,8 @@
#include "transport/StorageBackend.h"
#include "transport/Logging.h"
#include <boost/algorithm/string.hpp>
namespace Transport {
DEFINE_LOGGER(logger, "SlackUserManager");
@ -102,5 +104,52 @@ void SlackUserManager::handleUserCreated(User *user) {
static_cast<SlackUser *>(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<std::string> 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<std::string> 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<SlackUser *>(getUser(args[1]));
if (user) {
user->getSession()->handleJoinMessage("", args, true);
}
message->setBody("Joined the room");
return true;
}
}
return false;
}
}

View file

@ -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);

View file

@ -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) {

View file

@ -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<std::string> 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/");
}

View file

@ -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