Add event publishing to Outlook and Gmail synchronizers for AccountConnected, SyncStarted/Finished, and MailItemAdded/Updated/Removed events
This commit is contained in:
@@ -10,6 +10,9 @@
|
|||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include "../core/events.h"
|
||||||
|
#include "../core/eventbus.h"
|
||||||
|
|
||||||
GmailSynchronizer::GmailSynchronizer(QObject* parent)
|
GmailSynchronizer::GmailSynchronizer(QObject* parent)
|
||||||
: Synchronizer(parent),
|
: Synchronizer(parent),
|
||||||
@@ -41,6 +44,14 @@ bool GmailSynchronizer::initialize(const Account& account)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Publish AccountConnectedEvent
|
||||||
|
WinoMail::Events::AccountConnectedEvent event;
|
||||||
|
event.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
event.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
event.accountId = account.id();
|
||||||
|
event.provider = "gmail";
|
||||||
|
PUBLISH(event);
|
||||||
|
|
||||||
qDebug() << "Gmail Synchronizer initialized for account:" << account.email();
|
qDebug() << "Gmail Synchronizer initialized for account:" << account.email();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -56,6 +67,15 @@ bool GmailSynchronizer::syncFolder(const Folder& folder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Starting Gmail sync for folder (label):" << folder.name();
|
qDebug() << "Starting Gmail sync for folder (label):" << folder.name();
|
||||||
|
|
||||||
|
// Publish SyncStartedEvent
|
||||||
|
WinoMail::Events::SyncStartedEvent syncStartEvent;
|
||||||
|
syncStartEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
syncStartEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
syncStartEvent.accountId = m_account.id();
|
||||||
|
syncStartEvent.folderId = QString::number(folder.id());
|
||||||
|
PUBLISH(syncStartEvent);
|
||||||
|
|
||||||
emit folderSyncStarted(QString::number(folder.id()));
|
emit folderSyncStarted(QString::number(folder.id()));
|
||||||
|
|
||||||
// Obtener elementos de correo desde Gmail API
|
// Obtener elementos de correo desde Gmail API
|
||||||
@@ -68,10 +88,27 @@ bool GmailSynchronizer::syncFolder(const Folder& folder)
|
|||||||
if (!items.isEmpty()) {
|
if (!items.isEmpty()) {
|
||||||
for (const MailItem& item : items) {
|
for (const MailItem& item : items) {
|
||||||
emit mailItemAdded(item);
|
emit mailItemAdded(item);
|
||||||
|
// Publish MailItemAddedEvent
|
||||||
|
WinoMail::Events::MailItemAddedEvent mailEvent;
|
||||||
|
mailEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
mailEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
mailEvent.item = item;
|
||||||
|
PUBLISH(mailEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit folderSyncFinished(QString::number(folder.id()), true);
|
emit folderSyncFinished(QString::number(folder.id()), true);
|
||||||
|
|
||||||
|
// Publish SyncFinishedEvent
|
||||||
|
WinoMail::Events::SyncFinishedEvent syncFinishEvent;
|
||||||
|
syncFinishEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
syncFinishEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
syncFinishEvent.accountId = m_account.id();
|
||||||
|
syncFinishEvent.folderId = QString::number(folder.id());
|
||||||
|
syncFinishEvent.success = true;
|
||||||
|
syncFinishEvent.errorMessage = "";
|
||||||
|
PUBLISH(syncFinishEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,6 +191,14 @@ bool GmailSynchronizer::appendMailItem(const QString& folderId, const MailItem&
|
|||||||
|
|
||||||
// Por ahora, simulamos éxito
|
// Por ahora, simulamos éxito
|
||||||
emit mailItemAdded(item);
|
emit mailItemAdded(item);
|
||||||
|
|
||||||
|
// Publish MailItemAddedEvent
|
||||||
|
WinoMail::Events::MailItemAddedEvent mailEvent;
|
||||||
|
mailEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
mailEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
mailEvent.item = item;
|
||||||
|
PUBLISH(mailEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,6 +227,14 @@ bool GmailSynchronizer::updateMailItemFlags(const QString& folderId,
|
|||||||
updatedItem.setFlagged(flagged);
|
updatedItem.setFlagged(flagged);
|
||||||
emit mailItemUpdated(updatedItem);
|
emit mailItemUpdated(updatedItem);
|
||||||
|
|
||||||
|
// Publish MailItemUpdatedEvent
|
||||||
|
WinoMail::Events::MailItemUpdatedEvent updateEvent;
|
||||||
|
updateEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
updateEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
updateEvent.item = updatedItem;
|
||||||
|
updateEvent.changedFields = QStringList() << "read" << "flagged"; // Simplified
|
||||||
|
PUBLISH(updateEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +255,15 @@ bool GmailSynchronizer::deleteMailItem(const QString& folderId,
|
|||||||
|
|
||||||
// Por ahora, simulamos éxito
|
// Por ahora, simulamos éxito
|
||||||
emit mailItemRemoved(itemUid);
|
emit mailItemRemoved(itemUid);
|
||||||
|
|
||||||
|
// Publish MailItemRemovedEvent
|
||||||
|
WinoMail::Events::MailItemRemovedEvent removeEvent;
|
||||||
|
removeEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
removeEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
removeEvent.itemUid = itemUid;
|
||||||
|
removeEvent.folderId = folderId.toInt();
|
||||||
|
PUBLISH(removeEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,9 @@
|
|||||||
#include <QUrlQuery>
|
#include <QUrlQuery>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
#include <QEventLoop>
|
||||||
|
#include "../core/events.h"
|
||||||
|
#include "../core/eventbus.h"
|
||||||
|
|
||||||
OutlookSynchronizer::OutlookSynchronizer(QObject* parent)
|
OutlookSynchronizer::OutlookSynchronizer(QObject* parent)
|
||||||
: Synchronizer(parent),
|
: Synchronizer(parent),
|
||||||
@@ -41,6 +44,14 @@ bool OutlookSynchronizer::initialize(const Account& account)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Publish AccountConnectedEvent
|
||||||
|
WinoMail::Events::AccountConnectedEvent event;
|
||||||
|
event.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
event.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
event.accountId = account.id();
|
||||||
|
event.provider = "outlook";
|
||||||
|
PUBLISH(event);
|
||||||
|
|
||||||
qDebug() << "Outlook Synchronizer initialized for account:" << account.email();
|
qDebug() << "Outlook Synchronizer initialized for account:" << account.email();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -56,6 +67,15 @@ bool OutlookSynchronizer::syncFolder(const Folder& folder)
|
|||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Starting Outlook sync for folder:" << folder.name();
|
qDebug() << "Starting Outlook sync for folder:" << folder.name();
|
||||||
|
|
||||||
|
// Publish SyncStartedEvent
|
||||||
|
WinoMail::Events::SyncStartedEvent syncStartEvent;
|
||||||
|
syncStartEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
syncStartEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
syncStartEvent.accountId = m_account.id();
|
||||||
|
syncStartEvent.folderId = QString::number(folder.id());
|
||||||
|
PUBLISH(syncStartEvent);
|
||||||
|
|
||||||
emit folderSyncStarted(QString::number(folder.id()));
|
emit folderSyncStarted(QString::number(folder.id()));
|
||||||
|
|
||||||
// Obtener elementos de correo desde Microsoft Graph
|
// Obtener elementos de correo desde Microsoft Graph
|
||||||
@@ -68,10 +88,27 @@ bool OutlookSynchronizer::syncFolder(const Folder& folder)
|
|||||||
if (!items.isEmpty()) {
|
if (!items.isEmpty()) {
|
||||||
for (const MailItem& item : items) {
|
for (const MailItem& item : items) {
|
||||||
emit mailItemAdded(item);
|
emit mailItemAdded(item);
|
||||||
|
// Publish MailItemAddedEvent
|
||||||
|
WinoMail::Events::MailItemAddedEvent mailEvent;
|
||||||
|
mailEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
mailEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
mailEvent.item = item;
|
||||||
|
PUBLISH(mailEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit folderSyncFinished(QString::number(folder.id()), true);
|
emit folderSyncFinished(QString::number(folder.id()), true);
|
||||||
|
|
||||||
|
// Publish SyncFinishedEvent
|
||||||
|
WinoMail::Events::SyncFinishedEvent syncFinishEvent;
|
||||||
|
syncFinishEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
syncFinishEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
syncFinishEvent.accountId = m_account.id();
|
||||||
|
syncFinishEvent.folderId = QString::number(folder.id());
|
||||||
|
syncFinishEvent.success = true;
|
||||||
|
syncFinishEvent.errorMessage = "";
|
||||||
|
PUBLISH(syncFinishEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,6 +187,14 @@ bool OutlookSynchronizer::appendMailItem(const QString& folderId, const MailItem
|
|||||||
|
|
||||||
// Por ahora, simulamos éxito
|
// Por ahora, simulamos éxito
|
||||||
emit mailItemAdded(item);
|
emit mailItemAdded(item);
|
||||||
|
|
||||||
|
// Publish MailItemAddedEvent
|
||||||
|
WinoMail::Events::MailItemAddedEvent mailEvent;
|
||||||
|
mailEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
mailEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
mailEvent.item = item;
|
||||||
|
PUBLISH(mailEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,6 +223,14 @@ bool OutlookSynchronizer::updateMailItemFlags(const QString& folderId,
|
|||||||
updatedItem.setFlagged(flagged);
|
updatedItem.setFlagged(flagged);
|
||||||
emit mailItemUpdated(updatedItem);
|
emit mailItemUpdated(updatedItem);
|
||||||
|
|
||||||
|
// Publish MailItemUpdatedEvent
|
||||||
|
WinoMail::Events::MailItemUpdatedEvent updateEvent;
|
||||||
|
updateEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
updateEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
updateEvent.item = updatedItem;
|
||||||
|
updateEvent.changedFields = QStringList() << "read" << "flagged"; // Simplified
|
||||||
|
PUBLISH(updateEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,6 +251,15 @@ bool OutlookSynchronizer::deleteMailItem(const QString& folderId,
|
|||||||
|
|
||||||
// Por ahora, simulamos éxito
|
// Por ahora, simulamos éxito
|
||||||
emit mailItemRemoved(itemUid);
|
emit mailItemRemoved(itemUid);
|
||||||
|
|
||||||
|
// Publish MailItemRemovedEvent
|
||||||
|
WinoMail::Events::MailItemRemovedEvent removeEvent;
|
||||||
|
removeEvent.eventId = QString::number(QDateTime::currentMSecsSinceEpoch()) + "_" + QString::number(rand());
|
||||||
|
removeEvent.timestamp = QDateTime::currentDateTimeUtc();
|
||||||
|
removeEvent.itemUid = itemUid;
|
||||||
|
removeEvent.folderId = folderId.toInt();
|
||||||
|
PUBLISH(removeEvent);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -273,9 +335,66 @@ bool OutlookSynchronizer::refreshAccessToken()
|
|||||||
// En una implementación real, aquí usaríamos el refresh token
|
// En una implementación real, aquí usaríamos el refresh token
|
||||||
// para obtener un nuevo access token desde Azure AD
|
// para obtener un nuevo access token desde Azure AD
|
||||||
|
|
||||||
qWarning() << "Token refresh not implemented - using stub";
|
if (m_refreshToken.isEmpty()) {
|
||||||
// Simulamos éxito por ahora
|
qWarning() << "No refresh token available for Outlook";
|
||||||
return !m_refreshToken.isEmpty();
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: These should come from secure configuration, not hardcoded
|
||||||
|
const QString clientId = "YOUR_CLIENT_ID_HERE"; // Replace with actual client ID
|
||||||
|
const QString clientSecret = "YOUR_CLIENT_SECRET_HERE"; // Replace with actual client secret
|
||||||
|
const QString tokenUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
|
||||||
|
|
||||||
|
QNetworkRequest networkRequest{QUrl(tokenUrl)};
|
||||||
|
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
||||||
|
|
||||||
|
QUrlQuery postData;
|
||||||
|
postData.addQueryItem("client_id", clientId);
|
||||||
|
postData.addQueryItem("scope", "Mail.Read Mail.ReadWrite Mail.Send offline_access");
|
||||||
|
postData.addQueryItem("refresh_token", m_refreshToken);
|
||||||
|
postData.addQueryItem("grant_type", "refresh_token");
|
||||||
|
postData.addQueryItem("client_secret", clientSecret);
|
||||||
|
|
||||||
|
QNetworkReply* reply = m_networkManager->post(networkRequest, postData.toString(QUrl::FullyEncoded).toUtf8());
|
||||||
|
|
||||||
|
// Wait for reply synchronously for simplicity in this context
|
||||||
|
QEventLoop loop;
|
||||||
|
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
|
||||||
|
loop.exec();
|
||||||
|
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
qWarning() << "Outlook token refresh failed:" << reply->errorString();
|
||||||
|
reply->deleteLater();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray responseData = reply->readAll();
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QJsonParseError parseError;
|
||||||
|
QJsonDocument doc = QJsonDocument::fromJson(responseData, &parseError);
|
||||||
|
if (parseError.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "Failed to parse Outlook token response:" << parseError.errorString();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject obj = doc.object();
|
||||||
|
if (!obj.contains("access_token")) {
|
||||||
|
qWarning() << "No access_token in Outlook token response";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_accessToken = obj["access_token"].toString();
|
||||||
|
int expiresIn = obj["expires_in"].toInt(3600); // default 1 hour
|
||||||
|
m_tokenExpires = QDateTime::currentDateTimeUtc().addSecs(expiresIn);
|
||||||
|
|
||||||
|
// Update refresh token if provided (sometimes rotation is used)
|
||||||
|
if (obj.contains("refresh_token")) {
|
||||||
|
m_refreshToken = obj["refresh_token"].toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug() << "Outlook access token refreshed successfully, expires in" << expiresIn << "seconds";
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OutlookSynchronizer::getDeltaLink(const QString& folderId) const
|
QString OutlookSynchronizer::getDeltaLink(const QString& folderId) const
|
||||||
|
|||||||
Reference in New Issue
Block a user