From 6b9041a1109c12b535130d5052bd9354d057696f Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Mon, 11 Dec 2023 10:44:24 +0100 Subject: [PATCH] api work --- resources/scripts/libmpv | 2 +- src/librssguard/core/feedsmodel.cpp | 4 -- src/librssguard/core/feedsmodel.h | 5 -- src/librssguard/core/message.cpp | 8 +++ src/librssguard/core/message.h | 4 +- src/librssguard/database/databasequeries.cpp | 49 +++++++++++++++++++ src/librssguard/database/databasequeries.h | 8 +++ src/librssguard/network-web/apiserver.cpp | 24 +++++++-- src/librssguard/network-web/apiserver.h | 2 +- src/librssguard/network-web/httpserver.cpp | 20 ++++---- src/librssguard/network-web/httpserver.h | 6 +-- .../network-web/oauthhttphandler.cpp | 2 +- .../network-web/oauthhttphandler.h | 2 +- 13 files changed, 104 insertions(+), 32 deletions(-) diff --git a/resources/scripts/libmpv b/resources/scripts/libmpv index 2b41d67a3..b874b2fad 160000 --- a/resources/scripts/libmpv +++ b/resources/scripts/libmpv @@ -1 +1 @@ -Subproject commit 2b41d67a372b6ce42ed666e7d88e7815694f1966 +Subproject commit b874b2fad4fcb91861b62ae2a52df44efac98ddd diff --git a/src/librssguard/core/feedsmodel.cpp b/src/librssguard/core/feedsmodel.cpp index 53187e4d4..d161d2361 100644 --- a/src/librssguard/core/feedsmodel.cpp +++ b/src/librssguard/core/feedsmodel.cpp @@ -275,10 +275,6 @@ QList FeedsModel::feedsForScheduledUpdate(bool auto_update_now) { return feeds_for_update; } -QList FeedsModel::messagesForItem(RootItem* item) const { - return item->undeletedMessages(); -} - int FeedsModel::columnCount(const QModelIndex& parent) const { Q_UNUSED(parent) return FEEDS_VIEW_COLUMN_COUNT; diff --git a/src/librssguard/core/feedsmodel.h b/src/librssguard/core/feedsmodel.h index 45d0ce36e..afea3688a 100644 --- a/src/librssguard/core/feedsmodel.h +++ b/src/librssguard/core/feedsmodel.h @@ -54,11 +54,6 @@ class RSSGUARD_DLLSPEC FeedsModel : public QAbstractItemModel { // This method might change some properties of some feeds. QList feedsForScheduledUpdate(bool auto_update_now); - // Returns (undeleted) messages for given feeds. - // This is usually used for displaying whole feeds - // in "newspaper" mode. - QList messagesForItem(RootItem* item) const; - // Returns ALL RECURSIVE CHILD feeds contained within single index. QList feedsForIndex(const QModelIndex& index = QModelIndex()) const; diff --git a/src/librssguard/core/message.cpp b/src/librssguard/core/message.cpp index 76fff3fd6..cd9c14720 100644 --- a/src/librssguard/core/message.cpp +++ b/src/librssguard/core/message.cpp @@ -164,6 +164,14 @@ void Message::sanitize(const Feed* feed, bool fix_future_datetimes) { } } +QJsonObject Message::toJson() const { + QJsonObject obj; + + obj.insert(QSL("contents"), m_contents); + + return obj; +} + Message Message::fromSqlRecord(const QSqlRecord& record, bool* result) { if (record.count() != MSG_DB_LABELS_IDS + 1) { if (result != nullptr) { diff --git a/src/librssguard/core/message.h b/src/librssguard/core/message.h index d04640c66..5d2480568 100644 --- a/src/librssguard/core/message.h +++ b/src/librssguard/core/message.h @@ -3,7 +3,7 @@ #ifndef MESSAGE_H #define MESSAGE_H -//#include "definitions/definitions.h" +// #include "definitions/definitions.h" #include #include @@ -56,6 +56,8 @@ class RSSGUARD_DLLSPEC Message { void sanitize(const Feed* feed, bool fix_future_datetimes); + QJsonObject toJson() const; + // Creates Message from given record, which contains // row from query SELECT * FROM Messages WHERE ....; static Message fromSqlRecord(const QSqlRecord& record, bool* result = nullptr); diff --git a/src/librssguard/database/databasequeries.cpp b/src/librssguard/database/databasequeries.cpp index c18d22f8e..f4f68a96f 100644 --- a/src/librssguard/database/databasequeries.cpp +++ b/src/librssguard/database/databasequeries.cpp @@ -1174,6 +1174,55 @@ QList DatabaseQueries::getUndeletedUnreadMessages(const QSqlDatabase& d return messages; } +QList DatabaseQueries::getFeedsSlice(const QSqlDatabase& db, + const QString& feed_custom_id, + int account_id, + bool newest_first, + bool unread_only, + int row_offset, + int row_limit) { + QList messages; + QSqlQuery q(db); + + q.setForwardOnly(true); + q.prepare(QSL("SELECT %1 " + "FROM Messages " + "WHERE is_deleted = 0 AND is_pdeleted = 0 AND " + " is_read = :is_read " + " feed = :feed AND account_id = :account_id " + "ORDER BY Messages.date_created %2 " + "LIMIT :row_limit OFFSET :row_offset;") + .arg(messageTableAttributes(true, db.driverName() == QSL(APP_DB_SQLITE_DRIVER)).values().join(QSL(", ")), + newest_first ? QSL("DESC") : QSL("ASC"))); + q.bindValue(QSL(":feed"), feed_custom_id); + q.bindValue(QSL(":account_id"), account_id); + q.bindValue(QSL(":row_limit"), row_limit); + q.bindValue(QSL(":row_offset"), row_offset); + + if (unread_only) { + q.bindValue(QSL(":is_read"), 0); + } + else { + q.bindValue(QSL(":is_read"), QSL("is_read")); + } + + if (q.exec()) { + while (q.next()) { + bool decoded; + Message message = Message::fromSqlRecord(q.record(), &decoded); + + if (decoded) { + messages.append(message); + } + } + } + else { + throw ApplicationException(q.lastError().driverText()); + } + + return messages; +} + QList DatabaseQueries::getUndeletedMessagesForFeed(const QSqlDatabase& db, const QString& feed_custom_id, int account_id, diff --git a/src/librssguard/database/databasequeries.h b/src/librssguard/database/databasequeries.h index 4a27d405b..a2692eccb 100644 --- a/src/librssguard/database/databasequeries.h +++ b/src/librssguard/database/databasequeries.h @@ -118,6 +118,14 @@ class DatabaseQueries { static QList getUndeletedMessagesForBin(const QSqlDatabase& db, int account_id, bool* ok = nullptr); static QList getUndeletedMessagesForAccount(const QSqlDatabase& db, int account_id, bool* ok = nullptr); + static QList getFeedsSlice(const QSqlDatabase& db, + const QString& feed_custom_id, + int account_id, + bool newest_first, + bool unread_only, + int row_offset, + int row_limit); + // Custom ID accumulators. static QStringList bagOfMessages(const QSqlDatabase& db, ServiceRoot::BagOfMessages bag, const Feed* feed); static QHash bagsOfMessages(const QSqlDatabase& db, const QList& labels); diff --git a/src/librssguard/network-web/apiserver.cpp b/src/librssguard/network-web/apiserver.cpp index d12ef018f..634c558e4 100644 --- a/src/librssguard/network-web/apiserver.cpp +++ b/src/librssguard/network-web/apiserver.cpp @@ -11,7 +11,7 @@ ApiServer::ApiServer(QObject* parent) : HttpServer(parent) {} -void ApiServer::answerClient(QTcpSocket* socket, const QHttpRequest& request) { +void ApiServer::answerClient(QTcpSocket* socket, const HttpRequest& request) { QByteArray incoming_data = socket->readAll(); QByteArray output_data; @@ -26,9 +26,17 @@ void ApiServer::answerClient(QTcpSocket* socket, const QHttpRequest& request) { } else { ApiRequest req(incoming_doc); - ApiResponse resp(processRequest(req)); - output_data = resp.toJson().toJson(); + try { + ApiResponse resp(processRequest(req)); + + output_data = resp.toJson().toJson(); + } + catch (const ApplicationException& ex) { + ApiResponse err_resp(ApiResponse::Result::Error, req.m_method, ex.message()); + + output_data = err_resp.toJson().toJson(); + } } const QByteArray reply_message = QSL("HTTP/1.0 200 OK \r\n" @@ -63,17 +71,23 @@ ApiResponse ApiServer::processAppVersion() const { ApiResponse ApiServer::processArticlesFromFeed(const QJsonValue& req) const { QJsonObject data = req.toObject(); + QString feed_id = data.value(QSL("feed")).toString(); int account_id = data.value(QSL("account")).toInt(); + bool newest_first = data.value(QSL("newest_first")).toBool(); + bool unread_only = data.value(QSL("unread_only")).toBool(); + int row_offset = data.value(QSL("row_offset")).toInt(); + int row_limit = data.value(QSL("row_limit")).toInt(); QSqlDatabase database = qApp->database()->driver()->connection(metaObject()->className()); - QList msgs = DatabaseQueries::getUndeletedMessagesForFeed(database, feed_id, account_id); + QList msgs = + DatabaseQueries::getFeedsSlice(database, feed_id, account_id, newest_first, unread_only, row_offset, row_limit); QJsonArray msgs_json_array; for (const Message& msg : msgs) { QJsonObject msg_obj; - msg_obj.insert(QSL("contents"), msg.m_contents); + msg_obj.insert(QSL("contents"), msg.toJson()); msgs_json_array.append(msg_obj); } diff --git a/src/librssguard/network-web/apiserver.h b/src/librssguard/network-web/apiserver.h index 37fafc044..01086a50c 100644 --- a/src/librssguard/network-web/apiserver.h +++ b/src/librssguard/network-web/apiserver.h @@ -45,7 +45,7 @@ class ApiServer : public HttpServer { explicit ApiServer(QObject* parent = nullptr); protected: - virtual void answerClient(QTcpSocket* socket, const QHttpRequest& request); + virtual void answerClient(QTcpSocket* socket, const HttpRequest& request); private: ApiResponse processRequest(const ApiRequest& req) const; diff --git a/src/librssguard/network-web/httpserver.cpp b/src/librssguard/network-web/httpserver.cpp index 5a9c74df7..b539316b4 100644 --- a/src/librssguard/network-web/httpserver.cpp +++ b/src/librssguard/network-web/httpserver.cpp @@ -79,28 +79,28 @@ void HttpServer::readReceivedData(QTcpSocket* socket) { m_connectedClients[socket].m_port = m_httpServer.serverPort(); } - QHttpRequest* request = &m_connectedClients[socket]; + HttpRequest* request = &m_connectedClients[socket]; bool error = false; - if (Q_LIKELY(request->m_state == QHttpRequest::State::ReadingMethod)) { + if (Q_LIKELY(request->m_state == HttpRequest::State::ReadingMethod)) { if (Q_UNLIKELY(error = !request->readMethod(socket))) { qWarningNN << LOGSEC_NETWORK << "Invalid method."; } } - if (Q_LIKELY(!error && request->m_state == QHttpRequest::State::ReadingUrl)) { + if (Q_LIKELY(!error && request->m_state == HttpRequest::State::ReadingUrl)) { if (Q_UNLIKELY(error = !request->readUrl(socket))) { qWarningNN << LOGSEC_NETWORK << "Invalid URL."; } } - if (Q_LIKELY(!error && request->m_state == QHttpRequest::State::ReadingStatus)) { + if (Q_LIKELY(!error && request->m_state == HttpRequest::State::ReadingStatus)) { if (Q_UNLIKELY(error = !request->readStatus(socket))) { qWarningNN << LOGSEC_NETWORK << "Invalid status."; } } - if (Q_LIKELY(!error && request->m_state == QHttpRequest::State::ReadingHeader)) { + if (Q_LIKELY(!error && request->m_state == HttpRequest::State::ReadingHeader)) { if (Q_UNLIKELY(error = !request->readHeader(socket))) { qWarningNN << LOGSEC_NETWORK << "Invalid header."; } @@ -111,7 +111,7 @@ void HttpServer::readReceivedData(QTcpSocket* socket) { m_connectedClients.remove(socket); } else if (!request->m_url.isEmpty()) { - Q_ASSERT(request->m_state != QHttpRequest::State::ReadingUrl); + Q_ASSERT(request->m_state != HttpRequest::State::ReadingUrl); answerClient(socket, *request); m_connectedClients.remove(socket); @@ -130,7 +130,7 @@ quint16 HttpServer::listenPort() const { return m_listenPort; } -bool HttpServer::QHttpRequest::readMethod(QTcpSocket* socket) { +bool HttpServer::HttpRequest::readMethod(QTcpSocket* socket) { bool finished = false; while ((socket->bytesAvailable() != 0) && !finished) { @@ -173,7 +173,7 @@ bool HttpServer::QHttpRequest::readMethod(QTcpSocket* socket) { return true; } -bool HttpServer::QHttpRequest::readUrl(QTcpSocket* socket) { +bool HttpServer::HttpRequest::readUrl(QTcpSocket* socket) { bool finished = false; while ((socket->bytesAvailable() != 0) && !finished) { @@ -208,7 +208,7 @@ bool HttpServer::QHttpRequest::readUrl(QTcpSocket* socket) { return true; } -bool HttpServer::QHttpRequest::readStatus(QTcpSocket* socket) { +bool HttpServer::HttpRequest::readStatus(QTcpSocket* socket) { bool finished = false; while ((socket->bytesAvailable() != 0) && !finished) { @@ -235,7 +235,7 @@ bool HttpServer::QHttpRequest::readStatus(QTcpSocket* socket) { return true; } -bool HttpServer::QHttpRequest::readHeader(QTcpSocket* socket) { +bool HttpServer::HttpRequest::readHeader(QTcpSocket* socket) { while (socket->bytesAvailable() != 0) { m_fragment += socket->read(1); diff --git a/src/librssguard/network-web/httpserver.h b/src/librssguard/network-web/httpserver.h index e4416550d..58b198a8e 100644 --- a/src/librssguard/network-web/httpserver.h +++ b/src/librssguard/network-web/httpserver.h @@ -35,7 +35,7 @@ class HttpServer : public QObject { void setListenAddressPort(const QString& full_uri, bool start_handler); protected: - struct QHttpRequest { + struct HttpRequest { bool readMethod(QTcpSocket* socket); bool readUrl(QTcpSocket* socket); bool readStatus(QTcpSocket* socket); @@ -67,7 +67,7 @@ class HttpServer : public QObject { QMap m_headers; }; - virtual void answerClient(QTcpSocket* socket, const QHttpRequest& request) = 0; + virtual void answerClient(QTcpSocket* socket, const HttpRequest& request) = 0; private slots: void clientConnected(); @@ -76,7 +76,7 @@ class HttpServer : public QObject { void readReceivedData(QTcpSocket* socket); private: - QMap m_connectedClients; + QMap m_connectedClients; QTcpServer m_httpServer; QHostAddress m_listenAddress; quint16 m_listenPort; diff --git a/src/librssguard/network-web/oauthhttphandler.cpp b/src/librssguard/network-web/oauthhttphandler.cpp index d5c42062f..ab9d964b3 100644 --- a/src/librssguard/network-web/oauthhttphandler.cpp +++ b/src/librssguard/network-web/oauthhttphandler.cpp @@ -44,7 +44,7 @@ void OAuthHttpHandler::handleRedirection(const QVariantMap& data) { } } -void OAuthHttpHandler::answerClient(QTcpSocket* socket, const QHttpRequest& request) { +void OAuthHttpHandler::answerClient(QTcpSocket* socket, const HttpRequest& request) { if (!request.m_url.path().remove(QL1C('/')).isEmpty()) { qCriticalNN << LOGSEC_OAUTH << "Invalid request:" << QUOTE_W_SPACE_DOT(request.m_url.toString()); } diff --git a/src/librssguard/network-web/oauthhttphandler.h b/src/librssguard/network-web/oauthhttphandler.h index e5534478e..92ea1fdf8 100644 --- a/src/librssguard/network-web/oauthhttphandler.h +++ b/src/librssguard/network-web/oauthhttphandler.h @@ -17,7 +17,7 @@ class OAuthHttpHandler : public HttpServer { void authGranted(const QString& auth_code, const QString& state); protected: - virtual void answerClient(QTcpSocket* socket, const QHttpRequest& request); + virtual void answerClient(QTcpSocket* socket, const HttpRequest& request); private: void handleRedirection(const QVariantMap& data);