Files
pay/modules/social-feed/FeedDataProvider.cpp
T
tomFlowee 37c1dc044d Starting new data provider
This reads the social data from a dedicated json file on our
webserver and provides this to QML
2025-02-01 14:07:22 +01:00

175 lines
4.6 KiB
C++

/*
* This file is part of the Flowee project
* Copyright (C) 2025 Tom Zander <tom@flowee.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "FeedDataProvider.h"
#include <utils/Logger.h>
#include <FloweePay.h>
#include <QFile>
#include <QFileInfo>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QNetworkRequest>
#include <QTimer>
#include <QUrl>
constexpr const char *FEED = "https://flowee.org/v/index.json";
constexpr const char *FLOWEE_JSON = "flowee.json";
FeedDataProvider::FeedDataProvider(QObject *parent)
: QObject(parent)
{
QFileInfo info(FLOWEE_JSON);
bool useOld = info.exists();
if (useOld) {
m_lastCheck = info.lastModified();
readFeed();
}
else if (m_lastCheck.isNull()
|| m_lastCheck.msecsTo(QDateTime::currentDateTime()) > 4 * 60 * 60 * 1000) {
QTimer::singleShot(10, this, SLOT(start()));
}
}
void FeedDataProvider::start()
{
QUrl uri(FEED);
QNetworkRequest req(uri);
req.setHeader(QNetworkRequest::UserAgentHeader, "flowee-pay");
if (m_lastCheck.isNull())
m_reply = FloweePay::instance()->network()->get(req);
else
m_reply = FloweePay::instance()->network()->head(req);
logInfo() << "fetching social feed file from:" << FEED;
connect(m_reply, SIGNAL(finished()), this, SLOT(downloadFinished()));
connect(m_reply, SIGNAL(errorOccurred(QNetworkReply::NetworkError)),
this, SLOT(errored(QNetworkReply::NetworkError)));
connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(sslErrors(QList<QSslError>)));
}
void FeedDataProvider::downloadFinished()
{
assert(m_reply);
if (m_reply->operation() == QNetworkAccessManager::HeadOperation) {
auto lastModified = m_reply->header(QNetworkRequest::LastModifiedHeader);
m_reply->deleteLater();
m_reply = nullptr;
// check if the server has a newer one.
if (lastModified.toDateTime() > m_lastCheck) {
m_lastCheck = QDateTime();
assert(m_lastCheck.isNull());
start(); // this will now do a download of the actual data.
}
return;
}
auto data = m_reply->readAll();
m_reply->deleteLater();
m_reply = nullptr;
QFile feed(FLOWEE_JSON);
if (feed.open(QIODevice::WriteOnly)) {
feed.write(data);
feed.close();
}
readFeed();
}
void FeedDataProvider::readFeed()
{
QFile feed(FLOWEE_JSON);
if (!feed.open(QIODevice::ReadOnly))
return;
auto data = feed.readAll();
feed.close();
QJsonDocument doc = QJsonDocument::fromJson(data);
if (doc.isNull()) {
logWarning() << "Parsing error of social json";
return;
}
m_listItems.clear();
QJsonArray list = doc.array();
for (auto i = list.begin(); i != list.end(); ++i) {
auto obj = i->toObject();
auto text = obj["text"];
if (!text.isString()) {
logWarning() << "Skipping item in JSON, missing text attribute";
continue;
}
auto *item = new ListItem(this);
item->m_text = text.toString();
item->m_url = obj["url"].toString();
item->m_videoLength = obj["length"].toString();
item->m_title = obj["title"].toString();
auto date = obj["date"].toString();
item->m_date = QDate::fromString(date, Qt::ISODate);
m_listItems.append(item);
}
emit listItemsChanged();
}
QList<ListItem *> FeedDataProvider::listItems() const
{
return m_listItems;
}
void FeedDataProvider::errored(QNetworkReply::NetworkError err)
{
// TODO
}
void FeedDataProvider::sslErrors(const QList<QSslError> &errors)
{
// TODO
}
// ------------------------------------
ListItem::ListItem(QObject *parent)
: QObject(parent)
{
}
QDate ListItem::date() const
{
return m_date;
}
QString ListItem::videoLength() const
{
return m_videoLength;
}
QString ListItem::text() const
{
return m_text;
}
QString ListItem::title() const
{
return m_title;
}
QString ListItem::url() const
{
return m_url;
}