Verified Commit c35bf4d4 authored by Phobos D'thorga's avatar Phobos D'thorga 🐲
Browse files

Merge branch 'develop'

parents 46e3e8c0 d6b52794
Pipeline #1008 passed with stages
in 37 minutes and 31 seconds
......@@ -139,6 +139,10 @@ namespace GekkoFyre {
#define GK_XMPP_CREATE_CONN_PROG_BAR_MAX_PERCT (100)
#define GK_XMPP_CREATE_CONN_PROG_BAR_TOT_PERCT (4)
#define GK_XMPP_MAM_BACKLOG_BULK_FETCH_COUNT (125)
#define GK_XMPP_MAM_BACKLOG_FINE_FETCH_COUNT (1)
#define GK_XMPP_MAM_THREAD_SLEEP_MILLISECS (3000)
#define GK_DEFAULT_XMPP_SERVER_PORT (5222)
#define GK_XMPP_AVAIL_COMBO_AVAILABLE_IDX (0)
#define GK_XMPP_AVAIL_COMBO_AWAY_FROM_KB_IDX (1)
......@@ -379,6 +383,8 @@ namespace Filesystem {
constexpr char gk_crashpad_handler_linux[] = "crashpad_handler"; // The name of the Crashpad handler executable under Linux and possibly Unix-like operating systems.
constexpr char linux_sys_tty[] = "/sys/class/tty/"; // The location of the TTY-devices under most major Linux distributions
#define GK_SYSTEM_FILE_LOG_DATA_MAX_SIZE_BYTES (33554432)
}
namespace Network {
......
......@@ -116,6 +116,14 @@ GkEventLogger::GkEventLogger(const QPointer<QSystemTrayIcon> &sysTrayIcon, const
}
gkWriteCsvIo.setFileName(QString::fromStdString(log_data_loc.string()));
if (gkWriteCsvIo.size() > GK_SYSTEM_FILE_LOG_DATA_MAX_SIZE_BYTES) {
bool succ = gkWriteCsvIo.remove();
if (!succ) {
throw std::runtime_error(tr("Unable to delete file, \"%1\", due to its excessive size which exceeds the recommended amount of %2 MB. An error was henceforth encountered.")
.arg(QString::fromStdString(log_data_loc.string()), QString::number(GK_SYSTEM_FILE_LOG_DATA_MAX_SIZE_BYTES)).toStdString());
}
}
if (!gkWriteCsvIo.open(QFile::Append | QFile::Text)) {
throw std::runtime_error(tr("Error with opening File I/O for logging data!").toStdString());
}
......
......@@ -43,6 +43,7 @@
#include <qxmpp/QXmppMucIq.h>
#include <qxmpp/QXmppUtils.h>
#include <qxmpp/QXmppStreamFeatures.h>
#include <chrono>
#include <iostream>
#include <iterator>
#include <exception>
......@@ -149,6 +150,7 @@ GkXmppClient::GkXmppClient(const GkUserConn &connection_details, QPointer<GekkoF
m_askToReconnectAuto = false;
m_sslIsEnabled = false;
m_isMuc = false;
m_msgRecved = false;
sys::error_code ec;
fs::path slash = "/";
native_slash = slash.make_preferred().native();
......@@ -248,6 +250,7 @@ GkXmppClient::GkXmppClient(const GkUserConn &connection_details, QPointer<GekkoF
this, SLOT(archiveListReceived(const QList<QXmppArchiveChat> &, const QXmppResultSetReply &)));
QObject::connect(m_xmppMamMgr.get(), SIGNAL(archivedMessageReceived(const QString &, const QXmppMessage &)),
this, SLOT(archivedMessageReceived(const QString &, const QXmppMessage &)));
QObject::connect(this, SIGNAL(msgRecved(const bool &)), this, SLOT(setMsgRecved(const bool &)));
//
// The spelling mistake for the SIGNAL, QXmppMamManager::resultsRecieved(), seems to be unknowingly intentional by
......@@ -398,8 +401,8 @@ GkXmppClient::GkXmppClient(const GkUserConn &connection_details, QPointer<GekkoF
//
// Enable carbon copies for this client!
m_xmppCarbonMgr->setCarbonsEnabled(true);
QObject::connect(m_xmppCarbonMgr.get(), SIGNAL(messageSent(const QXmppMessage &)), this, SLOT(recvXmppMsgUpdate(const QXmppMessage &)));
QObject::connect(m_xmppCarbonMgr.get(), SIGNAL(messageReceived(const QXmppMessage &)), this, SLOT(recvXmppMsgUpdate(const QXmppMessage &)));
QObject::connect(m_xmppCarbonMgr.get(), &QXmppCarbonManager::messageSent, this, &QXmppClient::messageReceived);
QObject::connect(m_xmppCarbonMgr.get(), &QXmppCarbonManager::messageReceived, this, &QXmppClient::messageReceived);
});
QObject::connect(this, &QXmppClient::disconnected, this, [=]() {
......@@ -975,6 +978,16 @@ QString GkXmppClient::obtainAvatarFilePath()
return filePath;
}
/**
* @brief GkXmppClient::getMsgRecved
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @return
*/
bool GkXmppClient::getMsgRecved() const
{
return m_msgRecved;
}
/**
* @brief GkXmppClient::getArchivedMessagesBulk retrieves archived messages. For each received message, the
* `m_xmppMamMgr->archivedMessageReceived()` signal is emitted. Once all messages are received, the `m_xmppMamMgr->resultsRecieved()`
......@@ -983,33 +996,21 @@ QString GkXmppClient::obtainAvatarFilePath()
* a bulk manner, grabbing what it can and as much of it as possible, quite unlike its cousin function which is much
* more fine-tuned, GkXmppClient::getArchivedMessagesFine().
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param to
* @param node
* @param from
* @param start
* @param end
* @param resultSetQuery
* @see GkXmppClient::getArchivedMessagesFine().
*/
void GkXmppClient::getArchivedMessagesBulk(const QString &to, const QString &node, const QString &from, const QDateTime &start,
const QDateTime &end, const QXmppResultSetQuery &resultSetQuery)
void GkXmppClient::getArchivedMessagesBulk(const QString &from)
{
Q_UNUSED(node);
Q_UNUSED(end);
Q_UNUSED(start);
Q_UNUSED(end);
try {
//
// It is VERY IMPORTANT that we execute this particular function!
updateRecordedMsgHistory(to);
updateRecordedMsgHistory(from);
QXmppResultSetQuery queryLimit;
queryLimit.setBefore("");
queryLimit.setMax(GK_XMPP_MAM_BACKLOG_BULK_FETCH_COUNT);
//
// Retrieve any archived messages from the given XMPP server as according to the specification, XEP-0313!
m_xmppMamMgr->retrieveArchivedMessages(to, "", from, QDateTime::currentDateTime().addDays(-5), QDateTime::currentDateTime(), resultSetQuery);
m_xmppMamMgr->retrieveArchivedMessages({}, {}, from, {}, QDateTime::currentDateTimeUtc(), queryLimit);
} catch (const std::exception &e) {
gkEventLogger->publishEvent(QString::fromStdString(e.what()), GkSeverity::Fatal, "", false, true, false, true, false);
std::throw_with_nested(std::runtime_error(e.what()));
}
return;
......@@ -1019,43 +1020,49 @@ void GkXmppClient::getArchivedMessagesBulk(const QString &to, const QString &nod
* @brief GkXmppClient::getArchivedMessagesFine retrieves archived messages. For each received message, the
* `m_xmppMamMgr->archivedMessageReceived()` signal is emitted. Once all messages are received, the `m_xmppMamMgr->resultsRecieved()`
* signal is emitted. It returns a result set that can be used to page through the results. The number of results may
* be limited by the server. This particular function tries to selectively receive only a few archived messages at a
* time, quite unlike its cousin function, GkXmppClient::getArchivedMessagesBulk().
* be limited by the server. This function in particular tries to receive a particular set of the archived messages in
* question via a filtered manner, grabbing what it via calculated QDateTime's, quite unlike its cousin function which is
* more for grabbing a bulk amount of messages, GkXmppClient::getArchivedMessagesBulk().
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param to
* @param node
* @param from
* @param start
* @param end
* @param resultSetQuery
* @see GkXmppClient::getArchivedMessagesBulk().
* @param recursion The amount of times this function has been recurisvely executed.
* @param from The bareJid we are receiving from.
* @param preset_time A pre-calculated time to use instead that is faster and more reliable, provided it's available.
* @see GkXmppClient::getArchivedMessagesBulk()
*/
void GkXmppClient::getArchivedMessagesFine(const QString &to, const QString &node, const QString &from,
const QDateTime &start, const QDateTime &end,
const QXmppResultSetQuery &resultSetQuery)
void GkXmppClient::getArchivedMessagesFine(qint32 recursion, const QString &from, const QDateTime &preset_time)
{
Q_UNUSED(node);
Q_UNUSED(end);
try {
if (!m_rosterList.isEmpty()) {
updateRecordedMsgHistory(from); // It is VERY IMPORTANT that we execute this function!
QDateTime min_timestamp;
if (start.isValid()) {
min_timestamp = start;
} else {
min_timestamp = calcMinTimestampForXmppMsgHistory(from, m_rosterList);
}
QXmppResultSetQuery queryLimit;
queryLimit.setBefore("");
queryLimit.setMax(GK_XMPP_MAM_BACKLOG_FINE_FETCH_COUNT);
gkEventLogger->publishEvent(tr("Minimum date required for message archive retrieval is: %1").arg(QDateTime(min_timestamp).toString("dd MMM yyyy @ hh:mm:ss.zzz")),
GkSeverity::Debug, "", false, true, false, false);
//
// Calculate the most minimum timestamp we can possibly use, therefore minimizing the amount of bandwidth used to
// download archived messages over the Internet!
QDateTime min_time;
if (preset_time.isValid() && !preset_time.isNull()) {
min_time = preset_time;
} else {
min_time = calcMinTimestampForXmppMsgHistory(from, m_rosterList);
}
if (!min_time.isValid() || min_time.isNull()) {
throw std::invalid_argument(tr("Unable to calculate a minimum time value for grabbing newly archived messages from the given XMPP server!").toStdString());
}
gkEventLogger->publishEvent(tr("Most minimum XEP-0313 timestamp calculated for user, \"%1\", is: %2.").arg(from, min_time.toLocalTime().toString()),
GkSeverity::Debug, "", false, true, false, false, false);
while (!m_msgRecved) {
//
// Retrieve any archived messages from the given XMPP server as according to the specification, XEP-0313!
m_xmppMamMgr->retrieveArchivedMessages(to, "", from, min_timestamp, QDateTime::currentDateTime(), resultSetQuery);
m_xmppMamMgr->retrieveArchivedMessages({}, {}, from, min_time, QDateTime::currentDateTimeUtc(), queryLimit);
std::this_thread::sleep_for(std::chrono::milliseconds(GK_XMPP_MAM_THREAD_SLEEP_MILLISECS));
}
} catch (const std::exception &e) {
gkEventLogger->publishEvent(QString::fromStdString(e.what()), GkSeverity::Fatal, "", false, true, false, true, false);
return;
} catch (const std:: exception &e) {
std::throw_with_nested(std::runtime_error(e.what()));
}
return;
......@@ -1550,6 +1557,19 @@ void GkXmppClient::sendXmppMsg(const QXmppMessage &msg)
{
if (msg.isXmppStanza()) {
const bool msg_sent_succ = sendPacket(msg);
if (msg_sent_succ) {
if (m_archivedMsgsFineThread.joinable()) {
m_archivedMsgsFineThread.join();
}
if (!m_archivedMsgsFineThread.joinable()) {
const QDateTime curr_time = QDateTime::currentDateTimeUtc();
m_archivedMsgsFineThread = std::thread(&GkXmppClient::getArchivedMessagesFine, this, 0, msg.to(), curr_time);
m_archivedMsgsFineThread.detach();
}
emit msgRecved(false);
}
}
return;
......@@ -1673,7 +1693,7 @@ void GkXmppClient::handleError(const QString &errorMsg)
}
std::cerr << errorMsg.toStdString() << std::endl;
QMessageBox::warning(nullptr, tr("Error!"), errorMsg, QMessageBox::Ok);
gkEventLogger->publishEvent(errorMsg, GkSeverity::Fatal, "", false, true, false, true, false);
}
return;
......@@ -2275,6 +2295,7 @@ void GkXmppClient::resultsReceived(const QString &queryId, const QXmppResultSetR
for (auto filter = m_filterArchivedMsgFut.begin(); filter != m_filterArchivedMsgFut.end(); ++filter) {
const bool result = filter->second.get();
if (result) { // The message therefore does not exist within memory (i.e. `m_rosterList`) already!
emit procXmppMsg(filter->first, false);
insertArchiveMessage(filter->first);
}
}
......@@ -2334,6 +2355,21 @@ void GkXmppClient::updateRecordedMsgHistory(const QString &bareJid)
return;
}
/**
* @brief GkXmppClient::setMsgRecved
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param setValid
*/
void GkXmppClient::setMsgRecved(const bool &setValid)
{
m_msgRecved = false;
if (setValid) {
m_msgRecved = true;
}
return;
}
/**
* @brief GkXmppClient::filterArchivedMessage filters archived messages according to XMPP standard, XEP-0313, as they
* come in via functions, GkXmppClient::getArchivedMessagesBulk() and/or GkXmppClient::getArchivedMessagesFine(), to see
......@@ -2349,16 +2385,15 @@ bool GkXmppClient::filterArchivedMessage(const QList<GekkoFyre::Network::GkXmpp:
try {
for (const auto &roster: rosterList) {
if (roster.bareJid == message.to()) {
if (message.isXmppStanza() && !message.body().isEmpty()) {
if (message.isXmppStanza() && !message.body().isEmpty() && !message.id().isEmpty()) {
for (const auto &existing: roster.messages) {
if (existing.message.stamp() != message.stamp() && existing.message.body() != message.body()) { // Message identifiers are shared across carbon copies, so be aware of this fact!
m_sharedMessageIdentifiers.insert(existing.message.stamp().toMSecsSinceEpoch(), std::make_pair(false, existing.message));
if (existing.message.id() != message.id()) { // Message identifiers are shared across carbon copies, so be aware of this fact!
return true; // Return the fact that the object did not originally exist in memory...
}
return false; // The object already existed in memory
}
}
return false; // The object already existed in memory
}
}
......@@ -2367,36 +2402,22 @@ bool GkXmppClient::filterArchivedMessage(const QList<GekkoFyre::Network::GkXmpp:
//
for (const auto &roster: rosterList) {
if (roster.bareJid == message.from()) {
if (message.isXmppStanza() && !message.body().isEmpty()) {
if (message.isXmppStanza() && !message.body().isEmpty() && !message.id().isEmpty()) {
for (const auto &existing: roster.messages) {
if (existing.message.stamp() != message.stamp() && existing.message.body() != message.body()) {
if (existing.message.id() != message.id()) {
return true;
}
//
// Test whether a carbon copy (if applicable) already exists in memory or not, according to its
// specific circumstances!
for (auto sharedMsg = m_sharedMessageIdentifiers.begin(); sharedMsg != m_sharedMessageIdentifiers.end(); ++sharedMsg) {
if (sharedMsg->second.to() == roster.bareJid) {
if (sharedMsg.key() == existing.message.stamp().toMSecsSinceEpoch()) { // Do the unique identifiers match?
if (!sharedMsg->first) { // The object does not exist in memory yet!
sharedMsg->first = true; // Mark the object as existing in memory!
return true; // Return the fact that the object did not originally exist in memory...
}
}
}
}
return false; // The object already existed in memory
}
}
return false; // The object already existed in memory
}
}
} catch (const std::exception &e) {
gkEventLogger->publishEvent(e.what(), GkSeverity::Fatal, "", false, true, false, true);
}
return false;
return false; // Something has gone wrong without being detected?
}
/**
......
......@@ -138,21 +138,25 @@ public:
//
// User, roster and presence details
std::shared_ptr<QXmppRegistrationManager> getRegistrationMgr();
QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> getRosterMap();
[[nodiscard]] std::shared_ptr<QXmppRegistrationManager> getRegistrationMgr();
[[nodiscard]] QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> getRosterMap();
void updateRosterMap(const QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> &rosterList);
QXmppPresence statusToPresence(const Network::GkXmpp::GkOnlineStatus &status);
Network::GkXmpp::GkOnlineStatus presenceToStatus(const QXmppPresence::AvailableStatusType &xmppPresence);
QString presenceToString(const QXmppPresence::AvailableStatusType &xmppPresence);
QIcon presenceToIcon(const QXmppPresence::AvailableStatusType &xmppPresence);
[[nodiscard]] QXmppPresence statusToPresence(const Network::GkXmpp::GkOnlineStatus &status);
[[nodiscard]] Network::GkXmpp::GkOnlineStatus presenceToStatus(const QXmppPresence::AvailableStatusType &xmppPresence);
[[nodiscard]] QString presenceToString(const QXmppPresence::AvailableStatusType &xmppPresence);
[[nodiscard]] QIcon presenceToIcon(const QXmppPresence::AvailableStatusType &xmppPresence);
bool deleteUserAccount();
QString obtainAvatarFilePath();
[[nodiscard]] QString obtainAvatarFilePath();
//
// Message and QXmppMamManager handling
[[nodiscard]] bool getMsgRecved() const;
//
// vCard management
QByteArray processImgToByteArray(const QString &filePath);
[[nodiscard]] QByteArray processImgToByteArray(const QString &filePath);
QString getErrorCondition(const QXmppStanza::Error::Condition &condition);
[[nodiscard]] QString getErrorCondition(const QXmppStanza::Error::Condition &condition);
public slots:
void clientConnected();
......@@ -181,12 +185,7 @@ public slots:
//
// QXmppMamManager handling
void getArchivedMessagesBulk(const QString &to = QString(), const QString &node = QString(), const QString &from = QString(),
const QDateTime &start = QDateTime(), const QDateTime &end = QDateTime(),
const QXmppResultSetQuery &resultSetQuery = QXmppResultSetQuery());
void getArchivedMessagesFine(const QString &to = QString(), const QString &node = QString(), const QString &from = QString(),
const QDateTime &start = QDateTime(), const QDateTime &end = QDateTime(),
const QXmppResultSetQuery &resultSetQuery = QXmppResultSetQuery());
void getArchivedMessagesBulk(const QString &from = QString());
//
// Message handling
......@@ -235,6 +234,7 @@ private slots:
void archivedMessageReceived(const QString &queryId, const QXmppMessage &message);
void resultsReceived(const QString &queryId, const QXmppResultSetReply &resultSetReply, bool complete);
void updateRecordedMsgHistory(const QString &bareJid);
void setMsgRecved(const bool &setValid);
signals:
//
......@@ -271,11 +271,13 @@ signals:
void updateMsgHistory();
//
// QXmppMamManager handling
// Message handling and QXmppMamManager handling
void msgArchiveSuccReceived();
void procXmppMsg(const QXmppMessage &msg, const bool &wipeExistingHistory = false);
void msgRecved(const bool &setValid);
private:
bool filterArchivedMessage(const QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> &rosterList, const QXmppMessage &message);
[[nodiscard]] bool filterArchivedMessage(const QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> &rosterList, const QXmppMessage &message);
void insertArchiveMessage(const QXmppMessage &message);
QPointer<GekkoFyre::GkLevelDb> gkDb;
......@@ -310,10 +312,6 @@ private:
QVector<QString> m_blockList;
QList<GekkoFyre::Network::GkXmpp::GkXmppCallsign> m_rosterList; // A list of all the bareJids, including the client themselves!
//
// QXmppMamManager handling
QMap<qint64, std::pair<bool, QXmppMessage>> m_sharedMessageIdentifiers; // The key is the unique message timestamp and the value consists of whether the message already exists in memory!
//
// Filesystem & Directories
//
......@@ -335,10 +333,17 @@ private:
//
std::queue<QXmppPresence::AvailableStatusType> m_availStatusTypeQueue;
//
// Message handling
void getArchivedMessagesFine(qint32 recursion, const QString &from = QString(), const QDateTime &preset_time = {});
bool m_msgRecved;
//
// Multithreading, mutexes, etc.
//
std::mutex m_updateRosterMapMtx;
std::mutex m_archivedMsgsFineMtx;
std::thread m_archivedMsgsFineThread;
std::vector<std::pair<QXmppMessage, std::future<bool>>> m_filterArchivedMsgFut;
//
......
......@@ -267,7 +267,7 @@ QVariant GkXmppRecvMsgsTableViewModel::data(const QModelIndex &index, int role)
switch (index.column()) {
case GK_XMPP_RECV_MSGS_TABLEVIEW_MODEL_DATETIME_IDX:
return row_timestamp.toString("[ dd MMM yy ] h:mm:ss ap");
return row_timestamp.toLocalTime().toString("[ dd MMM yy ] h:mm:ss ap");
case GK_XMPP_RECV_MSGS_TABLEVIEW_MODEL_NICKNAME_IDX:
return row_nickname;
case GK_XMPP_RECV_MSGS_TABLEVIEW_MODEL_MSG_IDX:
......
......@@ -111,10 +111,6 @@ GkXmppMessageDialog::GkXmppMessageDialog(QPointer<GekkoFyre::StringFuncs> string
m_xmppClient = std::move(xmppClient);
m_bareJids = bareJids;
//
// Initialize any boolean values...
startupSucc = false; // Has startup of this class already succeeded?
//
// Setup and initialize signals and slots...
QObject::connect(this, SIGNAL(updateToolbar(const QString &)), this, SLOT(updateToolbarStatus(const QString &)));
......@@ -122,8 +118,9 @@ GkXmppMessageDialog::GkXmppMessageDialog(QPointer<GekkoFyre::StringFuncs> string
QObject::connect(m_xmppClient, SIGNAL(xmppMsgUpdate(const QXmppMessage &)), this, SLOT(recvXmppMsg(const QXmppMessage &)));
QObject::connect(m_xmppClient, SIGNAL(updateMsgHistory()), this, SLOT(updateMsgHistory()));
QObject::connect(m_xmppClient, SIGNAL(msgArchiveSuccReceived()), this, SLOT(msgArchiveSuccReceived()));
QObject::connect(this, SIGNAL(updateMamArchive(const bool &)),
this, SLOT(procMamArchive(const bool &)));
QObject::connect(m_xmppClient, SIGNAL(procXmppMsg(const QXmppMessage &, const bool &)),
this, SLOT(getArchivedMessagesFromDb(const QXmppMessage &, const bool &)));
QObject::connect(this, SIGNAL(msgRecved(const bool &)), m_xmppClient, SIGNAL(msgRecved(const bool &)));
//
// Setup and initialize QTableView's...
......@@ -162,7 +159,7 @@ GkXmppMessageDialog::GkXmppMessageDialog(QPointer<GekkoFyre::StringFuncs> string
if (m_xmppClient->isConnected()) {
ui->textEdit_tx_msg_dialog->setEnabled(true);
getArchivedMessages(); // Gather anything possible from the Google LevelDB database!
dlArchivedMessages(); // Gather anything possible from the Google LevelDB database!
}
QObject::connect(m_xmppClient, &QXmppClient::connected, this, [=]() {
......@@ -170,7 +167,7 @@ GkXmppMessageDialog::GkXmppMessageDialog(QPointer<GekkoFyre::StringFuncs> string
//
// Now gather any data possible from the given XMPP server via the Internet!
getArchivedMessages();
dlArchivedMessages();
});
QObject::connect(m_xmppClient, &QXmppClient::disconnected, this, [=]() {
......@@ -370,7 +367,6 @@ void GkXmppMessageDialog::submitMsgEnterKey()
const auto toMsg = createXmppMessageIq(bareJid, gkConnDetails.jid, plaintext);
if (toMsg.isXmppStanza()) {
emit sendXmppMsg(toMsg);
m_xmppClient->getArchivedMessagesFine(gkConnDetails.jid, QString(), bareJid);
}
}
}
......@@ -444,6 +440,7 @@ void GkXmppMessageDialog::recvXmppMsg(const QXmppMessage &msg)
*/
void GkXmppMessageDialog::procMsgArchive(const QString &bareJid)
{
// TODO: Refactor this code!
auto rosterMap = m_xmppClient->getRosterMap();
if (!rosterMap.isEmpty()) {
gkXmppRecvMsgsTableViewModel.clear();
......@@ -489,11 +486,12 @@ QXmppMessage GkXmppMessageDialog::createXmppMessageIq(const QString &to, const Q
QUuid uuid = QUuid::createUuid();
QXmppMessage xmppMsg;
xmppMsg.setId(uuid.toString());
xmppMsg.setStamp(QDateTime::currentDateTimeUtc());
xmppMsg.setFrom(from);
xmppMsg.setTo(to);
xmppMsg.setBody(message);
xmppMsg.setPrivate(false);
xmppMsg.setReceiptRequested(true);
// xmppMsg.setReceiptRequested(true);
xmppMsg.setType(QXmppMessage::Chat);
return xmppMsg;
......@@ -505,35 +503,7 @@ QXmppMessage GkXmppMessageDialog::createXmppMessageIq(const QString &to, const Q
*/
void GkXmppMessageDialog::msgArchiveSuccReceived()
{
if (!startupSucc) {
emit updateMamArchive(true);
for (const auto &bareJid: m_bareJids) {
emit updateMamArchive(false);
}
startupSucc = true;
}
return;
}
/**
* @brief GkXmppMessageDialog::procMamArchive is a helper class for dealing with the processing of recorded messages that
* have been archived to a given XMPP server, according to specification, XEP-0313 (Message Archive Management).
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param wipeExistingHistory Whether to wipe the pre-existing chat history or not, specifically from the given QTableView
* object, GekkoFyre::GkXmppRecvMsgsTableViewModel().
*/
void GkXmppMessageDialog::procMamArchive(const bool &wipeExistingHistory)
{
try {
if (!startupSucc) {
getArchivedMessagesFromDb(true, wipeExistingHistory);
}
} catch (const std::exception &e) {
gkStringFuncs->print_exception(e);
}
gkEventLogger->publishEvent(tr("New message received!"), GkSeverity::Info, "", true, true, false, false, true);
return;
}
......@@ -541,10 +511,10 @@ void GkXmppMessageDialog::procMamArchive(const bool &wipeExistingHistory)
* @brief GkXmppMessageDialog::getArchivedMessagesBulk
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
*/
void GkXmppMessageDialog::getArchivedMessages()
void GkXmppMessageDialog::dlArchivedMessages()
{
for (const auto &bareJid: m_bareJids) {
m_xmppClient->getArchivedMessagesBulk(gkConnDetails.jid, QString(), bareJid); // Get archived messages sent by the Jid in question!
m_xmppClient->getArchivedMessagesBulk(bareJid); // Get archived messages sent by the Jid in question!
}
return;
......@@ -557,46 +527,26 @@ void GkXmppMessageDialog::getArchivedMessages()
* again.
* NOTE: The Google LevelDB functionality is currently disabled!
* @author Phobos A. D'thorga <phobos.gekko@gekkofyre.io>
* @param insertData Whether to insert the archived messages into the given QTableView or not.
* @param message The QXmppMessage stanza itself to be inserted into the QTableView model, GekkoFyre::GkXmppRecvMsgsTableViewModel().
* @param wipeExistingHistory Whether to wipe the pre-existing chat history or not, specifically from the given QTableView
* object, GekkoFyre::GkXmppRecvMsgsTableViewModel().
* @param updateSortFilterProxy Should the QSortFilterProxyModel for the QTableView be updated and reset back to its beginning
* values (please use this sparingly because of required system resources for calculations!)?
*/
void GkXmppMessageDialog::getArchivedMessagesFromDb(const bool &insertData, const bool &wipeExistingHistory,
const bool &updateSortFilterProxy)
void GkXmppMessageDialog::getArchivedMessagesFromDb(const QXmppMessage &message, const bool &wipeExistingHistory)
{
try {
auto rosterMap = m_xmppClient->getRosterMap(); // Grab the `GkXmppCallsign()` object and temporarily store it in memory for just use in this function!
if (!rosterMap.isEmpty()) {
std::lock_guard<std::mutex> lock_guard(m_archivedMsgsFromDbMtx);
if (wipeExistingHistory) {
gkXmppRecvMsgsTableViewModel->removeData();
}
for (auto roster = rosterMap.begin(); roster != rosterMap.end(); ++roster) {
gkEventLogger->publishEvent(tr("Gathering archived messages for XMPP user, \"%1\", from the database!").arg(roster->bareJid), GkSeverity::Debug,
"", false, true, false, false, false);
if (!roster->messages.isEmpty()) {
//
// Performs a comparison between two, QDateTime objects, and sorts the QList accordingly!
// std::sort(roster->messages.begin(), roster->messages.end(), [](const GkXmppMamMsg &left, const GkXmppMamMsg &right)->bool{ return left.message.stamp().toMSecsSinceEpoch() < right.message.stamp().toMSecsSinceEpoch(); });
//
// Insert the archived messages, now downloaded from the given XMPP server and then sorted, into the QTableView provided!
for (auto iter = roster->messages.begin(); iter != roster->messages.end(); ++iter) {
if (!iter->presented && insertData) {
gkXmppRecvMsgsTableViewModel->insertData(roster->bareJid, iter->message.body(), iter->message.stamp());
iter->presented = true;
}
}
m_xmppClient->updateRosterMap(rosterMap);
}
std::lock_guard<std::mutex> lock_guard(m_archivedMsgsFromDbMtx);
if (wipeExistingHistory) {
gkXmppRecvMsgsTableViewModel->removeData();