swarm: relink setMessageDisplayed

Change-Id: Ic1e002a1e8edf79c5c392e707dd857c7e88667ec
GitLab: #319
This commit is contained in:
Sébastien Blin
2021-01-04 12:27:25 -05:00
parent a1b04c7213
commit 427e6b3ab3
19 changed files with 290 additions and 40 deletions

View File

@ -584,13 +584,14 @@
</signal>
<signal name="accountMessageStatusChanged" tp:name-for-bindings="accountMessageStatusChanged">
<tp:added version="2.3.0"/>
<tp:added version="10.0.0"/>
<tp:docstring>
Notify clients that a sent text message status have changed
</tp:docstring>
<arg type="s" name="accountID"/>
<arg type="t" name="id"/>
<arg type="s" name="to"/>
<arg type="s" name="id"/>
<arg type="s" name="conversationId"/>
<arg type="s" name="peer"/>
<arg type="i" name="status">
<tp:docstring>The new status of the message, see getMessageStatus for possible values.</tp:docstring>
</arg>
@ -640,9 +641,9 @@
The account ID
</tp:docstring>
</arg>
<arg type="s" name="contactId" direction="in">
<arg type="s" name="conversationUri" direction="in">
<tp:docstring>
The contact ID
A conversation uri (swarm:xxxx or jami:xxxx)
</tp:docstring>
</arg>
<arg type="s" name="messageId" direction="in">

View File

@ -224,7 +224,7 @@ DBusClient::initLibrary(int flags)
exportable_callback<ConfigurationSignal::IncomingAccountMessage>(
bind(&DBusConfigurationManager::incomingAccountMessage, confM, _1, _2, _3, _4)),
exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>(
bind(&DBusConfigurationManager::accountMessageStatusChanged, confM, _1, _2, _3, _4)),
bind(&DBusConfigurationManager::accountMessageStatusChanged, confM, _1, _2, _3, _4, _5)),
exportable_callback<ConfigurationSignal::ProfileReceived>(
bind(&DBusConfigurationManager::profileReceived, confM, _1, _2, _3)),
exportable_callback<ConfigurationSignal::ComposingStatusChanged>(

View File

@ -234,11 +234,11 @@ DBusConfigurationManager::setIsComposing(const std::string& accountID,
bool
DBusConfigurationManager::setMessageDisplayed(const std::string& accountID,
const std::string& contactId,
const std::string& conversationUri,
const std::string& messageId,
const int32_t& status)
{
return DRing::setMessageDisplayed(accountID, contactId, messageId, status);
return DRing::setMessageDisplayed(accountID, conversationUri, messageId, status);
}
auto

View File

@ -97,7 +97,7 @@ public:
int getMessageStatus(const std::string& accountID, const uint64_t& id);
bool cancelMessage(const std::string& accountID, const uint64_t& messageId);
void setIsComposing(const std::string& accountID, const std::string& to, const bool& isWriting);
bool setMessageDisplayed(const std::string& accountID, const std::string& contactId, const std::string& messageId, const int32_t& status);
bool setMessageDisplayed(const std::string& accountID, const std::string& conversationUri, const std::string& messageId, const int32_t& status);
std::vector<std::string> getSupportedCiphers(const std::string& accountID);
std::vector<unsigned> getCodecList();
std::vector<std::string> getSupportedTlsMethod();

View File

@ -34,7 +34,7 @@ public:
virtual void registrationStateChanged(const std::string& account_id, const std::string& state, int code, const std::string& detail_str){}
virtual void volatileAccountDetailsChanged(const std::string& account_id, const std::map<std::string, std::string>& details){}
virtual void incomingAccountMessage(const std::string& /*account_id*/, const std::string& /*message_id*/, const std::string& /*from*/, const std::map<std::string, std::string>& /*payload*/){}
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, uint64_t /*message_id*/, const std::string& /*to*/, int /*state*/){}
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, const std::string& /*message_id*/, const std::string& /*conversationId*/, const std::string& /*peer*/, int /*state*/){}
virtual void profileReceived(const std::string& /*account_id*/, const std::string& /*from*/, const std::string& /*path*/){}
virtual void composingStatusChanged(const std::string& /*account_id*/, const std::string& /*convId*/, const std::string& /*from*/, int /*state*/){}
virtual void knownDevicesChanged(const std::string& /*account_id*/, const std::map<std::string, std::string>& /*devices*/){}
@ -99,7 +99,7 @@ int getMessageStatus(uint64_t id);
int getMessageStatus(const std::string& accountID, uint64_t id);
bool cancelMessage(const std::string& accountID, uint64_t id);
void setIsComposing(const std::string& accountID, const std::string& to, bool isWriting);
bool setMessageDisplayed(const std::string& accountID, const std::string& contactId, const std::string& messageId, int status);
bool setMessageDisplayed(const std::string& accountID, const std::string& conversationUri, const std::string& messageId, int status);
bool changeAccountPassword(const std::string& accountID, const std::string& password_old, const std::string& password_new);
bool lookupName(const std::string& account, const std::string& nameserver, const std::string& name);
@ -250,7 +250,7 @@ public:
virtual void registrationStateChanged(const std::string& account_id, const std::string& state, int code, const std::string& detail_str){}
virtual void volatileAccountDetailsChanged(const std::string& account_id, const std::map<std::string, std::string>& details){}
virtual void incomingAccountMessage(const std::string& /*account_id*/, const std::string& /*message_id*/, const std::string& /*from*/, const std::map<std::string, std::string>& /*payload*/){}
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, uint64_t /*message_id*/, const std::string& /*to*/, int /*state*/){}
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, const std::string& /*message_id*/, const std::string& /*conversationId*/, const std::string& /*peer*/, int /*state*/){}
virtual void composingStatusChanged(const std::string& /*account_id*/, const std::string& /*convId*/, const std::string& /*from*/, int /*state*/){}
virtual void knownDevicesChanged(const std::string& /*account_id*/, const std::map<std::string, std::string>& /*devices*/){}
virtual void exportOnRingEnded(const std::string& /*account_id*/, int /*state*/, const std::string& /*pin*/){}

View File

@ -270,7 +270,7 @@ void init(ConfigurationCallback* confM, Callback* callM, PresenceCallback* presM
exportable_callback<ConfigurationSignal::ExportOnRingEnded>(bind(&ConfigurationCallback::exportOnRingEnded, confM, _1, _2, _3)),
exportable_callback<ConfigurationSignal::Error>(bind(&ConfigurationCallback::errorAlert, confM, _1)),
exportable_callback<ConfigurationSignal::IncomingAccountMessage>(bind(&ConfigurationCallback::incomingAccountMessage, confM, _1, _2, _3, _4 )),
exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>(bind(&ConfigurationCallback::accountMessageStatusChanged, confM, _1, _2, _3, _4 )),
exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>(bind(&ConfigurationCallback::accountMessageStatusChanged, confM, _1, _2, _3, _4, _5 )),
exportable_callback<ConfigurationSignal::ProfileReceived>(bind(&ConfigurationCallback::profileReceived, confM, _1, _2, _3 )),
exportable_callback<ConfigurationSignal::ComposingStatusChanged>(bind(&ConfigurationCallback::composingStatusChanged, confM, _1, _2, _3, _4 )),
exportable_callback<ConfigurationSignal::IncomingTrustRequest>(bind(&ConfigurationCallback::incomingTrustRequest, confM, _1, _2, _3, _4 )),

View File

@ -330,10 +330,10 @@ registeredNameFound(const std::string& accountId,
uv_async_send(&signalAsync);
}
void accountMessageStatusChanged(const std::string& account_id, uint64_t message_id, const std::string& to, int state) {
void accountMessageStatusChanged(const std::string& account_id, const std::string& message_id, const std::string& conversationId, const std::string& peer, int state) {
std::lock_guard<std::mutex> lock(pendingSignalsLock);
pendingSignals.emplace([account_id, message_id, to, state]() {
pendingSignals.emplace([account_id, message_id, peer, state]() {
Local<Function> func = Local<Function>::New(Isolate::GetCurrent(), accountMessageStatusChangedCb);
if (!func.IsEmpty()) {
Local<Value> callback_args[] = {V8_STRING_NEW_LOCAL(account_id), SWIGV8_INTEGER_NEW_UNS(message_id), V8_STRING_NEW_LOCAL(to), SWIGV8_INTEGER_NEW(state)};

View File

@ -33,7 +33,8 @@ public:
virtual void registrationStateChanged(const std::string& account_id, const std::string& state, int code, const std::string& detail_str){}
virtual void volatileAccountDetailsChanged(const std::string& account_id, const std::map<std::string, std::string>& details){}
virtual void incomingAccountMessage(const std::string& /*account_id*/, const std::string& /*from*/, const std::map<std::string, std::string>& /*payload*/){}
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, uint64_t /*message_id*/, const std::string& /*to*/, int /*state*/){}
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, const std::string& /*message_id*/, const std::string& /*conversationId*/, const std::string& /*peer*/, int /*state*/){}
virtual void profileReceived(const std::string& /*account_id*/, const std::string& /*from*/, const std::string& /*path*/){}
virtual void knownDevicesChanged(const std::string& /*account_id*/, const std::map<std::string, std::string>& /*devices*/){}
virtual void exportOnRingEnded(const std::string& /*account_id*/, int /*state*/, const std::string& /*pin*/){}
@ -90,7 +91,7 @@ std::vector<Message> getLastMessages(const std::string& accountID, const uint64_
int getMessageStatus(uint64_t id);
int getMessageStatus(const std::string& accountID, uint64_t id);
bool cancelMessage(const std::string& accountID, uint64_t id);
bool setMessageDisplayed(const std::string& accountID, const std::string& contactId, const std::string& messageId, int status);
bool setMessageDisplayed(const std::string& accountID, const std::string& conversationUri, const std::string& messageId, int status);
bool lookupName(const std::string& account, const std::string& nameserver, const std::string& name);
bool lookupAddress(const std::string& account, const std::string& nameserver, const std::string& address);
bool registerName(const std::string& account, const std::string& password, const std::string& name);
@ -231,7 +232,12 @@ public:
virtual void registrationStateChanged(const std::string& account_id, const std::string& state, int code, const std::string& detail_str){}
virtual void volatileAccountDetailsChanged(const std::string& account_id, const std::map<std::string, std::string>& details){}
virtual void incomingAccountMessage(const std::string& /*account_id*/, const std::string& /*from*/, const std::map<std::string, std::string>& /*payload*/){}
<<<<<<< HEAD
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, uint64_t /*message_id*/, const std::string& /*to*/, int /*state*/){}
=======
virtual void accountMessageStatusChanged(const std::string& /*account_id*/, const std::string& /*message_id*/, const std::string& /*conversationId*/, const std::string& /*peer*/, int /*state*/){}
virtual void profileReceived(const std::string& /*account_id*/, const std::string& /*from*/, const std::string& /*path*/){}
>>>>>>> 503df0a61 (swarm: relink setMessageDisplayed)
virtual void knownDevicesChanged(const std::string& /*account_id*/, const std::map<std::string, std::string>& /*devices*/){}
virtual void exportOnRingEnded(const std::string& /*account_id*/, int /*state*/, const std::string& /*pin*/){}

View File

@ -139,7 +139,8 @@ void init(const SWIGV8_VALUE& funcMap){
exportable_callback<ConfigurationSignal::VolatileDetailsChanged>(bind(&volatileDetailsChanged, _1, _2)),
exportable_callback<ConfigurationSignal::KnownDevicesChanged>(bind(&knownDevicesChanged, _1, _2 )),
exportable_callback<ConfigurationSignal::IncomingAccountMessage>(bind(&incomingAccountMessage, _1, _2, _3, _4 )),
exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>(bind(&accountMessageStatusChanged, _1, _2, _3, _4 )),
exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>(bind(&accountMessageStatusChanged, _1, _2, _3, _4, _5 )),
exportable_callback<ConfigurationSignal::ProfileReceived>(bind(&profileReceived, _1, _2, _3, _4 )),
exportable_callback<ConfigurationSignal::IncomingTrustRequest>(bind(&incomingTrustRequest, _1, _2, _3, _4 )),
};

View File

@ -189,6 +189,8 @@ libring_la_SOURCES = \
scheduled_executor.h \
scheduled_executor.cpp \
transport/peer_channel.h \
uri.h \
uri.cpp \
vcard.h
if HAVE_WIN32

View File

@ -185,7 +185,7 @@ public:
const std::string& /*peer*/,
bool /*isWriting*/);
virtual bool setMessageDisplayed(const std::string& /*contactId*/,
virtual bool setMessageDisplayed(const std::string& /*conversationUri*/,
const std::string& /*messageId*/,
int /*status*/)
{

View File

@ -292,12 +292,12 @@ setIsComposing(const std::string& accountID, const std::string& to, bool isWriti
bool
setMessageDisplayed(const std::string& accountID,
const std::string& contactId,
const std::string& conversationUri,
const std::string& messageId,
int status)
{
if (const auto acc = jami::Manager::instance().getAccount(accountID))
return acc->setMessageDisplayed(contactId, messageId, status);
return acc->setMessageDisplayed(conversationUri, messageId, status);
return false;
}

View File

@ -104,7 +104,7 @@ DRING_PUBLIC void setIsComposing(const std::string& accountID,
const std::string& to,
bool isWriting);
DRING_PUBLIC bool setMessageDisplayed(const std::string& accountID,
const std::string& contactId,
const std::string& conversationUri,
const std::string& messageId,
int status);
@ -381,8 +381,9 @@ struct DRING_PUBLIC ConfigurationSignal
{
constexpr static const char* name = "AccountMessageStatusChanged";
using cb_type = void(const std::string& /*account_id*/,
uint64_t /*message_id*/,
const std::string& /*to*/,
const std::string& /*message_id*/,
const std::string& /*conversation_id*/,
const std::string& /*peer*/,
int /*state*/);
};
struct DRING_PUBLIC ProfileReceived

View File

@ -102,7 +102,11 @@ MessageEngine::retrySend(const std::string& peer, bool retryOnTimeout)
for (const auto& p : pending) {
JAMI_DBG() << "[message " << p.token << "] Retry sending";
emitSignal<DRing::ConfigurationSignal::AccountMessageStatusChanged>(
account_.getAccountID(), p.token, p.to, (int) DRing::Account::MessageStates::SENDING);
account_.getAccountID(),
"",
std::to_string(p.token),
p.to,
(int) DRing::Account::MessageStates::SENDING);
account_.sendTextMessage(p.to, p.payloads, p.token, retryOnTimeout);
}
}
@ -129,7 +133,8 @@ MessageEngine::cancel(MessageToken t)
m->second.status = MessageStatus::CANCELLED;
emitSignal<DRing::ConfigurationSignal::AccountMessageStatusChanged>(
account_.getAccountID(),
t,
"",
std::to_string(t),
m->second.to,
static_cast<int>(DRing::Account::MessageStates::CANCELLED));
save_();
@ -157,7 +162,8 @@ MessageEngine::onMessageSent(const std::string& peer, MessageToken token, bool o
JAMI_DBG() << "[message " << token << "] Status changed to SENT";
emitSignal<DRing::ConfigurationSignal::AccountMessageStatusChanged>(
account_.getAccountID(),
token,
"",
std::to_string(token),
f->second.to,
static_cast<int>(DRing::Account::MessageStates::SENT));
save_();
@ -166,7 +172,8 @@ MessageEngine::onMessageSent(const std::string& peer, MessageToken token, bool o
JAMI_DBG() << "[message " << token << "] Status changed to FAILURE";
emitSignal<DRing::ConfigurationSignal::AccountMessageStatusChanged>(
account_.getAccountID(),
token,
"",
std::to_string(token),
f->second.to,
static_cast<int>(DRing::Account::MessageStates::FAILURE));
save_();
@ -190,7 +197,8 @@ MessageEngine::onMessageDisplayed(const std::string& peer, MessageToken token, b
JAMI_DBG() << "[message " << token << "] Displayed by peer";
emitSignal<DRing::ConfigurationSignal::AccountMessageStatusChanged>(
account_.getAccountID(),
token,
"", /* No related conversation */
std::to_string(token),
peer,
static_cast<int>(DRing::Account::MessageStates::DISPLAYED));
}

View File

@ -37,6 +37,7 @@
#include "fileutils.h"
#include "sip_utils.h"
#include "utf8_utils.h"
#include "uri.h"
#include "manager.h"
#ifdef ENABLE_PLUGIN
@ -136,15 +137,16 @@ getIsComposing(const std::string& conversationId, bool isWriting)
}
std::string
getDisplayed(const std::string& messageId)
getDisplayed(const std::string& conversationId, const std::string& messageId)
{
// implementing https://tools.ietf.org/rfc/rfc5438.txt
return fmt::format(
"<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
"<imdn><message-id>{}</message-id>\n"
"<display-notification><status><displayed/></status></display-notification>\n"
"</imdn>",
messageId);
return fmt::format("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n"
"<imdn><message-id>{}</message-id>\n"
"{}"
"<display-notification><status><displayed/></status></display-notification>\n"
"</imdn>",
messageId,
conversationId.empty()? "" : "<conversation>" + conversationId + "</conversation>");
}
void
@ -571,7 +573,28 @@ SIPAccountBase::onTextMessage(const std::string& id,
JAMI_WARN("Message displayed: can't parse status");
continue;
}
messageEngine_.onMessageDisplayed(from, from_hex_string(messageId), isDisplayed);
static const std::regex CONVID_REGEX(
"<conversation>\\s*(\\w+)\\s*<\\/conversation>");
std::regex_search(m.second, matched_pattern, CONVID_REGEX);
std::string conversationId = "";
if (matched_pattern.ready() && !matched_pattern.empty()
&& matched_pattern[1].matched) {
conversationId = matched_pattern[1];
}
if (conversationId.empty()) // Old method
messageEngine_.onMessageDisplayed(from, from_hex_string(messageId), isDisplayed);
else if (isDisplayed) {
JAMI_DBG() << "[message " << messageId << "] Displayed by peer";
emitSignal<DRing::ConfigurationSignal::AccountMessageStatusChanged>(
accountID_,
messageId,
conversationId,
from,
static_cast<int>(DRing::Account::MessageStates::DISPLAYED));
return;
}
if (payloads.size() == 1)
return;
} catch (const std::exception& e) {
@ -637,12 +660,17 @@ SIPAccountBase::onTextMessage(const std::string& id,
}
bool
SIPAccountBase::setMessageDisplayed(const std::string& contactId,
SIPAccountBase::setMessageDisplayed(const std::string& conversationUri,
const std::string& messageId,
int status)
{
Uri uri(conversationUri);
std::string conversationId = {};
if (uri.scheme() == Uri::Scheme::SWARM)
conversationId = uri.authority();
if (status == (int) DRing::Account::MessageStates::DISPLAYED)
sendTextMessage(contactId, {{MIME_TYPE_IMDN, getDisplayed(messageId)}});
sendInstantMessage(uri.authority(),
{{MIME_TYPE_IMDN, getDisplayed(conversationId, messageId)}});
return true;
}

View File

@ -272,7 +272,7 @@ public:
void setIsComposing(const std::string& to, bool isWriting) override;
bool setMessageDisplayed(const std::string& contactId,
bool setMessageDisplayed(const std::string& conversationUri,
const std::string& messageId,
int status) override;

79
src/uri.cpp Normal file
View File

@ -0,0 +1,79 @@
/*
* Copyright (C) 2021 Savoir-faire Linux Inc.
*
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "uri.h"
namespace jami {
Uri::Uri(const std::string_view& uri)
{
// TODO better handling of Uri, for now it's only used for
// setMessageDisplayed to differentiate swarm:xxx
scheme_ = Uri::Scheme::JAMI;
auto posSep = uri.find(':');
if (posSep != std::string::npos) {
auto scheme_str = uri.substr(0, posSep);
if (scheme_str == "sip")
scheme_ = Uri::Scheme::SIP;
else if (scheme_str == "swarm")
scheme_ = Uri::Scheme::SWARM;
else if (scheme_str == "jami")
scheme_ = Uri::Scheme::JAMI;
else
scheme_ = Uri::Scheme::UNRECOGNIZED;
authority_ = uri.substr(posSep + 1);
} else {
authority_ = uri;
}
}
const std::string&
Uri::authority() const
{
return authority_;
}
Uri::Scheme
Uri::scheme() const
{
return scheme_;
}
std::string
Uri::toString() const
{
return schemeToString() + ":" + authority_;
}
std::string
Uri::schemeToString() const
{
switch (scheme_) {
case Uri::Scheme::SIP:
return "sip";
case Uri::Scheme::SWARM:
return "swarm";
case Uri::Scheme::JAMI:
case Uri::Scheme::UNRECOGNIZED:
default:
return "jami";
}
}
} // namespace jami

49
src/uri.h Normal file
View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2021 Savoir-faire Linux Inc.
*
* Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#pragma once
#include <string>
#include <string_view>
namespace jami {
class Uri
{
public:
enum class Scheme {
JAMI, // Start with "jami:" and 45 ASCII chars OR 40 ASCII chars
SIP, // Start with "sip:"
SWARM, // Start with "swarm:" and 40 ASCII chars
UNRECOGNIZED // Anything that doesn't fit in other categories
};
Uri(const std::string_view& uri);
const std::string& authority() const;
Scheme scheme() const;
std::string toString() const;
// TODO hostname, transport, handle sip:
private:
std::string schemeToString() const;
Scheme scheme_;
std::string authority_;
};
} // namespace jami

View File

@ -109,6 +109,7 @@ private:
void testSendMessageToMultipleParticipants();
void testPingPongMessages();
void testIsComposing();
void testSetMessageDisplayed();
void testRemoveMember();
void testMemberBanNoBadFile();
void testMemberTryToRemoveAdmin();
@ -170,6 +171,7 @@ private:
CPPUNIT_TEST(testSendMessageToMultipleParticipants);
CPPUNIT_TEST(testPingPongMessages);
CPPUNIT_TEST(testIsComposing);
CPPUNIT_TEST(testSetMessageDisplayed);
CPPUNIT_TEST(testRemoveMember);
CPPUNIT_TEST(testMemberBanNoBadFile);
CPPUNIT_TEST(testMemberTryToRemoveAdmin);
@ -1169,6 +1171,79 @@ ConversationTest::testIsComposing()
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return !aliceComposing; }));
}
void
ConversationTest::testSetMessageDisplayed()
{
auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
auto aliceUri = aliceAccount->getUsername();
auto bobUri = bobAccount->getUsername();
auto convId = aliceAccount->startConversation();
std::mutex mtx;
std::unique_lock<std::mutex> lk {mtx};
std::condition_variable cv;
std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
bool conversationReady = false, requestReceived = false, memberMessageGenerated = false,
msgDisplayed = false;
confHandlers.insert(
DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
[&](const std::string& /*accountId*/,
const std::string& /* conversationId */,
std::map<std::string, std::string> /*metadatas*/) {
requestReceived = true;
cv.notify_one();
}));
confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
[&](const std::string& accountId, const std::string& conversationId) {
if (accountId == bobId && conversationId == convId) {
conversationReady = true;
cv.notify_one();
}
}));
confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::MessageReceived>(
[&](const std::string& accountId,
const std::string& conversationId,
std::map<std::string, std::string> message) {
if (accountId == aliceId && conversationId == convId && message["type"] == "member") {
memberMessageGenerated = true;
cv.notify_one();
}
}));
confHandlers.insert(
DRing::exportable_callback<DRing::ConfigurationSignal::AccountMessageStatusChanged>(
[&](const std::string& accountId,
const std::string& msgId,
const std::string& conversationId,
const std::string& peer,
int status) {
if (accountId == bobId && conversationId == convId && msgId == conversationId
&& peer == aliceUri && status == 3) {
msgDisplayed = true;
cv.notify_one();
}
}));
DRing::registerSignalHandlers(confHandlers);
CPPUNIT_ASSERT(aliceAccount->addConversationMember(convId, bobUri));
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(30), [&]() { return memberMessageGenerated; }));
// Assert that repository exists
auto repoPath = fileutils::get_data_dir() + DIR_SEPARATOR_STR + aliceAccount->getAccountID()
+ DIR_SEPARATOR_STR + "conversations" + DIR_SEPARATOR_STR + convId;
CPPUNIT_ASSERT(fileutils::isDirectory(repoPath));
// Check created files
auto bobInvited = repoPath + DIR_SEPARATOR_STR + "invited" + DIR_SEPARATOR_STR + bobUri;
CPPUNIT_ASSERT(fileutils::isFile(bobInvited));
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return requestReceived; }));
memberMessageGenerated = false;
bobAccount->acceptConversationRequest(convId);
CPPUNIT_ASSERT(
cv.wait_for(lk, std::chrono::seconds(30), [&]() { return memberMessageGenerated; }));
aliceAccount->setMessageDisplayed(convId, convId, 3);
CPPUNIT_ASSERT(cv.wait_for(lk, std::chrono::seconds(30), [&]() { return msgDisplayed; }));
DRing::unregisterSignalHandlers();
}
void
ConversationTest::testRemoveMember()
{