diff --git a/include/transport/abstractbuddy.h b/include/transport/abstractbuddy.h index 9f051e5b..a94e8a26 100644 --- a/include/transport/abstractbuddy.h +++ b/include/transport/abstractbuddy.h @@ -59,7 +59,7 @@ class AbstractBuddy { /// Returns full JID of this buddy. /// \param hostname hostname used as domain in returned JID /// \return full JID of this buddy - const Swift::JID &getJID(const std::string &hostname); + const Swift::JID &getJID(); /// Generates whole Presennce stanza with current status/show for this buddy. /// Presence stanza does not containt "to" attribute, it has to be added manually. @@ -103,6 +103,8 @@ class AbstractBuddy { /// so it can be used in JIDs. std::string getSafeName(); + void buddyChanged(); + /// Returns legacy network username of this buddy. (for example UIN for ICQ, /// JID for Jabber, ...). /// \return legacy network username diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index d8d099be..ec4c37f4 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -69,6 +69,9 @@ class RosterManager { private: void setBuddyCallback(AbstractBuddy *buddy); + void sendBuddyRosterPush(AbstractBuddy *buddy); + void handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, const std::string &key); + std::map m_buddies; Component *m_component; User *m_user; diff --git a/include/transport/transport.h b/include/transport/transport.h index 31efc6c0..b31ee150 100644 --- a/include/transport/transport.h +++ b/include/transport/transport.h @@ -73,6 +73,8 @@ namespace Transport { /// \return Swift::Component associated with this Transport::Component Swift::StanzaChannel *getStanzaChannel(); + Swift::IQRouter *getIQRouter() { return m_iqRouter; } + /// Returns Swift::PresenceOracle associated with this Transport::Component. /// You can use it to check current resource connected for particular user. /// \return Swift::PresenceOracle associated with this Transport::Component diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 1fef2ff0..87c8fe6a 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -71,6 +71,39 @@ static void buddyListNewNode(PurpleBlistNode *node) { } } +static void buddyStatusChanged(PurpleBuddy *buddy, PurpleStatus *status, PurpleStatus *old_status) { + SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data; + PurpleAccount *account = purple_buddy_get_account(buddy); + User *user = (User *) account->ui_data; + + if (!user || !s_buddy) + return; + + s_buddy->buddyChanged(); +} + +static void buddySignedOn(PurpleBuddy *buddy) { + SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data; + PurpleAccount *account = purple_buddy_get_account(buddy); + User *user = (User *) account->ui_data; + + if (!user || !s_buddy) + return; + + s_buddy->buddyChanged(); +} + +static void buddySignedOff(PurpleBuddy *buddy) { + SpectrumBuddy *s_buddy = (SpectrumBuddy *) buddy->node.ui_data; + PurpleAccount *account = purple_buddy_get_account(buddy); + User *user = (User *) account->ui_data; + + if (!user || !s_buddy) + return; + + s_buddy->buddyChanged(); +} + static void NodeRemoved(PurpleBlistNode *node, void *data) { if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) return; @@ -205,9 +238,9 @@ static bool initPurple(Config &cfg) { // purple_signal_connect(purple_conversations_get_handle(), "buddy-typing-stopped", &conversation_handle, PURPLE_CALLBACK(buddyTypingStopped), NULL); // purple_signal_connect(purple_connections_get_handle(), "signed-on", &conn_handle,PURPLE_CALLBACK(signed_on), NULL); // purple_signal_connect(purple_blist_get_handle(), "buddy-removed", &blist_handle,PURPLE_CALLBACK(buddyRemoved), NULL); -// purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &blist_handle,PURPLE_CALLBACK(buddySignedOn), NULL); -// purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &blist_handle,PURPLE_CALLBACK(buddySignedOff), NULL); -// purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &blist_handle,PURPLE_CALLBACK(buddyStatusChanged), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-on", &blist_handle,PURPLE_CALLBACK(buddySignedOn), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-signed-off", &blist_handle,PURPLE_CALLBACK(buddySignedOff), NULL); + purple_signal_connect(purple_blist_get_handle(), "buddy-status-changed", &blist_handle,PURPLE_CALLBACK(buddyStatusChanged), NULL); purple_signal_connect(purple_blist_get_handle(), "blist-node-removed", &blist_handle,PURPLE_CALLBACK(NodeRemoved), NULL); // purple_signal_connect(purple_conversations_get_handle(), "chat-topic-changed", &conversation_handle, PURPLE_CALLBACK(conv_chat_topic_changed), NULL); // diff --git a/spectrum/src/spectrumbuddy.cpp b/spectrum/src/spectrumbuddy.cpp index 0caa5811..1cafe4ad 100644 --- a/spectrum/src/spectrumbuddy.cpp +++ b/spectrum/src/spectrumbuddy.cpp @@ -55,7 +55,31 @@ bool SpectrumBuddy::getStatus(Swift::StatusShow &status, std::string &statusMess if (stat == NULL) return false; int st = purple_status_type_get_primitive(purple_status_get_type(stat)); - // TODO: populate status + + switch(st) { + case PURPLE_STATUS_AVAILABLE: { + break; + } + case PURPLE_STATUS_AWAY: { + status = Swift::StatusShow::Away; + break; + } + case PURPLE_STATUS_UNAVAILABLE: { + status = Swift::StatusShow::DND; + break; + } + case PURPLE_STATUS_EXTENDED_AWAY: { + status = Swift::StatusShow::XA; + break; + } + case PURPLE_STATUS_OFFLINE: { + status = Swift::StatusShow::None; + break; + } + default: + break; + } + const char *message = purple_status_get_attr_string(stat, "message"); if (message != NULL) { diff --git a/src/abstractbuddy.cpp b/src/abstractbuddy.cpp index 49e541c8..f8535ae4 100644 --- a/src/abstractbuddy.cpp +++ b/src/abstractbuddy.cpp @@ -56,7 +56,7 @@ BuddyFlag AbstractBuddy::getFlags() { return m_flags; } -const Swift::JID &AbstractBuddy::getJID(const std::string &hostname) { +const Swift::JID &AbstractBuddy::getJID() { if (!m_jid.isValid()) { generateJID(); } @@ -94,7 +94,8 @@ Swift::Presence::ref AbstractBuddy::generatePresenceStanza(int features, bool on return Swift::Presence::ref(); Swift::Presence::ref presence = Swift::Presence::create(); -// presence->setFrom(getJID()); + presence->setFrom(m_jid); + presence->setTo(m_rosterManager->getUser()->getJID().toBare()); presence->setType(Swift::Presence::Available); if (!statusMessage.empty()) @@ -145,4 +146,11 @@ std::string AbstractBuddy::getSafeName() { return name; } +void AbstractBuddy::buddyChanged() { + Swift::Presence::ref presence = generatePresenceStanza(255); + if (presence) { + m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence); + } +} + } diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 9a9a8453..777c2d65 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -23,13 +23,16 @@ #include "transport/usermanager.h" #include "transport/abstractbuddy.h" #include "transport/user.h" +#include "Swiften/Roster/SetRosterRequest.h" +#include "Swiften/Elements/RosterPayload.h" +#include "Swiften/Elements/RosterItemPayload.h" namespace Transport { RosterManager::RosterManager(User *user, Component *component){ m_user = user; m_component = component; - m_setBuddyTimer = m_component->getFactories()->getTimerFactory()->createTimer(10); + m_setBuddyTimer = m_component->getFactories()->getTimerFactory()->createTimer(1000); } RosterManager::~RosterManager() { @@ -40,12 +43,30 @@ void RosterManager::setBuddy(AbstractBuddy *buddy) { m_setBuddyTimer->start(); } +void RosterManager::sendBuddyRosterPush(AbstractBuddy *buddy) { + Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload()); + Swift::RosterItemPayload item; + item.setJID(buddy->getJID().toBare()); + item.setName(buddy->getAlias()); + item.setGroups(buddy->getGroups()); + + payload->addItem(item); + + Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, m_component->getIQRouter(), m_user->getJID().toBare()); + request->onResponse.connect(boost::bind(&RosterManager::handleBuddyRosterPushResponse, this, _1, buddy->getSafeName())); + request->send(); +} + void RosterManager::setBuddyCallback(AbstractBuddy *buddy) { m_setBuddyTimer->onTick.disconnect(boost::bind(&RosterManager::setBuddyCallback, this, buddy)); m_buddies[buddy->getSafeName()] = buddy; onBuddySet(buddy); + if (m_component->inServerMode()) { + sendBuddyRosterPush(buddy); + } + if (m_setBuddyTimer->onTick.empty()) { m_setBuddyTimer->stop(); } @@ -56,4 +77,10 @@ void RosterManager::unsetBuddy(AbstractBuddy *buddy) { onBuddyUnset(buddy); } +void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, const std::string &key) { + if (m_buddies[key] != NULL) { + m_buddies[key]->buddyChanged(); + } +} + } \ No newline at end of file