Changeset - 26a01b8efa0a
[Not reviewed]
include/transport/HTTPRequestQueue.h
Show inline comments
 
@@ -6,28 +6,35 @@
 
#include "transport/ThreadPool.h"
 
#include <iostream>
 
#include <sstream>
 
#include <string.h>
 
#include "rapidjson/document.h"
 

	
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class HTTPRequest;
 
class Component;
 

	
 
class HTTPRequestQueue {
 
	public:
 
		HTTPRequestQueue(int delayBetweenRequests = 1);
 
		HTTPRequestQueue(Component *component, int delayBetweenRequests = 1);
 

	
 
		virtual ~HTTPRequestQueue();
 

	
 
		void queueRequest(HTTPRequest *req);
 

	
 
		void sendNextRequest();
 

	
 
	private:
 
		void handleRequestFinished();
 

	
 
	private:
 
		int m_delay;
 
		std::queue<HTTPRequest *> m_queue;
 
		bool m_processing;
 
		Swift::Timer::ref m_queueTimer;
 
};
 

	
 
}
 

	
include/transport/NetworkPlugin.h
Show inline comments
 
@@ -37,13 +37,13 @@ namespace Transport {
 
class NetworkPlugin {
 
	public:
 
		enum ExitCode { StorageBackendNeeded = -2 };
 

	
 
		class PluginConfig {
 
			public:
 
				PluginConfig() : m_needPassword(true), m_needRegistration(false), m_supportMUC(false), m_rawXML(false),
 
				PluginConfig() : m_needPassword(true), m_needRegistration(true), m_supportMUC(false), m_rawXML(false),
 
				m_disableJIDEscaping(false) {}
 
				virtual ~PluginConfig() {}
 

	
 
				void setNeedRegistration(bool needRegistration = false) { m_needRegistration = needRegistration; }
 
				void setNeedPassword(bool needPassword = true) { m_needPassword = needPassword; }
 
				void setSupportMUC(bool supportMUC = true) { m_supportMUC = supportMUC; }
spectrum/src/frontends/slack/SlackAPI.cpp
Show inline comments
 
@@ -33,13 +33,35 @@
 
#include <iterator>
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SlackAPI");
 

	
 
SlackAPI::SlackAPI(Component *component, const std::string &token) {
 
#define GET_ARRAY(FROM, NAME) rapidjson::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.IsArray()) { \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' object in the reply."); \
 
		return; \
 
	}
 
	
 
#define STORE_STRING(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsString()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' string in the reply."); \
 
		LOG4CXX_ERROR(logger, data); \
 
		return; \
 
	} \
 
	std::string NAME = NAME##_tmp.GetString();
 

	
 
#define STORE_BOOL(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsBool()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' string in the reply."); \
 
		LOG4CXX_ERROR(logger, data); \
 
		return; \
 
	} \
 
	bool NAME = NAME##_tmp.GetBool();
 

	
 
SlackAPI::SlackAPI(Component *component, const std::string &token) : HTTPRequestQueue(component) {
 
	m_component = component;
 
	m_token = token;
 
}
 

	
 
SlackAPI::~SlackAPI() {
 
}
 
@@ -57,12 +79,35 @@ void SlackAPI::sendMessage(const std::string &from, const std::string &to, const
 

	
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url,
 
			boost::bind(&SlackAPI::handleSendMessage, this, _1, _2, _3, _4));
 
	queueRequest(req);
 
}
 

	
 
void SlackAPI::deleteMessage(const std::string &channel, const std::string &ts) {
 
	LOG4CXX_INFO(logger, "Deleting message " << channel << " " << ts);
 
	std::string url = "https://slack.com/api/chat.delete?";
 
	url += "&channel=" + Util::urlencode(channel);
 
	url += "&ts=" + Util::urlencode(ts);
 
	url += "&token=" + Util::urlencode(m_token);
 

	
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url,
 
			boost::bind(&SlackAPI::handleSendMessage, this, _1, _2, _3, _4));
 
	queueRequest(req);
 
}
 

	
 
void SlackAPI::setPurpose(const std::string &channel, const std::string &purpose) {
 
	std::string url = "https://slack.com/api/channels.setPurpose?";
 
	url += "&channel=" + Util::urlencode(channel);
 
	url += "&purpose=" + Util::urlencode(purpose);
 
	url += "&token=" + Util::urlencode(m_token);
 

	
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url,
 
			boost::bind(&SlackAPI::handleSendMessage, this, _1, _2, _3, _4));
 
	queueRequest(req);
 
}
 

	
 
std::string SlackAPI::getChannelId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		LOG4CXX_ERROR(logger, data);
 
		return "";
 
	}
 
@@ -134,34 +179,12 @@ std::string SlackAPI::getOwnerId(HTTPRequest *req, bool ok, rapidjson::Document
 
void SlackAPI::usersList(HTTPRequest::Callback callback) {
 
	std::string url = "https://slack.com/api/users.list?presence=0&token=" + Util::urlencode(m_token);
 
	HTTPRequest *req = new HTTPRequest(THREAD_POOL(m_component), HTTPRequest::Get, url, callback);
 
	queueRequest(req);
 
}
 

	
 
#define GET_ARRAY(FROM, NAME) rapidjson::Value &NAME = FROM[#NAME]; \
 
	if (!NAME.IsArray()) { \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' object in the reply."); \
 
		return; \
 
	}
 
	
 
#define STORE_STRING(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsString()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' string in the reply."); \
 
		LOG4CXX_ERROR(logger, data); \
 
		return; \
 
	} \
 
	std::string NAME = NAME##_tmp.GetString();
 

	
 
#define STORE_BOOL(FROM, NAME) rapidjson::Value &NAME##_tmp = FROM[#NAME]; \
 
	if (!NAME##_tmp.IsBool()) {  \
 
		LOG4CXX_ERROR(logger, "No '" << #NAME << "' string in the reply."); \
 
		LOG4CXX_ERROR(logger, data); \
 
		return; \
 
	} \
 
	bool NAME = NAME##_tmp.GetBool();
 

	
 
void SlackAPI::getSlackChannelInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackChannelInfo> &ret) {
 
	if (!ok) {
 
		LOG4CXX_ERROR(logger, req->getError());
 
		return;
 
	}
 

	
 
@@ -179,17 +202,17 @@ void SlackAPI::getSlackChannelInfo(HTTPRequest *req, bool ok, rapidjson::Documen
 

	
 
		STORE_STRING(channels[i], name);
 
		info.name = name;
 

	
 
		rapidjson::Value &members = channels[i]["members"];
 
		for (int y = 0; members.IsArray() && y < members.Size(); y++) {
 
			if (!members[i].IsString()) {
 
			if (!members[y].IsString()) {
 
				continue;
 
			}
 

	
 
			info.members.push_back(members[i].GetString());
 
			info.members.push_back(members[y].GetString());
 
		}
 

	
 
		ret[info.name] = info;
 
	}
 

	
 
	return;
spectrum/src/frontends/slack/SlackAPI.h
Show inline comments
 
@@ -76,13 +76,15 @@ 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 imOpen(const std::string &uid, HTTPRequest::Callback callback);
 
		std::string getChannelId(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data);
 

	
 
		void deleteMessage(const std::string &channel, const std::string &ts);
 
		void sendMessage(const std::string &from, const std::string &to, const std::string &text);
 
		void setPurpose(const std::string &channel, const std::string &purpose);
 

	
 
		static void getSlackChannelInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackChannelInfo> &channels);
 
		static void getSlackImInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackImInfo> &ims);
 
		static void getSlackUserInfo(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data, std::map<std::string, SlackUserInfo> &users);
 
		static std::string SlackObjectToPlainText(const std::string &object, bool isChannel = false, bool returnName = false);
 

	
spectrum/src/frontends/slack/SlackRTM.cpp
Show inline comments
 
@@ -86,13 +86,14 @@ void SlackRTM::handlePayloadReceived(const std::string &payload) {
 
	STORE_STRING(d, type);
 

	
 
	if (type == "message") {
 
		STORE_STRING(d, channel);
 
		STORE_STRING(d, user);
 
		STORE_STRING(d, text);
 
		onMessageReceived(channel, user, text);
 
		STORE_STRING(d, ts);
 
		onMessageReceived(channel, user, text, ts);
 
	}
 
}
 

	
 
void SlackRTM::sendMessage(const std::string &channel, const std::string &message) {
 
	m_counter++;
 

	
spectrum/src/frontends/slack/SlackRTM.h
Show inline comments
 
@@ -77,13 +77,13 @@ class SlackRTM {
 
		}
 

	
 
		SlackAPI *getAPI() {
 
			return m_api;
 
		}
 

	
 
		boost::signal<void (const std::string &channel, const std::string &user, const std::string &text)> onMessageReceived;
 
		boost::signal<void (const std::string &channel, const std::string &user, const std::string &text, const std::string &ts)> onMessageReceived;
 

	
 
	private:
 
		void handlePayloadReceived(const std::string &payload);
 
		void handleRTMStart(HTTPRequest *req, bool ok, rapidjson::Document &resp, const std::string &data);
 
		void handleWebSocketConnected();
 

	
spectrum/src/frontends/slack/SlackRosterManager.cpp
Show inline comments
 
@@ -18,12 +18,13 @@
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "SlackRosterManager.h"
 
#include "SlackFrontend.h"
 
#include "SlackUser.h"
 
#include "SlackSession.h"
 

	
 
#include "transport/Buddy.h"
 
#include "transport/User.h"
 
#include "transport/Logging.h"
 
#include "transport/Factory.h"
 
#include "transport/PresenceOracle.h"
 
@@ -37,17 +38,55 @@
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SlackRosterManager");
 

	
 
SlackRosterManager::SlackRosterManager(User *user, Component *component) : RosterManager(user, component){
 
	m_user = user;
 
	m_transport = component;
 
	m_component = component;
 

	
 
	m_onlineBuddiesTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(20000);
 
	m_onlineBuddiesTimer->onTick.connect(boost::bind(&SlackRosterManager::sendOnlineBuddies, this));
 
	m_onlineBuddiesTimer->start();
 
}
 

	
 
SlackRosterManager::~SlackRosterManager() {
 
	m_onlineBuddiesTimer->stop();
 
}
 

	
 
void SlackRosterManager::sendOnlineBuddies() {
 
	std::string onlineBuddies = "Online users: ";
 
	Swift::StatusShow s;
 
	std::string statusMessage;
 

	
 
	const RosterManager::BuddiesMap &roster = getBuddies();
 
	for(RosterManager::BuddiesMap::const_iterator bt = roster.begin(); bt != roster.end(); bt++) {
 
		Buddy *b = (*bt).second;
 
		if (!b) {
 
			continue;
 
		}
 

	
 
		if (!(b->getStatus(s, statusMessage))) {
 
			continue;
 
		}
 

	
 
		if (s.getType() == Swift::StatusShow::None) {
 
			continue;
 
		}
 

	
 
		onlineBuddies += b->getAlias() + ", ";
 
	}
 

	
 
	if (m_onlineBuddies != onlineBuddies) {
 
		m_onlineBuddies = onlineBuddies;
 
		SlackSession *session = static_cast<SlackUser *>(m_user)->getSession();
 
		if (session) {
 
			session->setPurpose(m_onlineBuddies);
 
		}
 
	}
 

	
 
	m_onlineBuddiesTimer->start();
 
}
 

	
 
void SlackRosterManager::doRemoveBuddy(Buddy *buddy) {
 

	
 
}
 

	
spectrum/src/frontends/slack/SlackRosterManager.h
Show inline comments
 
@@ -23,12 +23,14 @@
 
#include "transport/RosterManager.h"
 

	
 
#include <string>
 
#include <algorithm>
 
#include <map>
 

	
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class Buddy;
 
class User;
 
class Component;
 
class StorageBackend;
 
@@ -41,14 +43,17 @@ class SlackRosterManager : public RosterManager {
 
		virtual ~SlackRosterManager();
 

	
 
		virtual void doRemoveBuddy(Buddy *buddy);
 
		virtual void doAddBuddy(Buddy *buddy);
 
		virtual void doUpdateBuddy(Buddy *buddy);
 

	
 
		void sendOnlineBuddies();
 

	
 
	private:
 
		RosterStorage *m_rosterStorage;
 
		User *m_user;
 
		Component *m_transport;
 
		Component *m_component;
 
		Swift::Timer::ref m_onlineBuddiesTimer;
 
		std::string m_onlineBuddies;
 
};
 

	
 
}
spectrum/src/frontends/slack/SlackSession.cpp
Show inline comments
 
@@ -19,12 +19,13 @@
 
 */
 

	
 
#include "SlackSession.h"
 
#include "SlackFrontend.h"
 
#include "SlackUser.h"
 
#include "SlackRTM.h"
 
#include "SlackRosterManager.h"
 

	
 
#include "transport/Transport.h"
 
#include "transport/HTTPRequest.h"
 
#include "transport/Util.h"
 
#include "transport/Buddy.h"
 
#include "transport/Config.h"
 
@@ -40,54 +41,77 @@
 
#include <iterator>
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SlackSession");
 

	
 
SlackSession::SlackSession(Component *component, StorageBackend *storageBackend, UserInfo uinfo) : m_uinfo(uinfo) {
 
SlackSession::SlackSession(Component *component, StorageBackend *storageBackend, UserInfo uinfo) : m_uinfo(uinfo), m_user(NULL) {
 
	m_component = component;
 
	m_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, false));
 
	m_rtm->onMessageReceived.connect(boost::bind(&SlackSession::handleMessageReceived, this, _1, _2, _3, _4, false));
 

	
 
}
 

	
 
SlackSession::~SlackSession() {
 
	delete m_rtm;
 
}
 

	
 
void SlackSession::sendMessage(boost::shared_ptr<Swift::Message> message) {
 
	if (message->getFrom().getResource() == m_uinfo.uin) {
 
		return;
 
	}
 

	
 
	std::string &channel = m_jid2channel[message->getFrom().toBare().toString()];
 
	std::string from = message->getFrom().getResource();
 
	std::string channel = m_jid2channel[message->getFrom().toBare().toString()];
 
	LOG4CXX_INFO(logger, "JID is " << message->getFrom().toBare().toString());
 
	if (channel.empty()) {
 
		if (m_slackChannel.empty()) {
 
			LOG4CXX_ERROR(logger, m_uinfo.jid << ": Received message for unknown channel from " << message->getFrom().toBare().toString());
 
			return;
 
		}
 
		channel = m_slackChannel;
 
		from = Buddy::JIDToLegacyName(message->getFrom());
 

	
 
		Buddy *b;
 
		if (m_user && (b = m_user->getRosterManager()->getBuddy(from)) != NULL) {
 
			from = b->getAlias() + " (" + from + ")";
 
		}
 
	}
 

	
 
	m_rtm->getAPI()->sendMessage(message->getFrom().getResource(), channel, message->getBody());
 
	LOG4CXX_INFO(logger, "FROM " << from);
 
	m_rtm->getAPI()->sendMessage(from, channel, message->getBody());
 
}
 

	
 
void SlackSession::setPurpose(const std::string &purpose) {
 
	if (m_slackChannel.empty()) {
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, "Setting channel purppose: " << m_slackChannel << " " << purpose);
 
	m_rtm->getAPI()->setPurpose(m_slackChannel, purpose);
 
}
 

	
 
void SlackSession::handleJoinMessage(const std::string &message, std::vector<std::string> &args, bool quiet) {
 
	// .spectrum2 join.room BotName #room irc.freenode.net channel
 
	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);
 

	
 
	m_uinfo.uin = name;
 
	m_storageBackend->setUser(m_uinfo);
 

	
 
	std::string to = legacyRoom + "%" + legacyServer + "@" + m_component->getJID().toString();
 
	if (!CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true)) {
 
		m_uinfo.uin = name;
 
		m_storageBackend->setUser(m_uinfo);
 
	}
 
// 	else {
 
// 		to =  legacyRoom + "\\40" + legacyServer + "@" + m_component->getJID().toString();
 
// 	}
 

	
 
	m_jid2channel[to] = slackChannel;
 
	m_channel2jid[slackChannel] = to;
 

	
 
	LOG4CXX_INFO(logger, "Setting transport between " << to << " and " << slackChannel);
 

	
 
	std::string rooms = "";
 
@@ -170,25 +194,59 @@ void SlackSession::handleRegisterMessage(const std::string &message, std::vector
 
		std::string msg;
 
		msg += "You have successfully registered 3rd-party account. Spectrum 2 is now connecting to the 3rd-party network.";
 
		m_rtm->sendMessage(m_ownerChannel, msg);
 
	}
 
}
 

	
 
void SlackSession::handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message, bool quiet) {
 
void SlackSession::handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message, const std::string &ts, bool quiet) {
 
	if (m_ownerChannel != channel) {
 
		std::string to = m_channel2jid[channel];
 
		if (!to.empty()) {
 
			boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
			msg->setType(Swift::Message::Groupchat);
 
			msg->setTo(to);
 
			msg->setFrom(Swift::JID("", m_uinfo.jid, "default"));
 
			msg->setBody("<" + user + "> " + message);
 
			m_component->getFrontend()->onMessageReceived(msg);
 
		}
 
		else {
 
			// When changing the purpose, we do not want to spam to room with the info,
 
			// so remove the purpose message.
 
// 			if (message.find("set the channel purpose") != std::string::npos) {
 
// 				m_rtm->getAPI()->deleteMessage(channel, ts);
 
// 			}
 
			// TODO: MAP `user` to JID somehow and send the message to proper JID.
 
			// So far send to all online contacts
 

	
 
			if (!m_user || !m_user->getRosterManager()) {
 
				return;
 
			}
 

	
 
			Swift::StatusShow s;
 
			std::string statusMessage;
 
			const RosterManager::BuddiesMap &roster = m_user->getRosterManager()->getBuddies();
 
			for(RosterManager::BuddiesMap::const_iterator bt = roster.begin(); bt != roster.end(); bt++) {
 
				Buddy *b = (*bt).second;
 
				if (!b) {
 
					continue;
 
				}
 

	
 
				if (!(b->getStatus(s, statusMessage))) {
 
					continue;
 
				}
 

	
 
				if (s.getType() == Swift::StatusShow::None) {
 
					continue;
 
				}
 

	
 
				boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
				msg->setTo(b->getJID());
 
				msg->setFrom(Swift::JID("", m_uinfo.jid, "default"));
 
				msg->setBody("<" + user + "> " + message);
 
				m_component->getFrontend()->onMessageReceived(msg);
 
			}
 
		}
 
		return;
 
	}
 

	
 
	std::vector<std::string> args;
 
	boost::split(args, message, boost::is_any_of(" "));
 
@@ -237,36 +295,36 @@ void SlackSession::handleImOpen(HTTPRequest *req, bool ok, rapidjson::Document &
 
	LOG4CXX_INFO(logger, "Opened channel with team owner: " << m_ownerChannel);
 

	
 
	std::string rooms = "";
 
	int type = (int) TYPE_STRING;
 
	m_storageBackend->getUserSetting(m_uinfo.id, "rooms", type, rooms);
 

	
 
	if (CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", false)) {
 
	if (!CONFIG_BOOL_DEFAULTED(m_component->getConfig(), "registration.needRegistration", true)) {
 
		if (rooms.empty()) {
 
			std::string msg;
 
			msg =  "Hi, it seems you have enabled Spectrum 2 transport for your Team. As a Team owner, you should now configure it:\\n";
 
			msg += "1. At first, create new channel in which you want this Spectrum 2 transport to send the messages, or choose the existing one.\\n";
 
			msg += "2. Invite this Spectrum 2 bot into this channel.\\n";
 
			msg += "3. Configure the transportation between 3rd-party network and this channel by executing following command in this chat:\\n";
 
			msg += "```.spectrum2 register 3rdPartyAccount 3rdPartyPassword #SlackChannel```\\n";
 
			msg += "For example to join XMPP account test@xmpp.tld and  transport it into #slack_channel, the command would look like this:\\n";
 
			msg += "```.spectrum2 register test@xmpp.tld mypassword #slack_channel```\\n";
 
			msg += "```.spectrum2 join.room NameOfYourBotIn3rdPartyNetwork #3rdPartyRoom hostname_of_3rd_party_server #SlackChannel```\\n";
 
			msg += "For example to join #test123 channel on Freenode IRC server as MyBot and transport it into #slack_channel, the command would look like this:\\n";
 
			msg += "```.spectrum2 join.room MyBot #test123 adams.freenode.net #slack_channel```\\n";
 
			msg += "To get full list of available commands, executa `.spectrum2 help`\\n";
 
			m_rtm->sendMessage(m_ownerChannel, msg);
 
		}
 
	}
 
	else {
 
		if (m_uinfo.uin.empty()) {
 
			std::string msg;
 
			msg =  "Hi, it seems you have enabled Spectrum 2 transport for your Team. As a Team owner, you should now configure it:\\n";
 
			msg += "1. At first, create new channel in which you want this Spectrum 2 transport to send the messages, or choose the existing one.\\n";
 
			msg += "2. Invite this Spectrum 2 bot into this channel.\\n";
 
			msg += "3. Configure the transportation between 3rd-party network and this channel by executing following command in this chat:\\n";
 
			msg += "```.spectrum2 join.room NameOfYourBotIn3rdPartyNetwork #3rdPartyRoom hostname_of_3rd_party_server #SlackChannel```\\n";
 
			msg += "For example to join #test123 channel on Freenode IRC server as MyBot and transport it into #slack_channel, the command would look like this:\\n";
 
			msg += "```.spectrum2 join.room MyBot #test123 adams.freenode.net #slack_channel```\\n";
 
			msg += "```.spectrum2 register 3rdPartyAccount 3rdPartyPassword #SlackChannel```\\n";
 
			msg += "For example to join XMPP account test@xmpp.tld and  transport it into #slack_channel, the command would look like this:\\n";
 
			msg += "```.spectrum2 register test@xmpp.tld mypassword #slack_channel```\\n";
 
			msg += "To get full list of available commands, executa `.spectrum2 help`\\n";
 
			m_rtm->sendMessage(m_ownerChannel, msg);
 
		}
 
		else {
 
			m_storageBackend->getUserSetting(m_uinfo.id, "slack_channel", type, m_slackChannel);
 
			if (!m_slackChannel.empty()) {
 
@@ -285,13 +343,13 @@ void SlackSession::handleImOpen(HTTPRequest *req, bool ok, rapidjson::Document &
 
		std::vector<std::string> commands;
 
		boost::split(commands, rooms, boost::is_any_of("\n"));
 

	
 
		BOOST_FOREACH(const std::string &command, commands) {
 
			if (command.size() > 5) {
 
				LOG4CXX_INFO(logger, m_uinfo.jid << ": Sending command from storage: " << command);
 
				handleMessageReceived(m_ownerChannel, "owner", command, true);
 
				handleMessageReceived(m_ownerChannel, "owner", command, "", true);
 
			}
 
		}
 
	}
 
}
 

	
 
void SlackSession::handleRTMStarted() {
spectrum/src/frontends/slack/SlackSession.h
Show inline comments
 
@@ -35,26 +35,33 @@ namespace Transport {
 

	
 
class Component;
 
class StorageBackend;
 
class HTTPRequest;
 
class SlackRTM;
 
class SlackAPI;
 
class User;
 

	
 
class SlackSession {
 
	public:
 
		SlackSession(Component *component, StorageBackend *storageBackend, UserInfo uinfo);
 

	
 
		virtual ~SlackSession();
 

	
 
		boost::signal<void (const std::string &user)> onInstallationDone;
 

	
 
		void sendMessage(boost::shared_ptr<Swift::Message> message);
 

	
 
		void setPurpose(const std::string &purpose);
 

	
 
		void setUser(User *user) {
 
			m_user = user;
 
		}
 

	
 
	private:
 
		void handleRTMStarted();
 
		void handleMessageReceived(const std::string &channel, const std::string &user, const std::string &message, bool quiet);
 
		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);
 

	
 
@@ -65,9 +72,10 @@ class SlackSession {
 
		std::string m_ownerName;
 
		SlackRTM *m_rtm;
 
		std::string m_ownerChannel;
 
		std::map<std::string, std::string> m_jid2channel;
 
		std::map<std::string, std::string> m_channel2jid;
 
		std::string m_slackChannel;
 
		User *m_user;
 
};
 

	
 
}
spectrum/src/frontends/slack/SlackUser.cpp
Show inline comments
 
@@ -42,12 +42,13 @@ SlackUser::SlackUser(const Swift::JID &jid, UserInfo &userInfo, Component *compo
 

	
 
	m_component = component;
 
	m_userManager = userManager;
 
	m_userInfo = userInfo;
 

	
 
	m_session = static_cast<SlackUserManager *>(userManager)->moveTempSession(m_jid.toString());
 
	m_session->setUser(this);
 
}
 

	
 
SlackUser::~SlackUser(){
 
	if (m_session) {
 
		delete m_session;
 
	}
src/Config.cpp
Show inline comments
 
@@ -310,13 +310,13 @@ std::string Config::getCommandLineArgs() const {
 
}
 

	
 
void Config::updateBackendConfig(const std::string &backendConfig) {
 
	options_description opts("Backend options");
 
	opts.add_options()
 
		("registration.needPassword", value<bool>()->default_value(true), "")
 
		("registration.needRegistration", value<bool>()->default_value(false), "")
 
		("registration.needRegistration", value<bool>()->default_value(true), "")
 
		("registration.extraField", value<std::vector<std::string> >()->multitoken(), "")
 
		("features.receipts", value<bool>()->default_value(false), "")
 
		("features.muc", value<bool>()->default_value(false), "")
 
		("features.rawxml", value<bool>()->default_value(false), "")
 
		("features.disable_jid_escaping", value<bool>()->default_value(false), "")
 
		("features.send_buddies_on_login", value<bool>()->default_value(false), "")
src/HTTPRequestQueue.cpp
Show inline comments
 
#include "transport/HTTPRequestQueue.h"
 
#include "transport/HTTPRequest.h"
 
#include "transport/Transport.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "HTTPRequestQueue")
 

	
 
HTTPRequestQueue::HTTPRequestQueue(int delay) {
 
HTTPRequestQueue::HTTPRequestQueue(Component *component, int delay) {
 
	m_delay = delay;
 
	m_processing = false;
 

	
 
	m_queueTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(500);
 
	m_queueTimer->onTick.connect(boost::bind(&HTTPRequestQueue::sendNextRequest, this));
 
}
 

	
 
HTTPRequestQueue::~HTTPRequestQueue() {
 
	
 
	m_queueTimer->stop();
 
}
 

	
 
void HTTPRequestQueue::handleRequestFinished() {
 
	m_queueTimer->start();
 
}
 

	
 
void HTTPRequestQueue::sendNextRequest() {
 
	if (m_queue.empty()) {
 
		m_processing = false;
 
		m_queueTimer->stop();
 
		return;
 
	}
 

	
 
	if (m_processing) {
 
		return;
 
	}
 

	
 
	HTTPRequest *req = m_queue.front();
 
	m_queue.pop();
 
	req->onRequestFinished.connect(boost::bind(&HTTPRequestQueue::sendNextRequest, this));
 
	req->onRequestFinished.connect(boost::bind(&HTTPRequestQueue::handleRequestFinished, this));
 
	req->execute();
 
}
 

	
 
void HTTPRequestQueue::queueRequest(HTTPRequest *req) {
 
	m_queue.push(req);
 

	
src/Transport.cpp
Show inline comments
 
@@ -63,13 +63,13 @@ Component::~Component() {
 

	
 
Transport::PresenceOracle *Component::getPresenceOracle() {
 
	return m_presenceOracle;
 
}
 

	
 
bool Component::inServerMode() {
 
	 return CONFIG_BOOL_DEFAULTED(m_config, "service.server_mode", true);
 
	 return CONFIG_BOOL_DEFAULTED(m_config, "service.server_mode", false);
 
}
 

	
 
void Component::start() {
 
	m_frontend->connectToServer();
 
	m_reconnectCount++;
 
	m_reconnectTimer->stop();
src/WebSocketClient.cpp
Show inline comments
 
@@ -20,12 +20,14 @@
 

	
 
#include "transport/WebSocketClient.h"
 
#include "transport/Transport.h"
 
#include "transport/Util.h"
 
#include "transport/Logging.h"
 

	
 
#include "Swiften/StringCodecs/Hexify.h"
 

	
 
#include <boost/foreach.hpp>
 
#include <boost/make_shared.hpp>
 
#include <map>
 
#include <iterator>
 

	
 
namespace Transport {
 
@@ -128,16 +130,22 @@ void WebSocketClient::handleDataRead(boost::shared_ptr<Swift::SafeByteArray> dat
 
			return;
 
		}
 
	}
 

	
 
	while (m_buffer.size() > 0) {
 
		if (m_buffer.size() >= 2) {
 
			LOG4CXX_INFO(logger, "BUFFER: '" << m_buffer << "'");
 
			LOG4CXX_INFO(logger, "BUFFER: '" << Swift::Hexify::hexify(Swift::createByteArray(m_buffer)) << "'");
 
			uint8_t opcode = *((uint8_t *) &m_buffer[0]) & 0xf;
 
			uint8_t size7 = *((uint8_t *) &m_buffer[1]);
 
			uint8_t size7 = *((uint8_t *) &m_buffer[1]) & 127;
 
			bool mask = *((uint8_t *) &m_buffer[1]) & 128;
 
			uint16_t size16 = 0;
 
			int header_size = 2;
 
			LOG4CXX_INFO(logger, "OPCODE: " << (int) opcode);
 
			LOG4CXX_INFO(logger, "SIZE7: " << (int) size7);
 
			LOG4CXX_INFO(logger, "MASK: " << (int) mask);
 
			if (size7 == 126) {
 
				if (m_buffer.size() >= 4) {
 
					size16 = *((uint16_t *) &m_buffer[2]);
 
					size16 = ntohs(size16);
 
					header_size += 2;
 
				}
0 comments (0 inline, 0 general)