File indexing completed on 2024-05-12 04:57:44

0001 /*
0002     This file is part of Choqok, the KDE micro-blogging client
0003 
0004     SPDX-FileCopyrightText: 2010-2012 Andrey Esin <gmlastik@gmail.com>
0005 
0006     SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0007 */
0008 
0009 #include "posterous.h"
0010 
0011 #include <QDebug>
0012 #include <QJsonDocument>
0013 
0014 #include <KIO/StoredTransferJob>
0015 #include <KPluginFactory>
0016 
0017 #include "accountmanager.h"
0018 #include "mediamanager.h"
0019 #include "passwordmanager.h"
0020 
0021 #include "twitterapiaccount.h"
0022 #include "twitterapimicroblog.h"
0023 
0024 #include "posteroussettings.h"
0025 
0026 K_PLUGIN_CLASS_WITH_JSON(Posterous, "choqok_posterous.json")
0027 
0028 Posterous::Posterous(QObject *parent, const QList<QVariant> &)
0029     : Choqok::Uploader(QLatin1String("choqok_posterous"), parent)
0030 {
0031 }
0032 
0033 Posterous::~Posterous()
0034 {
0035 }
0036 
0037 QString Posterous::getAuthToken(const QUrl &localUrl)
0038 {
0039     QUrl url(QLatin1String("http://posterous.com/api/2/auth/token"));
0040     QString login = PosterousSettings::login();
0041     QString pass = Choqok::PasswordManager::self()->readPassword(QStringLiteral("posterous_%1").arg(PosterousSettings::login()));
0042     KIO::StoredTransferJob *job = KIO::storedGet(url, KIO::Reload, KIO::HideProgressInfo);
0043     job->addMetaData(QLatin1String("customHTTPHeader"),
0044                      QLatin1String("Authorization: Basic ") + QLatin1String(QStringLiteral("%1:%2").arg(login).arg(pass).toUtf8().toBase64()));
0045     job->exec();
0046     if (!job->error()) {
0047         const QByteArray data = job->data();
0048         const QJsonDocument json = QJsonDocument::fromJson(data);
0049         if (!json.isNull()) {
0050             QVariantMap map = json.toVariant().toMap();
0051             if (map.contains(QLatin1String("api_token"))) {
0052                 QString tkn = map.value(QLatin1String("api_token")).toString();
0053                 return tkn;
0054             } else {
0055                 Q_EMIT uploadingFailed(localUrl, map.value(QLatin1String("error")).toString());
0056                 qWarning() << "Parse error:" << data;
0057             }
0058         }
0059     } else {
0060         qCritical() << "Job error:" << job->errorString();
0061     }
0062 
0063     return QString();
0064 }
0065 
0066 void Posterous::upload(const QUrl &localUrl, const QByteArray &medium, const QByteArray &mediumType)
0067 {
0068     PosterousSettings::self()->load();
0069     KIO::StoredTransferJob *job = nullptr;
0070     if (PosterousSettings::basic()) {
0071         QString login = PosterousSettings::login();
0072         QString pass = Choqok::PasswordManager::self()->readPassword(QStringLiteral("posterous_%1").arg(PosterousSettings::login()));
0073         QString token = getAuthToken(localUrl);
0074         if (!token.isEmpty()) {
0075             QUrl url(QLatin1String("http://posterous.com/api/2/users/me/sites/primary/posts"));
0076             QMap<QString, QByteArray> formdata;
0077             formdata[QLatin1String("post[title]")] = QByteArray();
0078             formdata[QLatin1String("post[body]")] = QByteArray();
0079             formdata[QLatin1String("autopost")] = "0";
0080             formdata[QLatin1String("source")] = QCoreApplication::applicationName().toLatin1();
0081             formdata[QLatin1String("api_token")] = token.toUtf8();
0082 
0083             QMap<QString, QByteArray> mediafile;
0084             mediafile[QLatin1String("name")] = "media";
0085             mediafile[QLatin1String("filename")] = localUrl.fileName().toUtf8();
0086             mediafile[QLatin1String("mediumType")] = mediumType;
0087             mediafile[QLatin1String("medium")] = medium;
0088             QList< QMap<QString, QByteArray> > listMediafiles;
0089             listMediafiles.append(mediafile);
0090 
0091             QByteArray data = Choqok::MediaManager::createMultipartFormData(formdata, listMediafiles);
0092             job = KIO::storedHttpPost(data, url, KIO::HideProgressInfo);
0093             job->addMetaData(QLatin1String("customHTTPHeader"),
0094                              QLatin1String("Authorization: Basic ") +
0095                              QLatin1String(QStringLiteral("%1:%2").arg(login).arg(pass).toUtf8().toBase64()));
0096         }
0097     } else if (PosterousSettings::oauth()) {
0098         QString alias = PosterousSettings::alias();
0099         if (alias.isEmpty()) {
0100             qCritical() << "No account to use";
0101             Q_EMIT uploadingFailed(localUrl, i18n("There is no Twitter account configured to use."));
0102             return;
0103         }
0104         TwitterApiAccount *acc = qobject_cast<TwitterApiAccount *> (Choqok::AccountManager::self()->findAccount(alias));
0105         if (!acc) {
0106             return;
0107         }
0108 
0109         QUrl url(QLatin1String("http://posterous.com/api2/upload.json"));
0110 
0111         QMap<QString, QByteArray> formdata;
0112         formdata[QLatin1String("source")] = QCoreApplication::applicationName().toLatin1();
0113         formdata[QLatin1String("sourceLink")] = "https://choqok.kde.org/";
0114 
0115         QMap<QString, QByteArray> mediafile;
0116         mediafile[QLatin1String("name")] = "media";
0117         mediafile[QLatin1String("filename")] = localUrl.fileName().toUtf8();
0118         mediafile[QLatin1String("mediumType")] = mediumType;
0119         mediafile[QLatin1String("medium")] = medium;
0120         QList< QMap<QString, QByteArray> > listMediafiles;
0121         listMediafiles.append(mediafile);
0122 
0123         QByteArray data = Choqok::MediaManager::createMultipartFormData(formdata, listMediafiles);
0124 
0125         KIO::StoredTransferJob *job = KIO::storedHttpPost(data, url, KIO::HideProgressInfo);
0126         QUrl requrl(QLatin1String("https://api.twitter.com/1/account/verify_credentials.json"));
0127         QByteArray credentials = acc->oauthInterface()->authorizationHeader(requrl, QNetworkAccessManager::GetOperation);
0128 
0129         QString cHeader = QLatin1String("X-Verify-Credentials-Authorization: ") +  QLatin1String(credentials) + QLatin1String("\r\n");
0130         cHeader.append(QLatin1String("X-Auth-Service-Provider: https://api.twitter.com/1/account/verify_credentials.json"));
0131         job->addMetaData(QLatin1String("customHTTPHeader"), cHeader);
0132     }
0133     if (!job) {
0134         qCritical() << "Cannot create a http POST request!";
0135         return;
0136     }
0137     job->addMetaData(QStringLiteral("content-type"),
0138                      QStringLiteral("Content-Type: multipart/form-data; boundary=AaB03x"));
0139     mUrlMap[job] = localUrl;
0140     connect(job, &KIO::StoredTransferJob::result, this, &Posterous::slotUpload);
0141     job->start();
0142 }
0143 
0144 void Posterous::slotUpload(KJob *job)
0145 {
0146     QUrl localUrl = mUrlMap.take(job);
0147     if (job->error()) {
0148         qCritical() << "Job Error:" << job->errorString();
0149         Q_EMIT uploadingFailed(localUrl, job->errorString());
0150         return;
0151     } else {
0152         KIO::StoredTransferJob *stj = qobject_cast<KIO::StoredTransferJob *>(job);
0153         //qDebug() << stj->data();
0154         const QJsonDocument json = QJsonDocument::fromJson(stj->data());
0155         if (!json.isNull()) {
0156             const QVariantMap map = json.toVariant().toMap();
0157             if (map.contains(QLatin1String("error"))) {
0158                 Q_EMIT uploadingFailed(localUrl, map.value(QLatin1String("error")).toString());
0159             } else {
0160                 if (PosterousSettings::oauth()) {
0161                     Q_EMIT mediumUploaded(localUrl, map.value(QLatin1String("url")).toString());
0162                 }
0163                 if (PosterousSettings::basic()) {
0164                     Q_EMIT mediumUploaded(localUrl, map.value(QLatin1String("full_url")).toString());
0165                 }
0166             }
0167         } else {
0168             Q_EMIT uploadingFailed(localUrl, i18n("Malformed response"));
0169             qWarning() << "Parse error:" << stj->data();
0170         }
0171     }
0172 }
0173 
0174 #include "moc_posterous.cpp"
0175 #include "posterous.moc"