File indexing completed on 2025-01-05 03:53:25

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2008-12-26
0007  * Description : a tool to export items to Facebook web service
0008  *
0009  * SPDX-FileCopyrightText: 2008-2010 by Luka Renko <lure at kubuntu dot org>
0010  * SPDX-FileCopyrightText: 2011      by Dirk Tilger <dirk dot kde at miriup dot de>
0011  * SPDX-FileCopyrightText: 2008-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0012  * SPDX-FileCopyrightText: 2018      by Thanh Trung Dinh <dinhthanhtrung1996 at gmail dot com>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "fbtalker.h"
0019 
0020 // Qt includes
0021 
0022 #include <QJsonDocument>
0023 #include <QJsonParseError>
0024 #include <QJsonObject>
0025 #include <QJsonValue>
0026 #include <QJsonArray>
0027 #include <QByteArray>
0028 #include <QDomDocument>
0029 #include <QDomElement>
0030 #include <QtAlgorithms>
0031 #include <QVBoxLayout>
0032 #include <QLineEdit>
0033 #include <QApplication>
0034 #include <QPushButton>
0035 #include <QDialog>
0036 #include <QDialogButtonBox>
0037 #include <QUrlQuery>
0038 #include <QSettings>
0039 #include <QMessageBox>
0040 
0041 // KDE includes
0042 
0043 #include <klocalizedstring.h>
0044 
0045 // Local includes
0046 
0047 #include "digikam_debug.h"
0048 #include "digikam_version.h"
0049 #include "fbmpform.h"
0050 #include "wstoolutils.h"
0051 #include "webbrowserdlg.h"
0052 #include "networkmanager.h"
0053 
0054 
0055 using namespace Digikam;
0056 
0057 namespace DigikamGenericFaceBookPlugin
0058 {
0059 
0060 bool operator< (const FbUser& first, const FbUser& second)
0061 {
0062     return first.name < second.name;
0063 }
0064 
0065 bool operator< (const FbAlbum& first, const FbAlbum& second)
0066 {
0067     return first.title < second.title;
0068 }
0069 
0070 // -----------------------------------------------------------------------------
0071 
0072 class Q_DECL_HIDDEN FbTalker::Private
0073 {
0074 public:
0075 
0076     enum State
0077     {
0078         FB_GETLOGGEDINUSER = 0,
0079         FB_LOGOUTUSER,
0080         FB_LISTALBUMS,
0081         FB_CREATEALBUM,
0082         FB_ADDPHOTO
0083     };
0084 
0085 public:
0086 
0087     explicit Private()
0088       : dialog(nullptr),
0089         parent(nullptr),
0090         settings(nullptr),
0091         netMngr(nullptr),
0092         reply(nullptr),
0093         browser(nullptr),
0094         state(FB_GETLOGGEDINUSER)
0095     {
0096         apiURL       = QLatin1String("https://graph.facebook.com/%1/%2");
0097         authUrl      = QLatin1String("https://www.facebook.com/dialog/oauth");
0098         tokenUrl     = QLatin1String("https://graph.facebook.com/oauth/access_token");
0099         redirectUrl  = QLatin1String("https://www.facebook.com/connect/login_success.html");
0100         scope        = QLatin1String("user_photos,publish_pages,manage_pages"); //publish_to_groups,user_friends not necessary?
0101         apikey       = QLatin1String("400589753481372");
0102         clientSecret = QLatin1String("5b0b5cd096e110cd4f4c72f517e2c544");
0103 
0104         serviceName  = QLatin1String("Facebook");
0105         serviceTime  = QLatin1String("token_time");
0106         serviceKey   = QLatin1String("access_token");
0107     }
0108 
0109     QString                apiURL;
0110     QString                authUrl;
0111     QString                tokenUrl;
0112     QString                redirectUrl;
0113     QString                scope;
0114     QString                apikey;
0115     QString                clientSecret;
0116     QString                accessToken;
0117     QString                serviceName;
0118     QString                serviceTime;
0119     QString                serviceKey;
0120 
0121     QDateTime              expiryTime;
0122 
0123     QDialog*               dialog;
0124     QWidget*               parent;
0125 
0126     QSettings*             settings;
0127 
0128     QNetworkAccessManager* netMngr;
0129     QNetworkReply*         reply;
0130 
0131     WebBrowserDlg*         browser;
0132 
0133     State                  state;
0134 
0135     FbUser                 user;
0136 };
0137 
0138 // -----------------------------------------------------------------------------
0139 
0140 FbTalker::FbTalker(QWidget* const parent)
0141     : d(new Private())
0142 {
0143     d->parent   = parent;
0144     d->netMngr  = NetworkManager::instance()->getNetworkManager(this);
0145     d->settings = WSToolUtils::getOauthSettings(this);
0146 
0147     connect(this, SIGNAL(linkingSucceeded()),
0148             this, SLOT(slotLinkingSucceeded()));
0149 
0150     connect(d->netMngr, SIGNAL(finished(QNetworkReply*)),
0151             this, SLOT(slotFinished(QNetworkReply*)));
0152 }
0153 
0154 FbTalker::~FbTalker()
0155 {
0156     if (d->reply)
0157     {
0158         d->reply->abort();
0159     }
0160 
0161     delete d;
0162 }
0163 
0164 // ----------------------------------------------------------------------------------------------
0165 
0166 void FbTalker::link()
0167 {
0168     Q_EMIT signalBusy(true);
0169     Q_EMIT signalLoginProgress(1, 3);
0170 
0171     QUrl url(d->authUrl);
0172     QUrlQuery query(url);
0173     query.addQueryItem(QLatin1String("client_id"), d->apikey);
0174     query.addQueryItem(QLatin1String("response_type"), QLatin1String("token"));
0175     query.addQueryItem(QLatin1String("redirect_uri"), d->redirectUrl);
0176     query.addQueryItem(QLatin1String("scope"), d->scope);
0177     url.setQuery(query);
0178 
0179     delete d->browser;
0180     d->browser = new WebBrowserDlg(url, d->parent, true);
0181     d->browser->setModal(true);
0182 
0183     connect(d->browser, SIGNAL(urlChanged(QUrl)),
0184             this, SLOT(slotCatchUrl(QUrl)));
0185 
0186     connect(d->browser, SIGNAL(closeView(bool)),
0187             this, SIGNAL(signalBusy(bool)));
0188 
0189     d->browser->show();
0190 }
0191 
0192 void FbTalker::unlink()
0193 {
0194     d->accessToken = QString();
0195     d->user        = FbUser();
0196 
0197     d->settings->beginGroup(d->serviceName);
0198     d->settings->remove(QString());
0199     d->settings->endGroup();
0200 
0201     Q_EMIT linkingSucceeded();
0202 }
0203 
0204 void FbTalker::cancel()
0205 {
0206     if (d->reply)
0207     {
0208         d->reply->abort();
0209         d->reply = nullptr;
0210     }
0211 
0212     Q_EMIT signalBusy(false);
0213 }
0214 
0215 void FbTalker::slotLinkingSucceeded()
0216 {
0217     if (d->accessToken.isEmpty())
0218     {
0219         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "UNLINK to Facebook";
0220         Q_EMIT signalBusy(false);
0221         return;
0222     }
0223 
0224     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "LINK to Facebook";
0225 
0226     if (d->browser)
0227     {
0228         d->browser->close();
0229     }
0230 
0231     getLoggedInUser();
0232 }
0233 
0234 void FbTalker::slotCatchUrl(const QUrl& url)
0235 {
0236     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Received URL from webview:" << url;
0237 
0238     QString   str = url.toString();
0239     QUrlQuery query(str.section(QLatin1Char('#'), -1, -1));
0240 
0241     if (query.hasQueryItem(QLatin1String("access_token")))
0242     {
0243         d->accessToken = query.queryItemValue(QLatin1String("access_token"));
0244         int seconds    = query.queryItemValue(QLatin1String("expires_in")).toInt();
0245         d->expiryTime  = QDateTime::currentDateTime().addSecs(seconds);
0246 
0247         writeSettings();
0248 
0249         qDebug(DIGIKAM_WEBSERVICES_LOG) << "Access token received";
0250         Q_EMIT linkingSucceeded();
0251     }
0252     else
0253     {
0254         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "No access token in URL";
0255         Q_EMIT signalBusy(false);
0256     }
0257 }
0258 
0259 FbUser FbTalker::getUser() const
0260 {
0261     return d->user;
0262 }
0263 
0264 bool FbTalker::linked()
0265 {
0266     return (!d->accessToken.isEmpty());
0267 }
0268 
0269 void FbTalker::getLoggedInUser()
0270 {
0271     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "getLoggedInUser called";
0272 
0273     if (d->reply)
0274     {
0275         d->reply->abort();
0276         d->reply = nullptr;
0277     }
0278 
0279     Q_EMIT signalBusy(true);
0280     Q_EMIT signalLoginProgress(2, 3);
0281 
0282     QUrl url(d->apiURL.arg(QLatin1String("me")).arg(QString()));
0283 
0284     QUrlQuery q;
0285     q.addQueryItem(QLatin1String("access_token"), d->accessToken);
0286     url.setQuery(q);
0287 
0288     QNetworkRequest netRequest(url);
0289     netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0290                          QLatin1String("application/x-www-form-urlencoded"));
0291 
0292     d->reply = d->netMngr->get(netRequest);
0293 
0294     d->state = Private::FB_GETLOGGEDINUSER;
0295 }
0296 
0297 // ----------------------------------------------------------------------------------------------
0298 
0299 void FbTalker::logout()
0300 {
0301     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "logout called";
0302 
0303     if (d->reply)
0304     {
0305         d->reply->abort();
0306         d->reply = nullptr;
0307     }
0308 
0309     Q_EMIT signalBusy(true);
0310 
0311     QUrl url(QLatin1String("https://www.facebook.com/logout.php"));
0312     QUrlQuery q;
0313     q.addQueryItem(QLatin1String("next"), d->redirectUrl);
0314     q.addQueryItem(QLatin1String("access_token"), d->accessToken);
0315     url.setQuery(q);
0316 
0317     QNetworkRequest netRequest(url);
0318     netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0319                          QLatin1String("application/x-www-form-urlencoded"));
0320 
0321     d->reply = d->netMngr->get(netRequest);
0322 
0323     d->state = Private::FB_LOGOUTUSER;
0324 }
0325 
0326 //----------------------------------------------------------------------------------------------------
0327 
0328 void FbTalker::listAlbums(long long userID)
0329 {
0330     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Requesting albums for user" << userID;
0331 
0332     if (d->reply)
0333     {
0334         d->reply->abort();
0335         d->reply = nullptr;
0336     }
0337 
0338     Q_EMIT signalBusy(true);
0339     Q_EMIT signalLoginProgress(1, 3);
0340 
0341     QUrl url;
0342 
0343     /*
0344      * If userID is specified, load albums of that user,
0345      * else load albums of current user
0346      */
0347     if (!userID)
0348     {
0349         url = QUrl(d->apiURL.arg(d->user.id)
0350                             .arg(QLatin1String("albums")));
0351     }
0352     else
0353     {
0354         url = QUrl(d->apiURL.arg(userID)
0355                             .arg(QLatin1String("albums")));
0356     }
0357 
0358     QUrlQuery q;
0359     q.addQueryItem(QLatin1String("fields"),
0360                    QLatin1String("id,name,description,privacy,link,location"));
0361     q.addQueryItem(QLatin1String("access_token"), d->accessToken);
0362     url.setQuery(q);
0363 
0364     QNetworkRequest netRequest(url);
0365     netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0366                          QLatin1String("application/x-www-form-urlencoded"));
0367 
0368     d->reply = d->netMngr->get(netRequest);
0369 
0370     d->state = Private::FB_LISTALBUMS;
0371 }
0372 
0373 void FbTalker::createAlbum(const FbAlbum& album)
0374 {
0375     if (d->reply)
0376     {
0377         d->reply->abort();
0378         d->reply = nullptr;
0379     }
0380 
0381     Q_EMIT signalBusy(true);
0382 
0383     QUrlQuery params;
0384     params.addQueryItem(QLatin1String("access_token"), d->accessToken);
0385     params.addQueryItem(QLatin1String("name"), album.title);
0386 
0387     if (!album.location.isEmpty())
0388         params.addQueryItem(QLatin1String("location"), album.location);
0389     /*
0390      * description is deprecated and now a param of message
0391      */
0392     if (!album.description.isEmpty())
0393         params.addQueryItem(QLatin1String("message"), album.description);
0394 
0395     // TODO (Dirk): Wasn't that a requested feature in Bugzilla?
0396     switch (album.privacy)
0397     {
0398         case FB_ME:
0399             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'SELF'}"));
0400             break;
0401         case FB_FRIENDS:
0402             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'ALL_FRIENDS'}"));
0403             break;
0404         case FB_FRIENDS_OF_FRIENDS:
0405             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'FRIENDS_OF_FRIENDS'}"));
0406             break;
0407         case FB_EVERYONE:
0408             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'EVERYONE'}"));
0409             break;
0410         case FB_CUSTOM:
0411             //TODO
0412             params.addQueryItem(QLatin1String("privacy"), QLatin1String("{'value':'CUSTOM'}"));
0413             break;
0414     }
0415 
0416     QUrl url(QUrl(d->apiURL.arg(d->user.id)
0417                            .arg(QLatin1String("albums"))));
0418     url.setQuery(params);
0419 
0420     QNetworkRequest netRequest(url);
0421     netRequest.setHeader(QNetworkRequest::ContentTypeHeader,
0422                          QLatin1String("application/x-www-form-urlencoded"));
0423 
0424     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "url to create new album" << netRequest.url() << params.query();
0425 
0426     d->reply = d->netMngr->post(netRequest, params.query().toUtf8());
0427 
0428     d->state = Private::FB_CREATEALBUM;
0429 }
0430 
0431 void FbTalker::addPhoto(const QString& imgPath, const QString& albumID, const QString& caption)
0432 {
0433     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Adding photo" << imgPath << "to album with id"
0434                                      << albumID << "using caption '" << caption << "'";
0435 
0436     if (d->reply)
0437     {
0438         d->reply->abort();
0439         d->reply = nullptr;
0440     }
0441 
0442     Q_EMIT signalBusy(true);
0443 
0444     QMap<QString, QString> args;
0445     args[QLatin1String("access_token")] = d->accessToken;
0446 
0447     if (!caption.isEmpty())
0448         args[QLatin1String("message")]  = caption;
0449 
0450     FbMPForm form;
0451 
0452     for (QMap<QString, QString>::const_iterator it = args.constBegin() ;
0453         it != args.constEnd() ; ++it)
0454     {
0455         form.addPair(it.key(), it.value());
0456     }
0457 
0458     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "FORM:" << QT_ENDL << form.formData();
0459 
0460     if (!form.addFile(QUrl::fromLocalFile(imgPath).fileName(), imgPath))
0461     {
0462         Q_EMIT signalAddPhotoDone(666, i18n("Cannot open file"));
0463         Q_EMIT signalBusy(false);
0464         return;
0465     }
0466 
0467     form.finish();
0468 
0469     QVariant arg_1;
0470 
0471     if (albumID.isEmpty())
0472     {
0473         arg_1 = d->user.id;
0474     }
0475     else
0476     {
0477         arg_1 = albumID;
0478     }
0479 
0480     QNetworkRequest netRequest(QUrl(d->apiURL.arg(arg_1.toString()).arg(QLatin1String("photos"))));
0481     netRequest.setHeader(QNetworkRequest::ContentTypeHeader, form.contentType());
0482 
0483     d->reply = d->netMngr->post(netRequest, form.formData());
0484 
0485     d->state = Private::FB_ADDPHOTO;
0486 }
0487 
0488 //----------------------------------------------------------------------------------------------------
0489 
0490 QString FbTalker::errorToText(int errCode, const QString& errMsg)
0491 {
0492     QString transError;
0493     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "errorToText:" << errCode << ":" << errMsg;
0494 
0495     switch (errCode)
0496     {
0497         case 0:
0498             transError = QLatin1String("");
0499             break;
0500         case 2:
0501             transError = i18n("The service is not available at this time.");
0502             break;
0503         case 4:
0504             transError = i18n("The application has reached the maximum number of requests allowed.");
0505             break;
0506         case 102:
0507             transError = i18n("Invalid session key or session expired. Try to log in again.");
0508             break;
0509         case 120:
0510             transError = i18n("Invalid album ID.");
0511             break;
0512         case 321:
0513             transError = i18n("Album is full.");
0514             break;
0515         case 324:
0516             transError = i18n("Missing or invalid file.");
0517             break;
0518         case 325:
0519             transError = i18n("Too many unapproved photos pending.");
0520             break;
0521         default:
0522             transError = errMsg;
0523             break;
0524     }
0525 
0526     return transError;
0527 }
0528 
0529 void FbTalker::slotFinished(QNetworkReply* reply)
0530 {
0531     if (reply != d->reply)
0532     {
0533         return;
0534     }
0535 
0536     d->reply = nullptr;
0537 
0538     if (reply->error() != QNetworkReply::NoError)
0539     {
0540         if (d->state == Private::FB_ADDPHOTO)
0541         {
0542             Q_EMIT signalBusy(false);
0543             Q_EMIT signalAddPhotoDone(reply->error(), reply->errorString());
0544         }
0545         else
0546         {
0547             Q_EMIT signalBusy(false);
0548             QMessageBox::critical(QApplication::activeWindow(),
0549                                   i18nc("@title:window", "Error"), reply->errorString());
0550         }
0551 
0552         reply->deleteLater();
0553         return;
0554     }
0555 
0556     QByteArray buffer = reply->readAll();
0557 
0558     switch (d->state)
0559     {
0560         case (Private::FB_GETLOGGEDINUSER):
0561             parseResponseGetLoggedInUser(buffer);
0562             break;
0563         case (Private::FB_LOGOUTUSER):
0564             parseResponseLogoutUser();
0565             break;
0566         case (Private::FB_LISTALBUMS):
0567             parseResponseListAlbums(buffer);
0568             break;
0569         case (Private::FB_CREATEALBUM):
0570             parseResponseCreateAlbum(buffer);
0571             break;
0572         case (Private::FB_ADDPHOTO):
0573             parseResponseAddPhoto(buffer);
0574             break;
0575     }
0576 
0577     reply->deleteLater();
0578 }
0579 
0580 int FbTalker::parseErrorResponse(const QDomElement& e, QString& errMsg)
0581 {
0582     int errCode = -1;
0583 
0584     for (QDomNode node = e.firstChild() ;
0585          !node.isNull() ; node = node.nextSibling())
0586     {
0587         if (!node.isElement())
0588             continue;
0589 
0590         if (node.nodeName() == QLatin1String("error_code"))
0591         {
0592             errCode = node.toElement().text().toInt();
0593             qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Error Code:" << errCode;
0594         }
0595         else if (node.nodeName() == QLatin1String("error_msg"))
0596         {
0597             errMsg = node.toElement().text();
0598             qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Error Text:" << errMsg;
0599         }
0600     }
0601 
0602     return errCode;
0603 }
0604 
0605 void FbTalker::parseResponseGetLoggedInUser(const QByteArray& data)
0606 {
0607     QString errMsg;
0608     QJsonParseError err;
0609     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0610 
0611     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Logged in data" << doc;
0612 
0613     if (err.error != QJsonParseError::NoError)
0614     {
0615         Q_EMIT signalBusy(false);
0616         return;
0617     }
0618 
0619     QJsonObject jsonObject = doc.object();
0620     d->user.id             = jsonObject[QLatin1String("id")].toString();
0621 
0622     if (!(QString::compare(jsonObject[QLatin1String("id")].toString(), QLatin1String(""), Qt::CaseInsensitive) == 0))
0623     {
0624         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "ID found in response of GetLoggedInUser";
0625     }
0626 
0627     d->user.name       = jsonObject[QLatin1String("name")].toString();
0628     d->user.profileURL = jsonObject[QLatin1String("link")].toString();
0629 
0630     Q_EMIT signalLoginDone(0, QString());
0631 }
0632 
0633 void FbTalker::parseResponseAddPhoto(const QByteArray& data)
0634 {
0635     qCDebug(DIGIKAM_WEBSERVICES_LOG) <<"Parse Add Photo data is" << data;
0636     int errCode       = -1;
0637     QString errMsg;
0638     QJsonParseError err;
0639     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0640 
0641     if (err.error != QJsonParseError::NoError)
0642     {
0643         Q_EMIT signalBusy(false);
0644         return;
0645     }
0646 
0647     QJsonObject jsonObject = doc.object();
0648 
0649     if (jsonObject.contains(QLatin1String("id")))
0650     {
0651         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Id of photo exported is"
0652                                          << jsonObject[QLatin1String("id")].toString();
0653         errCode = 0;
0654     }
0655 
0656     if (jsonObject.contains(QLatin1String("error")))
0657     {
0658         QJsonObject obj = jsonObject[QLatin1String("error")].toObject();
0659         errCode         = obj[QLatin1String("code")].toInt();
0660         errMsg          = obj[QLatin1String("message")].toString();
0661     }
0662 
0663     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "add photo:" << doc;
0664 
0665     Q_EMIT signalBusy(false);
0666     Q_EMIT signalAddPhotoDone(errCode, errorToText(errCode, errMsg));
0667 }
0668 
0669 void FbTalker::parseResponseCreateAlbum(const QByteArray& data)
0670 {
0671     qCDebug(DIGIKAM_WEBSERVICES_LOG) <<"Parse Create album data is" << data;
0672     int errCode       = -1;
0673     QString errMsg;
0674     QString newAlbumID;
0675     QJsonParseError err;
0676     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0677 
0678     if (err.error != QJsonParseError::NoError)
0679     {
0680         Q_EMIT signalBusy(false);
0681         return;
0682     }
0683 
0684     QJsonObject jsonObject = doc.object();
0685 
0686     if (jsonObject.contains(QLatin1String("id")))
0687     {
0688         newAlbumID = jsonObject[QLatin1String("id")].toString();
0689         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Id of album created is" << newAlbumID;
0690         errCode    = 0;
0691     }
0692 
0693     if (jsonObject.contains(QLatin1String("error")))
0694     {
0695         QJsonObject obj = jsonObject[QLatin1String("error")].toObject();
0696         errCode         = obj[QLatin1String("code")].toInt();
0697         errMsg          = obj[QLatin1String("message")].toString();
0698     }
0699 
0700     qCDebug(DIGIKAM_WEBSERVICES_LOG) << "error create photo:" << doc;
0701 
0702     Q_EMIT signalBusy(false);
0703     Q_EMIT signalCreateAlbumDone(errCode, errorToText(errCode, errMsg), newAlbumID);
0704 }
0705 
0706 void FbTalker::parseResponseListAlbums(const QByteArray& data)
0707 {
0708     int errCode = -1;
0709     QString errMsg;
0710     QJsonParseError err;
0711     QList<FbAlbum> albumsList;
0712     QJsonDocument doc = QJsonDocument::fromJson(data, &err);
0713 
0714     if (err.error != QJsonParseError::NoError)
0715     {
0716         Q_EMIT signalBusy(false);
0717         return;
0718     }
0719 
0720     QJsonObject jsonObject = doc.object();
0721 
0722     if (jsonObject.contains(QLatin1String("data")))
0723     {
0724         QJsonArray jsonArray = jsonObject[QLatin1String("data")].toArray();
0725 
0726         Q_FOREACH (const QJsonValue& value, jsonArray)
0727         {
0728             QJsonObject obj   = value.toObject();
0729             FbAlbum album;
0730             album.id          = obj[QLatin1String("id")].toString();
0731             album.title       = obj[QLatin1String("name")].toString();
0732             album.location    = obj[QLatin1String("location")].toString();
0733             album.url         = obj[QLatin1String("link")].toString();
0734             album.description = obj[QLatin1String("description")].toString();
0735             album.uploadable  = obj[QLatin1String("can_upload")].toBool();
0736 
0737             qCDebug(DIGIKAM_WEBSERVICES_LOG) << "can_upload " << album.uploadable;
0738 
0739             if (QString::compare(obj[QLatin1String("privacy")].toString(),
0740                                  QLatin1String("ALL_FRIENDS"), Qt::CaseInsensitive) == 0)
0741             {
0742                 album.privacy = FB_FRIENDS;
0743             }
0744             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0745                                       QLatin1String("FRIENDS_OF_FRIENDS"), Qt::CaseInsensitive) == 0)
0746             {
0747                 album.privacy = FB_FRIENDS;
0748             }
0749             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0750                                       QLatin1String("EVERYONE"), Qt::CaseInsensitive) == 0)
0751             {
0752                 album.privacy = FB_EVERYONE;
0753             }
0754             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0755                                       QLatin1String("CUSTOM"), Qt::CaseInsensitive) == 0)
0756             {
0757                 album.privacy = FB_CUSTOM;
0758             }
0759             else if (QString::compare(obj[QLatin1String("privacy")].toString(),
0760                                       QLatin1String("SELF"), Qt::CaseInsensitive) == 0)
0761             {
0762                 album.privacy = FB_ME;
0763             }
0764 
0765             albumsList.append(album);
0766         }
0767 
0768         errCode = 0;
0769     }
0770 
0771     if (jsonObject.contains(QLatin1String("error")))
0772     {
0773         QJsonObject obj = jsonObject[QLatin1String("error")].toObject();
0774         errCode         = obj[QLatin1String("code")].toInt();
0775         errMsg          = obj[QLatin1String("message")].toString();
0776     }
0777 
0778     std::sort(albumsList.begin(), albumsList.end());
0779 
0780     Q_EMIT signalBusy(false);
0781     Q_EMIT signalListAlbumsDone(errCode, errorToText(errCode, errMsg), albumsList);
0782 }
0783 
0784 void FbTalker::writeSettings()
0785 {
0786     d->settings->beginGroup(d->serviceName);
0787     d->settings->setValue(d->serviceTime, d->expiryTime);
0788     d->settings->setValue(d->serviceKey,  d->accessToken);
0789     d->settings->endGroup();
0790 }
0791 
0792 void FbTalker::readSettings()
0793 {
0794     d->settings->beginGroup(d->serviceName);
0795     d->expiryTime  = d->settings->value(d->serviceTime).toDateTime();
0796     d->accessToken = d->settings->value(d->serviceKey).toString();
0797     d->settings->endGroup();
0798 
0799     if (d->accessToken.isEmpty())
0800     {
0801         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Access token is empty";
0802         Q_EMIT signalLoginDone(-1, QString());
0803     }
0804     else if (QDateTime::currentDateTime() > d->expiryTime)
0805     {
0806         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Access token has expired";
0807         d->accessToken = QString();
0808         Q_EMIT signalLoginDone(-1, QString());
0809     }
0810     else
0811     {
0812         qCDebug(DIGIKAM_WEBSERVICES_LOG) << "Already Linked";
0813         Q_EMIT linkingSucceeded();
0814     }
0815 }
0816 
0817 void FbTalker::parseResponseLogoutUser()
0818 {
0819     unlink();
0820     Q_EMIT signalLoginDone(-1, QString());
0821 }
0822 
0823 } // namespace DigikamGenericFaceBookPlugin
0824 
0825 #include "moc_fbtalker.cpp"