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"