File indexing completed on 2024-05-19 04:03:03
0001 /* 0002 SPDX-FileCopyrightText: 2014 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "mpform.h" 0008 #include <KIO/StoredTransferJob> 0009 #include <KIO/TransferJob> 0010 #include <KJob> 0011 #include <KLocalizedString> 0012 #include <KNotification> 0013 #include <KPluginFactory> 0014 #include <QClipboard> 0015 #include <QDebug> 0016 #include <QGuiApplication> 0017 #include <QJsonArray> 0018 #include <QJsonDocument> 0019 #include <QJsonObject> 0020 #include <QStandardPaths> 0021 #include <purpose/pluginbase.h> 0022 0023 Q_GLOBAL_STATIC_WITH_ARGS(const QUrl, imageImgurUrl, (QLatin1String("https://api.imgur.com/3/image"))) 0024 Q_GLOBAL_STATIC_WITH_ARGS(const QUrl, albumImgurUrl, (QLatin1String("https://api.imgur.com/3/album"))) 0025 0026 // key associated with aleixpol@kde.org 0027 Q_GLOBAL_STATIC_WITH_ARGS(const QString, YOUR_CLIENT_ID, (QLatin1String("0bffa5b4ac8383c"))) 0028 0029 class ImgurShareJob : public Purpose::Job 0030 { 0031 Q_OBJECT 0032 public: 0033 explicit ImgurShareJob(QObject *parent) 0034 : Purpose::Job(parent) 0035 , m_pendingJobs(0) 0036 { 0037 } 0038 0039 void start() override 0040 { 0041 m_pendingJobs = 0; 0042 const QJsonArray urls = data().value(QLatin1String("urls")).toArray(); 0043 if (urls.isEmpty()) { 0044 qWarning() << "no urls to share" << urls << data(); 0045 emitResult(); 0046 return; 0047 } 0048 0049 if (urls.count() > 1) { 0050 KIO::TransferJob *tJob = KIO::storedHttpPost("", *albumImgurUrl, KIO::HideProgressInfo); 0051 tJob->setMetaData(QMap<QString, QString>{{QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: Client-ID ") + *YOUR_CLIENT_ID}}); 0052 connect(tJob, &KJob::result, this, &ImgurShareJob::albumCreated); 0053 } else { 0054 startUploading(); 0055 } 0056 } 0057 0058 QJsonObject processResponse(KJob *job) 0059 { 0060 KIO::StoredTransferJob *sjob = qobject_cast<KIO::StoredTransferJob *>(job); 0061 QJsonParseError error; 0062 const QJsonObject resultMap = QJsonDocument::fromJson(sjob->data(), &error).object(); 0063 if (sjob->isErrorPage()) { 0064 setError(3); 0065 setErrorText(i18n("Error page returned")); 0066 } else if (job->error()) { 0067 setError(job->error()); 0068 setErrorText(job->errorText()); 0069 } else if (error.error) { 0070 setError(1); 0071 setErrorText(error.errorString()); 0072 } else if (!resultMap.value(QLatin1String("success")).toBool()) { 0073 setError(2); 0074 const QJsonObject dataMap = resultMap[QLatin1String("data")].toObject(); 0075 setErrorText(dataMap[QLatin1String("error")].toString()); 0076 } else { 0077 return resultMap[QLatin1String("data")].toObject(); 0078 } 0079 emitResult(); 0080 return {}; 0081 } 0082 0083 void albumCreated(KJob *job) 0084 { 0085 const QJsonObject dataMap = processResponse(job); 0086 if (!dataMap.isEmpty()) { 0087 m_albumId = dataMap[QLatin1String("id")].toString(); 0088 m_albumDeleteHash = dataMap[QLatin1String("deletehash")].toString(); 0089 startUploading(); 0090 } 0091 } 0092 0093 void startUploading() 0094 { 0095 Q_EMIT infoMessage(this, i18n("Uploading files to imgur...")); 0096 const QJsonArray urls = data().value(QLatin1String("urls")).toArray(); 0097 for (const QJsonValue &val : urls) { 0098 QString u = val.toString(); 0099 KIO::StoredTransferJob *job = KIO::storedGet(QUrl(u)); 0100 connect(job, &KJob::finished, this, &ImgurShareJob::fileFetched); 0101 m_pendingJobs++; 0102 } 0103 } 0104 0105 void fileFetched(KJob *j) 0106 { 0107 if (j->error()) { 0108 setError(j->error()); 0109 setErrorText(j->errorText()); 0110 emitResult(); 0111 0112 qDebug() << "error:" << j->errorText() << j->errorString(); 0113 0114 return; 0115 } 0116 0117 MPForm form; 0118 KIO::StoredTransferJob *job = qobject_cast<KIO::StoredTransferJob *>(j); 0119 form.addFile(QStringLiteral("image"), job->url(), job->data()); 0120 form.addPair(QStringLiteral("album"), m_albumDeleteHash, {}); 0121 form.finish(); 0122 0123 KIO::StoredTransferJob *tJob = KIO::storedHttpPost(form.formData(), *imageImgurUrl, KIO::HideProgressInfo); 0124 tJob->setMetaData(QMap<QString, QString>{ 0125 {QStringLiteral("content-type"), QString::fromLocal8Bit(form.contentType())}, 0126 {QStringLiteral("customHTTPHeader"), QStringLiteral("Authorization: Client-ID ") + *YOUR_CLIENT_ID}, 0127 }); 0128 connect(tJob, &KJob::result, this, &ImgurShareJob::imageUploaded); 0129 } 0130 0131 void imageUploaded(KJob *job) 0132 { 0133 const QJsonObject dataMap = processResponse(job); 0134 if (!dataMap.isEmpty()) { 0135 const QString url = dataMap[QStringLiteral("link")].toString(); 0136 Q_EMIT infoMessage(this, url); 0137 const QString deletehash = dataMap[QStringLiteral("deletehash")].toString(); 0138 Q_EMIT infoMessage(this, deletehash); 0139 --m_pendingJobs; 0140 0141 if (m_pendingJobs == 0) { 0142 const QString finalUrl = m_albumId.isEmpty() ? url : QStringLiteral("https://imgur.com/a/") + m_albumId; 0143 const QString deleteUrl = QStringLiteral("https://imgur.com/delete/") + deletehash; 0144 0145 QGuiApplication::clipboard()->setText(url); 0146 KNotification::event(KNotification::Notification, 0147 i18n("Imgur Upload"), 0148 i18n("The shared image link (<a href=\"%1\">%1</a>) has been copied to the clipboard.<br><br>If you would like to remove " 0149 "the uploaded image, visit <a href=\"%2\">%2</a>", 0150 finalUrl, 0151 deleteUrl), 0152 KNotification::Persistent); 0153 0154 emitResult(); 0155 } 0156 } 0157 } 0158 0159 private: 0160 QString m_albumId; 0161 QString m_albumDeleteHash; 0162 int m_pendingJobs; 0163 }; 0164 0165 class ImgurPlugin : public Purpose::PluginBase 0166 { 0167 Q_OBJECT 0168 public: 0169 using PluginBase::PluginBase; 0170 Purpose::Job *createJob() const override 0171 { 0172 return new ImgurShareJob(nullptr); 0173 } 0174 }; 0175 0176 K_PLUGIN_CLASS_WITH_JSON(ImgurPlugin, "imgurplugin.json") 0177 0178 #include "imgurplugin.moc"