1/*
2 SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
3
4 SPDX-License-Identifier: LGPL-2.1-or-later
5*/
6
7#include "mpform.h"
8#include <KIO/StoredTransferJob>
9#include <KIO/TransferJob>
10#include <KJob>
11#include <KLocalizedString>
12#include <KNotification>
13#include <KPluginFactory>
14#include <QClipboard>
15#include <QDebug>
16#include <QGuiApplication>
17#include <QJsonArray>
18#include <QJsonDocument>
19#include <QJsonObject>
20#include <QStandardPaths>
21#include <purpose/pluginbase.h>
22
23Q_GLOBAL_STATIC_WITH_ARGS(const QUrl, imageImgurUrl, (QLatin1String("https://api.imgur.com/3/image")))
24Q_GLOBAL_STATIC_WITH_ARGS(const QUrl, albumImgurUrl, (QLatin1String("https://api.imgur.com/3/album")))
25
26// key associated with aleixpol@kde.org
27Q_GLOBAL_STATIC_WITH_ARGS(const QString, YOUR_CLIENT_ID, (QLatin1String("0bffa5b4ac8383c")))
28
29class ImgurShareJob : public Purpose::Job
30{
31 Q_OBJECT
32public:
33 explicit ImgurShareJob(QObject *parent)
34 : Purpose::Job(parent)
35 , m_pendingJobs(0)
36 {
37 }
38
39 void start() override
40 {
41 m_pendingJobs = 0;
42 const QJsonArray urls = data().value(key: QLatin1String("urls")).toArray();
43 if (urls.isEmpty()) {
44 qWarning() << "no urls to share" << urls << data();
45 emitResult();
46 return;
47 }
48
49 if (urls.count() > 1) {
50 KIO::TransferJob *tJob = KIO::storedHttpPost(arr: "", url: *albumImgurUrl, flags: KIO::HideProgressInfo);
51 tJob->setMetaData(QMap<QString, QString>{{QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: Client-ID ") + *YOUR_CLIENT_ID}});
52 connect(sender: tJob, signal: &KJob::result, context: this, slot: &ImgurShareJob::albumCreated);
53 } else {
54 startUploading();
55 }
56 }
57
58 QJsonObject processResponse(KJob *job)
59 {
60 KIO::StoredTransferJob *sjob = qobject_cast<KIO::StoredTransferJob *>(object: job);
61 QJsonParseError error;
62 const QJsonObject resultMap = QJsonDocument::fromJson(json: sjob->data(), error: &error).object();
63 if (sjob->isErrorPage()) {
64 setError(3);
65 setErrorText(i18n("Error page returned"));
66 } else if (job->error()) {
67 setError(job->error());
68 setErrorText(job->errorText());
69 } else if (error.error) {
70 setError(1);
71 setErrorText(error.errorString());
72 } else if (!resultMap.value(key: QLatin1String("success")).toBool()) {
73 setError(2);
74 const QJsonObject dataMap = resultMap[QLatin1String("data")].toObject();
75 setErrorText(dataMap[QLatin1String("error")].toString());
76 } else {
77 return resultMap[QLatin1String("data")].toObject();
78 }
79 emitResult();
80 return {};
81 }
82
83 void albumCreated(KJob *job)
84 {
85 const QJsonObject dataMap = processResponse(job);
86 if (!dataMap.isEmpty()) {
87 m_albumId = dataMap[QLatin1String("id")].toString();
88 m_albumDeleteHash = dataMap[QLatin1String("deletehash")].toString();
89 startUploading();
90 }
91 }
92
93 void startUploading()
94 {
95 Q_EMIT infoMessage(job: this, i18n("Uploading files to imgur..."));
96 const QJsonArray urls = data().value(key: QLatin1String("urls")).toArray();
97 for (const QJsonValue &val : urls) {
98 QString u = val.toString();
99 KIO::StoredTransferJob *job = KIO::storedGet(url: QUrl(u));
100 connect(sender: job, signal: &KJob::finished, context: this, slot: &ImgurShareJob::fileFetched);
101 m_pendingJobs++;
102 }
103 }
104
105 void fileFetched(KJob *j)
106 {
107 if (j->error()) {
108 setError(j->error());
109 setErrorText(j->errorText());
110 emitResult();
111
112 qDebug() << "error:" << j->errorText() << j->errorString();
113
114 return;
115 }
116
117 MPForm form;
118 KIO::StoredTransferJob *job = qobject_cast<KIO::StoredTransferJob *>(object: j);
119 form.addFile(QStringLiteral("image"), filePath: job->url(), fileData: job->data());
120 form.addPair(QStringLiteral("album"), value: m_albumDeleteHash, type: {});
121 form.finish();
122
123 KIO::StoredTransferJob *tJob = KIO::storedHttpPost(arr: form.formData(), url: *imageImgurUrl, flags: KIO::HideProgressInfo);
124 tJob->setMetaData(QMap<QString, QString>{
125 {QStringLiteral("content-type"), QString::fromLocal8Bit(ba: form.contentType())},
126 {QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: Client-ID ") + *YOUR_CLIENT_ID},
127 });
128 connect(sender: tJob, signal: &KJob::result, context: this, slot: &ImgurShareJob::imageUploaded);
129 }
130
131 void imageUploaded(KJob *job)
132 {
133 const QJsonObject dataMap = processResponse(job);
134 if (!dataMap.isEmpty()) {
135 const QString url = dataMap[QStringLiteral("link")].toString();
136 Q_EMIT infoMessage(job: this, message: url);
137 const QString deletehash = dataMap[QStringLiteral("deletehash")].toString();
138 Q_EMIT infoMessage(job: this, message: deletehash);
139 --m_pendingJobs;
140
141 if (m_pendingJobs == 0) {
142 const QString finalUrl = m_albumId.isEmpty() ? url : QStringLiteral("https://imgur.com/a/") + m_albumId;
143 const QString deleteUrl = QStringLiteral("https://imgur.com/delete/") + deletehash;
144
145 QGuiApplication::clipboard()->setText(url);
146 KNotification::event(eventId: KNotification::Notification,
147 i18n("Imgur Upload"),
148 i18n("The shared image link (<a href=\"%1\">%1</a>) has been copied to the clipboard.<br><br>If you would like to remove "
149 "the uploaded image, visit <a href=\"%2\">%2</a>",
150 finalUrl,
151 deleteUrl),
152 flags: KNotification::Persistent);
153
154 emitResult();
155 }
156 }
157 }
158
159private:
160 QString m_albumId;
161 QString m_albumDeleteHash;
162 int m_pendingJobs;
163};
164
165class ImgurPlugin : public Purpose::PluginBase
166{
167 Q_OBJECT
168public:
169 using PluginBase::PluginBase;
170 Purpose::Job *createJob() const override
171 {
172 return new ImgurShareJob(nullptr);
173 }
174};
175
176K_PLUGIN_CLASS_WITH_JSON(ImgurPlugin, "imgurplugin.json")
177
178#include "imgurplugin.moc"
179

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of purpose/src/plugins/imgur/imgurplugin.cpp