Skip to content

Commit

Permalink
fix #1154
Browse files Browse the repository at this point in the history
  • Loading branch information
martinrotter committed Feb 13, 2025
1 parent 25c5326 commit fc147a4
Show file tree
Hide file tree
Showing 13 changed files with 171 additions and 8 deletions.
14 changes: 10 additions & 4 deletions src/librssguard-standard/src/gui/formeditstandardaccount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,27 @@ FormEditStandardAccount::~FormEditStandardAccount() = default;
void FormEditStandardAccount::loadAccountData() {
FormAccountDetails::loadAccountData();

StandardServiceRoot* acc = account<StandardServiceRoot>();

if (m_creatingNew) {
m_standardDetails->m_ui.m_txtTitle->setText(StandardServiceRoot::defaultTitle());
}
else {
m_standardDetails->m_ui.m_txtTitle->setText(m_account->title());
m_standardDetails->m_ui.m_txtTitle->setText(acc->title());
}

m_standardDetails->m_ui.m_btnIcon->setIcon(m_account->fullIcon());
m_standardDetails->m_ui.m_btnIcon->setIcon(acc->fullIcon());
m_standardDetails->m_ui.m_spinFeedSpacing->setValue(acc->spacingSameHostsRequests());
}

void FormEditStandardAccount::apply() {
FormAccountDetails::apply();

m_account->setIcon(m_standardDetails->m_ui.m_btnIcon->icon());
m_account->setTitle(m_standardDetails->m_ui.m_txtTitle->text());
StandardServiceRoot* acc = account<StandardServiceRoot>();

acc->setIcon(m_standardDetails->m_ui.m_btnIcon->icon());
acc->setTitle(m_standardDetails->m_ui.m_txtTitle->text());
acc->setSpacingSameHostsRequests(m_standardDetails->m_ui.m_spinFeedSpacing->value());

m_account->saveAccountDataToDatabase();
m_account->itemChanged({m_account});
Expand Down
2 changes: 2 additions & 0 deletions src/librssguard-standard/src/gui/formstandardfeeddetails.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ void FormStandardFeedDetails::guessFeed() {
m_standardFeedDetails->guessFeed(m_standardFeedDetails->sourceType(),
m_standardFeedDetails->m_ui.m_txtSource->textEdit()->toPlainText(),
m_standardFeedDetails->m_ui.m_txtPostProcessScript->textEdit()->toPlainText(),
qobject_cast<StandardServiceRoot*>(m_serviceRoot),
m_authDetails->authenticationType(),
m_authDetails->username(),
m_authDetails->password(),
Expand All @@ -63,6 +64,7 @@ void FormStandardFeedDetails::guessIconOnly() {
m_standardFeedDetails->guessIconOnly(m_standardFeedDetails->sourceType(),
m_standardFeedDetails->m_ui.m_txtSource->textEdit()->toPlainText(),
m_standardFeedDetails->m_ui.m_txtPostProcessScript->textEdit()->toPlainText(),
qobject_cast<StandardServiceRoot*>(m_serviceRoot),
m_authDetails->authenticationType(),
m_authDetails->username(),
m_authDetails->password(),
Expand Down
3 changes: 2 additions & 1 deletion src/librssguard-standard/src/gui/formstandardfeeddetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
#ifndef FORMSSFEEDDETAILS_H
#define FORMSSFEEDDETAILS_H

#include "src/standardserviceroot.h"

#include <librssguard/services/abstract/gui/formfeeddetails.h>

class StandardFeedDetails;
class StandardFeedExpDetails;
class HttpHeadersDetails;
class StandardServiceRoot;
class AuthenticationDetails;
class StandardFeed;

Expand Down
20 changes: 20 additions & 0 deletions src/librssguard-standard/src/gui/standardaccountdetails.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ StandardAccountDetails::StandardAccountDetails(QWidget* parent) : QWidget(parent
icon_menu->addAction(action_default_icon);

m_ui.m_btnIcon->setMenu(icon_menu);

m_ui.m_helpFeedSpacing
->setHelpText(tr("When you fetch many feeds from same website/host, then %1 could be (likely "
"temporarily) banned for making too many network requests at once.\n\n"
"If that is the case, then you need to set some time gaps when fetching those feeds.")
.arg(QSL(APP_NAME)),
false);

connect(m_ui.m_spinFeedSpacing, &QSpinBox::valueChanged, this, &StandardAccountDetails::onFeedSpacingChanged);

onFeedSpacingChanged(m_ui.m_spinFeedSpacing->value());
}

void StandardAccountDetails::onLoadIconFromFile() {
Expand Down Expand Up @@ -63,3 +74,12 @@ void StandardAccountDetails::onLoadIconFromFile() {
void StandardAccountDetails::onUseDefaultIcon() {
m_ui.m_btnIcon->setIcon(StandardServiceEntryPoint().icon());
}

void StandardAccountDetails::onFeedSpacingChanged(int spacing) {
if (spacing <= 0) {
m_ui.m_spinFeedSpacing->setSuffix(tr(" = no spacing"));
}
else {
m_ui.m_spinFeedSpacing->setSuffix(tr(" seconds", nullptr, spacing));
}
}
1 change: 1 addition & 0 deletions src/librssguard-standard/src/gui/standardaccountdetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class StandardAccountDetails : public QWidget {
private slots:
void onLoadIconFromFile();
void onUseDefaultIcon();
void onFeedSpacingChanged(int spacing);

private:
Ui::StandardAccountDetails m_ui;
Expand Down
43 changes: 42 additions & 1 deletion src/librssguard-standard/src/gui/standardaccountdetails.ui
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<property name="text">
<string>Title</string>
</property>
<property name="buddy">
<cstring>m_txtTitle</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
Expand All @@ -29,6 +32,9 @@
<property name="text">
<string>Icon</string>
</property>
<property name="buddy">
<cstring>m_btnIcon</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
Expand All @@ -43,12 +49,47 @@
<string>Select icon for your account.</string>
</property>
<property name="popupMode">
<enum>QToolButton::InstantPopup</enum>
<enum>QToolButton::ToolButtonPopupMode::InstantPopup</enum>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Feed fetch spacing</string>
</property>
<property name="buddy">
<cstring>m_spinFeedSpacing</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="m_spinFeedSpacing">
<property name="maximum">
<number>120</number>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="HelpSpoiler" name="m_helpFeedSpacing" native="true">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>HelpSpoiler</class>
<extends>QWidget</extends>
<header>helpspoiler.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
4 changes: 4 additions & 0 deletions src/librssguard-standard/src/gui/standardfeeddetails.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ StandardFeedDetails::StandardFeedDetails(QWidget* parent) : QWidget(parent) {
void StandardFeedDetails::guessIconOnly(StandardFeed::SourceType source_type,
const QString& source,
const QString& post_process_script,
StandardServiceRoot* account,
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
Expand All @@ -149,6 +150,7 @@ void StandardFeedDetails::guessIconOnly(StandardFeed::SourceType source_type,
auto metadata = StandardFeed::guessFeed(source_type,
source,
post_process_script,
account,
protection,
true,
username,
Expand Down Expand Up @@ -185,6 +187,7 @@ void StandardFeedDetails::guessIconOnly(StandardFeed::SourceType source_type,
void StandardFeedDetails::guessFeed(StandardFeed::SourceType source_type,
const QString& source,
const QString& post_process_script,
StandardServiceRoot* account,
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
Expand All @@ -194,6 +197,7 @@ void StandardFeedDetails::guessFeed(StandardFeed::SourceType source_type,
auto metadata = StandardFeed::guessFeed(source_type,
source,
post_process_script,
account,
protection,
true,
username,
Expand Down
2 changes: 2 additions & 0 deletions src/librssguard-standard/src/gui/standardfeeddetails.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class StandardFeedDetails : public QWidget {
void guessIconOnly(StandardFeed::SourceType source_type,
const QString& source,
const QString& post_process_script,
StandardServiceRoot* account,
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
Expand All @@ -36,6 +37,7 @@ class StandardFeedDetails : public QWidget {
void guessFeed(StandardFeed::SourceType source_type,
const QString& source,
const QString& post_process_script,
StandardServiceRoot* account,
NetworkFactory::NetworkAuthentication protection,
const QString& username,
const QString& password,
Expand Down
7 changes: 7 additions & 0 deletions src/librssguard-standard/src/standardfeed.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ void StandardFeed::fetchMetadataForItself() {
auto metadata = guessFeed(sourceType(),
source(),
postProcessScript(),
serviceRoot(),
protection(),
true,
username(),
Expand Down Expand Up @@ -298,6 +299,7 @@ void StandardFeed::setSourceType(SourceType source_type) {
QPair<StandardFeed*, NetworkResult> StandardFeed::guessFeed(StandardFeed::SourceType source_type,
const QString& source,
const QString& post_process_script,
StandardServiceRoot* account,
NetworkFactory::NetworkFactory::NetworkAuthentication
protection,
bool fetch_icons,
Expand All @@ -310,6 +312,9 @@ QPair<StandardFeed*, NetworkResult> StandardFeed::guessFeed(StandardFeed::Source
NetworkResult network_result;

if (source_type == StandardFeed::SourceType::Url) {
QString host = QUrl(source).host();
account->spaceHost(host, source);

QList<QPair<QByteArray, QByteArray>> headers = http_headers;
headers << NetworkFactory::generateBasicAuthHeader(protection, username, password);

Expand All @@ -324,6 +329,8 @@ QPair<StandardFeed*, NetworkResult> StandardFeed::guessFeed(StandardFeed::Source
{},
custom_proxy);

// account->resetHostSpacing(host);

if (network_result.m_networkError != QNetworkReply::NetworkError::NoError) {
throw NetworkException(network_result.m_networkError);
}
Expand Down
1 change: 1 addition & 0 deletions src/librssguard-standard/src/standardfeed.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class StandardFeed : public Feed {
static QPair<StandardFeed*, NetworkResult> guessFeed(SourceType source_type,
const QString& url,
const QString& post_process_script,
StandardServiceRoot* account,
NetworkFactory::NetworkAuthentication protection,
bool fetch_icons = true,
const QString& username = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ bool FeedsImportExportModel::produceFeed(const FeedLookup& feed_lookup) {
auto new_feed_data = StandardFeed::guessFeed(source_type,
feed_lookup.url,
pp_script,
m_account,
NetworkFactory::NetworkAuthentication::NoAuthentication,
!feed_lookup.do_not_fetch_icons,
{},
Expand Down
65 changes: 63 additions & 2 deletions src/librssguard-standard/src/standardserviceroot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
#include <QStack>
#include <QTextCodec>

StandardServiceRoot::StandardServiceRoot(RootItem* parent) : ServiceRoot(parent) {
StandardServiceRoot::StandardServiceRoot(RootItem* parent) : ServiceRoot(parent), m_spacingSameHostsRequests(0) {
setIcon(StandardServiceEntryPoint().icon());
setDescription(tr("This is the obligatory service account for standard RSS/RDF/ATOM feeds."));
}
Expand Down Expand Up @@ -195,6 +195,49 @@ Qt::ItemFlags StandardServiceRoot::additionalFlags() const {
return ServiceRoot::additionalFlags() | Qt::ItemFlag::ItemIsDragEnabled | Qt::ItemFlag::ItemIsDropEnabled;
}

void StandardServiceRoot::spaceHost(const QString& host, const QString& url) {
if (m_spacingSameHostsRequests <= 0 || host.simplified().isEmpty()) {
// Spacing not enabled or host information unavailable.
return;
}

m_spacingMutex.lock();

QDateTime host_last_fetched = m_spacingHosts.value(host);
QDateTime now = QDateTime::currentDateTimeUtc();
int secs_to_wait = 0;

if (host_last_fetched.isValid()) {
// No last fetch time saved yet.
QDateTime last = host_last_fetched.addSecs(m_spacingSameHostsRequests);

if (last < now) {
// This host was last fetched sometimes in the past and not within the critical spacing window.
// We can therefore fetch now.
secs_to_wait = 0;
}
else {
secs_to_wait = now.secsTo(last);
}
}

resetHostSpacing(host, now.addSecs(secs_to_wait));

m_spacingMutex.unlock();

if (secs_to_wait > 0) {
qDebugNN << LOGSEC_CORE << "Freezing feed with URL" << QUOTE_W_SPACE(url) << "for" << NONQUOTE_W_SPACE(secs_to_wait)
<< "seconds, because its host was used for fetching another feed during the spacing period.";
QThread::sleep(ulong(secs_to_wait));
qDebugNN << LOGSEC_CORE << "Freezing feed with URL" << QUOTE_W_SPACE(url) << "is done.";
}
}

void StandardServiceRoot::resetHostSpacing(const QString& host, const QDateTime& next_dt) {
m_spacingHosts.insert(host, next_dt);
qDebugNN << LOGSEC_CORE << "Setting spacing for" << QUOTE_W_SPACE(host) << "to" << QUOTE_W_SPACE_DOT(next_dt);
}

QList<Message> StandardServiceRoot::obtainNewMessages(Feed* feed,
const QHash<ServiceRoot::BagOfMessages, QStringList>&
stated_messages,
Expand All @@ -203,11 +246,14 @@ QList<Message> StandardServiceRoot::obtainNewMessages(Feed* feed,
Q_UNUSED(tagged_messages)

StandardFeed* f = static_cast<StandardFeed*>(feed);
QString host = QUrl(f->source()).host();
QByteArray feed_contents;
QString formatted_feed_contents;
int download_timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();

if (f->sourceType() == StandardFeed::SourceType::Url) {
spaceHost(host, f->source());

qDebugNN << LOGSEC_CORE << "Downloading URL" << QUOTE_W_SPACE(feed->source()) << "to obtain feed data.";

QList<QPair<QByteArray, QByteArray>> headers = StandardFeed::httpHeadersToList(f->httpHeaders());
Expand All @@ -232,11 +278,15 @@ QList<Message> StandardServiceRoot::obtainNewMessages(Feed* feed,
networkProxy(),
f->http2Status());

// Update last datetime this host was used.
// resetHostSpacing(host);

if (network_result.m_networkError != QNetworkReply::NetworkError::NoError) {
qWarningNN << LOGSEC_CORE << "Error" << QUOTE_W_SPACE(network_result.m_networkError)
<< "during fetching of new messages for feed" << QUOTE_W_SPACE_DOT(feed->source());
throw FeedFetchException(Feed::Status::NetworkError,
NetworkFactory::networkErrorText(network_result.m_networkError));
NetworkFactory::networkErrorText(network_result.m_networkError),
QVariant::fromValue(network_result));
}
else {
f->setLastEtag(network_result.m_headers.value(QSL("etag")));
Expand Down Expand Up @@ -404,6 +454,7 @@ QVariantHash StandardServiceRoot::customDatabaseData() const {

data[QSL("title")] = title();
data[QSL("icon")] = IconFactory::toByteArray(icon());
data[QSL("requests_spacing")] = spacingSameHostsRequests();

return data;
}
Expand All @@ -418,6 +469,8 @@ void StandardServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
if (!icon_data.isEmpty()) {
setIcon(IconFactory::fromByteArray(icon_data));
}

setSpacingSameHostsRequests(data.value(QSL("requests_spacing")).toInt());
}

QString StandardServiceRoot::defaultTitle() {
Expand Down Expand Up @@ -530,6 +583,14 @@ bool StandardServiceRoot::mergeImportExportModel(FeedsImportExportModel* model,
return !some_feed_category_error;
}

int StandardServiceRoot::spacingSameHostsRequests() const {
return m_spacingSameHostsRequests;
}

void StandardServiceRoot::setSpacingSameHostsRequests(int spacing) {
m_spacingSameHostsRequests = spacing;
}

void StandardServiceRoot::addNewCategory(RootItem* selected_item) {
if (!qApp->feedUpdateLock()->tryLock()) {
// Lock was not obtained because
Expand Down
Loading

0 comments on commit fc147a4

Please sign in to comment.