From caecf5355aa1c22175866b6662871793e3acb060 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Mon, 13 Nov 2023 12:10:58 +0100 Subject: [PATCH] greader supports feed deleting --- .../scripts/github-actions/build-windows.ps1 | 2 +- src/librssguard/CMakeLists.txt | 7 +++ .../services/greader/definitions.h | 6 ++ .../services/greader/greadernetwork.cpp | 57 ++++++++++++++++++- .../services/greader/greadernetwork.h | 9 ++- .../services/greader/greaderserviceroot.cpp | 31 +++++++++- .../services/greader/greaderserviceroot.h | 2 + .../tt-rss/gui/formttrssfeeddetails.cpp | 7 +-- .../tt-rss/gui/formttrssfeeddetails.h | 6 +- 9 files changed, 115 insertions(+), 12 deletions(-) diff --git a/resources/scripts/github-actions/build-windows.ps1 b/resources/scripts/github-actions/build-windows.ps1 index fc8bffcf0..889528e35 100755 --- a/resources/scripts/github-actions/build-windows.ps1 +++ b/resources/scripts/github-actions/build-windows.ps1 @@ -30,7 +30,7 @@ else { $is_qt_6 = $qt_version.StartsWith("6") $maria_version = "11.1.2" -$maria_link = "https://archive.mariadb.org/mariadb-$maria_version/winx64-packages/mariadb-$maria_version-winx64.zip" +$maria_link = "https://mirror.netcologne.de/mariadb/mariadb-$maria_version/winx64-packages/mariadb-$maria_version-winx64.zip" $maria_output = "maria.zip" $cmake_version = "3.27.7" diff --git a/src/librssguard/CMakeLists.txt b/src/librssguard/CMakeLists.txt index 31cf059d6..90be4f626 100644 --- a/src/librssguard/CMakeLists.txt +++ b/src/librssguard/CMakeLists.txt @@ -352,10 +352,16 @@ set(SOURCES services/greader/greadernetwork.h services/greader/greaderserviceroot.cpp services/greader/greaderserviceroot.h + services/greader/greaderfeed.cpp + services/greader/greaderfeed.h services/greader/gui/formeditgreaderaccount.cpp services/greader/gui/formeditgreaderaccount.h services/greader/gui/greaderaccountdetails.cpp services/greader/gui/greaderaccountdetails.h + services/greader/gui/formgreaderfeeddetails.cpp + services/greader/gui/formgreaderfeeddetails.h + services/greader/gui/greaderfeeddetails.cpp + services/greader/gui/greaderfeeddetails.h services/owncloud/definitions.h services/owncloud/gui/formeditowncloudaccount.cpp services/owncloud/gui/formeditowncloudaccount.h @@ -487,6 +493,7 @@ set(UI_FILES services/gmail/gui/formaddeditemail.ui services/gmail/gui/gmailaccountdetails.ui services/greader/gui/greaderaccountdetails.ui + services/greader/gui/greaderfeeddetails.ui services/owncloud/gui/owncloudaccountdetails.ui services/reddit/gui/redditaccountdetails.ui services/standard/gui/formdiscoverfeeds.ui diff --git a/src/librssguard/services/greader/definitions.h b/src/librssguard/services/greader/definitions.h index b2acb8c9b..e41f4a08a 100644 --- a/src/librssguard/services/greader/definitions.h +++ b/src/librssguard/services/greader/definitions.h @@ -29,11 +29,17 @@ #define GREADER_API_EDIT_TAG "reader/api/0/edit-tag" #define GREADER_API_SUBSCRIPTION_EXPORT "reader/api/0/subscription/export" #define GREADER_API_SUBSCRIPTION_IMPORT "reader/api/0/subscription/import" +#define GREADER_API_SUBSCRIPTION_EDIT "reader/api/0/subscription/edit?ac=%1&s=%2" #define GREADER_API_ITEM_IDS "reader/api/0/stream/items/ids?output=json&n=%2&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" +// Edit subscription ops. +#define GREADER_API_EDIT_SUBSCRIPTION_ADD "subscribe" +#define GREADER_API_EDIT_SUBSCRIPTION_MODIFY "edit" +#define GREADER_API_EDIT_SUBSCRIPTION_DELETE "unsubscribe" + // Misc. #define GREADER_API_ITEM_IDS_MAX 200000 #define GREADER_API_EDIT_TAG_BATCH 200 diff --git a/src/librssguard/services/greader/greadernetwork.cpp b/src/librssguard/services/greader/greadernetwork.cpp index 98a876920..a04a868db 100644 --- a/src/librssguard/services/greader/greadernetwork.cpp +++ b/src/librssguard/services/greader/greadernetwork.cpp @@ -16,6 +16,7 @@ #include "services/abstract/label.h" #include "services/abstract/labelsnode.h" #include "services/greader/definitions.h" +#include "services/greader/greaderfeed.h" #include #include @@ -341,6 +342,57 @@ QNetworkReply::NetworkError GreaderNetwork::markMessagesStarred(RootItem::Import proxy); } +void GreaderNetwork::subscriptionEdit(const QString& op, + const QString& stream_id, + const QString& new_title, + const QString& set_label, + const QString& unset_label, + const QNetworkProxy& proxy) { + if (!ensureLogin(proxy)) { + throw ApplicationException(tr("login failed")); + } + + QString full_url = generateFullUrl(Operations::SubscriptionEdit).arg(op, stream_id); + + if (op == QSL(GREADER_API_EDIT_SUBSCRIPTION_ADD)) { + full_url += QSL("&t=%1").arg(new_title); + + if (!set_label.isEmpty()) { + full_url += QSL("&a=%1").arg(set_label); + } + } + + if (op == QSL(GREADER_API_EDIT_SUBSCRIPTION_MODIFY)) { + full_url += QSL("&t=%1").arg(new_title); + + if (!set_label.isEmpty()) { + full_url += QSL("&a=%1").arg(set_label); + } + else if (!unset_label.isEmpty()) { + full_url += QSL("&r=%1").arg(unset_label); + } + } + + auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt(); + + QByteArray output; + auto result = NetworkFactory::performNetworkOperation(full_url, + timeout, + {}, + output, + QNetworkAccessManager::Operation::PostOperation, + {authHeader()}, + false, + {}, + {}, + proxy); + + if (result.m_networkError != QNetworkReply::NetworkError::NoError) { + qCriticalNN << LOGSEC_GREADER << "Cannot edit subscription:" << QUOTE_W_SPACE_DOT(result.m_networkError); + throw NetworkException(result.m_networkError, output); + } +} + void GreaderNetwork::subscriptionImport(const QByteArray& opml_data, const QNetworkProxy& proxy) { if (!ensureLogin(proxy)) { throw ApplicationException(tr("login failed")); @@ -749,7 +801,7 @@ RootItem* GreaderNetwork::decodeTagsSubscriptions(const QString& categories, } // We have label (not "state"). - auto* feed = new Feed(); + auto* feed = new GreaderFeed(); feed->setDescription(url); feed->setSource(url); @@ -1127,6 +1179,9 @@ QString GreaderNetwork::generateFullUrl(GreaderNetwork::Operations operation) co case Operations::SubscriptionImport: return sanitizedBaseUrl() + QSL(GREADER_API_SUBSCRIPTION_IMPORT); + case Operations::SubscriptionEdit: + return sanitizedBaseUrl() + QSL(GREADER_API_SUBSCRIPTION_EDIT); + case Operations::Token: return sanitizedBaseUrl() + QSL(GREADER_API_TOKEN); diff --git a/src/librssguard/services/greader/greadernetwork.h b/src/librssguard/services/greader/greadernetwork.h index 2bf379723..ec357ec2a 100644 --- a/src/librssguard/services/greader/greadernetwork.h +++ b/src/librssguard/services/greader/greadernetwork.h @@ -26,7 +26,8 @@ class GreaderNetwork : public QObject { ItemIds, ItemContents, SubscriptionExport, - SubscriptionImport + SubscriptionImport, + SubscriptionEdit }; explicit GreaderNetwork(QObject* parent = nullptr); @@ -84,6 +85,12 @@ class GreaderNetwork : public QObject { void setOauth(OAuth2Service* oauth); // API methods. + void subscriptionEdit(const QString& op, + const QString& stream_id, + const QString& new_title, + const QString& set_label, + const QString& unset_label, + const QNetworkProxy& proxy); void subscriptionImport(const QByteArray& opml_data, const QNetworkProxy& proxy); QByteArray subscriptionExport(const QNetworkProxy& proxy); QNetworkReply::NetworkError editLabels(const QString& state, diff --git a/src/librssguard/services/greader/greaderserviceroot.cpp b/src/librssguard/services/greader/greaderserviceroot.cpp index 0d0e69f02..2b3c122d0 100644 --- a/src/librssguard/services/greader/greaderserviceroot.cpp +++ b/src/librssguard/services/greader/greaderserviceroot.cpp @@ -7,12 +7,15 @@ #include "gui/messagebox.h" #include "miscellaneous/application.h" #include "miscellaneous/iconfactory.h" +#include "miscellaneous/mutex.h" #include "miscellaneous/textfactory.h" #include "network-web/oauth2service.h" #include "services/greader/definitions.h" #include "services/greader/greaderentrypoint.h" +#include "services/greader/greaderfeed.h" #include "services/greader/greadernetwork.h" #include "services/greader/gui/formeditgreaderaccount.h" +#include "services/greader/gui/formgreaderfeeddetails.h" #include @@ -211,7 +214,7 @@ bool GreaderServiceRoot::wantsBaggedIdsOfExistingMessages() const { void GreaderServiceRoot::start(bool freshly_activated) { if (!freshly_activated) { - DatabaseQueries::loadRootFromDatabase(this); + DatabaseQueries::loadRootFromDatabase(this); loadCacheFromFile(); } @@ -331,6 +334,32 @@ ServiceRoot::LabelOperation GreaderServiceRoot::supportedLabelOperations() const return ServiceRoot::LabelOperation::Synchronised; } +bool GreaderServiceRoot::supportsFeedAdding() const { + return true; +} + +void GreaderServiceRoot::addNewFeed(RootItem* selected_item, const QString& url) { + if (!qApp->feedUpdateLock()->tryLock()) { + // 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}); + + return; + } + + QScopedPointer form_pointer(new FormGreaderFeedDetails(this, + selected_item, + url, + qApp->mainFormWidget())); + + form_pointer->addEditFeed(); + qApp->feedUpdateLock()->unlock(); +} + void GreaderServiceRoot::updateTitleIcon() { setTitle(QSL("%1 (%2)").arg(TextFactory::extractUsernameFromEmail(m_network->username()), GreaderServiceRoot::serviceToString(m_network->service()))); diff --git a/src/librssguard/services/greader/greaderserviceroot.h b/src/librssguard/services/greader/greaderserviceroot.h index d0f1d6fe2..1b9f480bf 100644 --- a/src/librssguard/services/greader/greaderserviceroot.h +++ b/src/librssguard/services/greader/greaderserviceroot.h @@ -35,6 +35,8 @@ class GreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot { virtual QList serviceMenu(); virtual void saveAllCachedData(bool ignore_errors); virtual LabelOperation supportedLabelOperations() const; + virtual bool supportsFeedAdding() const; + virtual void addNewFeed(RootItem* selected_item, const QString& url = QString()); virtual QVariantHash customDatabaseData() const; virtual void setCustomDatabaseData(const QVariantHash& data); virtual void aboutToBeginFeedFetching(const QList& feeds, diff --git a/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp b/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp index 11760f7a3..e41d39f79 100644 --- a/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp +++ b/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.cpp @@ -29,7 +29,7 @@ void FormTtRssFeedDetails::apply() { else { RootItem* parent = m_feedDetails->ui.m_cmbParentCategory->currentData().value(); auto* root = qobject_cast(parent->getParentServiceRoot()); - const int category_id = parent->kind() == RootItem::Kind::ServiceRoot ? 0 : parent->customId().toInt(); + const int category_id = parent->kind() == RootItem::Kind::ServiceRoot ? 0 : parent->customNumericId(); const TtRssSubscribeToFeedResponse response = root->network()->subscribeToFeed(m_feedDetails->ui.m_txtUrl->lineEdit()->text(), category_id, @@ -66,11 +66,6 @@ void FormTtRssFeedDetails::loadFeedData() { if (!m_urlToProcess.isEmpty()) { m_feedDetails->ui.m_txtUrl->lineEdit()->setText(m_urlToProcess); } - /* - else if (Application::clipboard()->mimeData()->hasText()) { - m_feedDetails->ui.m_txtUrl->lineEdit()->setText(Application::clipboard()->text()); - } - */ m_feedDetails->ui.m_txtUrl->lineEdit()->selectAll(); m_feedDetails->ui.m_txtUrl->setFocus(); diff --git a/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.h b/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.h index 00273a4ed..49ed09333 100644 --- a/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.h +++ b/src/librssguard/services/tt-rss/gui/formttrssfeeddetails.h @@ -11,8 +11,10 @@ class AuthenticationDetails; class FormTtRssFeedDetails : public FormFeedDetails { public: - explicit FormTtRssFeedDetails(ServiceRoot* service_root, RootItem* parent_to_select = nullptr, - const QString& url = QString(), QWidget* parent = nullptr); + explicit FormTtRssFeedDetails(ServiceRoot* service_root, + RootItem* parent_to_select = nullptr, + const QString& url = QString(), + QWidget* parent = nullptr); protected slots: virtual void apply();