diff --git a/resources/desktop/com.github.rssguard.appdata.xml b/resources/desktop/com.github.rssguard.appdata.xml index f8b9a18fc..3deebd2fd 100644 --- a/resources/desktop/com.github.rssguard.appdata.xml +++ b/resources/desktop/com.github.rssguard.appdata.xml @@ -30,7 +30,7 @@ https://martinrotter.github.io/donate/ - + none diff --git a/src/librssguard/services/greader/definitions.h b/src/librssguard/services/greader/definitions.h index ce6914dbe..bb069c79b 100755 --- a/src/librssguard/services/greader/definitions.h +++ b/src/librssguard/services/greader/definitions.h @@ -14,7 +14,6 @@ // Means "read" message. If both "reading-list" and "read" are specified, message is READ. If this state // is not present, message is UNREAD. #define GREADER_API_STATE_READ "state/com.google/read" - #define GREADER_API_STATE_IMPORTANT "state/com.google/starred" #define GREADER_API_FULL_STATE_READING_LIST "user/-/state/com.google/reading-list" @@ -27,8 +26,8 @@ #define GREADER_API_SUBSCRIPTION_LIST "reader/api/0/subscription/list?output=json" #define GREADER_API_STREAM_CONTENTS "reader/api/0/stream/contents/%1?output=json&n=%2" #define GREADER_API_EDIT_TAG "reader/api/0/edit-tag" -#define GREADER_API_ITEM_IDS "reader/api/0/stream/items/ids?output=json&s=%1" -#define GREADER_API_ITEM_CONTENTS "reader/api/0/stream/items/contents?output=json&n=%1" +#define GREADER_API_ITEM_IDS "reader/api/0/stream/items/ids?output=json&n=200000&s=%1" +#define GREADER_API_ITEM_CONTENTS "reader/api/0/stream/items/contents?output=json&n=200000" #define GREADER_API_TOKEN "reader/api/0/token" #define GREADER_API_USER_INFO "reader/api/0/user-info?output=json" diff --git a/src/librssguard/services/greader/greadernetwork.cpp b/src/librssguard/services/greader/greadernetwork.cpp index da0f3e063..3ff38009a 100755 --- a/src/librssguard/services/greader/greadernetwork.cpp +++ b/src/librssguard/services/greader/greadernetwork.cpp @@ -128,13 +128,35 @@ QList GreaderNetwork::getMessagesIntelligently(ServiceRoot* root, const QNetworkProxy& proxy) { // 1. Get unread IDs for a feed. // 2. Get read IDs for a feed. + // 3. Get starred IDs. Unfortunately, we cannot get only starred IDs for a feed, but all + // instead. // 3. Download messages/contents for missing or changed IDs. // 4. Download all starred messages and append those belonging to this feed. auto remote_all_ids_list = itemIds(stream_id, false, proxy); auto remote_unread_ids_list = itemIds(stream_id, true, proxy); + auto remote_starred_ids_list = itemIds(GREADER_API_FULL_STATE_IMPORTANT, false, proxy); + + // Convert item IDs to long form. + for (int i = 0; i < remote_all_ids_list.size(); i++) { + remote_all_ids_list.replace(i, + convertShortStreamIdToLongStreamId(remote_all_ids_list.at(i))); + } + + for (int i = 0; i < remote_unread_ids_list.size(); i++) { + remote_unread_ids_list.replace(i, + convertShortStreamIdToLongStreamId(remote_unread_ids_list.at(i))); + } + + for (int i = 0; i < remote_starred_ids_list.size(); i++) { + remote_starred_ids_list.replace(i, + convertShortStreamIdToLongStreamId(remote_starred_ids_list.at(i))); + } + QSet remote_all_ids(remote_all_ids_list.begin(), remote_all_ids_list.end()); + //remote_all_ids += QSet(remote_starred_ids_list.begin(), remote_starred_ids_list.end()); + // 1. auto local_unread_ids_list = stated_messages.value(ServiceRoot::BagOfMessages::Unread); QSet remote_unread_ids(remote_unread_ids_list.begin(), remote_unread_ids_list.end()); @@ -146,13 +168,37 @@ QList GreaderNetwork::getMessagesIntelligently(ServiceRoot* root, QSet remote_read_ids = remote_all_ids - remote_unread_ids; QSet local_read_ids(local_read_ids_list.begin(), local_read_ids_list.end()); + + // 3. + auto local_starred_ids_list = stated_messages.value(ServiceRoot::BagOfMessages::Starred); + QSet remote_starred_ids(remote_starred_ids_list.begin(), remote_starred_ids_list.end()); + QSet local_starred_ids(local_starred_ids_list.begin(), local_starred_ids_list.end()); + QSet local_unstarred_ids((local_read_ids + local_unread_ids) - local_starred_ids); + + // 4. auto not_downloaded = remote_all_ids - local_read_ids - local_unread_ids; auto moved_unread = local_unread_ids.intersect(remote_read_ids); auto moved_read = local_read_ids.intersect(remote_unread_ids); - auto to_download = not_downloaded + moved_read + moved_unread; - QList to_download_list(to_download.begin(), to_download.end()); + auto moved_unstarred = local_unstarred_ids.intersect(remote_starred_ids); + auto moved_starred = local_starred_ids - remote_starred_ids; + auto to_download = not_downloaded + moved_read + moved_unread + moved_starred + moved_unstarred + remote_starred_ids; - return itemContents(root, to_download_list, error, proxy); + if (to_download.isEmpty()) { + return {}; + } + + QList to_download_list(to_download.begin(), to_download.end()); + auto msgs = itemContents(root, to_download_list, error, proxy); + + // Filter out (starred) messages from other feeds. + // TODO: Cache them instead? + for (int i = 0; i < msgs.size(); i++) { + if (msgs.at(i).m_feedId != stream_id) { + msgs.removeAt(i--); + } + } + + return msgs; } QNetworkReply::NetworkError GreaderNetwork::markMessagesRead(RootItem::ReadStatus status, @@ -229,10 +275,11 @@ QList GreaderNetwork::itemContents(ServiceRoot* root, const QList msgs; - int target_msgs_size = 999; + + //int target_msgs_size = 999; do { - QString full_url = generateFullUrl(Operations::ItemContents).arg(QString::number(target_msgs_size)); + QString full_url = generateFullUrl(Operations::ItemContents); auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); if (!continuation.isEmpty()) { @@ -267,7 +314,7 @@ QList GreaderNetwork::itemContents(ServiceRoot* root, const QList GreaderNetwork::streamContents(ServiceRoot* root, const QString& do { QString full_url = generateFullUrl(Operations::StreamContents).arg(m_service == GreaderServiceRoot::Service::TheOldReader - ? stream_id - : QUrl::toPercentEncoding(stream_id), + ? stream_id + : QUrl::toPercentEncoding(stream_id), QString::number(target_msgs_size)); auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); @@ -688,6 +735,18 @@ bool GreaderNetwork::ensureLogin(const QNetworkProxy& proxy, QNetworkReply::Netw return true; } +QString GreaderNetwork::convertShortStreamIdToLongStreamId(const QString& stream_id) const { + if (m_service == GreaderServiceRoot::Service::TheOldReader) { + return QSL("tag:google.com,2005:reader/item/%1").arg(stream_id); + } + else { + return QSL("tag:google.com,2005:reader/item/%1").arg(stream_id.toULongLong(), + 16, + 16, + QL1C('0')); + } +} + QString GreaderNetwork::simplifyStreamId(const QString& stream_id) const { return QString(stream_id).replace(QRegularExpression("\\/\\d+\\/"), QSL("/-/")); } diff --git a/src/librssguard/services/greader/greadernetwork.h b/src/librssguard/services/greader/greadernetwork.h index 0b15690ee..f4aca4235 100755 --- a/src/librssguard/services/greader/greadernetwork.h +++ b/src/librssguard/services/greader/greadernetwork.h @@ -91,6 +91,7 @@ class GreaderNetwork : public QObject { // Make sure we are logged in and if we are not, return error. bool ensureLogin(const QNetworkProxy& proxy, QNetworkReply::NetworkError* output = nullptr); + QString convertShortStreamIdToLongStreamId(const QString& stream_id) const; QString simplifyStreamId(const QString& stream_id) const; QStringList decodeItemIds(const QString& stream_json_data, QString& continuation); QList decodeStreamContents(ServiceRoot* root, const QString& stream_json_data, const QString& stream_id, QString& continuation);