Attica

provider.cpp
1 /*
2  This file is part of KDE.
3 
4  SPDX-FileCopyrightText: 2008 Cornelius Schumacher <[email protected]>
5  SPDX-FileCopyrightText: 2010 Sebastian Kügler <[email protected]>
6  SPDX-FileCopyrightText: 2011 Laszlo Papp <[email protected]>
7 
8  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
9 */
10 
11 #include "provider.h"
12 
13 #include "accountbalance.h"
14 #include "accountbalanceparser.h"
15 #include "achievementparser.h"
16 #include "activity.h"
17 #include "activityparser.h"
18 #include "buildservice.h"
19 #include "buildservicejob.h"
20 #include "buildservicejoboutput.h"
21 #include "buildservicejoboutputparser.h"
22 #include "buildservicejobparser.h"
23 #include "buildserviceparser.h"
24 #include "categoryparser.h"
25 #include "commentparser.h"
26 #include "config.h"
27 #include "content.h"
28 #include "contentparser.h"
29 #include "distributionparser.h"
30 #include "downloaditem.h"
31 #include "downloaditemparser.h"
32 #include "event.h"
33 #include "eventparser.h"
34 #include "folder.h"
35 #include "folderparser.h"
36 #include "forumparser.h"
37 #include "homepagetype.h"
38 #include "homepagetypeparser.h"
39 #include "knowledgebaseentry.h"
40 #include "knowledgebaseentryparser.h"
41 #include "licenseparser.h"
42 #include "messageparser.h"
43 #include "person.h"
44 #include "personparser.h"
45 #include "platformdependent_v2.h"
46 #include "postfiledata.h"
47 #include "postjob.h"
48 #include "privatedata.h"
49 #include "privatedataparser.h"
50 #include "project.h"
51 #include "projectparser.h"
52 #include "publisher.h"
53 #include "publisherfield.h"
54 #include "publisherfieldparser.h"
55 #include "publisherparser.h"
56 #include "remoteaccount.h"
57 #include "remoteaccountparser.h"
58 #include "topic.h"
59 #include "topicparser.h"
60 #include "version.h"
61 
62 #include <QCoreApplication>
63 #include <QDebug>
64 #include <QFile>
65 #include <QNetworkAccessManager>
66 #include <QNetworkReply>
67 #include <QThreadStorage>
68 #include <QUrlQuery>
69 
70 using namespace Attica;
71 
72 class Q_DECL_HIDDEN Provider::Private : public QSharedData
73 {
74 public:
75  QUrl m_baseUrl;
76  QUrl m_icon;
77  QString m_name;
78  QString m_credentialsUserName;
79  QString m_credentialsPassword;
80  QString m_personVersion;
81  QString m_friendVersion;
82  QString m_messageVersion;
83  QString m_achievementVersion;
84  QString m_activityVersion;
85  QString m_contentVersion;
86  QString m_fanVersion;
87  QString m_forumVersion;
88  QString m_knowledgebaseVersion;
89  QString m_eventVersion;
90  QString m_commentVersion;
91  QString m_registerUrl;
92  PlatformDependent *m_internals;
93  QString m_additionalAgentInformation;
94 
95  Private()
96  : m_internals(nullptr)
97  {
98  }
99 
100  Private(const Private &other)
101  : QSharedData(other)
102  , m_baseUrl(other.m_baseUrl)
103  , m_name(other.m_name)
104  , m_credentialsUserName(other.m_credentialsUserName)
105  , m_credentialsPassword(other.m_credentialsPassword)
106  , m_personVersion(other.m_personVersion)
107  , m_friendVersion(other.m_friendVersion)
108  , m_messageVersion(other.m_messageVersion)
109  , m_achievementVersion(other.m_achievementVersion)
110  , m_activityVersion(other.m_activityVersion)
111  , m_contentVersion(other.m_contentVersion)
112  , m_fanVersion(other.m_fanVersion)
113  , m_forumVersion(other.m_forumVersion)
114  , m_knowledgebaseVersion(other.m_knowledgebaseVersion)
115  , m_eventVersion(other.m_eventVersion)
116  , m_commentVersion(other.m_commentVersion)
117  , m_registerUrl(other.m_registerUrl)
118  , m_internals(other.m_internals)
119  , m_additionalAgentInformation(other.m_additionalAgentInformation)
120  {
121  }
122 
123  Private(PlatformDependent *internals,
124  const QUrl &baseUrl,
125  const QString &name,
126  const QUrl &icon,
127  const QString &person,
128  const QString &friendV,
129  const QString &message,
130  const QString &achievement,
131  const QString &activity,
132  const QString &content,
133  const QString &fan,
134  const QString &forum,
135  const QString &knowledgebase,
136  const QString &event,
137  const QString &comment,
138  const QString &registerUrl,
139  const QString &additionalAgentInformation)
140  : m_baseUrl(baseUrl)
141  , m_icon(icon)
142  , m_name(name)
143  , m_personVersion(person)
144  , m_friendVersion(friendV)
145  , m_messageVersion(message)
146  , m_achievementVersion(achievement)
147  , m_activityVersion(activity)
148  , m_contentVersion(content)
149  , m_fanVersion(fan)
150  , m_forumVersion(forum)
151  , m_knowledgebaseVersion(knowledgebase)
152  , m_eventVersion(event)
153  , m_commentVersion(comment)
154  , m_registerUrl(registerUrl)
155  , m_internals(internals)
156  , m_additionalAgentInformation(additionalAgentInformation)
157  {
158  if (m_baseUrl.isEmpty()) {
159  return;
160  }
161  QString user;
162  QString pass;
163  if (m_internals->hasCredentials(m_baseUrl) && m_internals->loadCredentials(m_baseUrl, user, pass)) {
164  m_credentialsUserName = user;
165  m_credentialsPassword = pass;
166  }
167  }
168 
169  ~Private()
170  {
171  }
172 };
173 
174 Provider::Provider()
175  : d(new Private)
176 {
177 }
178 
179 Provider::Provider(const Provider &other)
180  : d(other.d)
181 {
182 }
183 
184 Provider::Provider(PlatformDependent *internals,
185  const QUrl &baseUrl,
186  const QString &name,
187  const QUrl &icon,
188  const QString &person,
189  const QString &friendV,
190  const QString &message,
191  const QString &achievement,
192  const QString &activity,
193  const QString &content,
194  const QString &fan,
195  const QString &forum,
196  const QString &knowledgebase,
197  const QString &event,
198  const QString &comment)
199  : d(new Private(internals,
200  baseUrl,
201  name,
202  icon,
203  person,
204  friendV,
205  message,
206  achievement,
207  activity,
208  content,
209  fan,
210  forum,
211  knowledgebase,
212  event,
213  comment,
214  QString(),
215  QString()))
216 {
217 }
218 
219 Provider::Provider(PlatformDependent *internals,
220  const QUrl &baseUrl,
221  const QString &name,
222  const QUrl &icon,
223  const QString &person,
224  const QString &friendV,
225  const QString &message,
226  const QString &achievement,
227  const QString &activity,
228  const QString &content,
229  const QString &fan,
230  const QString &forum,
231  const QString &knowledgebase,
232  const QString &event,
233  const QString &comment,
234  const QString &registerUrl)
235  : d(new Private(internals,
236  baseUrl,
237  name,
238  icon,
239  person,
240  friendV,
241  message,
242  achievement,
243  activity,
244  content,
245  fan,
246  forum,
247  knowledgebase,
248  event,
249  comment,
250  registerUrl,
251  QString()))
252 {
253 }
254 
255 Provider::Provider(PlatformDependent *internals,
256  const QUrl &baseUrl,
257  const QString &name,
258  const QUrl &icon,
259  const QString &person,
260  const QString &friendV,
261  const QString &message,
262  const QString &achievement,
263  const QString &activity,
264  const QString &content,
265  const QString &fan,
266  const QString &forum,
267  const QString &knowledgebase,
268  const QString &event,
269  const QString &comment,
270  const QString &registerUrl,
271  const QString &additionalAgentInformation)
272  : d(new Private(internals,
273  baseUrl,
274  name,
275  icon,
276  person,
277  friendV,
278  message,
279  achievement,
280  activity,
281  content,
282  fan,
283  forum,
284  knowledgebase,
285  event,
286  comment,
287  registerUrl,
288  additionalAgentInformation))
289 {
290 }
291 
292 Provider &Provider::operator=(const Attica::Provider &other)
293 {
294  d = other.d;
295  return *this;
296 }
297 
298 Provider::~Provider()
299 {
300 }
301 
303 {
304  return d->m_baseUrl;
305 }
306 
307 bool Provider::isValid() const
308 {
309  return d->m_baseUrl.isValid();
310 }
311 
313 {
314  if (!isValid()) {
315  return false;
316  }
317 
318  return d->m_internals->isEnabled(d->m_baseUrl);
319 }
320 
321 void Provider::setEnabled(bool enabled)
322 {
323  if (!isValid()) {
324  return;
325  }
326 
327  d->m_internals->enableProvider(d->m_baseUrl, enabled);
328 }
329 
330 void Provider::setAdditionalAgentInformation(const QString &additionalInformation)
331 {
332  d->m_additionalAgentInformation = additionalInformation;
333 }
334 
336 {
337  return d->m_additionalAgentInformation;
338 }
339 
341 {
342  return d->m_name;
343 }
344 
346 {
347  return d->m_icon;
348 }
349 
351 {
352  if (!isValid()) {
353  return false;
354  }
355 
356  return d->m_internals->hasCredentials(d->m_baseUrl);
357 }
358 
359 bool Provider::hasCredentials() const
360 {
361  if (!isValid()) {
362  return false;
363  }
364 
365  return d->m_internals->hasCredentials(d->m_baseUrl);
366 }
367 
369 {
370  if (!isValid()) {
371  return false;
372  }
373 
374  if (d->m_internals->loadCredentials(d->m_baseUrl, user, password)) {
375  d->m_credentialsUserName = user;
376  d->m_credentialsPassword = password;
377  return true;
378  }
379  return false;
380 }
381 
382 bool Provider::saveCredentials(const QString &user, const QString &password)
383 {
384  if (!isValid()) {
385  return false;
386  }
387 
388  d->m_credentialsUserName = user;
389  d->m_credentialsPassword = password;
390  return d->m_internals->saveCredentials(d->m_baseUrl, user, password);
391 }
392 
393 PostJob *Provider::checkLogin(const QString &user, const QString &password)
394 {
395  if (!isValid()) {
396  return nullptr;
397  }
398 
399  QMap<QString, QString> postParameters;
400 
401  postParameters.insert(QLatin1String("login"), user);
402  postParameters.insert(QLatin1String("password"), password);
403 
404  return new PostJob(d->m_internals, createRequest(QLatin1String("person/check")), postParameters);
405 }
406 
408 {
409  if (!isValid()) {
410  return nullptr;
411  }
412 
413  QUrl url = createUrl(QLatin1String("config"));
414  return doRequestConfig(url);
415 }
416 
417 PostJob *Provider::registerAccount(const QString &id, const QString &password, const QString &mail, const QString &firstName, const QString &lastName)
418 {
419  if (!isValid()) {
420  return nullptr;
421  }
422 
423  QMap<QString, QString> postParameters;
424 
425  postParameters.insert(QLatin1String("login"), id);
426  postParameters.insert(QLatin1String("password"), password);
427  postParameters.insert(QLatin1String("firstname"), firstName);
428  postParameters.insert(QLatin1String("lastname"), lastName);
429  postParameters.insert(QLatin1String("email"), mail);
430 
431  return new PostJob(d->m_internals, createRequest(QLatin1String("person/add")), postParameters);
432 }
433 
434 const QString &Provider::getRegisterAccountUrl() const
435 {
436  return d->m_registerUrl;
437 }
438 
439 ItemJob<Person> *Provider::requestPerson(const QString &id)
440 {
441  if (!isValid()) {
442  return nullptr;
443  }
444 
445  QUrl url = createUrl(QLatin1String("person/data/") + id);
446  return doRequestPerson(url);
447 }
448 
449 ItemJob<Person> *Provider::requestPersonSelf()
450 {
451  if (!isValid()) {
452  return nullptr;
453  }
454 
455  QUrl url = createUrl(QLatin1String("person/self"));
456  return doRequestPerson(url);
457 }
458 
459 ItemJob<AccountBalance> *Provider::requestAccountBalance()
460 {
461  if (!isValid()) {
462  return nullptr;
463  }
464 
465  QUrl url = createUrl(QLatin1String("person/balance"));
466  return doRequestAccountBalance(url);
467 }
468 
469 ListJob<Person> *Provider::requestPersonSearchByName(const QString &name)
470 {
471  if (!isValid()) {
472  return nullptr;
473  }
474 
475  QUrl url = createUrl(QStringLiteral("person/data"));
476  QUrlQuery q(url);
477  q.addQueryItem(QStringLiteral("name"), name);
478  url.setQuery(q);
479  return doRequestPersonList(url);
480 }
481 
482 ListJob<Person> *Provider::requestPersonSearchByLocation(qreal latitude, qreal longitude, qreal distance, int page, int pageSize)
483 {
484  if (!isValid()) {
485  return nullptr;
486  }
487 
488  QUrl url = createUrl(QStringLiteral("person/data"));
489  QUrlQuery q(url);
490  q.addQueryItem(QStringLiteral("latitude"), QString::number(latitude));
491  q.addQueryItem(QStringLiteral("longitude"), QString::number(longitude));
492  if (distance > 0.0) {
493  q.addQueryItem(QStringLiteral("distance"), QString::number(distance));
494  }
495  q.addQueryItem(QStringLiteral("page"), QString::number(page));
496  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
497  url.setQuery(q);
498 
499  return doRequestPersonList(url);
500 }
501 
502 ListJob<Person> *Provider::requestFriends(const QString &id, int page, int pageSize)
503 {
504  if (!isValid()) {
505  return nullptr;
506  }
507 
508  QUrl url = createUrl(QLatin1String("friend/data/") + id);
509  QUrlQuery q(url);
510  q.addQueryItem(QLatin1String("page"), QString::number(page));
511  q.addQueryItem(QLatin1String("pagesize"), QString::number(pageSize));
512  url.setQuery(q);
513 
514  return doRequestPersonList(url);
515 }
516 
517 ListJob<Person> *Provider::requestSentInvitations(int page, int pageSize)
518 {
519  if (!isValid()) {
520  return nullptr;
521  }
522 
523  QUrl url = createUrl(QStringLiteral("friend/sentinvitations"));
524  QUrlQuery q(url);
525  q.addQueryItem(QStringLiteral("page"), QString::number(page));
526  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
527  url.setQuery(q);
528 
529  return doRequestPersonList(url);
530 }
531 
532 ListJob<Person> *Provider::requestReceivedInvitations(int page, int pageSize)
533 {
534  if (!isValid()) {
535  return nullptr;
536  }
537 
538  QUrl url = createUrl(QStringLiteral("friend/receivedinvitations"));
539  QUrlQuery q(url);
540  q.addQueryItem(QStringLiteral("page"), QString::number(page));
541  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
542  url.setQuery(q);
543 
544  return doRequestPersonList(url);
545 }
546 
547 ListJob<Achievement> *Provider::requestAchievements(const QString &contentId, const QString &achievementId, const QString &userId)
548 {
549  if (!isValid()) {
550  return nullptr;
551  }
552 
553  QUrl url = createUrl(QLatin1String("achievements/content/") + contentId + achievementId);
554  QUrlQuery q(url);
555  q.addQueryItem(QStringLiteral("user_id"), userId);
556  url.setQuery(q);
557  return doRequestAchievementList(url);
558 }
559 
561 {
562  if (!isValid()) {
563  return nullptr;
564  }
565 
566  StringMap postParameters;
567  int i = 0;
568  int j = 0;
569 
570  postParameters.insert(QLatin1String("name"), newAchievement.name());
571  postParameters.insert(QLatin1String("description"), newAchievement.description());
572  postParameters.insert(QLatin1String("explanation"), newAchievement.explanation());
573  postParameters.insert(QLatin1String("points"), QString::number(newAchievement.points()));
574  postParameters.insert(QLatin1String("image"), newAchievement.image().toLocalFile());
575  const auto dependenciesList = newAchievement.dependencies();
576  for (const QString &dependency : dependenciesList) {
577  postParameters.insert(QString::fromLatin1("dependencies[%1]").arg(QString::number(i++)), dependency);
578  }
579 
580  postParameters.insert(QLatin1String("type"), Achievement::achievementTypeToString(newAchievement.type()));
581  const auto optionsList = newAchievement.options();
582  for (const QString &option : optionsList) {
583  postParameters.insert(QString::fromLatin1("options[%1]").arg(QString::number(j++)), option);
584  }
585 
586  postParameters.insert(QLatin1String("steps"), QString::number(newAchievement.steps()));
587  postParameters.insert(QLatin1String("visibility"), Achievement::achievementVisibilityToString(newAchievement.visibility()));
588 
589  return new ItemPostJob<Achievement>(d->m_internals, createRequest(QLatin1String("achievements/content/") + contentId), postParameters);
590 }
591 
592 PutJob *Provider::editAchievement(const QString &contentId, const QString &achievementId, const Achievement &achievement)
593 {
594  if (!isValid()) {
595  return nullptr;
596  }
597 
598  if (!dynamic_cast<Attica::PlatformDependentV2 *>(d->m_internals)) {
599  return nullptr;
600  }
601 
602  StringMap postParameters;
603  int i = 0;
604  int j = 0;
605 
606  postParameters.insert(QLatin1String("name"), achievement.name());
607  postParameters.insert(QLatin1String("description"), achievement.description());
608  postParameters.insert(QLatin1String("explanation"), achievement.explanation());
609  postParameters.insert(QLatin1String("points"), QString::number(achievement.points()));
610  postParameters.insert(QLatin1String("image"), achievement.image().toLocalFile());
611  const auto dependenciesList = achievement.dependencies();
612  for (const QString &dependency : dependenciesList) {
613  postParameters.insert(QString::fromLatin1("dependencies[%1]").arg(QString::number(i++)), dependency);
614  }
615 
616  postParameters.insert(QLatin1String("type"), Achievement::achievementTypeToString(achievement.type()));
617  const auto optionsList = achievement.options();
618  for (const QString &option : optionsList) {
619  postParameters.insert(QString::fromLatin1("options[%1]").arg(QString::number(j++)), option);
620  }
621 
622  postParameters.insert(QLatin1String("steps"), QString::number(achievement.steps()));
623  postParameters.insert(QLatin1String("visibility"), Achievement::achievementVisibilityToString(achievement.visibility()));
624 
625  return new ItemPutJob<Achievement>(d->m_internals, createRequest(QLatin1String("achievement/content/") + contentId + achievementId), postParameters);
626 }
627 
628 DeleteJob *Provider::deleteAchievement(const QString &contentId, const QString &achievementId)
629 {
630  if (!isValid()) {
631  return nullptr;
632  }
633 
634  if (!dynamic_cast<Attica::PlatformDependentV2 *>(d->m_internals)) {
635  return nullptr;
636  }
637 
638  return new ItemDeleteJob<Achievement>(d->m_internals, createRequest(QLatin1String("achievements/progress/") + contentId + achievementId));
639 }
640 
641 PostJob *Provider::setAchievementProgress(const QString &id, const QVariant &progress, const QDateTime &timestamp)
642 {
643  if (!isValid()) {
644  return nullptr;
645  }
646 
647  StringMap postParameters;
648 
649  postParameters.insert(QLatin1String("progress"), progress.toString());
650  postParameters.insert(QLatin1String("timestamp"), timestamp.toString());
651 
652  return new ItemPostJob<Achievement>(d->m_internals, createRequest(QLatin1String("achievements/progress/") + id), postParameters);
653 }
654 
655 DeleteJob *Provider::resetAchievementProgress(const QString &id)
656 {
657  if (!isValid()) {
658  return nullptr;
659  }
660 
661  if (!dynamic_cast<Attica::PlatformDependentV2 *>(d->m_internals)) {
662  return nullptr;
663  }
664 
665  return new ItemDeleteJob<Achievement>(d->m_internals, createRequest(QLatin1String("achievements/progress/") + id));
666 }
667 
668 ListJob<Activity> *Provider::requestActivities()
669 {
670  if (!isValid()) {
671  return nullptr;
672  }
673 
674  // qCDebug(ATTICA) << "request activity";
675  QUrl url = createUrl(QLatin1String("activity"));
676  return doRequestActivityList(url);
677 }
678 
680 {
681  if (!isValid()) {
682  return nullptr;
683  }
684 
685  // qCDebug(ATTICA) << "request projects";
686  QUrl url = createUrl(QLatin1String("buildservice/project/list"));
687  return new ListJob<Project>(d->m_internals, createRequest(url));
688 }
689 
691 {
692  if (!isValid()) {
693  return nullptr;
694  }
695 
696  QUrl url = createUrl(QLatin1String("buildservice/project/get/") + id);
697  // qCDebug(ATTICA) << url;
698  return new ItemJob<Project>(d->m_internals, createRequest(url));
699 }
700 
701 QMap<QString, QString> projectPostParameters(const Project &project)
702 {
703  QMap<QString, QString> postParameters;
704 
705  if (!project.name().isEmpty()) {
706  postParameters.insert(QLatin1String("name"), project.name());
707  }
708  if (!project.summary().isEmpty()) {
709  postParameters.insert(QLatin1String("summary"), project.summary());
710  }
711  if (!project.description().isEmpty()) {
712  postParameters.insert(QLatin1String("description"), project.description());
713  }
714  if (!project.url().isEmpty()) {
715  postParameters.insert(QLatin1String("url"), project.url());
716  }
717  if (!project.developers().isEmpty()) {
718  postParameters.insert(QLatin1String("developers"), project.developers().join(QLatin1Char('\n')));
719  }
720  if (!project.version().isEmpty()) {
721  postParameters.insert(QLatin1String("version"), project.version());
722  }
723  if (!project.license().isEmpty()) {
724  postParameters.insert(QLatin1String("license"), project.license());
725  }
726  if (!project.requirements().isEmpty()) {
727  postParameters.insert(QLatin1String("requirements"), project.requirements());
728  }
729  // The specfile generator expects an empty string parameter if it is supposed to regenerate the spec file
730  // So we need to check for nullity here as opposed to an empty string.
731  if (!project.specFile().isNull()) {
732  postParameters.insert(QLatin1String("specfile"), project.specFile());
733  }
734  return postParameters;
735 }
736 
738 {
739  if (!isValid()) {
740  return nullptr;
741  }
742 
743  return new PostJob(d->m_internals, createRequest(QLatin1String("buildservice/project/create")), projectPostParameters(project));
744 }
745 
747 {
748  if (!isValid()) {
749  return nullptr;
750  }
751 
752  return new PostJob(d->m_internals, createRequest(QLatin1String("buildservice/project/edit/") + project.id()), projectPostParameters(project));
753 }
754 
756 {
757  if (!isValid()) {
758  return nullptr;
759  }
760 
761  return new PostJob(d->m_internals, createRequest(QLatin1String("buildservice/project/delete/") + project.id()), projectPostParameters(project));
762 }
763 
765 {
766  if (!isValid()) {
767  return nullptr;
768  }
769 
770  QUrl url = createUrl(QLatin1String("buildservice/buildservices/get/") + id);
771  return new ItemJob<BuildService>(d->m_internals, createRequest(url));
772 }
773 
775 {
776  if (!isValid()) {
777  return nullptr;
778  }
779 
780  // qCDebug(ATTICA) << "request publisher" << id;
781  QUrl url = createUrl(QLatin1String("buildservice/publishing/getpublisher/") + id);
782  return new ItemJob<Publisher>(d->m_internals, createRequest(url));
783 }
784 
786 {
787  if (!isValid()) {
788  return nullptr;
789  }
790 
791  StringMap postParameters;
792  postParameters.insert(QLatin1String("fields[0][name]"), field.name());
793  postParameters.insert(QLatin1String("fields[0][fieldtype]"), field.type());
794  postParameters.insert(QLatin1String("fields[0][data]"), field.data());
795 
796  QString url = QLatin1String("buildservice/publishing/savefields/") + project.id();
797  // qCDebug(ATTICA) << "saving field values...";
798  return new PostJob(d->m_internals, createRequest(url), postParameters);
799 }
800 
801 PostJob *Provider::publishBuildJob(const BuildServiceJob &buildjob, const Publisher &publisher)
802 {
803  if (!isValid()) {
804  return nullptr;
805  }
806 
807  StringMap postParameters;
808  postParameters.insert(QLatin1String("dummyparameter"), QLatin1String("dummyvalue"));
809 
810  QString url = QLatin1String("buildservice/publishing/publishtargetresult/") + buildjob.id() + QLatin1Char('/') + publisher.id();
811  // qCDebug(ATTICA) << "pub'ing";
812  return new PostJob(d->m_internals, createRequest(url), postParameters);
813 }
814 
815 // Buildservices and their jobs
817 {
818  if (!isValid()) {
819  return nullptr;
820  }
821 
822  QUrl url = createUrl(QLatin1String("buildservice/jobs/getoutput/") + id);
823  // qCDebug(ATTICA) << url;
824  return new ItemJob<BuildServiceJobOutput>(d->m_internals, createRequest(url));
825 }
826 
828 {
829  if (!isValid()) {
830  return nullptr;
831  }
832 
833  QUrl url = createUrl(QLatin1String("buildservice/jobs/get/") + id);
834  // qCDebug(ATTICA) << url;
835  return new ItemJob<BuildServiceJob>(d->m_internals, createRequest(url));
836 }
837 
838 QMap<QString, QString> buildServiceJobPostParameters(const BuildServiceJob &buildjob)
839 {
840  QMap<QString, QString> postParameters;
841 
842  if (!buildjob.name().isEmpty()) {
843  postParameters.insert(QLatin1String("name"), buildjob.name());
844  }
845  if (!buildjob.projectId().isEmpty()) {
846  postParameters.insert(QLatin1String("projectid"), buildjob.projectId());
847  }
848  if (!buildjob.target().isEmpty()) {
849  postParameters.insert(QLatin1String("target"), buildjob.target());
850  }
851  if (!buildjob.buildServiceId().isEmpty()) {
852  postParameters.insert(QLatin1String("buildservice"), buildjob.buildServiceId());
853  }
854 
855  return postParameters;
856 }
857 
859 {
860  if (!isValid()) {
861  return nullptr;
862  }
863 
864  StringMap postParameters;
865  postParameters.insert(QLatin1String("dummyparameter"), QLatin1String("dummyvalue"));
866  // qCDebug(ATTICA) << "b....................b";
867  return new PostJob(d->m_internals, createRequest(QLatin1String("buildservice/jobs/cancel/") + job.id()), postParameters);
868 }
869 
871 {
872  if (!isValid()) {
873  return nullptr;
874  }
875 
876  StringMap postParameters;
877  // A postjob won't be run without parameters.
878  // so even while we don't need any in this case,
879  // we add dummy data to the request
880  postParameters.insert(QLatin1String("dummyparameter"), QLatin1String("dummyvalue"));
881  // qCDebug(ATTICA) << "Creating new BSJ on" << job.buildServiceId();
882  return new PostJob(
883  d->m_internals,
884  createRequest(QLatin1String("buildservice/jobs/create/") + job.projectId() + QLatin1Char('/') + job.buildServiceId() + QLatin1Char('/') + job.target()),
885  postParameters);
886 }
887 
889 {
890  if (!isValid()) {
891  return nullptr;
892  }
893 
894  // qCDebug(ATTICA) << "request projects";
895  QUrl url = createUrl(QLatin1String("buildservice/buildservices/list"));
896  return new ListJob<BuildService>(d->m_internals, createRequest(url));
897 }
898 
900 {
901  if (!isValid()) {
902  return nullptr;
903  }
904 
905  QUrl url = createUrl(QLatin1String("buildservice/publishing/getpublishingcapabilities"));
906  // qCDebug(ATTICA) << "request publishers" << url;
907  return new ListJob<Publisher>(d->m_internals, createRequest(url));
908 }
909 
911 {
912  if (!isValid()) {
913  return nullptr;
914  }
915 
916  // qCDebug(ATTICA) << "request projects";
917  QUrl url = createUrl(QLatin1String("buildservice/jobs/list/") + project.id());
918  return new ListJob<BuildServiceJob>(d->m_internals, createRequest(url));
919 }
920 
922 {
923  if (!isValid()) {
924  return nullptr;
925  }
926 
927  // qCDebug(ATTICA) << "request remoteaccounts";
928  QUrl url = createUrl(QLatin1String("buildservice/remoteaccounts/list/"));
929  return new ListJob<RemoteAccount>(d->m_internals, createRequest(url));
930 }
931 
933 {
934  if (!isValid()) {
935  return nullptr;
936  }
937 
938  StringMap postParameters;
939  // A postjob won't be run without parameters.
940  // so even while we don't need any in this case,
941  // we add dummy data to the request
942  postParameters.insert(QLatin1String("login"), account.login());
943  postParameters.insert(QLatin1String("password"), account.password());
944  postParameters.insert(QLatin1String("type"), account.type());
945  postParameters.insert(QLatin1String("typeid"), account.remoteServiceId()); // FIXME: remoteserviceid?
946  postParameters.insert(QLatin1String("data"), account.data());
947  // qCDebug(ATTICA) << "Creating new Remoteaccount" << account.id() << account.login() << account.password();
948  return new PostJob(d->m_internals, createRequest(QLatin1String("buildservice/remoteaccounts/add")), postParameters);
949 }
950 
952 {
953  if (!isValid()) {
954  return nullptr;
955  }
956 
957  StringMap postParameters;
958  // A postjob won't be run without parameters.
959  // so even while we don't need any in this case,
960  // we add dummy data to the request
961  postParameters.insert(QLatin1String("login"), account.login());
962  postParameters.insert(QLatin1String("password"), account.password());
963  postParameters.insert(QLatin1String("type"), account.type());
964  postParameters.insert(QLatin1String("typeid"), account.remoteServiceId()); // FIXME: remoteserviceid?
965  postParameters.insert(QLatin1String("data"), account.data());
966  // qCDebug(ATTICA) << "Creating new Remoteaccount" << account.id() << account.login() << account.password();
967  return new PostJob(d->m_internals, createRequest(QLatin1String("buildservice/remoteaccounts/edit/") + account.id()), postParameters);
968 }
969 
971 {
972  if (!isValid()) {
973  return nullptr;
974  }
975 
976  QUrl url = createUrl(QLatin1String("buildservice/remoteaccounts/get/") + id);
977  // qCDebug(ATTICA) << url;
978  return new ItemJob<RemoteAccount>(d->m_internals, createRequest(url));
979 }
980 
982 {
983  if (!isValid()) {
984  return nullptr;
985  }
986 
987  StringMap postParameters;
988  return new PostJob(d->m_internals, createRequest(QLatin1String("buildservice/remoteaccounts/remove/") + id), postParameters);
989 }
990 
991 PostJob *Provider::uploadTarballToBuildService(const QString &projectId, const QString &fileName, const QByteArray &payload)
992 {
993  if (!isValid()) {
994  return nullptr;
995  }
996 
997  QUrl url = createUrl(QLatin1String("buildservice/project/uploadsource/") + projectId);
998  // qCDebug(ATTICA) << "Up'ing tarball" << url << projectId << fileName << payload;
999  PostFileData postRequest(url);
1000  postRequest.addFile(fileName, payload, QLatin1String("application/octet-stream"), QLatin1String("source"));
1001  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1002 }
1003 
1004 // Activity
1005 
1006 PostJob *Provider::postActivity(const QString &message)
1007 {
1008  if (!isValid()) {
1009  return nullptr;
1010  }
1011 
1012  StringMap postParameters;
1013  postParameters.insert(QLatin1String("message"), message);
1014  return new PostJob(d->m_internals, createRequest(QLatin1String("activity")), postParameters);
1015 }
1016 
1017 PostJob *Provider::inviteFriend(const QString &to, const QString &message)
1018 {
1019  if (!isValid()) {
1020  return nullptr;
1021  }
1022 
1023  StringMap postParameters;
1024  postParameters.insert(QLatin1String("message"), message);
1025  return new PostJob(d->m_internals, createRequest(QLatin1String("friend/invite/") + to), postParameters);
1026 }
1027 
1028 PostJob *Provider::approveFriendship(const QString &to)
1029 {
1030  if (!isValid()) {
1031  return nullptr;
1032  }
1033 
1034  return new PostJob(d->m_internals, createRequest(QLatin1String("friend/approve/") + to));
1035 }
1036 
1037 PostJob *Provider::declineFriendship(const QString &to)
1038 {
1039  if (!isValid()) {
1040  return nullptr;
1041  }
1042 
1043  return new PostJob(d->m_internals, createRequest(QLatin1String("friend/decline/") + to));
1044 }
1045 
1046 PostJob *Provider::cancelFriendship(const QString &to)
1047 {
1048  if (!isValid()) {
1049  return nullptr;
1050  }
1051 
1052  return new PostJob(d->m_internals, createRequest(QLatin1String("friend/cancel/") + to));
1053 }
1054 
1055 PostJob *Provider::postLocation(qreal latitude, qreal longitude, const QString &city, const QString &country)
1056 {
1057  if (!isValid()) {
1058  return nullptr;
1059  }
1060 
1061  StringMap postParameters;
1062  postParameters.insert(QLatin1String("latitude"), QString::number(latitude));
1063  postParameters.insert(QLatin1String("longitude"), QString::number(longitude));
1064  postParameters.insert(QLatin1String("city"), city);
1065  postParameters.insert(QLatin1String("country"), country);
1066  return new PostJob(d->m_internals, createRequest(QLatin1String("person/self")), postParameters);
1067 }
1068 
1069 ListJob<Folder> *Provider::requestFolders()
1070 {
1071  if (!isValid()) {
1072  return nullptr;
1073  }
1074 
1075  return doRequestFolderList(createUrl(QLatin1String("message")));
1076 }
1077 
1078 ListJob<Message> *Provider::requestMessages(const Folder &folder)
1079 {
1080  if (!isValid()) {
1081  return nullptr;
1082  }
1083 
1084  return doRequestMessageList(createUrl(QLatin1String("message/") + folder.id()));
1085 }
1086 
1087 ListJob<Message> *Provider::requestMessages(const Folder &folder, Message::Status status)
1088 {
1089  if (!isValid()) {
1090  return nullptr;
1091  }
1092 
1093  QUrl url = createUrl(QLatin1String("message/") + folder.id());
1094  QUrlQuery q(url);
1095  q.addQueryItem(QStringLiteral("status"), QString::number(status));
1096  url.setQuery(q);
1097  return doRequestMessageList(url);
1098 }
1099 
1100 ItemJob<Message> *Provider::requestMessage(const Folder &folder, const QString &id)
1101 {
1102  if (!isValid()) {
1103  return nullptr;
1104  }
1105 
1106  return new ItemJob<Message>(d->m_internals, createRequest(QLatin1String("message/") + folder.id() + QLatin1Char('/') + id));
1107 }
1108 
1109 PostJob *Provider::postMessage(const Message &message)
1110 {
1111  if (!isValid()) {
1112  return nullptr;
1113  }
1114 
1115  StringMap postParameters;
1116  postParameters.insert(QLatin1String("message"), message.body());
1117  postParameters.insert(QLatin1String("subject"), message.subject());
1118  postParameters.insert(QLatin1String("to"), message.to());
1119  return new PostJob(d->m_internals, createRequest(QLatin1String("message/2")), postParameters);
1120 }
1121 
1123 {
1124  if (!isValid()) {
1125  return nullptr;
1126  }
1127 
1128  const QUrl url = createUrl(QLatin1String("content/categories"));
1129 
1130  // Thread-local cache of categories requests. They are fairly slow and block startup
1132  ListJob<Category> *job = reqs.localData().value(url);
1133  if (!job) {
1134  job = new ListJob<Category>(d->m_internals, createRequest(url));
1135  QObject::connect(job, &BaseJob::finished, [url] {
1136  reqs.localData().remove(url);
1137  });
1138  reqs.localData().insert(url, job);
1139  }
1140  return job;
1141 }
1142 
1144 {
1145  if (!isValid()) {
1146  return nullptr;
1147  }
1148 
1149  QUrl url = createUrl(QLatin1String("content/licenses"));
1150  ListJob<License> *job = new ListJob<License>(d->m_internals, createRequest(url));
1151  return job;
1152 }
1153 
1155 {
1156  if (!isValid()) {
1157  return nullptr;
1158  }
1159 
1160  QUrl url = createUrl(QLatin1String("content/distributions"));
1161  ListJob<Distribution> *job = new ListJob<Distribution>(d->m_internals, createRequest(url));
1162  return job;
1163 }
1164 
1166 {
1167  if (!isValid()) {
1168  return nullptr;
1169  }
1170 
1171  QUrl url = createUrl(QLatin1String("content/homepages"));
1172  ListJob<HomePageType> *job = new ListJob<HomePageType>(d->m_internals, createRequest(url));
1173  return job;
1174 }
1175 
1176 ListJob<Content> *Provider::searchContents(const Category::List &categories, const QString &search, SortMode sortMode, uint page, uint pageSize)
1177 {
1178  return searchContents(categories, QString(), Distribution::List(), License::List(), search, sortMode, page, pageSize);
1179 }
1180 
1182 Provider::searchContentsByPerson(const Category::List &categories, const QString &person, const QString &search, SortMode sortMode, uint page, uint pageSize)
1183 {
1184  return searchContents(categories, person, Distribution::List(), License::List(), search, sortMode, page, pageSize);
1185 }
1186 
1188  const QString &person,
1189  const Distribution::List &distributions,
1190  const License::List &licenses,
1191  const QString &search,
1192  SortMode sortMode,
1193  uint page,
1194  uint pageSize)
1195 {
1196  if (!isValid()) {
1197  return nullptr;
1198  }
1199 
1200  QUrl url = createUrl(QStringLiteral("content/data"));
1201  QUrlQuery q(url);
1202  QStringList categoryIds;
1203  categoryIds.reserve(categories.count());
1204  for (const Category &category : categories) {
1205  categoryIds.append(category.id());
1206  }
1207  q.addQueryItem(QStringLiteral("categories"), categoryIds.join(QLatin1Char('x')));
1208 
1209  QStringList distributionIds;
1210  for (const Distribution &distribution : distributions) {
1211  distributionIds.append(QString::number(distribution.id()));
1212  }
1213  q.addQueryItem(QStringLiteral("distribution"), distributionIds.join(QLatin1Char(',')));
1214 
1215  QStringList licenseIds;
1216  for (const License &license : licenses) {
1217  licenseIds.append(QString::number(license.id()));
1218  }
1219  q.addQueryItem(QStringLiteral("license"), licenseIds.join(QLatin1Char(',')));
1220 
1221  if (!person.isEmpty()) {
1222  q.addQueryItem(QStringLiteral("user"), person);
1223  }
1224 
1225  q.addQueryItem(QStringLiteral("search"), search);
1226  QString sortModeString;
1227  switch (sortMode) {
1228  case Newest:
1229  sortModeString = QLatin1String("new");
1230  break;
1231  case Alphabetical:
1232  sortModeString = QLatin1String("alpha");
1233  break;
1234  case Rating:
1235  sortModeString = QLatin1String("high");
1236  break;
1237  case Downloads:
1238  sortModeString = QLatin1String("down");
1239  break;
1240  }
1241 
1242  if (!sortModeString.isEmpty()) {
1243  q.addQueryItem(QStringLiteral("sortmode"), sortModeString);
1244  }
1245 
1246  q.addQueryItem(QStringLiteral("page"), QString::number(page));
1247  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
1248 
1249  url.setQuery(q);
1250  ListJob<Content> *job = new ListJob<Content>(d->m_internals, createRequest(url));
1251  return job;
1252 }
1253 
1255 {
1256  if (!isValid()) {
1257  return nullptr;
1258  }
1259 
1260  QUrl url = createUrl(QLatin1String("content/data/") + id);
1261  ItemJob<Content> *job = new ItemJob<Content>(d->m_internals, createRequest(url));
1262  return job;
1263 }
1264 
1265 ItemPostJob<Content> *Provider::addNewContent(const Category &category, const Content &cont)
1266 {
1267  if (!isValid() || !category.isValid()) {
1268  return nullptr;
1269  }
1270 
1271  QUrl url = createUrl(QLatin1String("content/add"));
1272  StringMap pars(cont.attributes());
1273 
1274  pars.insert(QLatin1String("type"), category.id());
1275  pars.insert(QLatin1String("name"), cont.name());
1276 
1277  // qCDebug(ATTICA) << "Parameter map: " << pars;
1278 
1279  return new ItemPostJob<Content>(d->m_internals, createRequest(url), pars);
1280 }
1281 
1282 ItemPostJob<Content> *Provider::editContent(const Category &updatedCategory, const QString &contentId, const Content &updatedContent)
1283 {
1284  if (!isValid()) {
1285  return nullptr;
1286  }
1287 
1288  // FIXME I get a server error message here, though the name of the item is changed
1289  QUrl url = createUrl(QLatin1String("content/edit/") + contentId);
1290  StringMap pars(updatedContent.attributes());
1291 
1292  pars.insert(QLatin1String("type"), updatedCategory.id());
1293  pars.insert(QLatin1String("name"), updatedContent.name());
1294 
1295  // qCDebug(ATTICA) << "Parameter map: " << pars;
1296 
1297  return new ItemPostJob<Content>(d->m_internals, createRequest(url), pars);
1298 }
1299 
1300 /*
1301 PostJob* Provider::setDownloadFile(const QString& contentId, QIODevice* payload)
1302 {
1303  QUrl url = createUrl("content/uploaddownload/" + contentId);
1304  PostFileData postRequest(url);
1305  // FIXME mime type
1306  //postRequest.addFile("localfile", payload, "application/octet-stream");
1307  postRequest.addFile("localfile", payload, "image/jpeg");
1308  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1309 }
1310 */
1311 
1312 PostJob *Provider::deleteContent(const QString &contentId)
1313 {
1314  if (!isValid()) {
1315  return nullptr;
1316  }
1317 
1318  QUrl url = createUrl(QLatin1String("content/delete/") + contentId);
1319  PostFileData postRequest(url);
1320  postRequest.addArgument(QLatin1String("contentid"), contentId);
1321  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1322 }
1323 
1324 PostJob *Provider::setDownloadFile(const QString &contentId, const QString &fileName, const QByteArray &payload)
1325 {
1326  if (!isValid()) {
1327  return nullptr;
1328  }
1329 
1330  QUrl url = createUrl(QLatin1String("content/uploaddownload/") + contentId);
1331  PostFileData postRequest(url);
1332  postRequest.addArgument(QLatin1String("contentid"), contentId);
1333  // FIXME mime type
1334  postRequest.addFile(fileName, payload, QLatin1String("application/octet-stream"));
1335  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1336 }
1337 
1338 PostJob *Provider::deleteDownloadFile(const QString &contentId)
1339 {
1340  if (!isValid()) {
1341  return nullptr;
1342  }
1343 
1344  QUrl url = createUrl(QLatin1String("content/deletedownload/") + contentId);
1345  PostFileData postRequest(url);
1346  postRequest.addArgument(QLatin1String("contentid"), contentId);
1347  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1348 }
1349 
1350 PostJob *Provider::setPreviewImage(const QString &contentId, const QString &previewId, const QString &fileName, const QByteArray &image)
1351 {
1352  if (!isValid()) {
1353  return nullptr;
1354  }
1355 
1356  QUrl url = createUrl(QLatin1String("content/uploadpreview/") + contentId + QLatin1Char('/') + previewId);
1357 
1358  PostFileData postRequest(url);
1359  postRequest.addArgument(QLatin1String("contentid"), contentId);
1360  postRequest.addArgument(QLatin1String("previewid"), previewId);
1361  // FIXME mime type
1362  postRequest.addFile(fileName, image, QLatin1String("application/octet-stream"));
1363 
1364  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1365 }
1366 
1367 PostJob *Provider::deletePreviewImage(const QString &contentId, const QString &previewId)
1368 {
1369  if (!isValid()) {
1370  return nullptr;
1371  }
1372 
1373  QUrl url = createUrl(QLatin1String("content/deletepreview/") + contentId + QLatin1Char('/') + previewId);
1374  PostFileData postRequest(url);
1375  postRequest.addArgument(QLatin1String("contentid"), contentId);
1376  postRequest.addArgument(QLatin1String("previewid"), previewId);
1377  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1378 }
1379 
1380 #if ATTICA_BUILD_DEPRECATED_SINCE(0, 2)
1381 PostJob *Provider::voteForContent(const QString &contentId, bool positiveVote)
1382 {
1383  if (!isValid()) {
1384  return nullptr;
1385  }
1386 
1387  StringMap postParameters;
1388  postParameters.insert(QLatin1String("vote"), positiveVote ? QLatin1String("good") : QLatin1String("bad"));
1389  // qCDebug(ATTICA) << "vote: " << positiveVote;
1390  return new PostJob(d->m_internals, createRequest(QLatin1String("content/vote/") + contentId), postParameters);
1391 }
1392 #endif
1393 
1394 PostJob *Provider::voteForContent(const QString &contentId, uint rating)
1395 {
1396  if (!isValid()) {
1397  return nullptr;
1398  }
1399 
1400  // according to OCS API, the rating is 0..100
1401  if (rating > 100) {
1402  qWarning() << "Rating cannot be superior to 100, fallback to 100.";
1403  rating = 100;
1404  }
1405 
1406  StringMap postParameters;
1407  postParameters.insert(QLatin1String("vote"), QString::number(rating));
1408  // qCDebug(ATTICA) << "vote: " << QString::number(rating);
1409  return new PostJob(d->m_internals, createRequest(QLatin1String("content/vote/") + contentId), postParameters);
1410 }
1411 
1412 PostJob *Provider::becomeFan(const QString &contentId)
1413 {
1414  if (!isValid()) {
1415  return nullptr;
1416  }
1417 
1418  QUrl url = createUrl(QLatin1String("fan/add/") + contentId);
1419  PostFileData postRequest(url);
1420  postRequest.addArgument(QLatin1String("contentid"), contentId);
1421  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1422 }
1423 
1424 ListJob<Person> *Provider::requestFans(const QString &contentId, uint page, uint pageSize)
1425 {
1426  if (!isValid()) {
1427  return nullptr;
1428  }
1429 
1430  QUrl url = createUrl(QLatin1String("fan/data/") + contentId);
1431  QUrlQuery q(url);
1432  q.addQueryItem(QStringLiteral("contentid"), contentId);
1433  q.addQueryItem(QStringLiteral("page"), QString::number(page));
1434  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
1435  url.setQuery(q);
1436  ListJob<Person> *job = new ListJob<Person>(d->m_internals, createRequest(url));
1437  return job;
1438 }
1439 
1440 ListJob<Forum> *Provider::requestForums(uint page, uint pageSize)
1441 {
1442  if (!isValid()) {
1443  return nullptr;
1444  }
1445 
1446  QUrl url = createUrl(QStringLiteral("forum/list"));
1447  QUrlQuery q(url);
1448  q.addQueryItem(QStringLiteral("page"), QString::number(page));
1449  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
1450  url.setQuery(q);
1451 
1452  return doRequestForumList(url);
1453 }
1454 
1456 Provider::requestTopics(const QString &forum, const QString &search, const QString &description, Provider::SortMode mode, int page, int pageSize)
1457 {
1458  if (!isValid()) {
1459  return nullptr;
1460  }
1461 
1462  QUrl url = createUrl(QStringLiteral("forum/topics/list"));
1463  QUrlQuery q(url);
1464  q.addQueryItem(QStringLiteral("forum"), forum);
1465  q.addQueryItem(QStringLiteral("search"), search);
1466  q.addQueryItem(QStringLiteral("description"), description);
1467  QString sortModeString;
1468  switch (mode) {
1469  case Newest:
1470  sortModeString = QLatin1String("new");
1471  break;
1472  case Alphabetical:
1473  sortModeString = QLatin1String("alpha");
1474  break;
1475  default:
1476  break;
1477  }
1478  if (!sortModeString.isEmpty()) {
1479  q.addQueryItem(QStringLiteral("sortmode"), sortModeString);
1480  }
1481  q.addQueryItem(QStringLiteral("page"), QString::number(page));
1482  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
1483  url.setQuery(q);
1484 
1485  return doRequestTopicList(url);
1486 }
1487 
1488 PostJob *Provider::postTopic(const QString &forumId, const QString &subject, const QString &content)
1489 {
1490  if (!isValid()) {
1491  return nullptr;
1492  }
1493 
1494  StringMap postParameters;
1495  postParameters.insert(QLatin1String("subject"), subject);
1496  postParameters.insert(QLatin1String("content"), content);
1497  postParameters.insert(QLatin1String("forum"), forumId);
1498  return new PostJob(d->m_internals, createRequest(QLatin1String("forum/topic/add")), postParameters);
1499 }
1500 
1501 ItemJob<DownloadItem> *Provider::downloadLink(const QString &contentId, const QString &itemId)
1502 {
1503  if (!isValid()) {
1504  return nullptr;
1505  }
1506 
1507  QUrl url = createUrl(QLatin1String("content/download/") + contentId + QLatin1Char('/') + itemId);
1508  ItemJob<DownloadItem> *job = new ItemJob<DownloadItem>(d->m_internals, createRequest(url));
1509  return job;
1510 }
1511 
1512 ItemJob<KnowledgeBaseEntry> *Provider::requestKnowledgeBaseEntry(const QString &id)
1513 {
1514  if (!isValid()) {
1515  return nullptr;
1516  }
1517 
1518  QUrl url = createUrl(QLatin1String("knowledgebase/data/") + id);
1519  ItemJob<KnowledgeBaseEntry> *job = new ItemJob<KnowledgeBaseEntry>(d->m_internals, createRequest(url));
1520  return job;
1521 }
1522 
1523 ListJob<KnowledgeBaseEntry> *Provider::searchKnowledgeBase(const Content &content, const QString &search, Provider::SortMode sortMode, int page, int pageSize)
1524 {
1525  if (!isValid()) {
1526  return nullptr;
1527  }
1528 
1529  QUrl url = createUrl(QStringLiteral("knowledgebase/data"));
1530  QUrlQuery q(url);
1531  if (content.isValid()) {
1532  q.addQueryItem(QStringLiteral("content"), content.id());
1533  }
1534 
1535  q.addQueryItem(QStringLiteral("search"), search);
1536  QString sortModeString;
1537  switch (sortMode) {
1538  case Newest:
1539  sortModeString = QLatin1String("new");
1540  break;
1541  case Alphabetical:
1542  sortModeString = QLatin1String("alpha");
1543  break;
1544  case Rating:
1545  sortModeString = QLatin1String("high");
1546  break;
1547  // FIXME: knowledge base doesn't have downloads
1548  case Downloads:
1549  sortModeString = QLatin1String("new");
1550  break;
1551  }
1552  if (!sortModeString.isEmpty()) {
1553  q.addQueryItem(QStringLiteral("sortmode"), sortModeString);
1554  }
1555 
1556  q.addQueryItem(QStringLiteral("page"), QString::number(page));
1557  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
1558  url.setQuery(q);
1559 
1560  ListJob<KnowledgeBaseEntry> *job = new ListJob<KnowledgeBaseEntry>(d->m_internals, createRequest(url));
1561  return job;
1562 }
1563 
1564 ItemJob<Event> *Provider::requestEvent(const QString &id)
1565 {
1566  if (!isValid()) {
1567  return nullptr;
1568  }
1569 
1570  ItemJob<Event> *job = new ItemJob<Event>(d->m_internals, createRequest(QLatin1String("event/data/") + id));
1571  return job;
1572 }
1573 
1574 ListJob<Event> *Provider::requestEvent(const QString &country, const QString &search, const QDate &startAt, Provider::SortMode mode, int page, int pageSize)
1575 {
1576  if (!isValid()) {
1577  return nullptr;
1578  }
1579 
1580  QUrl url = createUrl(QStringLiteral("event/data"));
1581  QUrlQuery q(url);
1582 
1583  if (!search.isEmpty()) {
1584  q.addQueryItem(QStringLiteral("search"), search);
1585  }
1586 
1587  QString sortModeString;
1588  switch (mode) {
1589  case Newest:
1590  sortModeString = QLatin1String("new");
1591  break;
1592  case Alphabetical:
1593  sortModeString = QLatin1String("alpha");
1594  break;
1595  default:
1596  break;
1597  }
1598  if (!sortModeString.isEmpty()) {
1599  q.addQueryItem(QStringLiteral("sortmode"), sortModeString);
1600  }
1601 
1602  if (!country.isEmpty()) {
1603  q.addQueryItem(QStringLiteral("country"), country);
1604  }
1605 
1606  q.addQueryItem(QStringLiteral("startat"), startAt.toString(Qt::ISODate));
1607 
1608  q.addQueryItem(QStringLiteral("page"), QString::number(page));
1609  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
1610  url.setQuery(q);
1611 
1612  ListJob<Event> *job = new ListJob<Event>(d->m_internals, createRequest(url));
1613  return job;
1614 }
1615 
1616 ListJob<Comment> *Provider::requestComments(const Comment::Type commentType, const QString &id, const QString &id2, int page, int pageSize)
1617 {
1618  if (!isValid()) {
1619  return nullptr;
1620  }
1621 
1622  QString commentTypeString;
1623  commentTypeString = Comment::commentTypeToString(commentType);
1624  if (commentTypeString.isEmpty()) {
1625  return nullptr;
1626  }
1627 
1628  QUrl url = createUrl(QLatin1String("comments/data/") + commentTypeString + QLatin1Char('/') + id + QLatin1Char('/') + id2);
1629 
1630  QUrlQuery q(url);
1631  q.addQueryItem(QStringLiteral("page"), QString::number(page));
1632  q.addQueryItem(QStringLiteral("pagesize"), QString::number(pageSize));
1633  url.setQuery(q);
1634 
1635  ListJob<Comment> *job = new ListJob<Comment>(d->m_internals, createRequest(url));
1636  return job;
1637 }
1638 
1639 ItemPostJob<Comment> *Provider::addNewComment(const Comment::Type commentType,
1640  const QString &id,
1641  const QString &id2,
1642  const QString &parentId,
1643  const QString &subject,
1644  const QString &message)
1645 {
1646  if (!isValid()) {
1647  return nullptr;
1648  }
1649 
1650  QString commentTypeString;
1651  commentTypeString = Comment::commentTypeToString(commentType);
1652  if (commentTypeString.isEmpty()) {
1653  return nullptr;
1654  }
1655 
1656  QMap<QString, QString> postParameters;
1657 
1658  postParameters.insert(QLatin1String("type"), commentTypeString);
1659  postParameters.insert(QLatin1String("content"), id);
1660  postParameters.insert(QLatin1String("content2"), id2);
1661  postParameters.insert(QLatin1String("parent"), parentId);
1662  postParameters.insert(QLatin1String("subject"), subject);
1663  postParameters.insert(QLatin1String("message"), message);
1664 
1665  return new ItemPostJob<Comment>(d->m_internals, createRequest(QLatin1String("comments/add")), postParameters);
1666 }
1667 
1668 PostJob *Provider::voteForComment(const QString &id, uint rating)
1669 {
1670  if (!isValid() || (rating > 100)) {
1671  return nullptr;
1672  }
1673 
1674  QMap<QString, QString> postParameters;
1675  postParameters.insert(QLatin1String("vote"), QString::number(rating));
1676 
1677  QUrl url = createUrl(QLatin1String("comments/vote/") + id);
1678  return new PostJob(d->m_internals, createRequest(url), postParameters);
1679 }
1680 
1681 PostJob *Provider::setPrivateData(const QString &app, const QString &key, const QString &value)
1682 {
1683  if (!isValid()) {
1684  return nullptr;
1685  }
1686 
1687  QUrl url = createUrl(QLatin1String("privatedata/setattribute/") + app + QLatin1Char('/') + key);
1688  PostFileData postRequest(url);
1689 
1690  postRequest.addArgument(QLatin1String("value"), value);
1691 
1692  return new PostJob(d->m_internals, postRequest.request(), postRequest.data());
1693 }
1694 
1696 {
1697  if (!isValid()) {
1698  return nullptr;
1699  }
1700 
1701  ItemJob<PrivateData> *job =
1702  new ItemJob<PrivateData>(d->m_internals, createRequest(QLatin1String("privatedata/getattribute/") + app + QLatin1Char('/') + key));
1703  return job;
1704 }
1705 
1706 QUrl Provider::createUrl(const QString &path)
1707 {
1708  QUrl url(d->m_baseUrl.toString() + path);
1709  return url;
1710 }
1711 
1712 QNetworkRequest Provider::createRequest(const QUrl &url)
1713 {
1714  QNetworkRequest request(url);
1715  request.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
1716 
1717  QString agentHeader;
1719  agentHeader = QString::fromLocal8Bit("%1/%2").arg(QCoreApplication::instance()->applicationName(), QCoreApplication::instance()->applicationVersion());
1720  } else {
1721  agentHeader = QString::fromLocal8Bit("Attica/%1").arg(QLatin1String(LIBATTICA_VERSION_STRING));
1722  }
1723  if (!d->m_additionalAgentInformation.isEmpty()) {
1724  agentHeader = QString::fromLocal8Bit("%1 (+%2)").arg(agentHeader, d->m_additionalAgentInformation);
1725  }
1726  request.setHeader(QNetworkRequest::UserAgentHeader, agentHeader);
1727 
1728  if (!d->m_credentialsUserName.isEmpty()) {
1729  request.setAttribute((QNetworkRequest::Attribute)BaseJob::UserAttribute, QVariant(d->m_credentialsUserName));
1730  request.setAttribute((QNetworkRequest::Attribute)BaseJob::PasswordAttribute, QVariant(d->m_credentialsPassword));
1731  }
1732  return request;
1733 }
1734 
1735 QNetworkRequest Provider::createRequest(const QString &path)
1736 {
1737  return createRequest(createUrl(path));
1738 }
1739 
1740 ItemJob<Config> *Provider::doRequestConfig(const QUrl &url)
1741 {
1742  return new ItemJob<Config>(d->m_internals, createRequest(url));
1743 }
1744 
1745 ItemJob<Person> *Provider::doRequestPerson(const QUrl &url)
1746 {
1747  return new ItemJob<Person>(d->m_internals, createRequest(url));
1748 }
1749 
1750 ItemJob<AccountBalance> *Provider::doRequestAccountBalance(const QUrl &url)
1751 {
1752  return new ItemJob<AccountBalance>(d->m_internals, createRequest(url));
1753 }
1754 
1755 ListJob<Person> *Provider::doRequestPersonList(const QUrl &url)
1756 {
1757  return new ListJob<Person>(d->m_internals, createRequest(url));
1758 }
1759 
1760 ListJob<Achievement> *Provider::doRequestAchievementList(const QUrl &url)
1761 {
1762  return new ListJob<Achievement>(d->m_internals, createRequest(url));
1763 }
1764 
1765 ListJob<Activity> *Provider::doRequestActivityList(const QUrl &url)
1766 {
1767  return new ListJob<Activity>(d->m_internals, createRequest(url));
1768 }
1769 
1770 ListJob<Folder> *Provider::doRequestFolderList(const QUrl &url)
1771 {
1772  return new ListJob<Folder>(d->m_internals, createRequest(url));
1773 }
1774 
1775 ListJob<Forum> *Provider::doRequestForumList(const QUrl &url)
1776 {
1777  return new ListJob<Forum>(d->m_internals, createRequest(url));
1778 }
1779 
1780 ListJob<Topic> *Provider::doRequestTopicList(const QUrl &url)
1781 {
1782  return new ListJob<Topic>(d->m_internals, createRequest(url));
1783 }
1784 
1785 ListJob<Message> *Provider::doRequestMessageList(const QUrl &url)
1786 {
1787  return new ListJob<Message>(d->m_internals, createRequest(url));
1788 }
1789 
1791 {
1792  return d->m_achievementVersion;
1793 }
1794 
1796 {
1797  return d->m_activityVersion;
1798 }
1800 {
1801  return d->m_commentVersion;
1802 }
1804 {
1805  return d->m_contentVersion;
1806 }
1808 {
1809  return d->m_fanVersion;
1810 }
1812 {
1813  return d->m_forumVersion;
1814 }
1816 {
1817  return d->m_friendVersion;
1818 }
1820 {
1821  return d->m_knowledgebaseVersion;
1822 }
1824 {
1825  return d->m_messageVersion;
1826 }
1828 {
1829  return d->m_personVersion;
1830 }
1831 
1833 {
1834  return !d->m_achievementVersion.isEmpty();
1835 }
1836 
1838 {
1839  return !d->m_activityVersion.isEmpty();
1840 }
1842 {
1843  return !d->m_commentVersion.isEmpty();
1844 }
1846 {
1847  return !d->m_contentVersion.isEmpty();
1848 }
1850 {
1851  return !d->m_fanVersion.isEmpty();
1852 }
1854 {
1855  return !d->m_forumVersion.isEmpty();
1856 }
1858 {
1859  return !d->m_friendVersion.isEmpty();
1860 }
1862 {
1863  return !d->m_knowledgebaseVersion.isEmpty();
1864 }
1866 {
1867  return !d->m_messageVersion.isEmpty();
1868 }
1870 {
1871  return !d->m_personVersion.isEmpty();
1872 }
bool hasAchievementService() const
Test if the server supports the achievement part of the API.
Definition: provider.cpp:1832
void append(const T &value)
bool hasContentService() const
Test if the server supports the content part of the API.
Definition: provider.cpp:1845
bool isNull() const const
PostJob * createBuildServiceJob(const BuildServiceJob &job)
Create a new job for a given project on a given buildservice for a given target.
Definition: provider.cpp:870
ItemJob< BuildService > * requestBuildService(const QString &id)
Get the information for a specific build service instance.
Definition: provider.cpp:764
bool hasActivityService() const
Test if the server supports the activity part of the API.
Definition: provider.cpp:1837
QString number(int n, int base)
bool hasPersonService() const
Test if the server supports the person part of the API.
Definition: provider.cpp:1869
PostJob * setPreviewImage(const QString &contentId, const QString &previewId, const QString &fileName, const QByteArray &image)
Upload an image file as preview for the content.
Definition: provider.cpp:1350
bool isEnabled() const
Test if the provider is enabled by the settings.
Definition: provider.cpp:312
QUrl baseUrl() const
A url that identifies this provider.
Definition: provider.cpp:302
PutJob * editAchievement(const QString &contentId, const QString &achievementId, const Achievement &achievement)
Post modifications to an Achievement on the server.
Definition: provider.cpp:592
int count(const T &value) const const
void addQueryItem(const QString &key, const QString &value)
PostJob * createProject(const Project &project)
Post modifications to a Project on the server.
Definition: provider.cpp:737
QString id() const
Gets the id of the Folder.
Definition: folder.cpp:52
KI18NLOCALEDATA_EXPORT KCountry country(const char *ianaId)
QString fanServiceVersion() const
Version of the fan part of the API.
Definition: provider.cpp:1807
QString activityServiceVersion() const
Version of the activity part of the API.
Definition: provider.cpp:1795
QString id() const
Gets the id of the Content.
Definition: content.cpp:64
ListJob< Distribution > * requestDistributions()
Get a list of distributions (such as Ark, Debian)
Definition: provider.cpp:1154
ItemJob< Publisher > * requestPublisher(const QString &id)
Get the information for a specific publisher.
Definition: provider.cpp:774
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
ItemJob< BuildServiceJobOutput > * requestBuildServiceJobOutput(const QString &id)
Get the build output for a specific build service job.
Definition: provider.cpp:816
QString personServiceVersion() const
Version of the person part of the API.
Definition: provider.cpp:1827
PostJob * createRemoteAccount(const RemoteAccount &account)
Create a new remote account, an account for a build service instance which is stored in the OCS servi...
Definition: provider.cpp:932
ListJob< Content > * searchContentsByPerson(const Category::List &categories, const QString &person, const QString &search=QString(), SortMode mode=Rating, uint page=0, uint pageSize=10)
Request a list of Contents.
Definition: provider.cpp:1182
void reserve(int alloc)
PostJob * savePublisherField(const Project &project, const PublisherField &field)
Save the value of a single publishing field.
Definition: provider.cpp:785
QMap::iterator insert(const Key &key, const T &value)
QString name() const
Gets the name of the Content.
Definition: content.cpp:74
ItemPostJob< Achievement > * addNewAchievement(const QString &id, const Achievement &newAchievement)
Add a new achievement.
Definition: provider.cpp:560
QString additionalAgentInformation() const
The custom identifier sent along with requests.
Definition: provider.cpp:335
QString name() const
A name for the provider that can be displayed to the user.
Definition: provider.cpp:340
ItemJob< Project > * requestProject(const QString &id)
Get a Project's data.
Definition: provider.cpp:690
QString fromLocal8Bit(const char *str, int size)
ListJob< RemoteAccount > * requestRemoteAccounts()
Get a list of remote accounts, account for a build service instance which is stored in the OCS servic...
Definition: provider.cpp:921
bool hasCredentials() const
Test if the provider has user name/password available.
Definition: provider.cpp:350
bool isEmpty() const const
ItemJob< PrivateData > * requestPrivateData()
Fetches all stored private data.
Definition: provider.h:326
QString contentServiceVersion() const
Version of the content part of the API.
Definition: provider.cpp:1803
ItemJob< Config > * requestConfig()
Fetches server config.
Definition: provider.cpp:407
ListJob< License > * requestLicenses()
Get a list of licenses (such as GPL)
Definition: provider.cpp:1143
QUrl icon() const
An icon used to visually identify this provider.
Definition: provider.cpp:345
bool hasForumService() const
Test if the server supports the forum part of the API.
Definition: provider.cpp:1853
PostJob * editProject(const Project &project)
Post modifications to a Project on the server.
Definition: provider.cpp:746
ListJob< HomePageType > * requestHomePageTypes()
Get a list of home page types (such as blog, Facebook)
Definition: provider.cpp:1165
bool isEmpty() const const
bool hasKnowledgebaseService() const
Test if the server supports the knowledgebase part of the API.
Definition: provider.cpp:1861
ListJob< Achievement > * requestAchievements(const QString &contentId, const QString &achievementId, const QString &userId)
Get a list of achievements.
Definition: provider.cpp:547
QCoreApplication * instance()
PostJob * checkLogin(const QString &user, const QString &password)
Test if the server accepts the login/password.
Definition: provider.cpp:393
Q_SCRIPTABLE CaptureState status()
bool isEmpty() const const
QString toLocalFile() const const
AKONADI_CALENDAR_EXPORT KCalendarCore::Event::Ptr event(const Akonadi::Item &item)
DeleteJob * deleteAchievement(const QString &contentId, const QString &achievementId)
Deletes an achievement on the server.
Definition: provider.cpp:628
bool hasFanService() const
Test if the server supports the fan part of the API.
Definition: provider.cpp:1849
ListJob< BuildServiceJob > * requestBuildServiceJobs(const Project &project)
Get a list of build service projects.
Definition: provider.cpp:910
QString achievementServiceVersion() const
Version of the achievement part of the API.
Definition: provider.cpp:1790
QString join(const QString &separator) const const
QString friendServiceVersion() const
Version of the friend part of the API.
Definition: provider.cpp:1815
bool hasFriendService() const
Test if the server supports the friend part of the API.
Definition: provider.cpp:1857
bool loadCredentials(QString &user, QString &password)
Load user name and password from the store.
Definition: provider.cpp:368
bool hasMessageService() const
Test if the server supports the message part of the API.
Definition: provider.cpp:1865
ListJob< Content > * searchContents(const Category::List &categories, const QString &search=QString(), SortMode mode=Rating, uint page=0, uint pageSize=10)
Request a list of Contents.
Definition: provider.cpp:1176
void setQuery(const QString &query, QUrl::ParsingMode mode)
QString forumServiceVersion() const
Version of the forum part of the API.
Definition: provider.cpp:1811
QString messageServiceVersion() const
Version of the message part of the API.
Definition: provider.cpp:1823
ItemPostJob< Comment > * addNewComment(const Comment::Type commentType, const QString &id, const QString &id2, const QString &parentId, const QString &subject, const QString &message)
Add a new comment.
Definition: provider.cpp:1639
PostJob * publishBuildJob(const BuildServiceJob &buildjob, const Publisher &publisher)
Publish the result of a completed build job to a publisher.
Definition: provider.cpp:801
ListJob< Project > * requestProjects()
Get a list of build service projects.
Definition: provider.cpp:679
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
ListJob< Publisher > * requestPublishers()
Get a list of publishers.
Definition: provider.cpp:899
QString fromLatin1(const char *str, int size)
ItemJob< Content > * requestContent(const QString &contentId)
Retrieve a single content.
Definition: provider.cpp:1254
PostJob * deleteRemoteAccount(const QString &id)
Deletes a remote account stored on the OCS server.
Definition: provider.cpp:981
const char * name(StandardAction id)
bool hasCommentService() const
Test if the server supports the comments part of the API.
Definition: provider.cpp:1841
bool saveCredentials(const QString &user, const QString &password)
Sets (and remembers) user name and password for this provider.
Definition: provider.cpp:382
QString toString(Qt::DateFormat format) const const
PostJob * voteForComment(const QString &id, uint rating)
Vote a comment item.
Definition: provider.cpp:1668
PostJob * cancelBuildServiceJob(const BuildServiceJob &job)
Cancel a job.
Definition: provider.cpp:858
The Attica namespace,.
bool isValid() const
Returns true if the provider has been set up and can be used.
Definition: provider.cpp:307
PostJob * deleteProject(const Project &project)
Deletes a project on the server.
Definition: provider.cpp:755
PostJob * editRemoteAccount(const RemoteAccount &account)
Edit an existing remote account.
Definition: provider.cpp:951
bool isValid() const
Checks whether this Content has an id.
Definition: content.cpp:144
Attica::PostJob * uploadTarballToBuildService(const QString &projectId, const QString &fileName, const QByteArray &payload)
Upload a tarball to the buildservice.
Definition: provider.cpp:991
QString knowledgebaseServiceVersion() const
Version of the knowledgebase part of the API.
Definition: provider.cpp:1819
QMap< QString, QString > attributes() const
Get all attributes that are not included in the basis set of attributes exposed by the Content class.
Definition: content.cpp:139
ListJob< BuildService > * requestBuildServices()
Get a list of build service build services.
Definition: provider.cpp:888
QString toString(Qt::DateFormat format) const const
ListJob< Comment > * requestComments(const Comment::Type commentType, const QString &id, const QString &id2, int page, int pageSize)
Request a list of comments for a content / forum / knowledgebase / event.
Definition: provider.cpp:1616
ListJob< Category > * requestCategories()
Get a list of categories (such as wallpaper)
Definition: provider.cpp:1122
QString message
ItemJob< BuildServiceJob > * requestBuildServiceJob(const QString &id)
Get the information for a specific build service job, such as status and progress.
Definition: provider.cpp:827
QString commentServiceVersion() const
Version of the comments part of the API.
Definition: provider.cpp:1799
PostJob * voteForContent(const QString &contentId, bool positiveVote)
Vote for a content item This version is for the old OCS API < 1.6.
Definition: provider.cpp:1381
void setAdditionalAgentInformation(const QString &additionalInformation)
Set a custom identifier for your application (sent along with the requests as the http agent header i...
Definition: provider.cpp:330
PostJob * setPrivateData(const QString &app, const QString &key, const QString &value)
Sets the value of an attribute.
Definition: provider.cpp:1681
QString toString() const const
ItemJob< RemoteAccount > * requestRemoteAccount(const QString &id)
Get a remote account by its ID.
Definition: provider.cpp:970
QString id() const
Gets the id of the Category.
Definition: category.cpp:49
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Dec 11 2023 04:05:13 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.