Kgapi

personfetchjob.cpp
1/*
2 * This file is part of LibKGAPI library
3 *
4 * SPDX-FileCopyrightText: 2022 Claudio Cambra <claudio.cambra@kde.org>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8
9#include "personfetchjob.h"
10#include "peopleservice.h"
11#include "person.h"
12#include "../debug.h"
13#include "types.h"
14#include "utils.h"
15#include "account.h"
16
17#include <QNetworkRequest>
18#include <QNetworkReply>
19#include <QUrlQuery>
20#include <QJsonDocument>
21#include <QJsonObject>
22#include <QJsonArray>
23
24namespace KGAPI2::People
25{
26
27class Q_DECL_HIDDEN PersonFetchJob::Private
28{
29public:
30 explicit Private(PersonFetchJob *parent);
31
32 QNetworkRequest createRequest(const QUrl &url);
33 ObjectsList processReceivedData(const QByteArray &rawData);
34
35 QString personResourceName;
36 QString syncToken;
37 QString receivedSyncToken;
38
39public Q_SLOTS:
40 void startFetch();
41
42private:
43 PersonFetchJob * const q;
44};
45
46PersonFetchJob::Private::Private(PersonFetchJob *parent)
47 : q(parent)
48{
49}
50
51QNetworkRequest PersonFetchJob::Private::createRequest(const QUrl& url)
52{
53 QNetworkRequest request(url);
54 request.setRawHeader("Host", "people.googleapis.com");
55 return request;
56}
57
58void PersonFetchJob::Private::startFetch()
59{
60 QUrl url;
61 if (personResourceName.isEmpty()) {
62 url = PeopleService::fetchAllContactsUrl(syncToken);
63 } else {
64 url = PeopleService::fetchContactUrl(personResourceName);
65 }
66
67 const QNetworkRequest request = createRequest(url);
68 q->enqueueRequest(request);
69}
70
71ObjectsList PersonFetchJob::Private::processReceivedData(const QByteArray &rawData)
72{
73 FeedData feedData;
74 ObjectsList items;
75
76 if (personResourceName.isEmpty()) {
77 items = PeopleService::parseConnectionsJSONFeed(feedData, rawData, syncToken);
78 } else {
79 const auto jsonDocumentFromData = QJsonDocument::fromJson(rawData);
80 if(jsonDocumentFromData.isObject()) {
81 items << People::Person::fromJSON(jsonDocumentFromData.object());
82 } else {
83 qCDebug(KGAPIDebug) << "JSON document does not have object";
84 }
85 }
86
87 if (feedData.nextPageUrl.isValid()) {
88 q->emitProgress(feedData.startIndex, feedData.totalResults);
89
90 const QNetworkRequest request = createRequest(feedData.nextPageUrl);
91 q->enqueueRequest(request);
92 } else {
93 receivedSyncToken = feedData.syncToken;
94 q->emitFinished();
95 }
96
97 return items;
98}
99
100PersonFetchJob::PersonFetchJob(const AccountPtr& account, QObject* parent)
101 : FetchJob(account, parent)
102 , d(std::make_unique<Private>(this))
103{
104}
105
106PersonFetchJob::PersonFetchJob(const QString &resourceName, const AccountPtr &account, QObject* parent)
107 : FetchJob(account, parent)
108 , d(std::make_unique<Private>(this))
109{
110 d->personResourceName = resourceName;
111}
112
113PersonFetchJob::~PersonFetchJob() = default;
114
115QString PersonFetchJob::syncToken() const
116{
117 return d->syncToken;
118}
119
120void PersonFetchJob::setSyncToken(const QString &syncToken)
121{
122 if (syncToken == d->syncToken) {
123 return;
124 }
125
126 d->syncToken = syncToken;
127 Q_EMIT syncTokenChanged();
128}
129
130QString PersonFetchJob::receivedSyncToken() const
131{
132 return d->receivedSyncToken;
133}
134
135void PersonFetchJob::start()
136{
137 d->startFetch();
138}
139
140bool PersonFetchJob::handleError(int statusCode, const QByteArray &rawData)
141{
142 if (statusCode == KGAPI2::BadRequest) {
143 const auto error = QJsonDocument::fromJson(rawData);
144 if (error[u"error"][u"status"].toString() == u"INVALID_ARGUMENT") {
145 qCDebug(KGAPIDebug) << "Sync token is invalid, redoing request with no syncToken";
146 d->syncToken.clear();
147 d->startFetch();
148 return true;
149 }
150 for (const auto detail : error[u"error"][u"details"].toArray()) {
151 if (detail[u"reason"].toString() == u"EXPIRED_SYNC_TOKEN") {
152 qCDebug(KGAPIDebug) << "Sync token expired, redoing request with no syncToken";
153 d->syncToken.clear();
154 d->startFetch();
155 return true;
156 }
157 }
158 }
159
160 return FetchJob::handleError(statusCode, rawData);
161}
162
163ObjectsList PersonFetchJob::handleReplyWithItems(const QNetworkReply *reply, const QByteArray &rawData)
164{
165 const auto contentType = reply->header(QNetworkRequest::ContentTypeHeader).toString();
166 const auto ct = Utils::stringToContentType(contentType);
167
168 if (ct == KGAPI2::JSON) {
169 return d->processReceivedData(rawData);
170 }
171
172 return ObjectsList();
173}
174
175}
176
177#include "moc_personfetchjob.cpp"
char * toString(const EngineQuery &query)
@ BadRequest
Invalid (malformed) request.
Definition types.h:197
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
QJsonDocument fromJson(const QByteArray &json, QJsonParseError *error)
QVariant header(QNetworkRequest::KnownHeaders header) const const
QString toString() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 3 2024 11:50:41 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.