diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt index 9982d868..e52c6cf2 100644 --- a/backends/CMakeLists.txt +++ b/backends/CMakeLists.txt @@ -7,4 +7,6 @@ if (PROTOBUF_FOUND) ADD_SUBDIRECTORY(libircclient-qt) endif() + ADD_SUBDIRECTORY(libmsn) + endif() diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 2d6f6f94..cf7babcd 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -139,6 +139,58 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } } + void handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage) { + PurpleAccount *account = m_sessions[user]; + if (account) { + int st; + switch(status) { + case Swift::StatusShow::Away: { + st = PURPLE_STATUS_AWAY; + if (!purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AWAY)) + st = PURPLE_STATUS_EXTENDED_AWAY; + else + st = PURPLE_STATUS_AWAY; + break; + } + case Swift::StatusShow::DND: { + st = PURPLE_STATUS_UNAVAILABLE; + break; + } + case Swift::StatusShow::XA: { + if (!purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_EXTENDED_AWAY)) + st = PURPLE_STATUS_AWAY; + else + st = PURPLE_STATUS_EXTENDED_AWAY; + break; + } + case Swift::StatusShow::None: { + st = PURPLE_STATUS_OFFLINE; + break; + } + default: + st = PURPLE_STATUS_AVAILABLE; + break; + } + gchar *_markup = purple_markup_escape_text(statusMessage.c_str(), -1); + std::string markup(_markup); + g_free(_markup); + + std::cout << st << " < STATUS\n"; + + // we are already connected so we have to change status + const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive(account, (PurpleStatusPrimitive) st); + if (status_type != NULL) { + // send presence to legacy network + if (!markup.empty()) { + purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, "message", markup.c_str(), NULL); + } + else { + purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, NULL); + } + } + } + } + void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message) { PurpleAccount *account = m_sessions[user]; if (account) { diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 331ee690..836d377f 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -64,6 +64,7 @@ class NetworkPlugin { virtual void handleVCardRequest(const std::string &/*user*/, const std::string &/*legacyName*/, unsigned int /*id*/) {} virtual void handleJoinRoomRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*nickname*/, const std::string &/*pasword*/) {} virtual void handleLeaveRoomRequest(const std::string &/*user*/, const std::string &/*room*/) {} + virtual void handleStatusChangeRequest(const std::string &/*user*/, int status, const std::string &statusMessage) {} virtual void handleBuddyUpdatedRequest(const std::string &/*user*/, const std::string &/*buddyName*/, const std::string &/*alias*/, const std::string &/*groups*/) {} virtual void handleBuddyRemovedRequest(const std::string &/*user*/, const std::string &/*buddyName*/, const std::string &/*groups*/) {} @@ -72,6 +73,7 @@ class NetworkPlugin { void connect(); void handleLoginPayload(const std::string &payload); void handleLogoutPayload(const std::string &payload); + void handleStatusChangedPayload(const std::string &payload); void handleConvMessagePayload(const std::string &payload); void handleJoinRoomPayload(const std::string &payload); void handleLeaveRoomPayload(const std::string &payload); diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 1d1bff73..93154ec8 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -72,6 +72,7 @@ class NetworkPluginServer { void handleRoomJoined(User *user, const std::string &room, const std::string &nickname, const std::string &password); void handleRoomLeft(User *user, const std::string &room); void handleUserReadyToConnect(User *user); + void handleUserPresenceChanged(User *user, Swift::Presence::ref presence); void handleUserDestroyed(User *user); void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item); diff --git a/include/transport/user.h b/include/transport/user.h index 86f7214c..e79f165c 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -77,6 +77,7 @@ class User { void handleDisconnected(const std::string &error); boost::signal onReadyToConnect; + boost::signal onPresenceChanged; boost::signal onRoomJoined; boost::signal onRoomLeft; boost::signal onDisconnected; diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index 1c127d88..d0ecbf1c 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -6,9 +6,9 @@ port = 5222 server_mode = 1 backend=../../backends/libpurple/libpurple_backend #backend=../../backends/libircclient-qt/libircclient-qt_backend -#protocol=prpl-jabber +protocol=prpl-jabber #protocol=prpl-msn -protocol=prpl-icq +#protocol=prpl-icq [database] database = test.sql diff --git a/src/networkplugin.cpp b/src/networkplugin.cpp index c5bb1d0f..7343fa16 100644 --- a/src/networkplugin.cpp +++ b/src/networkplugin.cpp @@ -225,6 +225,16 @@ void NetworkPlugin::handleLogoutPayload(const std::string &data) { handleLogoutRequest(payload.user(), payload.legacyname()); } +void NetworkPlugin::handleStatusChangedPayload(const std::string &data) { + pbnetwork::Status payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + handleStatusChangeRequest(payload.username(), payload.status(), payload.statusmessage()); +} + void NetworkPlugin::handleConvMessagePayload(const std::string &data) { pbnetwork::ConversationMessage payload; if (payload.ParseFromString(data) == false) { @@ -336,6 +346,9 @@ void NetworkPlugin::handleDataRead(const Swift::SafeByteArray &data) { case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED: handleBuddyRemovedPayload(wrapper.payload()); break; + case pbnetwork::WrapperMessage_Type_TYPE_STATUS_CHANGED: + handleStatusChangedPayload(wrapper.payload()); + break; default: return; } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index f5a2f2da..cdea43fd 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -411,6 +411,7 @@ void NetworkPluginServer::handleUserCreated(User *user) { // UserInfo userInfo = user->getUserInfo(); user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user)); + user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1)); user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3)); user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1)); } @@ -432,6 +433,26 @@ void NetworkPluginServer::handleUserReadyToConnect(User *user) { send(c->connection, message); } +void NetworkPluginServer::handleUserPresenceChanged(User *user, Swift::Presence::ref presence) { + if (presence->getShow() == Swift::StatusShow::None) + return; + + UserInfo userInfo = user->getUserInfo(); + + pbnetwork::Status status; + status.set_username(user->getJID().toBare()); + status.set_status((int) presence->getShow()); + status.set_statusmessage(presence->getStatus()); + + std::string message; + status.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_STATUS_CHANGED); + + Client *c = (Client *) user->getData(); + send(c->connection, message); +} + void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, const std::string &nickname, const std::string &password) { UserInfo userInfo = user->getUserInfo(); diff --git a/src/pbnetwork.proto b/src/pbnetwork.proto index 8fcc80db..75de5fba 100644 --- a/src/pbnetwork.proto +++ b/src/pbnetwork.proto @@ -65,6 +65,12 @@ message VCard { optional bytes photo = 6; } +message Status { + required string userName = 1; + required int32 status = 3; + optional string statusMessage = 4; +} + message WrapperMessage { enum Type { TYPE_CONNECTED = 1; @@ -81,7 +87,8 @@ message WrapperMessage { TYPE_PARTICIPANT_CHANGED = 13; TYPE_ROOM_NICKNAME_CHANGED = 14; TYPE_ROOM_SUBJECT_CHANGED = 15; - TYPE_VCARD = 16; + TYPE_VCARD = 16; + TYPE_STATUS_CHANGED = 17; } required Type type = 1; optional bytes payload = 2; diff --git a/src/user.cpp b/src/user.cpp index 6fdda56e..5fbae291 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -104,11 +104,11 @@ void User::handlePresence(Swift::Presence::ref presence) { return; } - if (highest) { highest->setTo(presence->getFrom().toBare()); highest->setFrom(m_component->getJID()); m_component->getStanzaChannel()->sendPresence(highest); + onPresenceChanged(highest); } else { Swift::Presence::ref response = Swift::Presence::create(); @@ -116,6 +116,7 @@ void User::handlePresence(Swift::Presence::ref presence) { response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); m_component->getStanzaChannel()->sendPresence(response); + onPresenceChanged(response); } }