From 8761e976aeca6d4a05cbc2d5eaf976e80b3616ed Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 21 Dec 2012 11:20:05 +0100 Subject: [PATCH] Cache messages also when you leave room but do not disconnect --- backends/libcommuni/session.cpp | 3 ++ include/transport/conversation.h | 2 +- include/transport/conversationmanager.h | 2 + src/conversation.cpp | 24 +++++++-- src/conversationmanager.cpp | 9 ++++ src/tests/conversationmanager.cpp | 66 +++++++++++++++++++++++++ src/user.cpp | 3 ++ 7 files changed, 105 insertions(+), 4 deletions(-) diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index 43824d39..c8b271f6 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -117,6 +117,9 @@ void MyIrcSession::on_quit(IrcMessage *message) { for(AutoJoinMap::iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { bool op = 0; std::string nickname = TO_UTF8(m->sender().name()); + if (!hasIRCBuddy(it->second->getChannel(), nickname)) { + continue; + } op = correctNickname(nickname); removeIRCBuddy(it->second->getChannel(), nickname); LOG4CXX_INFO(logger, user << ": " << nickname << " quit " << it->second->getChannel() + suffix); diff --git a/include/transport/conversation.h b/include/transport/conversation.h index a8915e75..121794d6 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -140,7 +140,7 @@ class Conversation { void sendParticipants(const Swift::JID &to); - void sendCachedMessages(const Swift::JID &to); + void sendCachedMessages(const Swift::JID &to = Swift::JID()); private: Swift::Presence::ref generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname = ""); diff --git a/include/transport/conversationmanager.h b/include/transport/conversationmanager.h index c3900b95..0ef2842f 100644 --- a/include/transport/conversationmanager.h +++ b/include/transport/conversationmanager.h @@ -59,6 +59,8 @@ class ConversationManager { /// \return Conversation or NULL. Conversation *getConversation(const std::string &name); + void sendCachedChatMessages(); + /// Adds new Conversation to the manager. /// \param conv Conversation. diff --git a/src/conversation.cpp b/src/conversation.cpp index 62d4555c..1a8b8383 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -127,7 +127,20 @@ void Conversation::handleMessage(boost::shared_ptr &message, con message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), n)); } } - m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + + if (m_conversationManager->getComponent()->inServerMode() && m_conversationManager->getUser()->shouldCacheMessages()) { + boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time(); + boost::shared_ptr delay(boost::make_shared()); + delay->setStamp(timestamp); + message->addPayload(delay); + m_cachedMessages.push_back(message); + if (m_cachedMessages.size() > 100) { + m_cachedMessages.pop_front(); + } + } + else { + m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); + } } else { std::string legacyName = m_legacyName; @@ -142,7 +155,7 @@ void Conversation::handleMessage(boost::shared_ptr &message, con message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n)); - if (m_conversationManager->getUser()->shouldCacheMessages()) { + if (m_jids.empty()) { boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time(); boost::shared_ptr delay(boost::make_shared()); delay->setStamp(timestamp); @@ -176,7 +189,12 @@ void Conversation::sendParticipants(const Swift::JID &to) { void Conversation::sendCachedMessages(const Swift::JID &to) { for (std::list >::const_iterator it = m_cachedMessages.begin(); it != m_cachedMessages.end(); it++) { - (*it)->setTo(to); + if (to.isValid()) { + (*it)->setTo(to); + } + else { + (*it)->setTo(m_jid.toBare()); + } m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(*it); } m_cachedMessages.clear(); diff --git a/src/conversationmanager.cpp b/src/conversationmanager.cpp index d967df34..e6f7e2dc 100644 --- a/src/conversationmanager.cpp +++ b/src/conversationmanager.cpp @@ -42,6 +42,15 @@ ConversationManager::~ConversationManager() { deleteAllConversations(); } +void ConversationManager::sendCachedChatMessages() { + for (std::map::const_iterator it = m_convs.begin(); it != m_convs.end(); it++) { + if ((*it).second->isMUC()) { + continue; + } + (*it).second->sendCachedMessages(); + } +} + void ConversationManager::deleteAllConversations() { while(!m_convs.empty()) { LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Removing conversation " << (*m_convs.begin()).first); diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index 4cc56db7..5c9851ec 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -27,6 +27,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_TEST(handleNormalMessagesHeadline); CPPUNIT_TEST(handleGroupchatMessages); CPPUNIT_TEST(handleGroupchatMessagesBouncer); + CPPUNIT_TEST(handleGroupchatMessagesBouncerLeave); CPPUNIT_TEST(handleGroupchatMessagesTwoResources); CPPUNIT_TEST(handleChatstateMessages); CPPUNIT_TEST(handleSubjectMessages); @@ -355,6 +356,71 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe } + void handleGroupchatMessagesBouncerLeave() { + User *user = userManager->getUser("user@localhost"); + user->addUserSetting("stay_connected", "1"); + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "#room", true); + user->getConversationManager()->addConversation(conv); + conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); + conv->setNickname("nickname"); + conv->addJID("user@localhost/resource"); + + CPPUNIT_ASSERT(!user->shouldCacheMessages()); + + Swift::Presence::ref response3 = Swift::Presence::create(); + response3->setType(Swift::Presence::Unavailable); + response3->setTo("#room@localhost/hanzz"); + response3->setFrom("user@localhost/resource"); + + Swift::MUCPayload *payload3 = new Swift::MUCPayload(); + payload3->setPassword("password"); + response3->addPayload(boost::shared_ptr(payload3)); + injectPresence(response3); + loop->processEvents(); + + CPPUNIT_ASSERT(!user->shouldCacheMessages()); + + // reset resources should not touch this resource + user->getConversationManager()->resetResources(); + + boost::shared_ptr msg(new Swift::Message()); + msg->setBody("hi there!"); + conv->handleMessage(msg, "anotheruser"); + + boost::shared_ptr msg2(new Swift::Message()); + msg2->setBody("hi there2!"); + conv->handleMessage(msg2, "anotheruser"); + + loop->processEvents(); + CPPUNIT_ASSERT_EQUAL(0, (int) received.size()); + + userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password")); + userRegistry->onPasswordValid(Swift::JID("user@localhost/resource")); + loop->processEvents(); + + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo("#room@localhost/hanzz"); + response->setFrom("user@localhost/resource"); + + Swift::MUCPayload *payload = new Swift::MUCPayload(); + payload->setPassword("password"); + response->addPayload(boost::shared_ptr(payload)); + injectPresence(response); + loop->processEvents(); + + CPPUNIT_ASSERT_EQUAL(4, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[2]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); + + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[3]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[3]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[3]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[3]))->getFrom().toString()); + + } + void handleGroupchatMessagesTwoResources() { connectSecondResource(); received2.clear(); diff --git a/src/user.cpp b/src/user.cpp index 361cc487..86f908bd 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -186,6 +186,9 @@ void User::setConnected(bool connected) { } void User::setCacheMessages(bool cacheMessages) { + if (m_component->inServerMode() && !m_cacheMessages && cacheMessages) { + m_conversationManager->sendCachedChatMessages(); + } m_cacheMessages = cacheMessages; }