File indexing completed on 2024-12-08 04:18:15

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "wikidataquery.h"
0008 
0009 #include <QDebug>
0010 #include <QJsonDocument>
0011 #include <QJsonObject>
0012 #include <QNetworkRequest>
0013 #include <QNetworkReply>
0014 #include <QUrlQuery>
0015 
0016 namespace wd = Wikidata;
0017 
0018 enum {
0019     WikidataGetEntitiesMaxCount = 50,
0020     WikidataQueryMaxCount = 50
0021 };
0022 
0023 WikidataQuery::WikidataQuery(QObject *parent) :
0024     QObject(parent)
0025 {
0026 }
0027 
0028 WikidataQuery::~WikidataQuery() = default;
0029 
0030 WikidataQuery::Error WikidataQuery::error()
0031 {
0032     return m_error;
0033 }
0034 
0035 QUrlQuery WikidataQuery::commonUrlQuery() const
0036 {
0037     QUrlQuery query;
0038     query.addQueryItem(QStringLiteral("format"), QStringLiteral("json"));
0039     return query;
0040 }
0041 
0042 
0043 WikidataEntitiesQuery::WikidataEntitiesQuery(QObject* parent)
0044     : WikidataQuery(parent)
0045 {
0046 }
0047 
0048 WikidataEntitiesQuery::~WikidataEntitiesQuery() = default;
0049 
0050 void WikidataEntitiesQuery::setItems(std::vector<wd::Q> &&items)
0051 {
0052     m_items = std::move(items);
0053 }
0054 
0055 QNetworkRequest WikidataEntitiesQuery::nextRequest()
0056 {
0057     QUrl url(QStringLiteral("https://www.wikidata.org/w/api.php"));
0058     auto query = commonUrlQuery();
0059     query.addQueryItem(QStringLiteral("action"), QStringLiteral("wbgetentities"));
0060     query.addQueryItem(QStringLiteral("props"), QStringLiteral("claims"));
0061 
0062     QString ids;
0063     for (auto i = m_nextBatch; i < std::min(m_items.size(), m_nextBatch + WikidataGetEntitiesMaxCount); ++i) {
0064         if (i != m_nextBatch) {
0065             ids += QLatin1Char('|');
0066         }
0067         ids += m_items[i].toString();
0068     }
0069     m_nextBatch += WikidataGetEntitiesMaxCount;
0070     query.addQueryItem(QStringLiteral("ids"), ids);
0071     url.setQuery(query);
0072 
0073     QNetworkRequest req(url);
0074     req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
0075     return req;
0076 }
0077 
0078 std::vector<Wikidata::Item>&& WikidataEntitiesQuery::takeResult()
0079 {
0080     return std::move(m_result);
0081 }
0082 
0083 bool WikidataEntitiesQuery::processReply(QNetworkReply *reply)
0084 {
0085     const auto doc = QJsonDocument::fromJson(reply->readAll());
0086     const auto entities = doc.object().value(QLatin1String("entities")).toObject();
0087     m_result.reserve(entities.size());
0088     for (auto it = entities.begin(); it != entities.end(); ++it) {
0089         m_result.push_back(wd::Item(wd::Q(it.key()), it.value().toObject()));
0090     }
0091     Q_EMIT partialResult(this);
0092 
0093     if (m_nextBatch < m_items.size()) {
0094         return false;
0095     } else {
0096         Q_EMIT finished();
0097         return true;
0098     }
0099 }
0100 
0101 
0102 WikidataImageMetadataQuery::WikidataImageMetadataQuery(QObject* parent)
0103     : WikidataQuery(parent)
0104 {
0105 }
0106 
0107 WikidataImageMetadataQuery::~WikidataImageMetadataQuery() = default;
0108 
0109 void WikidataImageMetadataQuery::setImages(std::vector<QString> &&images)
0110 {
0111     m_images = std::move(images);
0112 }
0113 
0114 QNetworkRequest WikidataImageMetadataQuery::nextRequest()
0115 {
0116     QUrl url(QStringLiteral("https://commons.wikimedia.org/w/api.php"));
0117     auto query = commonUrlQuery();
0118     query.addQueryItem(QStringLiteral("action"), QStringLiteral("query"));
0119     query.addQueryItem(QStringLiteral("prop"), QStringLiteral("imageinfo"));
0120     query.addQueryItem(QStringLiteral("iiprop"), QStringLiteral("extmetadata|mime|size"));
0121     QString ids;
0122     for (auto i = m_nextBatch; i < std::min(m_images.size(), m_nextBatch + WikidataQueryMaxCount); ++i) {
0123         if (i != m_nextBatch) {
0124             ids += QLatin1Char('|');
0125         }
0126         ids += QLatin1String("File:") + m_images[i];
0127     }
0128     m_nextBatch += WikidataQueryMaxCount;
0129     query.addQueryItem(QStringLiteral("titles"), ids);
0130     url.setQuery(query);
0131 
0132     QNetworkRequest req(url);
0133     req.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
0134     return req;
0135 }
0136 
0137 std::vector<Wikidata::Image>&& WikidataImageMetadataQuery::takeResult()
0138 {
0139     return std::move(m_result);
0140 }
0141 
0142 bool WikidataImageMetadataQuery::processReply(QNetworkReply *reply)
0143 {
0144     const auto doc = QJsonDocument::fromJson(reply->readAll());
0145     const auto images = doc.object().value(QLatin1String("query")).toObject().value(QLatin1String("pages")).toObject();
0146     m_result.reserve(images.size());
0147     for (const auto &img : images) {
0148         m_result.push_back(wd::Image(img.toObject()));
0149     }
0150     Q_EMIT partialResult(this);
0151 
0152     if (m_nextBatch < m_images.size()) {
0153         return false;
0154     } else {
0155         Q_EMIT finished();
0156         return true;
0157     }
0158 }