138 lines
5.0 KiB
C++
138 lines
5.0 KiB
C++
#include "aurquery.h"
|
|
|
|
#include "alpm/package.h"
|
|
|
|
#include <QUrlQuery>
|
|
#include <QNetworkRequest>
|
|
#include <QNetworkReply>
|
|
#include <QNetworkAccessManager>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QJsonArray>
|
|
|
|
#include <iostream>
|
|
|
|
using namespace std;
|
|
|
|
namespace PackageManagement {
|
|
|
|
QUrl AurQuery::m_aurRpcUrl = QUrl(QStringLiteral("https://aur.archlinux.org/rpc.php"));
|
|
|
|
QUrl AurQuery::m_aurPkgbuildUrl = QUrl(QStringLiteral("https://aur.archlinux.org/cgit/aur.git/plain/PKGBUILD"));
|
|
|
|
const char *requestTypeProp = "type";
|
|
const QString rpcRequestTypeKey(QStringLiteral("type"));
|
|
const QString rpcRequestTypeSuggest(QStringLiteral("suggest"));
|
|
const QString rpcRequestTypeMultiInfo(QStringLiteral("multiinfo"));
|
|
const QString rpcArgKey(QStringLiteral("arg"));
|
|
const QString rpcArgArray(QStringLiteral("arg[]"));
|
|
const QString pkgbuildRequestType(QString("pkgbuild"));
|
|
|
|
AurQuery::AurQuery(QNetworkAccessManager &networkAccessManager, QObject *parent) :
|
|
QObject(parent),
|
|
m_networkAccessManager(networkAccessManager)
|
|
{}
|
|
|
|
QNetworkReply *AurQuery::requestSuggestions(const QString &phrase) const
|
|
{
|
|
auto url = m_aurRpcUrl;
|
|
QUrlQuery query;
|
|
query.addQueryItem(rpcRequestTypeKey, rpcRequestTypeSuggest);
|
|
query.addQueryItem(rpcArgKey, phrase);
|
|
url.setQuery(query);
|
|
auto *reply = m_networkAccessManager.get(QNetworkRequest(url));
|
|
reply->setProperty(requestTypeProp, rpcRequestTypeSuggest);
|
|
connect(reply, &QNetworkReply::finished, this, &AurQuery::dataReceived);
|
|
return reply;
|
|
}
|
|
|
|
/*!
|
|
* \brief Requests package information for the specified packages from the AUR.
|
|
* \returns Returns the QNetworkReply used for the request.
|
|
* \remarks
|
|
* If \a forceUpdate is true, package information which has already been retrieved
|
|
* and is still cached is requested again. Otherwise these packages will not be
|
|
* requested again. If it turns out, that all packages are already cached, nullptr
|
|
* is returned in this case.
|
|
*/
|
|
QNetworkReply *AurQuery::requestPackageInfo(const QStringList &packageNames, bool forceUpdate) const
|
|
{
|
|
QUrlQuery query;
|
|
for(const auto &packageName : packageNames) {
|
|
if(forceUpdate || !m_packages.count(packageName)) {
|
|
query.addQueryItem(rpcArgArray, packageName);
|
|
}
|
|
}
|
|
if(query.isEmpty()) {
|
|
return nullptr;
|
|
} else {
|
|
auto url = m_aurRpcUrl;
|
|
query.addQueryItem(rpcRequestTypeKey, rpcRequestTypeMultiInfo);
|
|
url.setQuery(query);
|
|
auto *reply = m_networkAccessManager.get(QNetworkRequest(url));
|
|
reply->setProperty(requestTypeProp, rpcRequestTypeMultiInfo);
|
|
connect(reply, &QNetworkReply::finished, this, &AurQuery::dataReceived);
|
|
return reply;
|
|
}
|
|
}
|
|
|
|
QNetworkReply *AurQuery::requestFullPackageInfo(const QString &package, bool forceUpdate) const
|
|
{
|
|
try {
|
|
const auto &pkg = m_packages.at(package);
|
|
if(pkg.hasFullInfo() && !forceUpdate) {
|
|
return nullptr;
|
|
}
|
|
} catch(const out_of_range &) {
|
|
}
|
|
auto url = m_aurPkgbuildUrl;
|
|
QUrlQuery query;
|
|
query.addQueryItem(QStringLiteral("h"), package);
|
|
url.setQuery(query);
|
|
auto *reply = m_networkAccessManager.get(QNetworkRequest(url));
|
|
reply->setProperty(requestTypeProp, pkgbuildRequestType);
|
|
connect(reply, &QNetworkReply::finished, this, &AurQuery::dataReceived);
|
|
return reply;
|
|
}
|
|
|
|
void AurQuery::dataReceived()
|
|
{
|
|
if(auto *reply = qobject_cast<QNetworkReply *>(sender())) {
|
|
if(reply->error() == QNetworkReply::NoError) {
|
|
QJsonParseError error;
|
|
QByteArray data = reply->readAll();
|
|
cerr << "AUR reply: " << data.data() << endl;
|
|
const QJsonDocument doc = QJsonDocument::fromJson(data, &error);
|
|
//const QJsonDocument doc = QJsonDocument::fromJson(reply->readAll(), &error);
|
|
if(error.error == QJsonParseError::NoError) {
|
|
const QString requestType = reply->property(requestTypeProp).toString();
|
|
if(requestType == rpcRequestTypeSuggest) {
|
|
emit suggestionsAvailable(reply, doc.array());
|
|
} else if(requestType == rpcRequestTypeMultiInfo) {
|
|
processPackageInfo(reply, doc.object().value(QStringLiteral("results")).toArray());
|
|
} else {
|
|
cerr << "Error: Reply has invalid type. (should never happen)" << endl;
|
|
}
|
|
} else {
|
|
cerr << "Error: Unable to parse JSON received from AUR: " << error.errorString().toLocal8Bit().data() << " at character " << error.offset << endl;
|
|
}
|
|
} else {
|
|
cerr << "Error: Unable to request data from AUR: " << reply->errorString().toLocal8Bit().data() << endl;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AurQuery::processPackageInfo(const QNetworkReply *reply, const QJsonArray &results)
|
|
{
|
|
for(const auto &result : results) {
|
|
AurPackage package(result);
|
|
if(!package.name().isEmpty()) {
|
|
m_packages[package.name()] = move(package);
|
|
}
|
|
}
|
|
emit packageInfoAvailable(reply);
|
|
}
|
|
|
|
} // namespace Alpm
|
|
|