diff options
Diffstat (limited to 'desktop-widgets/plugins/facebook/facebookconnectwidget.cpp')
-rw-r--r-- | desktop-widgets/plugins/facebook/facebookconnectwidget.cpp | 421 |
1 files changed, 0 insertions, 421 deletions
diff --git a/desktop-widgets/plugins/facebook/facebookconnectwidget.cpp b/desktop-widgets/plugins/facebook/facebookconnectwidget.cpp deleted file mode 100644 index 7a497e218..000000000 --- a/desktop-widgets/plugins/facebook/facebookconnectwidget.cpp +++ /dev/null @@ -1,421 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "facebookconnectwidget.h" - -#include <QJsonDocument> -#include <QJsonArray> -#include <QJsonObject> -#include <QNetworkReply> -#include <QNetworkRequest> -#include <QNetworkAccessManager> -#include <QNetworkCookieJar> - -#include <QUrlQuery> -#include <QHttpMultiPart> -#include <QFile> -#include <QBuffer> -#include <QDebug> -#include <QMessageBox> -#include <QInputDialog> -#include <QLoggingCategory> -#ifdef USE_WEBENGINE -#include <QWebEngineView> -#else -#include <QWebView> -#endif -#include "mainwindow.h" -#include "profile-widget/profilewidget2.h" - -#include "core/pref.h" -#include "core/qthelper.h" -#include "core/settings/qPrefFacebook.h" - -#include "ui_socialnetworksdialog.h" -#include "ui_facebookconnectwidget.h" - -Q_LOGGING_CATEGORY(lcFacebook, "subsurface.facebook") - -FacebookManager *FacebookManager::instance() -{ - static FacebookManager *self = new FacebookManager(); - return self; -} - -FacebookManager::FacebookManager(QObject *parent) : - QObject(parent), - manager(new QNetworkAccessManager(this)) -{ - // log only in verbose mode - QLoggingCategory::setFilterRules(QStringLiteral("subsurface.facebook=%1").arg(verbose ? "true" : "false")); - connect(this, &FacebookManager::albumIdReceived, this, &FacebookManager::sendDiveToAlbum); -} - -static QString graphApi = QStringLiteral("https://graph.facebook.com/v2.10/"); - -QUrl FacebookManager::albumListUrl() -{ - return QUrl("https://graph.facebook.com/me/albums?access_token=" + QString(prefs.facebook.access_token)); -} - -QUrl FacebookManager::connectUrl() { - return QUrl("https://www.facebook.com/dialog/oauth?" - "client_id=427722490709000" - "&redirect_uri=https://www.facebook.com/connect/login_success.html" - "&response_type=token,granted_scopes" - "&display=popup" - "&scope=publish_actions,user_photos" - ); -} - -bool FacebookManager::loggedIn() { - return prefs.facebook.access_token != NULL; -} - -void FacebookManager::tryLogin(const QUrl& loginResponse) -{ - qCDebug(lcFacebook) << "Current url call" << loginResponse; - QString result = loginResponse.toString(); - if (!result.contains("access_token")) { - qCDebug(lcFacebook) << "Response without access token!"; - return; - } - - if (result.contains("denied_scopes=publish_actions") || result.contains("denied_scopes=user_photos")) { - qCDebug(lcFacebook) << "user did not allow us access" << result; - return; - } - - int from = result.indexOf("access_token=") + strlen("access_token="); - int to = result.indexOf("&expires_in"); - QString securityToken = result.mid(from, to-from); - - qPrefFacebook::set_access_token(securityToken); - qCDebug(lcFacebook) << "Got securityToken" << securityToken; - requestUserId(); -} - -void FacebookManager::logout() -{ - qPrefFacebook::set_access_token(QString()); - qPrefFacebook::set_user_id(QString()); - qPrefFacebook::set_album_id(QString()); - emit justLoggedOut(true); -} - -void FacebookManager::requestAlbumId() -{ - qCDebug(lcFacebook) << "Starting to request the album id" << albumListUrl(); - QNetworkReply *reply = manager->get(QNetworkRequest(albumListUrl())); - connect(reply, &QNetworkReply::finished, this, &FacebookManager::albumListReceived); -} - -void FacebookManager::albumListReceived() -{ - qCDebug(lcFacebook) << "Reply for the album id"; - QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); - QJsonDocument albumsDoc = QJsonDocument::fromJson(reply->readAll()); - QJsonArray albumObj = albumsDoc.object().value("data").toArray(); - - reply->deleteLater(); - foreach(const QJsonValue &v, albumObj){ - QJsonObject obj = v.toObject(); - if (obj.value("name").toString() == fbInfo.albumName) { - qPrefFacebook::set_album_id(obj.value("id").toString()); - qCDebug(lcFacebook) << "Album" << fbInfo.albumName << "already exists, using id" << obj.value("id").toString(); - emit albumIdReceived(qPrefFacebook::album_id()); - return; - } - } - - // No album with the name we requested, create a new one. - createFacebookAlbum(); -} - -void FacebookManager::createFacebookAlbum() -{ - qCDebug(lcFacebook) << "Album with name" << fbInfo.albumName << "doesn't exists, creating it."; - QUrlQuery params; - params.addQueryItem("name", fbInfo.albumName ); - params.addQueryItem("description", "Subsurface Album"); - params.addQueryItem("privacy", "{'value': 'SELF'}"); - - QNetworkRequest request(albumListUrl()); - request.setHeader(QNetworkRequest::ContentTypeHeader, "application/octet-stream"); - - QNetworkReply *reply = manager->post(request, params.query().toUtf8()); - connect(reply, &QNetworkReply::finished, this, &FacebookManager::facebookAlbumCreated); -} - -void FacebookManager::facebookAlbumCreated() -{ - QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); - QJsonDocument albumsDoc = QJsonDocument::fromJson(reply->readAll()); - QJsonObject album = albumsDoc.object(); - - reply->deleteLater(); - - if (album.contains("id")) { - qCDebug(lcFacebook) << "Album" << fbInfo.albumName << "created successfully with id" << album.value("id").toString(); - qPrefFacebook::set_album_id(album.value("id").toString()); - emit albumIdReceived(qPrefFacebook::album_id()); - return; - } else { - qCDebug(lcFacebook) << "It was not possible to create the album with name" << fbInfo.albumName; - qCDebug(lcFacebook).noquote() << "Reply was: " << QString(albumsDoc.toJson(QJsonDocument::Indented)); - // FIXME: we are lacking 'user_photos' facebook permission to create an album, - // but we are able to upload the image to Facebook (album will be named 'Subsurface Photos') - qCDebug(lcFacebook) << "But we are still able to upload data. Album name will be 'Subsurface Photos'"; - emit albumIdReceived(qPrefFacebook::album_id()); - } -} - -void FacebookManager::requestUserId() -{ - qCDebug(lcFacebook) << "Requesting user id"; - QUrl userIdRequest("https://graph.facebook.com/me?fields=id&access_token=" + QString(prefs.facebook.access_token)); - QNetworkReply *reply = manager->get(QNetworkRequest(userIdRequest)); - - connect(reply, &QNetworkReply::finished, this, &FacebookManager::userIdReceived); -} - -void FacebookManager::userIdReceived() -{ - QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender()); - QJsonDocument jsonDoc = QJsonDocument::fromJson(reply->readAll()); - QJsonObject obj = jsonDoc.object(); - if (obj.keys().contains("id")) { - qCDebug(lcFacebook) << "User id requested successfully:" << obj.value("id").toString(); - qPrefFacebook::set_user_id(obj.value("id").toString()); - emit sendMessage(tr("Facebook logged in successfully")); - emit justLoggedIn(true); - } else { - emit sendMessage(tr("Error, unknown user id, cannot login.")); - qCDebug(lcFacebook) << "Error, unknown user id, cannot login."; - } - reply->deleteLater(); -} - -QPixmap FacebookManager::grabProfilePixmap() -{ - qCDebug(lcFacebook) << "Grabbing Dive Profile pixmap"; - ProfileWidget2 *profile = MainWindow::instance()->graphics; - - QSize size = fbInfo.profileSize == FacebookInfo::SMALL ? QSize(800,600) : - fbInfo.profileSize == FacebookInfo::MEDIUM ? QSize(1024,760) : - fbInfo.profileSize == FacebookInfo::BIG ? QSize(1280,1024) : QSize(); - - auto currSize = profile->size(); - profile->resize(size); - profile->setToolTipVisibile(false); - QPixmap pix = profile->grab(); - profile->setToolTipVisibile(true); - profile->resize(currSize); - - return pix; -} - - -/* to be changed to export the currently selected dive as shown on the profile. - * Much much easier, and its also good to people do not select all the dives - * and send erroniously *all* of them to facebook. */ -void FacebookManager::sendDiveInit() -{ - qCDebug(lcFacebook) << "Starting to upload the dive to facebook"; - - SocialNetworkDialog dialog(qApp->activeWindow()); - if (dialog.exec() != QDialog::Accepted) { - qCDebug(lcFacebook) << "User cancelled."; - return; - } - - fbInfo.bodyText = dialog.text(); - fbInfo.profileSize = dialog.profileSize(); - fbInfo.profileData = grabProfilePixmap(); - fbInfo.albumName = dialog.album(); - fbInfo.albumId = QString(); // request Album Id wil handle that. - - // will emit albumIdReceived, that's connected to sendDiveToAlbum - requestAlbumId(); -} - -void FacebookManager::sendDiveToAlbum(const QString& albumId) -{ - qCDebug(lcFacebook) << "Starting to upload the dive to album" << fbInfo.albumName << "id" << albumId; - QUrl url(graphApi + albumId + "/photos?" + - "&access_token=" + QString(prefs.facebook.access_token) + - "&source=image" + - "&message=" + fbInfo.bodyText.replace(""", "%22")); - - QNetworkRequest request(url); - - QString bound="margin"; - - //according to rfc 1867 we need to put this string here: - QByteArray data(QString("--" + bound + "\r\n").toUtf8()); - data.append("Content-Disposition: form-data; name=\"action\"\r\n\r\n"); - data.append(graphApi + "\r\n"); - data.append("--" + bound + "\r\n"); //according to rfc 1867 - - //name of the input is "uploaded" in my form, next one is a file name. - data.append("Content-Disposition: form-data; name=\"uploaded\"; filename=\"" + QString::number(qrand()) + ".png\"\r\n"); - data.append("Content-Type: image/jpeg\r\n\r\n"); //data type - - QByteArray bytes; - QBuffer buffer(&bytes); - buffer.open(QIODevice::WriteOnly); - fbInfo.profileData.save(&buffer, "PNG"); - - data.append(bytes); //let's read the file - data.append("\r\n"); - data.append("--" + bound + "--\r\n"); //closing boundary according to rfc 1867 - - request.setRawHeader(QByteArray("Content-Type"),QString("multipart/form-data; boundary=" + bound).toUtf8()); - request.setRawHeader(QByteArray("Content-Length"), QString::number(data.length()).toUtf8()); - QNetworkReply *reply = manager->post(request,data); - - connect(reply, &QNetworkReply::finished, this, &FacebookManager::uploadFinished); -} - -void FacebookManager::uploadFinished() -{ - qCDebug(lcFacebook) << "Upload finish"; - auto reply = qobject_cast<QNetworkReply*>(sender()); - QByteArray response = reply->readAll(); - QJsonDocument jsonDoc = QJsonDocument::fromJson(response); - QJsonObject obj = jsonDoc.object(); - - reply->deleteLater(); - - if (obj.keys().contains("id")){ - emit sendMessage(tr("Dive uploaded successfully to Facebook")); - } else { - emit sendMessage(tr("Dive upload failed. Please see debug output and send to Subsurface mailing list")); - qCDebug(lcFacebook) << "Dive upload failed" << response; - } - - emit sendDiveFinished(); -} - -void FacebookConnectWidget::showEvent(QShowEvent *event) -{ - if (FacebookManager::instance()->loggedIn()) { - facebookLoggedIn(); - } else { - facebookDisconnect(); - } - return QDialog::showEvent(event); -} - -FacebookConnectWidget::FacebookConnectWidget(QWidget *parent) : QDialog(parent), ui(new Ui::FacebookConnectWidget) { - ui->setupUi(this); - FacebookManager *fb = FacebookManager::instance(); -#ifdef USE_WEBENGINE - facebookWebView = new QWebEngineView(this); -#else - facebookWebView = new QWebView(this); -#endif - ui->fbWebviewContainer->layout()->addWidget(facebookWebView); -#ifdef USE_WEBENGINE - connect(facebookWebView, &QWebEngineView::urlChanged, fb, &FacebookManager::tryLogin); -#else - connect(facebookWebView, &QWebView::urlChanged, fb, &FacebookManager::tryLogin); -#endif - connect(fb, &FacebookManager::justLoggedIn, this, &FacebookConnectWidget::facebookLoggedIn); - connect(fb, &FacebookManager::justLoggedOut, this, &FacebookConnectWidget::facebookDisconnect); -} - -void FacebookConnectWidget::facebookLoggedIn() -{ - ui->fbWebviewContainer->hide(); - ui->fbWebviewContainer->setEnabled(false); - ui->FBLabel->setText(tr("To disconnect Subsurface from your Facebook account, use the 'Share on' menu entry.")); - close(); -} - -void FacebookConnectWidget::facebookDisconnect() -{ - qCDebug(lcFacebook) << "Disconnecting from facebook"; - // remove the connect/disconnect button - // and instead add the login view - ui->fbWebviewContainer->show(); - ui->fbWebviewContainer->setEnabled(true); - ui->FBLabel->setText(tr("To connect to Facebook, please log in. This enables Subsurface to publish dives to your timeline")); - if (facebookWebView) { -#ifdef USE_WEBENGINE - //FIX ME -#else - facebookWebView->page()->networkAccessManager()->setCookieJar(new QNetworkCookieJar()); -#endif - facebookWebView->setUrl(FacebookManager::instance()->connectUrl()); - } -} - -SocialNetworkDialog::SocialNetworkDialog(QWidget *parent) : - QDialog(parent), - ui( new Ui::SocialnetworksDialog()) -{ - ui->setupUi(this); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); - connect(ui->date, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged); - connect(ui->duration, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged); - connect(ui->Buddy, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged); - connect(ui->Divemaster, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged); - connect(ui->Location, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged); - connect(ui->Notes, &QCheckBox::clicked, this, &SocialNetworkDialog::selectionChanged); - connect(ui->album, &QLineEdit::textChanged, this, &SocialNetworkDialog::albumChanged); -} - -FacebookInfo::Size SocialNetworkDialog::profileSize() const -{ - QString currText = ui->profileSize->currentText(); - return currText.startsWith(tr("Small")) ? FacebookInfo::SMALL : - currText.startsWith(tr("Medium")) ? FacebookInfo::MEDIUM : - /* currText.startsWith(tr("Big")) ? */ FacebookInfo::BIG; -} - - -void SocialNetworkDialog::albumChanged() -{ - QAbstractButton *button = ui->buttonBox->button(QDialogButtonBox::Ok); - button->setEnabled(!ui->album->text().isEmpty()); -} - -void SocialNetworkDialog::selectionChanged() -{ - struct dive *d = current_dive; - QString fullText; - - if (!d) - return; - - if (ui->date->isChecked()) { - fullText += tr("Dive date: %1 \n").arg(get_short_dive_date_string(d->when)); - } - if (ui->duration->isChecked()) { - fullText += tr("Duration: %1 \n").arg(get_dive_duration_string(d->duration.seconds, - tr("h", "abbreviation for hours"), - tr("min", "abbreviation for minutes"))); - } - if (ui->Location->isChecked()) { - fullText += tr("Dive location: %1 \n").arg(get_dive_location(d)); - } - if (ui->Buddy->isChecked()) { - fullText += tr("Buddy: %1 \n").arg(d->buddy); - } - if (ui->Divemaster->isChecked()) { - fullText += tr("Divemaster: %1 \n").arg(d->divemaster); - } - if (ui->Notes->isChecked()) { - fullText += tr("\n%1").arg(d->notes); - } - ui->text->setPlainText(fullText); -} - -QString SocialNetworkDialog::text() const { - return ui->text->toPlainText().toHtmlEscaped(); -} - -QString SocialNetworkDialog::album() const { - return ui->album->text().toHtmlEscaped(); -} - - |