Migrate to new gmail api batch endpoint.

This commit is contained in:
Martin Rotter 2020-08-13 13:51:19 +02:00
parent 7e06964b82
commit 252cc59b8d
16 changed files with 95 additions and 36 deletions

View File

@ -83,6 +83,8 @@
#define HTTP_HEADERS_AUTHORIZATION "Authorization"
#define HTTP_HEADERS_USER_AGENT "User-Agent"
#define LOGSEC_NETWORK "network: "
#define LOGSEC_ADBLOCK "adblock: "
#define LOGSEC_FEEDMODEL "feed-model: "
#define LOGSEC_FEEDDOWNLOADER "feed-downloader: "
#define LOGSEC_MESSAGEMODEL "message-model: "

View File

@ -1874,6 +1874,27 @@ bool DatabaseQueries::deleteGmailAccount(const QSqlDatabase& db, int account_id)
return q.exec();
}
bool DatabaseQueries::storeNewGmailTokens(const QSqlDatabase& db, const QString& refresh_token, int account_id) {
QSqlQuery query(db);
query.prepare("UPDATE GmailAccounts "
"SET refresh_token = :refresh_token "
"WHERE id = :id;");
query.bindValue(QSL(":refresh_token"), refresh_token);
query.bindValue(QSL(":id"), account_id);
if (query.exec()) {
return true;
}
else {
qWarningNN << LOGSEC_GMAIL
<< "Updating tokens in DB failed: '"
<< query.lastError().text()
<< "'.";
return false;
}
}
bool DatabaseQueries::deleteInoreaderAccount(const QSqlDatabase& db, int account_id) {
QSqlQuery q(db);

View File

@ -147,6 +147,7 @@ class DatabaseQueries {
// Gmail account.
static QStringList getAllRecipients(const QSqlDatabase& db, int account_id);
static bool deleteGmailAccount(const QSqlDatabase& db, int account_id);
static bool storeNewGmailTokens(const QSqlDatabase& db, const QString& refresh_token, int account_id);
static QList<ServiceRoot*> getGmailAccounts(const QSqlDatabase& db, bool* ok = nullptr);
static bool overwriteGmailAccount(const QSqlDatabase& db, const QString& username, const QString& app_id,
const QString& app_key, const QString& redirect_url, const QString& refresh_token,

View File

@ -398,7 +398,7 @@ QString Settings::pathName() const {
}
QSettings::Status Settings::checkSettings() {
qDebug("Syncing settings.");
qDebugNN << LOGSEC_CORE << "Syncing settings.";
sync();
return status();
}
@ -414,14 +414,17 @@ void Settings::finishRestoration(const QString& desired_settings_file_path) {
BACKUP_NAME_SETTINGS + BACKUP_SUFFIX_SETTINGS;
if (QFile::exists(backup_settings_file)) {
qWarning("Backup settings file '%s' was detected. Restoring it.", qPrintable(QDir::toNativeSeparators(backup_settings_file)));
qWarningNN << LOGSEC_CORE
<< "Backup settings file"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(backup_settings_file))
<< "was detected. Restoring it.";
if (IOFactory::copyFile(backup_settings_file, desired_settings_file_path)) {
QFile::remove(backup_settings_file);
qDebug("Settings file was restored successully.");
qDebugNN << LOGSEC_CORE << "Settings file was restored successully.";
}
else {
qCritical("Settings file was NOT restored due to error when copying the file.");
qCriticalNN << LOGSEC_CORE << "Settings file was NOT restored due to error when copying the file.";
}
}
}
@ -441,11 +444,16 @@ Settings* Settings::setupSettings(QObject* parent) {
// Check if portable settings are available.
if (properties.m_type == SettingsProperties::SettingsType::Portable) {
qDebug("Initializing settings in '%s' (portable way).", qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName)));
qDebugNN << LOGSEC_CORE
<< "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))
<< "(portable way).";
}
else {
qDebug("Initializing settings in '%s' (non-portable way).",
qPrintable(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName)));
qDebugNN << LOGSEC_CORE
<< "Initializing settings in"
<< QUOTE_W_SPACE(QDir::toNativeSeparators(properties.m_absoluteSettingsFileName))
<< "(non-portable way).";
}
return new_settings;

View File

@ -13,6 +13,7 @@ SkinFactory::SkinFactory(QObject* parent) : QObject(parent) {}
void SkinFactory::loadCurrentSkin() {
QList<QString> skin_names_to_try;
skin_names_to_try.append(selectedSkinName());
skin_names_to_try.append(APP_SKIN_DEFAULT);
bool skin_parsed;
@ -28,15 +29,15 @@ void SkinFactory::loadCurrentSkin() {
// Set this 'Skin' object as active one.
m_currentSkin = skin_data;
qDebug("Skin '%s' loaded.", qPrintable(skin_name));
qDebugNN << LOGSEC_GUI << "Skin" << QUOTE_W_SPACE(skin_name) << "loaded.";
return;
}
else {
qWarning("Failed to load skin '%s'.", qPrintable(skin_name));
qWarningNN << LOGSEC_GUI << "Failed to load skin" << QUOTE_W_SPACE_DOT(skin_name);
}
}
qCritical("Failed to load selected or default skin. Quitting!");
qCriticalNN << LOGSEC_GUI << "Failed to load selected or default skin. Quitting!";
}
void SkinFactory::loadSkinFromData(const Skin& skin) {

View File

@ -65,7 +65,7 @@ SystemFactory::AutoStartStatus SystemFactory::autoStartStatus() const {
// No correct path was found.
if (desktop_file_location.isEmpty()) {
qWarning("Searching for auto-start function status failed. HOME variable not found.");
qWarningNN << LOGSEC_GUI << "Searching for auto-start function status failed. HOME variable not found.";
return AutoStartStatus::Unavailable;
}

View File

@ -120,7 +120,7 @@ QString TextFactory::decrypt(const QString& text) {
QString TextFactory::newline() {
#if defined(Q_OS_WIN)
return QSL("\r\n");
#elif defined(Q_OS_MACOSOS)
#elif defined(Q_OS_MACOS)
return QSL("\r");
#else
return QSL("\n");
@ -152,8 +152,10 @@ quint64 TextFactory::initializeSecretEncryptionKey() {
IOFactory::writeFile(encryption_file_path, QString::number(s_encryptionKey).toLocal8Bit());
}
catch (ApplicationException& ex) {
qCritical("Failed to write newly generated encryption key to file, error '%s'. Now, your passwords won't be "
"readable after you start this application again.", qPrintable(ex.message()));
qCriticalNN << LOGSEC_CORE
<< "Failed to write newly generated encryption key to file, error"
<< QUOTE_W_SPACE_DOT(ex.message())
<< " Now, your passwords won't be readable after you start this application again.";
}
}
}

View File

@ -174,7 +174,9 @@ AdBlockSubscription* AdBlockManager::addSubscription(const QString& title, const
QSaveFile file(filePath);
if (!file.open(QFile::WriteOnly)) {
qWarning("Cannot save AdBlock subscription to file '%s'.", qPrintable(filePath));
qWarningNN << LOGSEC_ADBLOCK
<< "Cannot save AdBlock subscription to file"
<< QUOTE_W_SPACE_DOT(filePath);
return nullptr;
}
@ -262,7 +264,9 @@ void AdBlockManager::load() {
QUrl url = QUrl(textStream.readLine(1024).remove(QLatin1String("Url: ")));
if (title.isEmpty() || !url.isValid()) {
qWarning("Invalid AdBlock subscription file '%s'.", qPrintable(absolutePath));
qWarningNN << LOGSEC_ADBLOCK
<< "Invalid AdBlock subscription file"
<< QUOTE_W_SPACE_DOT(absolutePath);
continue;
}

View File

@ -20,6 +20,8 @@
#include "network-web/adblock/adblockrule.h"
#include "network-web/adblock/adblocksearchtree.h"
#include "definitions/definitions.h"
#include <QWebEngineUrlRequestInfo>
AdBlockSearchTree::AdBlockSearchTree() : m_root(new Node) {}
@ -42,7 +44,7 @@ bool AdBlockSearchTree::add(const AdBlockRule* rule) {
int len = filter.size();
if (len <= 0) {
qDebug("AdBlockSearchTree: Inserting rule with filter len <= 0!");
qWarningNN << LOGSEC_ADBLOCK << "Inserting rule with filter len <= 0!";
return false;
}

View File

@ -94,7 +94,10 @@ void AdBlockSubscription::loadSubscription(const QStringList& disabledRules) {
}
if (!file.open(QFile::ReadOnly)) {
qWarning("Unable to open adblock file '%s' for reading.", qPrintable(m_filePath));
qWarningNN << LOGSEC_ADBLOCK
<< "Unable to open adblock file"
<< QUOTE_W_SPACE(m_filePath)
<< "for reading.";
QTimer::singleShot(0, this, SLOT(updateSubscription()));
return;
}
@ -109,7 +112,9 @@ void AdBlockSubscription::loadSubscription(const QStringList& disabledRules) {
QString header = textStream.readLine(1024);
if (!header.startsWith(QL1S("[Adblock")) || m_title.isEmpty()) {
qWarning("Invalid format of AdBlock file '%s'.", qPrintable(m_filePath));
qWarningNN << LOGSEC_ADBLOCK
<< "Invalid format of AdBlock file"
<< QUOTE_W_SPACE_DOT(m_filePath);
QTimer::singleShot(0, this, SLOT(updateSubscription()));
return;
}
@ -176,7 +181,10 @@ bool AdBlockSubscription::saveDownloadedData(const QByteArray& data) {
QSaveFile file(m_filePath);
if (!file.open(QFile::WriteOnly)) {
qWarning("Unable to open AdBlock file '%s' for writing.", qPrintable(m_filePath));
qWarningNN << LOGSEC_ADBLOCK
<< "Unable to open AdBlock file"
<< QUOTE_W_SPACE(m_filePath)
<< "for writing.";
return false;
}
else {
@ -306,7 +314,10 @@ void AdBlockCustomList::saveSubscription() {
QFile file(filePath());
if (!file.open(QFile::ReadWrite | QFile::Truncate)) {
qWarning("Unable to open AdBlock file '%s' for writing.", qPrintable(filePath()));
qWarningNN << LOGSEC_ADBLOCK
<< "Unable to open AdBlock file"
<< QUOTE_W_SPACE(filePath())
<< "for writing.";
return;
}

View File

@ -29,12 +29,18 @@ void BaseNetworkAccessManager::loadSettings() {
setProxy(QNetworkProxy::applicationProxy());
}
qDebug("Settings of BaseNetworkAccessManager loaded.");
qDebugNN << LOGSEC_NETWORK << "Settings of BaseNetworkAccessManager loaded.";
}
void BaseNetworkAccessManager::onSslErrors(QNetworkReply* reply, const QList<QSslError>& error) {
qWarning("Ignoring SSL errors for '%s': '%s' (code %d).", qPrintable(reply->url().toString()), qPrintable(reply->errorString()),
int(reply->error()));
qWarningNN << LOGSEC_NETWORK
<< "Ignoring SSL errors for '"
<< reply->url().toString()
<< "':"
<< QUOTE_W_SPACE(reply->errorString())
<< "(code "
<< reply->error()
<< ").";
reply->ignoreSslErrors(error);
}
@ -45,7 +51,7 @@ QNetworkReply* BaseNetworkAccessManager::createRequest(QNetworkAccessManager::Op
// This rapidly speeds up loading of web sites.
// NOTE: https://en.wikipedia.org/wiki/HTTP_pipelining
new_request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
new_request.setAttribute(QNetworkRequest::Attribute::HttpPipeliningAllowedAttribute, true);
// Setup custom user-agent.
new_request.setRawHeader(HTTP_HEADERS_USER_AGENT, QString(APP_USERAGENT).toLocal8Bit());

View File

@ -19,7 +19,9 @@ Downloader::Downloader(QObject* parent)
connect(m_timer, &QTimer::timeout, this, &Downloader::cancel);
}
Downloader::~Downloader() = default;
Downloader::~Downloader() {
qDebugNN << LOGSEC_NETWORK << "Destroying Downloader instance.";
}
void Downloader::downloadFile(const QString& url, int timeout, bool protected_contents, const QString& username,
const QString& password) {
@ -67,7 +69,9 @@ void Downloader::manipulateData(const QString& url,
m_timer->setInterval(timeout);
if (non_const_url.startsWith(URI_SCHEME_FEED)) {
qDebug("Replacing URI schemes for '%s'.", qPrintable(non_const_url));
qDebugNN << LOGSEC_NETWORK
<< "Replacing URI schemes for"
<< QUOTE_W_SPACE_DOT(non_const_url);
request.setUrl(non_const_url.replace(QRegularExpression(QString('^') + URI_SCHEME_FEED), QString(URI_SCHEME_HTTP)));
}
else {

View File

@ -19,8 +19,6 @@ class Downloader : public QObject {
Q_OBJECT
public:
// Constructors and destructors.
explicit Downloader(QObject* parent = nullptr);
virtual ~Downloader();
@ -81,10 +79,8 @@ class Downloader : public QObject {
private:
QNetworkReply* m_activeReply;
QScopedPointer<SilentNetworkAccessManager> m_downloadManager;
QTimer* m_timer;
QHash<QByteArray, QByteArray> m_customHeaders;
QByteArray m_inputData;
QHttpMultiPart* m_inputMultipartData;
@ -94,7 +90,6 @@ class Downloader : public QObject {
// Response data.
QByteArray m_lastOutputData;
QList<HttpResponse> m_lastOutputMultipartData;
QNetworkReply::NetworkError m_lastOutputError;

View File

@ -12,7 +12,7 @@
#define GMAIL_API_GET_ATTACHMENT "https://www.googleapis.com/gmail/v1/users/me/messages/%1/attachments/%2"
#define GMAIL_API_LABELS_LIST "https://www.googleapis.com/gmail/v1/users/me/labels"
#define GMAIL_API_MSGS_LIST "https://www.googleapis.com/gmail/v1/users/me/messages"
#define GMAIL_API_BATCH "https://www.googleapis.com/batch"
#define GMAIL_API_BATCH "https://www.googleapis.com/batch/gmail/v1"
#define GMAIL_ATTACHMENT_SEP "####"

View File

@ -118,10 +118,11 @@ void GmailNetworkFactory::initializeOauth() {
connect(m_oauth2, &OAuth2Service::authFailed, this, &GmailNetworkFactory::onAuthFailed);
connect(m_oauth2, &OAuth2Service::tokensReceived, this, [this](QString access_token, QString refresh_token, int expires_in) {
Q_UNUSED(expires_in)
Q_UNUSED(access_token)
if (m_service != nullptr && !access_token.isEmpty() && !refresh_token.isEmpty()) {
if (m_service != nullptr && !refresh_token.isEmpty()) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
DatabaseQueries::storeNewInoreaderTokens(database, refresh_token, m_service->accountId());
DatabaseQueries::storeNewGmailTokens(database, refresh_token, m_service->accountId());
qApp->showGuiMessage(tr("Logged in successfully"),
tr("Your login to Gmail was authorized."),

View File

@ -54,8 +54,9 @@ void InoreaderNetworkFactory::initializeOauth() {
connect(m_oauth2, &OAuth2Service::authFailed, this, &InoreaderNetworkFactory::onAuthFailed);
connect(m_oauth2, &OAuth2Service::tokensReceived, this, [this](QString access_token, QString refresh_token, int expires_in) {
Q_UNUSED(expires_in)
Q_UNUSED(access_token)
if (m_service != nullptr && !access_token.isEmpty() && !refresh_token.isEmpty()) {
if (m_service != nullptr && !refresh_token.isEmpty()) {
QSqlDatabase database = qApp->database()->connection(metaObject()->className());
DatabaseQueries::storeNewInoreaderTokens(database, refresh_token, m_service->accountId());