mirror of
https://github.com/martinrotter/rssguard.git
synced 2025-01-29 00:30:12 +01:00
sync-in works for freshrss
This commit is contained in:
parent
2a1289e70a
commit
51e0f1675d
@ -30,7 +30,7 @@
|
|||||||
<url type="donation">https://martinrotter.github.io/donate/</url>
|
<url type="donation">https://martinrotter.github.io/donate/</url>
|
||||||
<content_rating type="oars-1.1" />
|
<content_rating type="oars-1.1" />
|
||||||
<releases>
|
<releases>
|
||||||
<release version="3.8.4" date="2021-01-28"/>
|
<release version="3.8.4" date="2021-01-29"/>
|
||||||
</releases>
|
</releases>
|
||||||
<content_rating type="oars-1.0">
|
<content_rating type="oars-1.0">
|
||||||
<content_attribute id="violence-cartoon">none</content_attribute>
|
<content_attribute id="violence-cartoon">none</content_attribute>
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 9c10723bfbaf6cb85107d6ee16e0324e9e487749
|
Subproject commit 47f4125753452eff8800dbd6600c5a05540b15d9
|
@ -1485,8 +1485,8 @@ bool DatabaseQueries::storeAccountTree(const QSqlDatabase& db, RootItem* tree_ro
|
|||||||
query_feed.setForwardOnly(true);
|
query_feed.setForwardOnly(true);
|
||||||
query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) "
|
query_category.prepare("INSERT INTO Categories (parent_id, title, account_id, custom_id) "
|
||||||
"VALUES (:parent_id, :title, :account_id, :custom_id);");
|
"VALUES (:parent_id, :title, :account_id, :custom_id);");
|
||||||
query_feed.prepare("INSERT INTO Feeds (title, icon, category, protected, update_type, update_interval, account_id, custom_id) "
|
query_feed.prepare("INSERT INTO Feeds (title, icon, url, category, protected, update_type, update_interval, account_id, custom_id) "
|
||||||
"VALUES (:title, :icon, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);");
|
"VALUES (:title, :icon, :url, :category, :protected, :update_type, :update_interval, :account_id, :custom_id);");
|
||||||
|
|
||||||
// Iterate all children.
|
// Iterate all children.
|
||||||
for (RootItem* child : tree_root->getSubTree()) {
|
for (RootItem* child : tree_root->getSubTree()) {
|
||||||
@ -1508,9 +1508,10 @@ bool DatabaseQueries::storeAccountTree(const QSqlDatabase& db, RootItem* tree_ro
|
|||||||
|
|
||||||
query_feed.bindValue(QSL(":title"), feed->title());
|
query_feed.bindValue(QSL(":title"), feed->title());
|
||||||
query_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(feed->icon()));
|
query_feed.bindValue(QSL(":icon"), qApp->icons()->toByteArray(feed->icon()));
|
||||||
|
query_feed.bindValue(QSL(":url"), feed->url());
|
||||||
query_feed.bindValue(QSL(":category"), feed->parent()->id());
|
query_feed.bindValue(QSL(":category"), feed->parent()->id());
|
||||||
query_feed.bindValue(QSL(":protected"), 0);
|
query_feed.bindValue(QSL(":protected"), 0);
|
||||||
query_feed.bindValue(QSL(":update_type"), (int) feed->autoUpdateType());
|
query_feed.bindValue(QSL(":update_type"), int(feed->autoUpdateType()));
|
||||||
query_feed.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval());
|
query_feed.bindValue(QSL(":update_interval"), feed->autoUpdateInitialInterval());
|
||||||
query_feed.bindValue(QSL(":account_id"), account_id);
|
query_feed.bindValue(QSL(":account_id"), account_id);
|
||||||
query_feed.bindValue(QSL(":custom_id"), feed->customId());
|
query_feed.bindValue(QSL(":custom_id"), feed->customId());
|
||||||
|
@ -255,8 +255,10 @@ Assignment DatabaseQueries::getCategories(const QSqlDatabase& db, int account_id
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Assignment DatabaseQueries::getFeeds(const QSqlDatabase& db, const QList<MessageFilter*>& global_filters,
|
Assignment DatabaseQueries::getFeeds(const QSqlDatabase& db,
|
||||||
int account_id, bool* ok) {
|
const QList<MessageFilter*>& global_filters,
|
||||||
|
int account_id,
|
||||||
|
bool* ok) {
|
||||||
Assignment feeds;
|
Assignment feeds;
|
||||||
|
|
||||||
// All categories are now loaded.
|
// All categories are now loaded.
|
||||||
|
@ -18,6 +18,19 @@ quint64 TextFactory::s_encryptionKey = 0x0;
|
|||||||
|
|
||||||
TextFactory::TextFactory() = default;
|
TextFactory::TextFactory() = default;
|
||||||
|
|
||||||
|
QColor TextFactory::generateColorFromText(const QString& text) {
|
||||||
|
quint32 color = 0;
|
||||||
|
|
||||||
|
for (const QChar chr : text) {
|
||||||
|
color += chr.unicode();
|
||||||
|
}
|
||||||
|
|
||||||
|
color = QRandomGenerator(color).bounded(double(0xFFFFFF)) - 1;
|
||||||
|
auto color_name = QSL("#%1").arg(color, 6, 16);
|
||||||
|
|
||||||
|
return QColor(color_name);
|
||||||
|
}
|
||||||
|
|
||||||
int TextFactory::stringHeight(const QString& string, const QFontMetrics& metrics) {
|
int TextFactory::stringHeight(const QString& string, const QFontMetrics& metrics) {
|
||||||
const int count_lines = string.split(QL1C('\n')).size();
|
const int count_lines = string.split(QL1C('\n')).size();
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ class TextFactory {
|
|||||||
TextFactory();
|
TextFactory();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static QColor generateColorFromText(const QString& text);
|
||||||
static int stringHeight(const QString& string, const QFontMetrics& metrics);
|
static int stringHeight(const QString& string, const QFontMetrics& metrics);
|
||||||
static int stringWidth(const QString& string, const QFontMetrics& metrics);
|
static int stringWidth(const QString& string, const QFontMetrics& metrics);
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@ class QAction;
|
|||||||
class MessagesModel;
|
class MessagesModel;
|
||||||
class CacheForServiceRoot;
|
class CacheForServiceRoot;
|
||||||
|
|
||||||
// Car here represents ID (int, primary key) of the item.
|
// First item here represents ID (int, primary key) of the item.
|
||||||
typedef QList<QPair<int, RootItem*>> Assignment;
|
typedef QList<QPair<int, RootItem*>> Assignment;
|
||||||
typedef QPair<int, RootItem*> AssignmentItem;
|
typedef QPair<int, RootItem*> AssignmentItem;
|
||||||
typedef QPair<Message, RootItem::Importance> ImportanceChange;
|
typedef QPair<Message, RootItem::Importance> ImportanceChange;
|
||||||
|
@ -1,6 +1,15 @@
|
|||||||
#ifndef GREADER_DEFINITIONS_H
|
#ifndef GREADER_DEFINITIONS_H
|
||||||
#define GREADER_DEFINITIONS_H
|
#define GREADER_DEFINITIONS_H
|
||||||
|
|
||||||
#define GREADER_UNLIMITED_BATCH_SIZE -1
|
#define GREADER_UNLIMITED_BATCH_SIZE -1
|
||||||
|
|
||||||
|
// FreshRSS.
|
||||||
|
#define FRESHRSS_BASE_URL_PATH "api/greader.php/"
|
||||||
|
|
||||||
|
// API.
|
||||||
|
#define GREADER_API_CLIENT_LOGIN "accounts/ClientLogin?Email=%1&Passwd=%2"
|
||||||
|
#define GREADER_API_TAG_LIST "reader/api/0/tag/list?output=json"
|
||||||
|
#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"
|
||||||
|
|
||||||
#endif // GREADER_DEFINITIONS_H
|
#endif // GREADER_DEFINITIONS_H
|
||||||
|
@ -4,14 +4,185 @@
|
|||||||
|
|
||||||
#include "miscellaneous/application.h"
|
#include "miscellaneous/application.h"
|
||||||
#include "network-web/networkfactory.h"
|
#include "network-web/networkfactory.h"
|
||||||
|
#include "services/abstract/category.h"
|
||||||
|
#include "services/abstract/label.h"
|
||||||
|
#include "services/abstract/labelsnode.h"
|
||||||
|
#include "services/greader/definitions.h"
|
||||||
|
#include "services/greader/greaderfeed.h"
|
||||||
|
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
GreaderNetwork::GreaderNetwork(QObject* parent)
|
GreaderNetwork::GreaderNetwork(QObject* parent)
|
||||||
: QObject(parent), m_service(GreaderServiceRoot::Service::FreshRss) {}
|
: QObject(parent), m_service(GreaderServiceRoot::Service::FreshRss), m_username(QString()), m_password(QString()),
|
||||||
|
m_baseUrl(QString()), m_batchSize(GREADER_UNLIMITED_BATCH_SIZE) {
|
||||||
|
clearCredentials();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Message> GreaderNetwork::streamContents(ServiceRoot* root, const QString& stream_id, Feed::Status& error) {
|
||||||
|
QString full_url = generateFullUrl(Operations::StreamContents).arg(stream_id, batchSize());
|
||||||
|
auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
|
||||||
|
|
||||||
|
if (!ensureLogin(proxy)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray output_labels;
|
||||||
|
auto result_labels = NetworkFactory::performNetworkOperation(full_url,
|
||||||
|
timeout,
|
||||||
|
{},
|
||||||
|
output_labels,
|
||||||
|
QNetworkAccessManager::Operation::GetOperation,
|
||||||
|
{ authHeader() },
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
proxy);
|
||||||
|
|
||||||
QList<Message> GreaderNetwork::messages(ServiceRoot* root, const QString& stream_id, Feed::Status& error) {
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RootItem* GreaderNetwork::categoriesFeedsLabelsTree(bool obtain_icons, const QNetworkProxy& proxy) {
|
||||||
|
QString full_url = generateFullUrl(Operations::TagList);
|
||||||
|
auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
|
||||||
|
|
||||||
|
if (!ensureLogin(proxy)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray output_labels;
|
||||||
|
auto result_labels = NetworkFactory::performNetworkOperation(full_url,
|
||||||
|
timeout,
|
||||||
|
{},
|
||||||
|
output_labels,
|
||||||
|
QNetworkAccessManager::Operation::GetOperation,
|
||||||
|
{ authHeader() },
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
proxy);
|
||||||
|
|
||||||
|
if (result_labels.first != QNetworkReply::NetworkError::NoError) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
full_url = generateFullUrl(Operations::SubscriptionList);
|
||||||
|
QByteArray output_feeds;
|
||||||
|
auto result_feeds = NetworkFactory::performNetworkOperation(full_url,
|
||||||
|
timeout,
|
||||||
|
{},
|
||||||
|
output_feeds,
|
||||||
|
QNetworkAccessManager::Operation::GetOperation,
|
||||||
|
{ authHeader() },
|
||||||
|
false,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
proxy);
|
||||||
|
|
||||||
|
if (result_feeds.first != QNetworkReply::NetworkError::NoError) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto root = decodeFeedCategoriesData(output_labels, output_feeds, obtain_icons);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
RootItem* GreaderNetwork::decodeFeedCategoriesData(const QString& categories, const QString& feeds, bool obtain_icons) {
|
||||||
|
auto* parent = new RootItem();
|
||||||
|
auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
|
||||||
|
QJsonArray json = QJsonDocument::fromJson(categories.toUtf8()).object()["tags"].toArray();
|
||||||
|
QMap<QString, RootItem*> cats;
|
||||||
|
QList<RootItem*> lbls;
|
||||||
|
|
||||||
|
cats.insert(QString(), parent);
|
||||||
|
|
||||||
|
for (const QJsonValue& obj : json) {
|
||||||
|
auto label = obj.toObject();
|
||||||
|
|
||||||
|
if (label["type"].toString() == QL1S("folder")) {
|
||||||
|
QString label_id = label["id"].toString();
|
||||||
|
|
||||||
|
// We have label (not "state").
|
||||||
|
auto* category = new Category();
|
||||||
|
|
||||||
|
category->setDescription(label["htmlUrl"].toString());
|
||||||
|
category->setTitle(label_id.mid(label_id.lastIndexOf(QL1C('/')) + 1));
|
||||||
|
category->setCustomId(label_id);
|
||||||
|
|
||||||
|
cats.insert(category->customId(), category);
|
||||||
|
parent->appendChild(category);
|
||||||
|
}
|
||||||
|
else if (label["type"] == QL1S("tag")) {
|
||||||
|
QString name_id = label["id"].toString();
|
||||||
|
QString plain_name = QRegularExpression(".+\\/([^\\/]+)").match(name_id).captured(1);
|
||||||
|
auto* new_lbl = new Label(plain_name, TextFactory::generateColorFromText(name_id));
|
||||||
|
|
||||||
|
new_lbl->setCustomId(name_id);
|
||||||
|
lbls.append(new_lbl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
json = QJsonDocument::fromJson(feeds.toUtf8()).object()["subscriptions"].toArray();
|
||||||
|
|
||||||
|
for (const QJsonValue& obj : json) {
|
||||||
|
auto subscription = obj.toObject();
|
||||||
|
QString id = subscription["id"].toString();
|
||||||
|
QString title = subscription["title"].toString();
|
||||||
|
QString url = subscription["htmlUrl"].toString();
|
||||||
|
QString parent_label;
|
||||||
|
QJsonArray assigned_categories = subscription["categories"].toArray();
|
||||||
|
|
||||||
|
for (const QJsonValue& cat : assigned_categories) {
|
||||||
|
QString potential_id = cat.toObject()["id"].toString();
|
||||||
|
|
||||||
|
if (potential_id.contains(QSL("/label/"))) {
|
||||||
|
parent_label = potential_id;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have label (not "state").
|
||||||
|
auto* feed = new GreaderFeed();
|
||||||
|
|
||||||
|
feed->setDescription(url);
|
||||||
|
feed->setUrl(url);
|
||||||
|
feed->setTitle(title);
|
||||||
|
feed->setCustomId(id);
|
||||||
|
|
||||||
|
if (obtain_icons) {
|
||||||
|
QString icon_url = subscription["iconUrl"].toString();
|
||||||
|
|
||||||
|
if (!icon_url.isEmpty()) {
|
||||||
|
QByteArray icon_data;
|
||||||
|
|
||||||
|
if (NetworkFactory::performNetworkOperation(icon_url, timeout,
|
||||||
|
{}, icon_data,
|
||||||
|
QNetworkAccessManager::Operation::GetOperation).first ==
|
||||||
|
QNetworkReply::NetworkError::NoError) {
|
||||||
|
// Icon downloaded, set it up.
|
||||||
|
QPixmap icon_pixmap;
|
||||||
|
|
||||||
|
icon_pixmap.loadFromData(icon_data);
|
||||||
|
feed->setIcon(QIcon(icon_pixmap));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cats.contains(parent_label)) {
|
||||||
|
cats[parent_label]->appendChild(feed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* lblroot = new LabelsNode(parent);
|
||||||
|
|
||||||
|
lblroot->setChildItems(lbls);
|
||||||
|
parent->appendChild(lblroot);
|
||||||
|
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
QNetworkReply::NetworkError GreaderNetwork::clientLogin(const QNetworkProxy& proxy) {
|
QNetworkReply::NetworkError GreaderNetwork::clientLogin(const QNetworkProxy& proxy) {
|
||||||
QString full_url = generateFullUrl(Operations::ClientLogin);
|
QString full_url = generateFullUrl(Operations::ClientLogin);
|
||||||
auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
|
auto timeout = qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::UpdateTimeout)).toInt();
|
||||||
@ -30,7 +201,38 @@ QNetworkReply::NetworkError GreaderNetwork::clientLogin(const QNetworkProxy& pro
|
|||||||
if (network_result.first == QNetworkReply::NetworkError::NoError) {
|
if (network_result.first == QNetworkReply::NetworkError::NoError) {
|
||||||
// Save credentials.
|
// Save credentials.
|
||||||
auto lines = QString::fromUtf8(output).replace(QSL("\r"), QString()).split('\n');
|
auto lines = QString::fromUtf8(output).replace(QSL("\r"), QString()).split('\n');
|
||||||
int a = 5;
|
|
||||||
|
for (const QString& line : lines) {
|
||||||
|
int eq = line.indexOf('=');
|
||||||
|
|
||||||
|
if (eq > 0) {
|
||||||
|
QString id = line.mid(0, eq);
|
||||||
|
|
||||||
|
if (id == QSL("SID")) {
|
||||||
|
m_authSid = line.mid(eq + 1);
|
||||||
|
}
|
||||||
|
else if (id == QSL("Auth")) {
|
||||||
|
m_authAuth = line.mid(eq + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QRegularExpression exp("^(unused|none|null)$");
|
||||||
|
|
||||||
|
if (exp.match(m_authSid).hasMatch()) {
|
||||||
|
m_authSid = QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exp.match(m_authAuth).hasMatch()) {
|
||||||
|
m_authAuth = QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_authAuth.isEmpty() ||
|
||||||
|
(service() == GreaderServiceRoot::Service::FreshRss && m_authSid.isEmpty())) {
|
||||||
|
clearCredentials();
|
||||||
|
|
||||||
|
return QNetworkReply::NetworkError::InternalServerError;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return network_result.first;
|
return network_result.first;
|
||||||
@ -84,6 +286,25 @@ QString GreaderNetwork::serviceToString(GreaderServiceRoot::Service service) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPair<QByteArray, QByteArray> GreaderNetwork::authHeader() const {
|
||||||
|
return { QSL("Authorization").toLocal8Bit(), QSL("GoogleLogin auth=%1").arg(m_authAuth).toLocal8Bit() };
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GreaderNetwork::ensureLogin(const QNetworkProxy& proxy) {
|
||||||
|
if (m_authSid.isEmpty()) {
|
||||||
|
auto login = clientLogin(proxy);
|
||||||
|
|
||||||
|
if (login != QNetworkReply::NetworkError::NoError) {
|
||||||
|
qCriticalNN << LOGSEC_GREADER
|
||||||
|
<< "Login failed with error:"
|
||||||
|
<< QUOTE_W_SPACE_DOT(NetworkFactory::networkErrorText(login));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int GreaderNetwork::batchSize() const {
|
int GreaderNetwork::batchSize() const {
|
||||||
return m_batchSize;
|
return m_batchSize;
|
||||||
}
|
}
|
||||||
@ -92,18 +313,38 @@ void GreaderNetwork::setBatchSize(int batch_size) {
|
|||||||
m_batchSize = batch_size;
|
m_batchSize = batch_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GreaderNetwork::clearCredentials() {
|
||||||
|
m_authAuth = m_authSid = QString();
|
||||||
|
}
|
||||||
|
|
||||||
QString GreaderNetwork::sanitizedBaseUrl() const {
|
QString GreaderNetwork::sanitizedBaseUrl() const {
|
||||||
if (m_baseUrl.endsWith('/')) {
|
auto base_url = m_baseUrl;
|
||||||
return m_baseUrl;
|
|
||||||
|
if (!base_url.endsWith('/')) {
|
||||||
|
base_url = base_url + QL1C('/');
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return m_baseUrl + QL1C('/');
|
switch (m_service) {
|
||||||
|
case GreaderServiceRoot::Service::FreshRss:
|
||||||
|
base_url += FRESHRSS_BASE_URL_PATH;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return base_url;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString GreaderNetwork::generateFullUrl(GreaderNetwork::Operations operation) const {
|
QString GreaderNetwork::generateFullUrl(GreaderNetwork::Operations operation) const {
|
||||||
switch (operation) {
|
switch (operation) {
|
||||||
case Operations::ClientLogin:
|
case Operations::ClientLogin:
|
||||||
return sanitizedBaseUrl() + QSL("accounts/ClientLogin?Email=%1&Passwd=%2").arg(username(), password());
|
return sanitizedBaseUrl() + QSL(GREADER_API_CLIENT_LOGIN).arg(username(), password());
|
||||||
|
|
||||||
|
case Operations::TagList:
|
||||||
|
return sanitizedBaseUrl() + GREADER_API_TAG_LIST;
|
||||||
|
|
||||||
|
case Operations::SubscriptionList:
|
||||||
|
return sanitizedBaseUrl() + GREADER_API_SUBSCRIPTION_LIST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,18 +14,24 @@ class GreaderNetwork : public QObject {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Operations {
|
enum class Operations {
|
||||||
ClientLogin
|
ClientLogin,
|
||||||
|
TagList,
|
||||||
|
SubscriptionList,
|
||||||
|
StreamContents
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit GreaderNetwork(QObject* parent = nullptr);
|
explicit GreaderNetwork(QObject* parent = nullptr);
|
||||||
|
|
||||||
// Network operations.
|
// Stream contents for a feed/label/etc.
|
||||||
QList<Message> messages(ServiceRoot* root, const QString& stream_id, Feed::Status& error);
|
QList<Message> streamContents(ServiceRoot* root, const QString& stream_id, Feed::Status& error);
|
||||||
|
|
||||||
|
// Downloads and structures full tree for sync-in.
|
||||||
|
RootItem* categoriesFeedsLabelsTree(bool obtain_icons, const QNetworkProxy& proxy);
|
||||||
|
|
||||||
// Performs client login, if successful, then saves SID, LSID and Auth.
|
// Performs client login, if successful, then saves SID, LSID and Auth.
|
||||||
QNetworkReply::NetworkError clientLogin(const QNetworkProxy& proxy);
|
QNetworkReply::NetworkError clientLogin(const QNetworkProxy& proxy);
|
||||||
|
|
||||||
// Metadata.
|
// Getters/setters.
|
||||||
GreaderServiceRoot::Service service() const;
|
GreaderServiceRoot::Service service() const;
|
||||||
void setService(const GreaderServiceRoot::Service& service);
|
void setService(const GreaderServiceRoot::Service& service);
|
||||||
|
|
||||||
@ -38,12 +44,20 @@ class GreaderNetwork : public QObject {
|
|||||||
QString baseUrl() const;
|
QString baseUrl() const;
|
||||||
void setBaseUrl(const QString& base_url);
|
void setBaseUrl(const QString& base_url);
|
||||||
|
|
||||||
static QString serviceToString(GreaderServiceRoot::Service service);
|
|
||||||
|
|
||||||
int batchSize() const;
|
int batchSize() const;
|
||||||
void setBatchSize(int batch_size);
|
void setBatchSize(int batch_size);
|
||||||
|
|
||||||
|
void clearCredentials();
|
||||||
|
|
||||||
|
static QString serviceToString(GreaderServiceRoot::Service service);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QPair<QByteArray, QByteArray> authHeader() const;
|
||||||
|
|
||||||
|
// Make sure we are logged in and if we are not, return error.
|
||||||
|
bool ensureLogin(const QNetworkProxy& proxy);
|
||||||
|
|
||||||
|
RootItem* decodeFeedCategoriesData(const QString& categories, const QString& feeds, bool obtain_icons);
|
||||||
QString sanitizedBaseUrl() const;
|
QString sanitizedBaseUrl() const;
|
||||||
QString generateFullUrl(Operations operation) const;
|
QString generateFullUrl(Operations operation) const;
|
||||||
|
|
||||||
@ -53,6 +67,8 @@ class GreaderNetwork : public QObject {
|
|||||||
QString m_password;
|
QString m_password;
|
||||||
QString m_baseUrl;
|
QString m_baseUrl;
|
||||||
int m_batchSize;
|
int m_batchSize;
|
||||||
|
QString m_authSid;
|
||||||
|
QString m_authAuth;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // GREADERNETWORK_H
|
#endif // GREADERNETWORK_H
|
||||||
|
@ -131,16 +131,7 @@ void GreaderServiceRoot::saveAccountDataToDatabase(bool creating_new) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
RootItem* GreaderServiceRoot::obtainNewTreeForSyncIn() const {
|
RootItem* GreaderServiceRoot::obtainNewTreeForSyncIn() const {
|
||||||
return nullptr;
|
return m_network->categoriesFeedsLabelsTree(true, networkProxy());
|
||||||
|
|
||||||
/*OwnCloudGetFeedsCategoriesResponse feed_cats_response = m_network->feedsCategories(networkProxy());
|
|
||||||
|
|
||||||
if (feed_cats_response.networkError() == QNetworkReply::NetworkError::NoError) {
|
|
||||||
return feed_cats_response.feedsCategories(true);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return nullptr;
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GreaderServiceRoot::loadFromDatabase() {
|
void GreaderServiceRoot::loadFromDatabase() {
|
||||||
|
@ -14,14 +14,13 @@ GreaderAccountDetails::GreaderAccountDetails(QWidget* parent) : QWidget(parent)
|
|||||||
for (auto serv : { GreaderServiceRoot::Service::FreshRss,
|
for (auto serv : { GreaderServiceRoot::Service::FreshRss,
|
||||||
GreaderServiceRoot::Service::Bazqux,
|
GreaderServiceRoot::Service::Bazqux,
|
||||||
GreaderServiceRoot::Service::TheOldReader }) {
|
GreaderServiceRoot::Service::TheOldReader }) {
|
||||||
m_ui.m_cmbService->addItem(GreaderNetwork::serviceToString(serv),
|
m_ui.m_cmbService->addItem(GreaderNetwork::serviceToString(serv), QVariant::fromValue(serv));
|
||||||
QVariant::fromValue(serv));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ui.m_lblTestResult->label()->setWordWrap(true);
|
m_ui.m_lblTestResult->label()->setWordWrap(true);
|
||||||
m_ui.m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your Nextcloud account"));
|
m_ui.m_txtPassword->lineEdit()->setPlaceholderText(tr("Password for your account"));
|
||||||
m_ui.m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your Nextcloud account"));
|
m_ui.m_txtUsername->lineEdit()->setPlaceholderText(tr("Username for your account"));
|
||||||
m_ui.m_txtUrl->lineEdit()->setPlaceholderText(tr("URL of your Nextcloud server, without any API path"));
|
m_ui.m_txtUrl->lineEdit()->setPlaceholderText(tr("URL of your server, without any service-specific path"));
|
||||||
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Information,
|
m_ui.m_lblTestResult->setStatus(WidgetWithStatus::StatusType::Information,
|
||||||
tr("No test done yet."),
|
tr("No test done yet."),
|
||||||
tr("Here, results of connection test are shown."));
|
tr("Here, results of connection test are shown."));
|
||||||
@ -77,6 +76,7 @@ void GreaderAccountDetails::performTest(const QNetworkProxy& custom_proxy) {
|
|||||||
factory.setPassword(m_ui.m_txtPassword->lineEdit()->text());
|
factory.setPassword(m_ui.m_txtPassword->lineEdit()->text());
|
||||||
factory.setBaseUrl(m_ui.m_txtUrl->lineEdit()->text());
|
factory.setBaseUrl(m_ui.m_txtUrl->lineEdit()->text());
|
||||||
factory.setService(service());
|
factory.setService(service());
|
||||||
|
factory.clearCredentials();
|
||||||
|
|
||||||
auto result = factory.clientLogin(custom_proxy);
|
auto result = factory.clientLogin(custom_proxy);
|
||||||
|
|
||||||
|
@ -145,18 +145,8 @@ QList<RootItem*> InoreaderNetworkFactory::getLabels() {
|
|||||||
|
|
||||||
if (lbl_obj["type"] == QL1S("tag")) {
|
if (lbl_obj["type"] == QL1S("tag")) {
|
||||||
QString name_id = lbl_obj["id"].toString();
|
QString name_id = lbl_obj["id"].toString();
|
||||||
QString id = QRegularExpression("user\\/(\\d+)\\/").match(name_id).captured(1);
|
|
||||||
QString plain_name = QRegularExpression(".+\\/([^\\/]+)").match(name_id).captured(1);
|
QString plain_name = QRegularExpression(".+\\/([^\\/]+)").match(name_id).captured(1);
|
||||||
quint32 color = 0;
|
auto* new_lbl = new Label(plain_name, TextFactory::generateColorFromText(name_id));
|
||||||
|
|
||||||
for (const QChar chr : name_id) {
|
|
||||||
color += chr.unicode();
|
|
||||||
}
|
|
||||||
|
|
||||||
color = QRandomGenerator(color).bounded(double(0xFFFFFF)) - 1;
|
|
||||||
|
|
||||||
auto color_name = QSL("#%1").arg(color, 6, 16);
|
|
||||||
auto* new_lbl = new Label(plain_name, QColor(color_name));
|
|
||||||
|
|
||||||
new_lbl->setCustomId(name_id);
|
new_lbl->setCustomId(name_id);
|
||||||
lbls.append(new_lbl);
|
lbls.append(new_lbl);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user