fix for #732 + some related changes

This commit is contained in:
Martin Rotter 2022-05-11 11:11:15 +02:00
parent a70fcb663c
commit 3b064d8e34
17 changed files with 261 additions and 207 deletions

View File

@ -26,7 +26,7 @@
<url type="donation">https://github.com/sponsors/martinrotter</url>
<content_rating type="oars-1.1" />
<releases>
<release version="4.2.2" date="2022-05-10"/>
<release version="4.2.2" date="2022-05-11"/>
</releases>
<content_rating type="oars-1.0">
<content_attribute id="violence-cartoon">none</content_attribute>

View File

@ -170,8 +170,12 @@ void FormUpdate::loadAvailableFiles() {
m_ui.m_tabInfo->setCurrentIndex(1);
}
void FormUpdate::updateCompleted(const QUrl& url, QNetworkReply::NetworkError status, const QByteArray& contents) {
void FormUpdate::updateCompleted(const QUrl& url,
QNetworkReply::NetworkError status,
int http_code,
const QByteArray& contents) {
Q_UNUSED(url)
Q_UNUSED(http_code)
qDebugNN << LOGSEC_GUI << "Download of application update file was completed with code" << QUOTE_W_SPACE_DOT(status);

View File

@ -14,10 +14,9 @@
#include <QPushButton>
class RSSGUARD_DLLSPEC FormUpdate : public QDialog {
Q_OBJECT
Q_OBJECT
public:
// Constructors and destructors.
explicit FormUpdate(QWidget* parent);
@ -32,7 +31,10 @@ class RSSGUARD_DLLSPEC FormUpdate : public QDialog {
void startUpdate();
void updateProgress(qint64 bytes_received, qint64 bytes_total);
void updateCompleted(const QUrl &url, QNetworkReply::NetworkError status, const QByteArray& contents);
void updateCompleted(const QUrl& url,
QNetworkReply::NetworkError status,
int http_code,
const QByteArray& contents);
void saveUpdateFile(const QByteArray& file_contents);
private:

View File

@ -548,7 +548,12 @@ void TextBrowserViewer::downloadNextNeededResource() {
}
}
void TextBrowserViewer::resourceDownloaded(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents) {
void TextBrowserViewer::resourceDownloaded(const QUrl& url,
QNetworkReply::NetworkError status,
int http_code,
QByteArray contents) {
Q_UNUSED(http_code)
if (status == QNetworkReply::NetworkError::NoError) {
m_loadedResources.insert(url, contents);
}

View File

@ -86,7 +86,10 @@ class TextBrowserViewer : public QTextBrowser, public WebViewer {
private slots:
void reloadHtmlDelayed();
void downloadNextNeededResource();
void resourceDownloaded(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents = QByteArray());
void resourceDownloaded(const QUrl& url,
QNetworkReply::NetworkError status,
int http_code,
QByteArray contents = QByteArray());
private:
bool m_resourcesEnabled;

View File

@ -17,8 +17,8 @@
Downloader::Downloader(QObject* parent)
: QObject(parent), m_activeReply(nullptr), m_downloadManager(new SilentNetworkAccessManager(this)),
m_timer(new QTimer(this)), m_inputData(QByteArray()), m_inputMultipartData(nullptr), m_targetProtected(false),
m_targetUsername(QString()), m_targetPassword(QString()), m_lastOutputData(QByteArray()),
m_lastOutputError(QNetworkReply::NoError) {
m_targetUsername(QString()), m_targetPassword(QString()), m_lastOutputData({}),
m_lastOutputError(QNetworkReply::NetworkError::NoError), m_lastHttpStatusCode(0) {
m_timer->setInterval(DOWNLOAD_TIMEOUT);
m_timer->setSingleShot(true);
@ -212,8 +212,9 @@ void Downloader::finished() {
m_lastCookies = {};
}
m_lastContentType = reply->header(QNetworkRequest::ContentTypeHeader);
m_lastContentType = reply->header(QNetworkRequest::KnownHeaders::ContentTypeHeader);
m_lastOutputError = reply->error();
m_lastHttpStatusCode = reply->attribute(QNetworkRequest::Attribute::HttpStatusCodeAttribute).toInt();
// original_url = m_activeReply->property("original_url").toUrl();
@ -224,7 +225,7 @@ void Downloader::finished() {
m_inputMultipartData->deleteLater();
}
emit completed(original_url, m_lastOutputError, m_lastOutputData);
emit completed(original_url, m_lastOutputError, m_lastHttpStatusCode, m_lastOutputData);
}
}
@ -335,6 +336,10 @@ void Downloader::runGetRequest(const QNetworkRequest& request) {
connect(m_activeReply, &QNetworkReply::finished, this, &Downloader::finished);
}
int Downloader::lastHttpStatusCode() const {
return m_lastHttpStatusCode;
}
QList<QNetworkCookie> Downloader::lastCookies() const {
return m_lastCookies;
}

View File

@ -29,6 +29,7 @@ class Downloader : public QObject {
QList<HttpResponse> lastOutputMultipartData() const;
QVariant lastContentType() const;
QList<QNetworkCookie> lastCookies() const;
int lastHttpStatusCode() const;
void setProxy(const QNetworkProxy& proxy);
@ -68,9 +69,8 @@ class Downloader : public QObject {
const QString& password = QString());
signals:
// Emitted when new progress is known.
void progress(qint64 bytes_received, qint64 bytes_total);
void completed(const QUrl& url, QNetworkReply::NetworkError status, QByteArray contents = QByteArray());
void completed(const QUrl& url, QNetworkReply::NetworkError status, int http_code, QByteArray contents = {});
private slots:
@ -111,8 +111,8 @@ class Downloader : public QObject {
// Response data.
QByteArray m_lastOutputData;
QList<HttpResponse> m_lastOutputMultipartData;
QNetworkReply::NetworkError m_lastOutputError;
int m_lastHttpStatusCode;
QVariant m_lastContentType;
QList<QNetworkCookie> m_lastCookies;
};

View File

@ -156,8 +156,12 @@ void GoogleSuggest::autoSuggest() {
m_downloader->downloadFile(url);
}
void GoogleSuggest::handleNetworkData(const QUrl& url, QNetworkReply::NetworkError status, const QByteArray& contents) {
void GoogleSuggest::handleNetworkData(const QUrl& url,
QNetworkReply::NetworkError status,
int http_code,
const QByteArray& contents) {
Q_UNUSED(url)
Q_UNUSED(http_code)
if (status == QNetworkReply::NetworkError::NoError) {
QStringList choices;

View File

@ -54,7 +54,10 @@ class GoogleSuggest : public QObject {
void doneCompletion();
void preventSuggest();
void autoSuggest();
void handleNetworkData(const QUrl& url, QNetworkReply::NetworkError status, const QByteArray& contents);
void handleNetworkData(const QUrl& url,
QNetworkReply::NetworkError status,
int http_code,
const QByteArray& contents);
private:
LocationLineEdit* editor;

View File

@ -270,6 +270,7 @@ NetworkResult NetworkFactory::performNetworkOperation(const QString& url,
result.m_networkError = downloader.lastOutputError();
result.m_contentType = downloader.lastContentType().toString();
result.m_cookies = downloader.lastCookies();
result.m_httpCode = downloader.lastHttpStatusCode();
return result;
}
@ -309,12 +310,16 @@ NetworkResult NetworkFactory::performNetworkOperation(const QString& url,
result.m_networkError = downloader.lastOutputError();
result.m_contentType = downloader.lastContentType().toString();
result.m_cookies = downloader.lastCookies();
result.m_httpCode = downloader.lastHttpStatusCode();
return result;
}
NetworkResult::NetworkResult()
: m_networkError(QNetworkReply::NetworkError::NoError), m_contentType(QString()), m_cookies({}) {}
: m_networkError(QNetworkReply::NetworkError::NoError), m_httpCode(0), m_contentType(QString()), m_cookies({}) {}
NetworkResult::NetworkResult(QNetworkReply::NetworkError err, const QString& ct, const QList<QNetworkCookie>& cook)
: m_networkError(err), m_contentType(ct), m_cookies(cook) {}
NetworkResult::NetworkResult(QNetworkReply::NetworkError err,
int http_code,
const QString& ct,
const QList<QNetworkCookie>& cook)
: m_networkError(err), m_httpCode(http_code), m_contentType(ct), m_cookies(cook) {}

View File

@ -14,18 +14,22 @@
#include <QVariant>
struct NetworkResult {
QNetworkReply::NetworkError m_networkError;
QString m_contentType;
QList<QNetworkCookie> m_cookies;
QNetworkReply::NetworkError m_networkError;
int m_httpCode;
QString m_contentType;
QList<QNetworkCookie> m_cookies;
explicit NetworkResult();
explicit NetworkResult(QNetworkReply::NetworkError err, const QString& ct, const QList<QNetworkCookie>& cook);
explicit NetworkResult();
explicit NetworkResult(QNetworkReply::NetworkError err,
int http_code,
const QString& ct,
const QList<QNetworkCookie>& cook);
};
class Downloader;
class NetworkFactory {
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
Q_DECLARE_TR_FUNCTIONS(NetworkFactory)
private:
explicit NetworkFactory() = default;
@ -44,25 +48,32 @@ class NetworkFactory {
int timeout,
QIcon& output,
const QList<QPair<QByteArray, QByteArray>>& additional_headers,
const QNetworkProxy& custom_proxy = QNetworkProxy::ProxyType::DefaultProxy);
static NetworkResult performNetworkOperation(const QString& url, int timeout,
const QNetworkProxy& custom_proxy =
QNetworkProxy::ProxyType::DefaultProxy);
static NetworkResult performNetworkOperation(const QString& url,
int timeout,
const QByteArray& input_data,
QByteArray& output,
QNetworkAccessManager::Operation operation,
const QList<QPair<QByteArray, QByteArray>>& additional_headers = QList<QPair<QByteArray, QByteArray>>(),
const QList<QPair<QByteArray, QByteArray>>& additional_headers =
QList<QPair<QByteArray, QByteArray>>(),
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString(),
const QNetworkProxy& custom_proxy = QNetworkProxy::ProxyType::DefaultProxy);
static NetworkResult performNetworkOperation(const QString& url, int timeout,
const QNetworkProxy& custom_proxy =
QNetworkProxy::ProxyType::DefaultProxy);
static NetworkResult performNetworkOperation(const QString& url,
int timeout,
QHttpMultiPart* input_data,
QList<HttpResponse>& output,
QNetworkAccessManager::Operation operation,
const QList<QPair<QByteArray, QByteArray>>& additional_headers = QList<QPair<QByteArray, QByteArray>>(),
const QList<QPair<QByteArray, QByteArray>>& additional_headers =
QList<QPair<QByteArray, QByteArray>>(),
bool protected_contents = false,
const QString& username = QString(),
const QString& password = QString(),
const QNetworkProxy& custom_proxy = QNetworkProxy::ProxyType::DefaultProxy);
const QNetworkProxy& custom_proxy =
QNetworkProxy::ProxyType::DefaultProxy);
};
#endif // NETWORKFACTORY_H

View File

@ -442,11 +442,11 @@ void ServiceRoot::syncIn() {
setIcon(qApp->icons()->fromTheme(QSL("view-refresh")));
itemChanged({this});
qDebugNN << LOGSEC_CORE << "Starting sync-in process.";
try {
qDebugNN << LOGSEC_CORE << "Starting sync-in process.";
RootItem* new_tree = obtainNewTreeForSyncIn();
RootItem* new_tree = obtainNewTreeForSyncIn();
if (new_tree != nullptr) {
qDebugNN << LOGSEC_CORE << "New feed tree for sync-in obtained.";
auto feed_custom_data = storeCustomFeedsData();
@ -498,8 +498,15 @@ void ServiceRoot::syncIn() {
updateCounts(true);
requestReloadMessageList(true);
}
else {
qCriticalNN << LOGSEC_CORE << "New feed tree for sync-in NOT obtained.";
catch (const ApplicationException& ex) {
qCriticalNN << LOGSEC_CORE << "New feed tree for sync-in NOT obtained:" << QUOTE_W_SPACE_DOT(ex.message());
qApp->showGuiMessage(Notification::Event::GeneralEvent,
GuiMessage(tr("Error when fetching list of feeds"),
tr("Feeds & categories for account '%1' were not fetched, error: %2")
.arg(title(), ex.message()),
QSystemTrayIcon::MessageIcon::Critical),
GuiMessageDestination(true, true));
}
setIcon(original_icon);

View File

@ -2,7 +2,6 @@
#include "services/feedly/feedlynetwork.h"
#include "3rd-party/boolinq/boolinq.h"
#include "3rd-party/boolinq/boolinq.h"
#include "database/databasequeries.h"
#include "exceptions/networkexception.h"
@ -26,19 +25,18 @@
FeedlyNetwork::FeedlyNetwork(QObject* parent)
: QObject(parent), m_service(nullptr),
#if defined(FEEDLY_OFFICIAL_SUPPORT)
m_oauth(new OAuth2Service(QSL(FEEDLY_API_URL_BASE) + QSL(FEEDLY_API_URL_AUTH),
QSL(FEEDLY_API_URL_BASE) + QSL(FEEDLY_API_URL_TOKEN),
TextFactory::decrypt(QSL(FEEDLY_CLIENT_ID), OAUTH_DECRYPTION_KEY),
TextFactory::decrypt(QSL(FEEDLY_CLIENT_SECRET), OAUTH_DECRYPTION_KEY),
QSL(FEEDLY_API_SCOPE), this)),
m_oauth(new OAuth2Service(QSL(FEEDLY_API_URL_BASE) + QSL(FEEDLY_API_URL_AUTH),
QSL(FEEDLY_API_URL_BASE) + QSL(FEEDLY_API_URL_TOKEN),
TextFactory::decrypt(QSL(FEEDLY_CLIENT_ID), OAUTH_DECRYPTION_KEY),
TextFactory::decrypt(QSL(FEEDLY_CLIENT_SECRET), OAUTH_DECRYPTION_KEY),
QSL(FEEDLY_API_SCOPE),
this)),
#endif
m_username(QString()),
m_developerAccessToken(QString()), m_batchSize(FEEDLY_DEFAULT_BATCH_SIZE), m_downloadOnlyUnreadMessages(false),
m_intelligentSynchronization(true) {
m_username(QString()), m_developerAccessToken(QString()), m_batchSize(FEEDLY_DEFAULT_BATCH_SIZE),
m_downloadOnlyUnreadMessages(false), m_intelligentSynchronization(true) {
#if defined(FEEDLY_OFFICIAL_SUPPORT)
m_oauth->setRedirectUrl(QSL(OAUTH_REDIRECT_URI) + QL1C(':') + QString::number(FEEDLY_API_REDIRECT_URI_PORT),
true);
m_oauth->setRedirectUrl(QSL(OAUTH_REDIRECT_URI) + QL1C(':') + QString::number(FEEDLY_API_REDIRECT_URI_PORT), true);
connect(m_oauth, &OAuth2Service::tokensRetrieveError, this, &FeedlyNetwork::onTokensError);
connect(m_oauth, &OAuth2Service::authFailed, this, &FeedlyNetwork::onAuthFailed);
@ -118,8 +116,7 @@ void FeedlyNetwork::untagEntries(const QString& tag_id, const QStringList& msg_c
throw NetworkException(QNetworkReply::NetworkError::AuthenticationRequiredError);
}
QString target_url = fullUrl(Service::TagEntries) +
QSL("/%1/").arg(QString(QUrl::toPercentEncoding(tag_id)));
QString target_url = fullUrl(Service::TagEntries) + QSL("/%1/").arg(QString(QUrl::toPercentEncoding(tag_id)));
int timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
QByteArray output;
int i = 0;
@ -129,16 +126,18 @@ void FeedlyNetwork::untagEntries(const QString& tag_id, const QStringList& msg_c
i += FEEDLY_UNTAG_BATCH_SIZE;
auto ids = boolinq::from(msg_batch).select([](const QString& msg_id) {
return QString(QUrl::toPercentEncoding(msg_id));
}).toStdList();
auto ids = boolinq::from(msg_batch)
.select([](const QString& msg_id) {
return QString(QUrl::toPercentEncoding(msg_id));
})
.toStdList();
QString final_url = target_url + FROM_STD_LIST(QStringList, ids).join(',');
auto result = NetworkFactory::performNetworkOperation(final_url,
timeout,
{},
output,
QNetworkAccessManager::Operation::DeleteOperation,
{ bearerHeader(bear) },
{bearerHeader(bear)},
false,
{},
{},
@ -172,17 +171,17 @@ void FeedlyNetwork::tagEntries(const QString& tag_id, const QStringList& msg_cus
input[QSL("entryIds")] = QJsonArray::fromStringList(msg_custom_ids);
input_data = QJsonDocument(input).toJson(QJsonDocument::JsonFormat::Compact);
auto result = NetworkFactory::performNetworkOperation(target_url,
timeout,
input_data,
output,
QNetworkAccessManager::Operation::PutOperation,
{ bearerHeader(bear),
{ HTTP_HEADERS_CONTENT_TYPE, "application/json" } },
false,
{},
{},
m_service->networkProxy());
auto result =
NetworkFactory::performNetworkOperation(target_url,
timeout,
input_data,
output,
QNetworkAccessManager::Operation::PutOperation,
{bearerHeader(bear), {HTTP_HEADERS_CONTENT_TYPE, "application/json"}},
false,
{},
{},
m_service->networkProxy());
if (result.m_networkError != QNetworkReply::NetworkError::NoError) {
throw NetworkException(result.m_networkError, output);
@ -211,17 +210,17 @@ void FeedlyNetwork::markers(const QString& action, const QStringList& msg_custom
input[QSL("entryIds")] = QJsonArray::fromStringList(msg_custom_ids);
QByteArray input_data = QJsonDocument(input).toJson(QJsonDocument::JsonFormat::Compact);
auto result = NetworkFactory::performNetworkOperation(target_url,
timeout,
input_data,
output,
QNetworkAccessManager::Operation::PostOperation,
{ bearerHeader(bear),
{ HTTP_HEADERS_CONTENT_TYPE, "application/json" } },
false,
{},
{},
m_service->networkProxy());
auto result =
NetworkFactory::performNetworkOperation(target_url,
timeout,
input_data,
output,
QNetworkAccessManager::Operation::PostOperation,
{bearerHeader(bear), {HTTP_HEADERS_CONTENT_TYPE, "application/json"}},
false,
{},
{},
m_service->networkProxy());
if (result.m_networkError != QNetworkReply::NetworkError::NoError) {
throw NetworkException(result.m_networkError, output);
@ -245,21 +244,22 @@ QList<Message> FeedlyNetwork::entries(const QStringList& ids) {
do {
QJsonArray json;
for (int window = next_message + 1000; next_message < window && next_message < ids.size(); next_message++ ) {
for (int window = next_message + 1000; next_message < window && next_message < ids.size(); next_message++) {
json.append(QJsonValue(ids.at(next_message)));
}
QByteArray output;
auto result = NetworkFactory::performNetworkOperation(target_url,
timeout,
QJsonDocument(json).toJson(QJsonDocument::JsonFormat::Compact),
output,
QNetworkAccessManager::Operation::PostOperation,
{ bearerHeader(bear) },
false,
{},
{},
m_service->networkProxy());
auto result =
NetworkFactory::performNetworkOperation(target_url,
timeout,
QJsonDocument(json).toJson(QJsonDocument::JsonFormat::Compact),
output,
QNetworkAccessManager::Operation::PostOperation,
{bearerHeader(bear)},
false,
{},
{},
m_service->networkProxy());
if (result.m_networkError != QNetworkReply::NetworkError::NoError) {
throw NetworkException(result.m_networkError, output);
@ -311,7 +311,7 @@ QList<Message> FeedlyNetwork::streamContents(const QString& stream_id) {
{},
output,
QNetworkAccessManager::Operation::GetOperation,
{ bearerHeader(bear) },
{bearerHeader(bear)},
false,
{},
{},
@ -323,8 +323,7 @@ QList<Message> FeedlyNetwork::streamContents(const QString& stream_id) {
messages += decodeStreamContents(output, true, continuation);
}
while (!continuation.isEmpty() &&
(m_batchSize <= 0 || messages.size() < m_batchSize) &&
while (!continuation.isEmpty() && (m_batchSize <= 0 || messages.size() < m_batchSize) &&
messages.size() <= FEEDLY_MAX_TOTAL_SIZE);
return messages;
@ -369,7 +368,7 @@ QStringList FeedlyNetwork::streamIds(const QString& stream_id, bool unread_only,
{},
output,
QNetworkAccessManager::Operation::GetOperation,
{ bearerHeader(bear) },
{bearerHeader(bear)},
false,
{},
{},
@ -399,7 +398,9 @@ QStringList FeedlyNetwork::decodeStreamIds(const QByteArray& stream_ids, QString
return messages;
}
QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_contents, bool nested_items, QString& continuation) const {
QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_contents,
bool nested_items,
QString& continuation) const {
QList<Message> messages;
QJsonDocument json = QJsonDocument::fromJson(stream_contents);
auto active_labels = m_service->labelsNode() != nullptr ? m_service->labelsNode()->labels() : QList<Label*>();
@ -423,14 +424,25 @@ QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_cont
}
message.m_createdFromFeed = true;
message.m_created = QDateTime::fromMSecsSinceEpoch(entry_obj[QSL("published")].toVariant().toLongLong(),
Qt::TimeSpec::UTC);
message.m_created =
QDateTime::fromMSecsSinceEpoch(entry_obj[QSL("published")].toVariant().toLongLong(), Qt::TimeSpec::UTC);
message.m_customId = entry_obj[QSL("id")].toString();
message.m_isRead = !entry_obj[QSL("unread")].toBool();
message.m_url = entry_obj[QSL("canonicalUrl")].toString();
if (message.m_url.isEmpty()) {
message.m_url = entry_obj[QSL("canonical")].toObject()[QSL("href")].toString();
auto canonical_arr = entry_obj[QSL("canonical")].toArray();
if (!canonical_arr.isEmpty()) {
message.m_url = canonical_arr.first().toObject()[QSL("href")].toString();
}
else {
auto alternate_arr = entry_obj[QSL("alternate")].toArray();
if (!alternate_arr.isEmpty()) {
message.m_url = alternate_arr.first().toObject()[QSL("href")].toString();
}
}
}
auto enclosures = entry_obj[QSL("enclosure")].toArray();
@ -440,8 +452,8 @@ QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_cont
const QString& enc_href = enc_obj[QSL("href")].toString();
if (!boolinq::from(message.m_enclosures).any([enc_href](const Enclosure& existing_enclosure) {
return existing_enclosure.m_url == enc_href;
})) {
return existing_enclosure.m_url == enc_href;
})) {
message.m_enclosures.append(Enclosure(enc_href, enc_obj[QSL("type")].toString()));
}
}
@ -467,9 +479,7 @@ QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_cont
message.m_assignedLabels.append(label);
}
else {
qCriticalNN << LOGSEC_FEEDLY
<< "Failed to find live Label object for tag"
<< QUOTE_W_SPACE_DOT(tag_id);
qCriticalNN << LOGSEC_FEEDLY << "Failed to find live Label object for tag" << QUOTE_W_SPACE_DOT(tag_id);
}
}
}
@ -496,7 +506,7 @@ RootItem* FeedlyNetwork::collections(bool obtain_icons) {
{},
output,
QNetworkAccessManager::Operation::GetOperation,
{ bearerHeader(bear) },
{bearerHeader(bear)},
false,
{},
{},
@ -509,8 +519,10 @@ RootItem* FeedlyNetwork::collections(bool obtain_icons) {
return decodeCollections(output, obtain_icons, m_service->networkProxy(), timeout);
}
RootItem* FeedlyNetwork::decodeCollections(const QByteArray& json, bool obtain_icons,
const QNetworkProxy& proxy, int timeout) const {
RootItem* FeedlyNetwork::decodeCollections(const QByteArray& json,
bool obtain_icons,
const QNetworkProxy& proxy,
int timeout) const {
QJsonDocument doc = QJsonDocument::fromJson(json);
auto* parent = new RootItem();
QList<QString> used_feeds;
@ -529,9 +541,7 @@ RootItem* FeedlyNetwork::decodeCollections(const QByteArray& json, bool obtain_i
QJsonObject fee_obj = fee.toObject();
if (used_feeds.contains(fee_obj[QSL("id")].toString())) {
qWarningNN << LOGSEC_FEEDLY
<< "Feed"
<< QUOTE_W_SPACE(fee_obj[QSL("id")].toString())
qWarningNN << LOGSEC_FEEDLY << "Feed" << QUOTE_W_SPACE(fee_obj[QSL("id")].toString())
<< "is already decoded and cannot be placed under several categories.";
continue;
}
@ -545,9 +555,9 @@ RootItem* FeedlyNetwork::decodeCollections(const QByteArray& json, bool obtain_i
if (obtain_icons) {
QIcon icon;
auto result = NetworkFactory::downloadIcon({ { fee_obj[QSL("iconUrl")].toString(), true },
{ fee_obj[QSL("website")].toString(), false },
{ fee_obj[QSL("logo")].toString(), true } },
auto result = NetworkFactory::downloadIcon({{fee_obj[QSL("iconUrl")].toString(), true},
{fee_obj[QSL("website")].toString(), false},
{fee_obj[QSL("logo")].toString(), true}},
timeout,
icon,
{},
@ -592,7 +602,7 @@ QVariantHash FeedlyNetwork::profile(const QNetworkProxy& network_proxy) {
{},
output,
QNetworkAccessManager::Operation::GetOperation,
{ bearerHeader(bear) },
{bearerHeader(bear)},
false,
{},
{},
@ -621,7 +631,7 @@ QList<RootItem*> FeedlyNetwork::tags() {
{},
output,
QNetworkAccessManager::Operation::GetOperation,
{ bearerHeader(bear) },
{bearerHeader(bear)},
false,
{},
{},
@ -639,8 +649,7 @@ QList<RootItem*> FeedlyNetwork::tags() {
const QJsonObject& tag_obj = tag.toObject();
QString name_id = tag_obj[QSL("id")].toString();
if (name_id.endsWith(FEEDLY_API_SYSTEM_TAG_READ) ||
name_id.endsWith(FEEDLY_API_SYSTEM_TAG_SAVED)) {
if (name_id.endsWith(FEEDLY_API_SYSTEM_TAG_READ) || name_id.endsWith(FEEDLY_API_SYSTEM_TAG_SAVED)) {
continue;
}
@ -683,32 +692,30 @@ void FeedlyNetwork::setBatchSize(int batch_size) {
void FeedlyNetwork::onTokensError(const QString& error, const QString& error_description) {
Q_UNUSED(error)
qApp->showGuiMessage(Notification::Event::LoginFailure, {
tr("Feedly: authentication error"),
tr("Click this to login again. Error is: '%1'").arg(error_description),
QSystemTrayIcon::MessageIcon::Critical },
{}, {
tr("Login"),
[this]() {
m_oauth->setAccessToken(QString());
m_oauth->setRefreshToken(QString());
qApp->showGuiMessage(Notification::Event::LoginFailure,
{tr("Feedly: authentication error"),
tr("Click this to login again. Error is: '%1'").arg(error_description),
QSystemTrayIcon::MessageIcon::Critical},
{},
{tr("Login"), [this]() {
m_oauth->setAccessToken(QString());
m_oauth->setRefreshToken(QString());
//m_oauth->logout(false);
m_oauth->login();
} });
// m_oauth->logout(false);
m_oauth->login();
}});
}
void FeedlyNetwork::onAuthFailed() {
qApp->showGuiMessage(Notification::Event::LoginFailure, {
tr("Feedly: authorization denied"),
tr("Click this to login again."),
QSystemTrayIcon::MessageIcon::Critical },
{}, {
tr("Login"),
[this]() {
//m_oauth->logout(false);
m_oauth->login();
} });
qApp->showGuiMessage(Notification::Event::LoginFailure,
{tr("Feedly: authorization denied"),
tr("Click this to login again."),
QSystemTrayIcon::MessageIcon::Critical},
{},
{tr("Login"), [this]() {
// m_oauth->logout(false);
m_oauth->login();
}});
}
void FeedlyNetwork::onTokensRetrieved(const QString& access_token, const QString& refresh_token, int expires_in) {
@ -772,7 +779,7 @@ QString FeedlyNetwork::bearer() const {
}
QPair<QByteArray, QByteArray> FeedlyNetwork::bearerHeader(const QString& bearer) const {
return { QSL(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer.toLocal8Bit() };
return {QSL(HTTP_HEADERS_AUTHORIZATION).toLocal8Bit(), bearer.toLocal8Bit()};
}
void FeedlyNetwork::setIntelligentSynchronization(bool intelligent_sync) {

View File

@ -23,8 +23,7 @@
#include "network-web/oauth2service.h"
#endif
FeedlyServiceRoot::FeedlyServiceRoot(RootItem* parent)
: ServiceRoot(parent), m_network(new FeedlyNetwork(this)) {
FeedlyServiceRoot::FeedlyServiceRoot(RootItem* parent) : ServiceRoot(parent), m_network(new FeedlyNetwork(this)) {
setIcon(FeedlyEntryPoint().icon());
m_network->setService(this);
}
@ -75,7 +74,8 @@ void FeedlyServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList<Message> FeedlyServiceRoot::obtainNewMessages(Feed* feed,
const QHash<ServiceRoot::BagOfMessages, QStringList>& stated_messages,
const QHash<ServiceRoot::BagOfMessages, QStringList>&
stated_messages,
const QHash<QString, QStringList>& tagged_messages) {
Q_UNUSED(tagged_messages)
@ -128,16 +128,13 @@ void FeedlyServiceRoot::saveAllCachedData(bool ignore_errors) {
if (!ids.isEmpty()) {
try {
network()->markers(key == RootItem::ReadStatus::Read
? QSL(FEEDLY_MARKERS_READ)
: QSL(FEEDLY_MARKERS_UNREAD), ids);
network()->markers(key == RootItem::ReadStatus::Read ? QSL(FEEDLY_MARKERS_READ) : QSL(FEEDLY_MARKERS_UNREAD),
ids);
}
catch (const NetworkException& net_ex) {
qCriticalNN << LOGSEC_FEEDLY
<< "Failed to synchronize read/unread state with error:"
<< QUOTE_W_SPACE(net_ex.message())
<< "and HTTP code"
<< QUOTE_W_SPACE_DOT(net_ex.networkError());
<< "Failed to synchronize read/unread state with error:" << QUOTE_W_SPACE(net_ex.message())
<< "and HTTP code" << QUOTE_W_SPACE_DOT(net_ex.networkError());
if (!ignore_errors) {
addMessageStatesToCache(ids, key);
@ -162,16 +159,13 @@ void FeedlyServiceRoot::saveAllCachedData(bool ignore_errors) {
}
try {
network()->markers(key == RootItem::Importance::Important
? FEEDLY_MARKERS_IMPORTANT
: FEEDLY_MARKERS_UNIMPORTANT, ids);
network()->markers(key == RootItem::Importance::Important ? FEEDLY_MARKERS_IMPORTANT
: FEEDLY_MARKERS_UNIMPORTANT,
ids);
}
catch (const NetworkException& net_ex) {
qCriticalNN << LOGSEC_FEEDLY
<< "Failed to synchronize important/unimportant state with error:"
<< QUOTE_W_SPACE(net_ex.message())
<< "and HTTP code"
<< QUOTE_W_SPACE_DOT(net_ex.networkError());
qCriticalNN << LOGSEC_FEEDLY << "Failed to synchronize important/unimportant state with error:"
<< QUOTE_W_SPACE(net_ex.message()) << "and HTTP code" << QUOTE_W_SPACE_DOT(net_ex.networkError());
if (!ignore_errors) {
addMessageStatesToCache(messages, key);
@ -194,10 +188,8 @@ void FeedlyServiceRoot::saveAllCachedData(bool ignore_errors) {
}
catch (const NetworkException& net_ex) {
qCriticalNN << LOGSEC_FEEDLY
<< "Failed to synchronize tag assignments with error:"
<< QUOTE_W_SPACE(net_ex.message())
<< "and HTTP code"
<< QUOTE_W_SPACE_DOT(net_ex.networkError());
<< "Failed to synchronize tag assignments with error:" << QUOTE_W_SPACE(net_ex.message())
<< "and HTTP code" << QUOTE_W_SPACE_DOT(net_ex.networkError());
if (!ignore_errors) {
addLabelsAssignmentsToCache(messages, label_custom_id, true);
@ -220,10 +212,8 @@ void FeedlyServiceRoot::saveAllCachedData(bool ignore_errors) {
}
catch (const NetworkException& net_ex) {
qCriticalNN << LOGSEC_FEEDLY
<< "Failed to synchronize tag DEassignments with error:"
<< QUOTE_W_SPACE(net_ex.message())
<< "and HTTP code"
<< QUOTE_W_SPACE_DOT(net_ex.networkError());
<< "Failed to synchronize tag DEassignments with error:" << QUOTE_W_SPACE(net_ex.message())
<< "and HTTP code" << QUOTE_W_SPACE_DOT(net_ex.networkError());
if (!ignore_errors) {
addLabelsAssignmentsToCache(messages, label_custom_id, false);
@ -242,22 +232,14 @@ void FeedlyServiceRoot::updateTitle() {
}
RootItem* FeedlyServiceRoot::obtainNewTreeForSyncIn() const {
try {
auto tree = m_network->collections(true);
auto* lblroot = new LabelsNode(tree);
auto labels = m_network->tags();
auto tree = m_network->collections(true);
auto* lblroot = new LabelsNode(tree);
auto labels = m_network->tags();
lblroot->setChildItems(labels);
tree->appendChild(lblroot);
lblroot->setChildItems(labels);
tree->appendChild(lblroot);
return tree;
}
catch (const ApplicationException& ex) {
qCriticalNN << LOGSEC_FEEDLY
<< "Failed to obtain new sync-in tree:"
<< QUOTE_W_SPACE_DOT(ex.message());
return nullptr;
}
return tree;
}
bool FeedlyServiceRoot::wantsBaggedIdsOfExistingMessages() const {

View File

@ -602,7 +602,7 @@ RootItem* GreaderNetwork::categoriesFeedsLabelsTree(bool obtain_icons, const QNe
if (!ensureLogin(proxy)) {
qCriticalNN << LOGSEC_GREADER << "Cannot get feed tree, not logged-in.";
return nullptr;
throw ApplicationException(tr("you are not logged-in, maybe wrong credentials"));
}
QByteArray output_labels;
@ -618,7 +618,11 @@ RootItem* GreaderNetwork::categoriesFeedsLabelsTree(bool obtain_icons, const QNe
proxy);
if (result_labels.m_networkError != QNetworkReply::NetworkError::NoError) {
return nullptr;
qCriticalNN << LOGSEC_GREADER
<< "Cannot get labels tree, network error:" << QUOTE_W_SPACE_DOT(result_labels.m_networkError);
throw NetworkException(result_labels.m_networkError,
tr("cannot get list of labels, HTTP code '%1'").arg(result_labels.m_httpCode));
}
full_url = generateFullUrl(Operations::SubscriptionList);
@ -637,7 +641,9 @@ RootItem* GreaderNetwork::categoriesFeedsLabelsTree(bool obtain_icons, const QNe
if (result_feeds.m_networkError != QNetworkReply::NetworkError::NoError) {
qCriticalNN << LOGSEC_GREADER
<< "Cannot get feed tree, network error:" << QUOTE_W_SPACE_DOT(result_feeds.m_networkError);
return nullptr;
throw NetworkException(result_labels.m_networkError,
tr("cannot get list of feeds, HTTP code '%1'").arg(result_feeds.m_httpCode));
}
return decodeTagsSubscriptions(output_labels, output_feeds, obtain_icons, proxy);

View File

@ -5,6 +5,7 @@
#include "database/databasequeries.h"
#include "definitions/definitions.h"
#include "exceptions/feedfetchexception.h"
#include "exceptions/networkexception.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/mutex.h"
@ -124,7 +125,8 @@ RootItem* OwnCloudServiceRoot::obtainNewTreeForSyncIn() const {
return feed_cats_response.feedsCategories(true);
}
else {
return nullptr;
throw NetworkException(feed_cats_response.networkError(),
tr("cannot get list of feeds, network error '%1'").arg(feed_cats_response.networkError()));
}
}
@ -151,7 +153,8 @@ void OwnCloudServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList<Message> OwnCloudServiceRoot::obtainNewMessages(Feed* feed,
const QHash<ServiceRoot::BagOfMessages, QStringList>& stated_messages,
const QHash<ServiceRoot::BagOfMessages, QStringList>&
stated_messages,
const QHash<QString, QStringList>& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)

View File

@ -5,6 +5,7 @@
#include "3rd-party/boolinq/boolinq.h"
#include "database/databasequeries.h"
#include "exceptions/feedfetchexception.h"
#include "exceptions/networkexception.h"
#include "miscellaneous/application.h"
#include "miscellaneous/iconfactory.h"
#include "miscellaneous/mutex.h"
@ -26,8 +27,7 @@
#include <QPair>
#include <QSqlTableModel>
TtRssServiceRoot::TtRssServiceRoot(RootItem* parent)
: ServiceRoot(parent), m_network(new TtRssNetworkFactory()) {
TtRssServiceRoot::TtRssServiceRoot(RootItem* parent) : ServiceRoot(parent), m_network(new TtRssNetworkFactory()) {
setIcon(TtRssServiceEntryPoint().icon());
}
@ -68,8 +68,7 @@ void TtRssServiceRoot::start(bool freshly_activated) {
void TtRssServiceRoot::stop() {
m_network->logout(networkProxy());
qDebugNN << LOGSEC_TTRSS
<< "Stopping Tiny Tiny RSS account, logging out with result"
qDebugNN << LOGSEC_TTRSS << "Stopping Tiny Tiny RSS account, logging out with result"
<< QUOTE_W_SPACE_DOT(m_network->lastError());
}
@ -101,15 +100,18 @@ void TtRssServiceRoot::addNewFeed(RootItem* selected_item, const QString& url) {
// Lock was not obtained because
// it is used probably by feed updater or application
// is quitting.
qApp->showGuiMessage(Notification::Event::GeneralEvent, {
tr("Cannot add item"),
tr("Cannot add feed because another critical operation is ongoing."),
QSystemTrayIcon::MessageIcon::Warning });
qApp->showGuiMessage(Notification::Event::GeneralEvent,
{tr("Cannot add item"),
tr("Cannot add feed because another critical operation is ongoing."),
QSystemTrayIcon::MessageIcon::Warning});
return;
}
QScopedPointer<FormTtRssFeedDetails> form_pointer(new FormTtRssFeedDetails(this, selected_item, url, qApp->mainFormWidget()));
QScopedPointer<FormTtRssFeedDetails> form_pointer(new FormTtRssFeedDetails(this,
selected_item,
url,
qApp->mainFormWidget()));
form_pointer->addEditFeed<TtRssFeed>();
qApp->feedUpdateLock()->unlock();
@ -132,9 +134,8 @@ void TtRssServiceRoot::saveAllCachedData(bool ignore_errors) {
if (!ids.isEmpty()) {
auto res = network()->updateArticles(ids,
UpdateArticle::OperatingField::Unread,
key == RootItem::ReadStatus::Unread
? UpdateArticle::Mode::SetToTrue
: UpdateArticle::Mode::SetToFalse,
key == RootItem::ReadStatus::Unread ? UpdateArticle::Mode::SetToTrue
: UpdateArticle::Mode::SetToFalse,
networkProxy());
if (!ignore_errors && (network()->lastError() != QNetworkReply::NetworkError::NoError || res.hasError())) {
@ -155,9 +156,8 @@ void TtRssServiceRoot::saveAllCachedData(bool ignore_errors) {
QStringList ids = customIDsOfMessages(messages);
auto res = network()->updateArticles(ids,
UpdateArticle::OperatingField::Starred,
key == RootItem::Importance::Important
? UpdateArticle::Mode::SetToTrue
: UpdateArticle::Mode::SetToFalse,
key == RootItem::Importance::Important ? UpdateArticle::Mode::SetToTrue
: UpdateArticle::Mode::SetToFalse,
networkProxy());
if (!ignore_errors && (network()->lastError() != QNetworkReply::NetworkError::NoError || res.hasError())) {
@ -252,7 +252,8 @@ void TtRssServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
}
QList<Message> TtRssServiceRoot::obtainNewMessages(Feed* feed,
const QHash<ServiceRoot::BagOfMessages, QStringList>& stated_messages,
const QHash<ServiceRoot::BagOfMessages, QStringList>&
stated_messages,
const QHash<QString, QStringList>& tagged_messages) {
Q_UNUSED(stated_messages)
Q_UNUSED(tagged_messages)
@ -263,8 +264,12 @@ QList<Message> TtRssServiceRoot::obtainNewMessages(Feed* feed,
int skip = 0;
do {
TtRssGetHeadlinesResponse headlines = network()->getHeadlines(feed->customNumericId(), limit, skip,
true, true, false,
TtRssGetHeadlinesResponse headlines = network()->getHeadlines(feed->customNumericId(),
limit,
skip,
true,
true,
false,
network()->downloadOnlyUnreadMessages(),
networkProxy());
@ -286,12 +291,13 @@ QList<Message> TtRssServiceRoot::obtainNewMessages(Feed* feed,
QString TtRssServiceRoot::additionalTooltip() const {
return tr("Username: %1\nServer: %2\n"
"Last error: %3\nLast login on: %4").arg(m_network->username(),
m_network->url(),
NetworkFactory::networkErrorText(m_network->lastError()),
m_network->lastLoginTime().isValid()
? QLocale().toString(m_network->lastLoginTime(), QLocale::FormatType::ShortFormat)
: QSL("-"));
"Last error: %3\nLast login on: %4")
.arg(m_network->username(),
m_network->url(),
NetworkFactory::networkErrorText(m_network->lastError()),
m_network->lastLoginTime().isValid()
? QLocale().toString(m_network->lastLoginTime(), QLocale::FormatType::ShortFormat)
: QSL("-"));
}
TtRssNetworkFactory* TtRssServiceRoot::network() const {
@ -315,8 +321,9 @@ void TtRssServiceRoot::updateTitle() {
RootItem* TtRssServiceRoot::obtainNewTreeForSyncIn() const {
TtRssGetFeedsCategoriesResponse feed_cats = m_network->getFeedsCategories(networkProxy());
TtRssGetLabelsResponse labels = m_network->getLabels(networkProxy());
auto lst_error = m_network->lastError();
if (m_network->lastError() == QNetworkReply::NoError) {
if (lst_error == QNetworkReply::NoError) {
auto* tree = feed_cats.feedsCategories(m_network, true, networkProxy(), m_network->url());
auto* lblroot = new LabelsNode(tree);
@ -326,6 +333,6 @@ RootItem* TtRssServiceRoot::obtainNewTreeForSyncIn() const {
return tree;
}
else {
return nullptr;
throw NetworkException(lst_error, tr("cannot get list of feeds, network error '%1'").arg(lst_error));
}
}