mirror of
https://github.com/martinrotter/rssguard.git
synced 2025-02-03 10:47:47 +01:00
save
This commit is contained in:
parent
b19450932a
commit
6faeba1185
@ -30,7 +30,7 @@
|
||||
<url type="donation">https://martinrotter.github.io/donate/</url>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="3.8.4" date="2021-02-16"/>
|
||||
<release version="3.8.4" date="2021-02-17"/>
|
||||
</releases>
|
||||
<content_rating type="oars-1.0">
|
||||
<content_attribute id="violence-cartoon">none</content_attribute>
|
||||
|
@ -4,6 +4,7 @@
|
||||
#define FEEDLY_UNLIMITED_BATCH_SIZE -1
|
||||
#define FEEDLY_DEFAULT_BATCH_SIZE 20
|
||||
#define FEEDLY_MAX_BATCH_SIZE 500
|
||||
#define FEEDLX_MAX_TOTAL_SIZE 5000
|
||||
|
||||
#define FEEDLY_GENERATE_DAT "https://feedly.com/v3/auth/dev"
|
||||
|
||||
@ -16,6 +17,9 @@
|
||||
#define FEEDLY_API_URL_BASE "https://cloud.feedly.com/v3/"
|
||||
#endif
|
||||
|
||||
#define FEEDLY_API_SYSTEM_TAG_READ "global.read"
|
||||
#define FEEDLY_API_SYSTEM_TAG_SAVED "global.saved"
|
||||
|
||||
#define FEEDLY_API_URL_AUTH "auth/auth"
|
||||
#define FEEDLY_API_URL_TOKEN "auth/token"
|
||||
#define FEEDLY_API_URL_PROFILE "profile"
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "services/feedly/feedlyfeed.h"
|
||||
|
||||
#include "exceptions/applicationexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "services/feedly/feedlynetwork.h"
|
||||
@ -16,14 +17,23 @@ FeedlyServiceRoot* FeedlyFeed::serviceRoot() const {
|
||||
}
|
||||
|
||||
QList<Message> FeedlyFeed::obtainNewMessages(bool* error_during_obtaining) {
|
||||
Feed::Status error = Feed::Status::Normal;
|
||||
QList<Message> messages = serviceRoot()->network()->streamContents(customId());
|
||||
try {
|
||||
QList<Message> messages = serviceRoot()->network()->streamContents(customId());
|
||||
|
||||
setStatus(error);
|
||||
|
||||
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError) {
|
||||
*error_during_obtaining = true;
|
||||
setStatus(Feed::Status::Normal);
|
||||
*error_during_obtaining = false;
|
||||
return messages;;
|
||||
}
|
||||
catch (const ApplicationException& ex) {
|
||||
setStatus(Feed::Status::NetworkError);
|
||||
*error_during_obtaining = true;
|
||||
|
||||
return messages;
|
||||
qCriticalNN << LOGSEC_FEEDLY
|
||||
<< "Problem"
|
||||
<< QUOTE_W_SPACE(ex.message())
|
||||
<< "when obtaining messages for feed"
|
||||
<< QUOTE_W_SPACE_DOT(customId());
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "services/feedly/feedlynetwork.h"
|
||||
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "3rd-party/boolinq/boolinq.h"
|
||||
#include "exceptions/networkexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
@ -68,8 +69,14 @@ QList<Message> FeedlyNetwork::streamContents(const QString& stream_id) {
|
||||
if (!continuation.isEmpty()) {
|
||||
target_url += QSL("&continuation=%1").arg(continuation);
|
||||
}
|
||||
else if (m_batchSize > 0) {
|
||||
target_url += QSL("&count=%2").arg(QString::number(m_batchSize));
|
||||
|
||||
if (m_batchSize > 0) {
|
||||
target_url += QSL("&count=%1").arg(QString::number(m_batchSize));
|
||||
}
|
||||
else {
|
||||
// User wants to download all messages. Make sure we use large batches
|
||||
// to limit network requests.
|
||||
target_url += QSL("&count=%1").arg(QString::number(FEEDLY_MAX_BATCH_SIZE));
|
||||
}
|
||||
|
||||
auto result = NetworkFactory::performNetworkOperation(target_url,
|
||||
@ -83,10 +90,15 @@ QList<Message> FeedlyNetwork::streamContents(const QString& stream_id) {
|
||||
{},
|
||||
m_service->networkProxy());
|
||||
|
||||
messages += decodeStreamContents(output, continuation);
|
||||
if (result.first != QNetworkReply::NetworkError::NoError) {
|
||||
throw NetworkException(result.first);
|
||||
}
|
||||
|
||||
messages += decodeStreamContents(output, continuation);
|
||||
}
|
||||
while (!continuation.isEmpty());
|
||||
while (!continuation.isEmpty() &&
|
||||
(m_batchSize <= 0 || messages.size() < m_batchSize) &&
|
||||
messages.size() <= FEEDLX_MAX_TOTAL_SIZE);
|
||||
|
||||
return messages;
|
||||
}
|
||||
@ -94,6 +106,7 @@ QList<Message> FeedlyNetwork::streamContents(const QString& stream_id) {
|
||||
QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_contents, 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*>();
|
||||
|
||||
continuation = json.object()["continuation"].toString();
|
||||
|
||||
@ -104,10 +117,47 @@ QList<Message> FeedlyNetwork::decodeStreamContents(const QByteArray& stream_cont
|
||||
message.m_title = entry_obj["title"].toString();
|
||||
message.m_author = entry_obj["author"].toString();
|
||||
message.m_contents = entry_obj["content"].toObject()["content"].toString();
|
||||
|
||||
if (message.m_contents.isEmpty()) {
|
||||
message.m_contents = entry_obj["summary"].toObject()["content"].toString();
|
||||
}
|
||||
|
||||
message.m_createdFromFeed = true;
|
||||
message.m_created = QDateTime::fromMSecsSinceEpoch(entry_obj["published"].toVariant().toLongLong(),
|
||||
Qt::TimeSpec::UTC);
|
||||
message.m_customId = entry_obj["id"].toString();
|
||||
message.m_isRead = !entry_obj["unread"].toBool();
|
||||
message.m_url = entry_obj["canonicalUrl"].toString();
|
||||
|
||||
if (message.m_url.isEmpty()) {
|
||||
message.m_url = entry_obj["canonical"].toObject()["href"].toString();
|
||||
}
|
||||
|
||||
for (const QJsonValue& tag : entry_obj["tags"].toArray()) {
|
||||
const QJsonObject& tag_obj = tag.toObject();
|
||||
const QString& tag_id = tag_obj["id"].toString();
|
||||
|
||||
if (tag_id.endsWith(FEEDLY_API_SYSTEM_TAG_SAVED)) {
|
||||
message.m_isImportant = true;
|
||||
}
|
||||
else if (tag_id.endsWith(FEEDLY_API_SYSTEM_TAG_READ)) {
|
||||
// NOTE: We don't do anything with "global read" tag.
|
||||
}
|
||||
else {
|
||||
Label* label = boolinq::from(active_labels.begin(), active_labels.end()).firstOrDefault([tag_id](Label* lbl) {
|
||||
return lbl->customId() == tag_id;
|
||||
});
|
||||
|
||||
if (label != nullptr) {
|
||||
message.m_assignedLabels.append(label);
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_FEEDLY
|
||||
<< "Failed to find live Label object for tag"
|
||||
<< QUOTE_W_SPACE_DOT(tag_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
messages.append(message);
|
||||
}
|
||||
@ -267,6 +317,12 @@ QList<RootItem*> FeedlyNetwork::tags() {
|
||||
for (const QJsonValue& tag : json.array()) {
|
||||
const QJsonObject& tag_obj = tag.toObject();
|
||||
QString name_id = tag_obj["id"].toString();
|
||||
|
||||
if (name_id.endsWith(FEEDLY_API_SYSTEM_TAG_READ) ||
|
||||
name_id.endsWith(FEEDLY_API_SYSTEM_TAG_SAVED)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QString plain_name = tag_obj["label"].toString();
|
||||
auto* new_lbl = new Label(plain_name, TextFactory::generateColorFromText(name_id));
|
||||
|
||||
|
@ -74,7 +74,11 @@ class FeedlyNetwork : public QObject {
|
||||
|
||||
QString m_username;
|
||||
QString m_developerAccessToken;
|
||||
|
||||
// Only download N newest messages per feed.
|
||||
int m_batchSize;
|
||||
|
||||
// Only download unread messages.
|
||||
bool m_downloadOnlyUnreadMessages;
|
||||
};
|
||||
|
||||
|
@ -47,6 +47,10 @@ FeedlyAccountDetails::FeedlyAccountDetails(QWidget* parent) : QWidget(parent) {
|
||||
"each day.").arg(APP_NAME));
|
||||
#endif
|
||||
|
||||
m_ui.m_lblLimitMessagesInfo->setText(tr("Be very careful about downloading too many messages, because "
|
||||
"Feedly automagically caches ALL messages of a feed forever so you might "
|
||||
"end with thousands of messages you will never read anyway."));
|
||||
|
||||
connect(m_ui.m_spinLimitMessages, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [=](int value) {
|
||||
if (value <= 0) {
|
||||
m_ui.m_spinLimitMessages->setSuffix(QSL(" ") + tr("= unlimited"));
|
||||
@ -57,6 +61,7 @@ FeedlyAccountDetails::FeedlyAccountDetails(QWidget* parent) : QWidget(parent) {
|
||||
});
|
||||
|
||||
GuiUtilities::setLabelAsNotice(*m_ui.m_lblInfo, true);
|
||||
GuiUtilities::setLabelAsNotice(*m_ui.m_lblLimitMessagesInfo, true);
|
||||
|
||||
connect(m_ui.m_btnGetToken, &QPushButton::clicked, this, &FeedlyAccountDetails::getDeveloperAccessToken);
|
||||
connect(m_ui.m_txtUsername->lineEdit(), &BaseLineEdit::textChanged, this, &FeedlyAccountDetails::onUsernameChanged);
|
||||
|
@ -79,7 +79,7 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<item row="7" column="0" colspan="2">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
@ -92,7 +92,7 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<item row="6" column="0" colspan="2">
|
||||
<layout class="QFormLayout" name="formLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="m_btnTestSetup">
|
||||
@ -117,6 +117,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0" colspan="2">
|
||||
<widget class="QLabel" name="m_lblLimitMessagesInfo">
|
||||
<property name="text">
|
||||
<string>TextLabel</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
Loading…
x
Reference in New Issue
Block a user