File indexing completed on 2024-12-08 10:16:06
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 }