diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 2764e9e1..01e83277 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -244,6 +244,27 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } } + void handleTypingRequest(const std::string &user, const std::string &buddyName) { + PurpleAccount *account = m_sessions[user]; + if (account) { + serv_send_typing(purple_account_get_connection(account), buddyName.c_str(), PURPLE_TYPING); + } + } + + void handleTypedRequest(const std::string &user, const std::string &buddyName) { + PurpleAccount *account = m_sessions[user]; + if (account) { + serv_send_typing(purple_account_get_connection(account), buddyName.c_str(), PURPLE_TYPED); + } + } + + void handleStoppedTypingRequest(const std::string &user, const std::string &buddyName) { + PurpleAccount *account = m_sessions[user]; + if (account) { + serv_send_typing(purple_account_get_connection(account), buddyName.c_str(), PURPLE_NOT_TYPING); + } + } + std::map m_sessions; std::map m_accounts; std::map m_vcards; diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 88d4945c..f94509e1 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -73,6 +73,10 @@ class NetworkPlugin { 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*/) {} + + virtual void handleTypingRequest(const std::string &/*user*/, const std::string &/*buddyName*/) {} + virtual void handleTypedRequest(const std::string &/*user*/, const std::string &/*buddyName*/) {} + virtual void handleStoppedTypingRequest(const std::string &/*user*/, const std::string &/*buddyName*/) {} private: @@ -86,6 +90,7 @@ class NetworkPlugin { void handleVCardPayload(const std::string &payload); void handleBuddyChangedPayload(const std::string &payload); void handleBuddyRemovedPayload(const std::string &payload); + void handleChatStatePayload(const std::string &payload, Swift::ChatState::ChatStateType type); void handleDataRead(const Swift::SafeByteArray&); void _handleConnected(bool error); void handleDisconnected(); diff --git a/src/networkplugin.cpp b/src/networkplugin.cpp index 6d0b88cc..11733cd1 100644 --- a/src/networkplugin.cpp +++ b/src/networkplugin.cpp @@ -334,6 +334,28 @@ void NetworkPlugin::handleBuddyRemovedPayload(const std::string &data) { handleBuddyRemovedRequest(payload.username(), payload.buddyname(), payload.groups()); } +void NetworkPlugin::handleChatStatePayload(const std::string &data, Swift::ChatState::ChatStateType type) { + pbnetwork::Buddy payload; + if (payload.ParseFromString(data) == false) { + // TODO: ERROR + return; + } + + switch(type) { + case Swift::ChatState::Composing: + handleTypingRequest(payload.username(), payload.buddyname()); + break; + case Swift::ChatState::Paused: + handleTypedRequest(payload.username(), payload.buddyname()); + break; + case Swift::ChatState::Active: + handleStoppedTypingRequest(payload.username(), payload.buddyname()); + break; + default: + break; + } +} + void NetworkPlugin::handleDataRead(const Swift::SafeByteArray &data) { m_data.insert(m_data.end(), data.begin(), data.end()); @@ -388,6 +410,15 @@ void NetworkPlugin::handleDataRead(const Swift::SafeByteArray &data) { case pbnetwork::WrapperMessage_Type_TYPE_STATUS_CHANGED: handleStatusChangedPayload(wrapper.payload()); break; + case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPING: + handleChatStatePayload(wrapper.payload(), Swift::ChatState::Composing); + break; + case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPED: + handleChatStatePayload(wrapper.payload(), Swift::ChatState::Paused); + break; + case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_STOPPED_TYPING: + handleChatStatePayload(wrapper.payload(), Swift::ChatState::Active); + break; default: return; } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index d3995836..25ddcbd2 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -560,18 +560,52 @@ void NetworkPluginServer::handleUserDestroyed(User *user) { } void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost::shared_ptr &msg) { - pbnetwork::ConversationMessage m; - m.set_username(conv->getConversationManager()->getUser()->getJID().toBare()); - m.set_buddyname(conv->getLegacyName()); - m.set_message(msg->getBody()); - std::string message; - m.SerializeToString(&message); + boost::shared_ptr statePayload = msg->getPayload(); + if (statePayload) { + pbnetwork::WrapperMessage_Type type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED; + switch (statePayload->getChatState()) { + case Swift::ChatState::Active: + type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_STOPPED_TYPING; + break; + case Swift::ChatState::Composing: + type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPING; + break; + case Swift::ChatState::Paused: + type = pbnetwork::WrapperMessage_Type_TYPE_BUDDY_TYPED; + break; + default: + break; + } + if (type != pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED) { + pbnetwork::Buddy buddy; + buddy.set_username(conv->getConversationManager()->getUser()->getJID().toBare()); + buddy.set_buddyname(conv->getLegacyName()); - WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE); + std::string message; + buddy.SerializeToString(&message); - Client *c = (Client *) conv->getConversationManager()->getUser()->getData(); - send(c->connection, message); + WRAP(message, type); + + Client *c = (Client *) conv->getConversationManager()->getUser()->getData(); + send(c->connection, message); + } + } + + if (!msg->getBody().empty()) { + pbnetwork::ConversationMessage m; + m.set_username(conv->getConversationManager()->getUser()->getJID().toBare()); + m.set_buddyname(conv->getLegacyName()); + m.set_message(msg->getBody()); + + std::string message; + m.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE); + + Client *c = (Client *) conv->getConversationManager()->getUser()->getData(); + send(c->connection, message); + } } void NetworkPluginServer::handleBuddyRemoved(Buddy *b) {