kasts/src/models/podcastsearchmodel.cpp

160 lines
6.9 KiB
C++

/**
* SPDX-FileCopyrightText: 2021 Tobias Fella <tobias.fella@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
#include "models/podcastsearchmodel.h"
#include <QCryptographicHash>
#include <QDateTime>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QString>
#include <QVariant>
#include "fetcher.h"
PodcastSearchModel::PodcastSearchModel(QObject *parent)
: QAbstractListModel(parent)
{
}
QVariant PodcastSearchModel::data(const QModelIndex &index, int role) const
{
if (index.row() < 0 || index.row() >= rowCount(QModelIndex())) {
// invalid index
return QVariant::fromValue(QStringLiteral("DEADBEEF"));
}
switch (role) {
case Id:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("id")].toInt();
case Title:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("title")].toString();
case Url:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("url")].toString();
case OriginalUrl:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("originalUrl")].toString();
case Link:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("link")].toString();
case Description:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("description")].toString();
case Author:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("author")].toString();
case OwnerName:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("ownerName")].toString();
case Image:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("image")].toString();
case Artwork:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("artwork")].toString();
case LastUpdateTime:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("lastUpdateTime")].toInt();
case LastCrawlTime:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("lastCrawlTime")].toInt();
case LastParseTime:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("lastParseTime")].toInt();
case LastGoodHttpStatusTime:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("lastGoodHttpStatusTime")].toInt();
case LastHttpStatus:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("lastHttpStatus")].toInt();
case ContentType:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("contentType")].toString();
case ItunesId:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("itunesId")].toInt();
case Generator:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("generator")].toString();
case Language:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("language")].toString();
case Type:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("type")].toInt();
case Dead:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("dead")].toInt();
case CrawlErrors:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("crawlErrors")].toInt();
case ParseErrors:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("parseErrors")].toInt();
case Categories: {
// TODO: Implement this function to add to the list of categories.
}
case Locked:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("locked")].toInt();
case ImageUrlHash:
return m_data[QStringLiteral("feeds")].toArray()[index.row()].toObject()[QStringLiteral("imageUrlHash")].toInt();
default:
return QVariant();
}
}
QHash<int, QByteArray> PodcastSearchModel::roleNames() const
{
return {
{Id, "id"},
{Title, "title"},
{Url, "url"},
{OriginalUrl, "originalUrl"},
{Link, "link"},
{Description, "description"},
{Author, "author"},
{OwnerName, "ownerName"},
{Image, "image"},
{Artwork, "artwork"},
{LastUpdateTime, "lastUpdateTime"},
{LastCrawlTime, "lastCrawlTime"},
{LastParseTime, "lastParseTime"},
{LastGoodHttpStatusTime, "lastGoodHttpStatusTime"},
{LastHttpStatus, "lastHttpStatus"},
{ContentType, "contentType"},
{ItunesId, "itunesId"},
{Generator, "generator"},
{Language, "language"},
{Type, "type"},
{Dead, "dead"},
{CrawlErrors, "crawlErrors"},
{ParseErrors, "parseErrors"},
{Categories, "categories"},
{Locked, "locked"},
{ImageUrlHash, "imageUrlHash"},
};
}
int PodcastSearchModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
if (m_data.isEmpty()) {
return 0;
}
return m_data[QStringLiteral("feeds")].toArray().size();
}
void PodcastSearchModel::search(const QString &text)
{
QString safeText(text);
// TODO: Make this more urlsafe
safeText.replace(QLatin1Char(' '), QLatin1Char('+'));
QNetworkRequest request(QUrl(QStringLiteral("https://api.podcastindex.org/api/1.0/search/byterm?q=%1").arg(text)));
QString url = QStringLiteral("https://api.podcastindex.org/api/1.0/search/byterm?q=%1").arg(text);
request.setRawHeader("X-Auth-Key", "BLVCJJSWUJGD3WJQSZ56");
auto time = QDateTime::currentDateTime().toSecsSinceEpoch();
request.setRawHeader("X-Auth-Date", QString::number(time).toLatin1());
QString hashString = QStringLiteral(
"BLVCJJSWUJGD3WJQSZ56"
"vSPPqM8Tqh9Lr3xbEb77L4$f6kAdVw3v$9TwzGRH")
+ QString::number(time);
auto hash = QCryptographicHash::hash(hashString.toLatin1(), QCryptographicHash::Sha1);
request.setRawHeader("Authorization", hash.toHex());
auto reply = Fetcher::instance().get(request);
connect(reply, &QNetworkReply::finished, this, [=]() {
if (reply->error()) {
ErrorLogModel::instance().monitorErrorMessages(Error::Type::DiscoverError, url, QString(), reply->error(), reply->errorString(), url);
} else {
beginResetModel();
m_data = QJsonDocument::fromJson(reply->readAll()).object();
endResetModel();
}
});
}