File indexing completed on 2024-05-12 08:57:51

0001 /*
0002     This file is part of Choqok, the KDE micro-blogging client
0003 
0004     SPDX-FileCopyrightText: 2010-2012 Mehrdad Momeny <mehrdad.momeny@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 "ocsmicroblog.h"
0010 
0011 #include <KLocalizedString>
0012 #include <KMessageBox>
0013 #include <KPluginFactory>
0014 #include <KConfig>
0015 
0016 #include <Attica/ProviderManager>
0017 
0018 #include "application.h"
0019 #include "accountmanager.h"
0020 #include "editaccountwidget.h"
0021 #include "postwidget.h"
0022 
0023 #include "ocsaccount.h"
0024 #include "ocsdebug.h"
0025 #include "ocsconfigurewidget.h"
0026 
0027 K_PLUGIN_CLASS_WITH_JSON(OCSMicroblog, "choqok_ocs.json")
0028 
0029 OCSMicroblog::OCSMicroblog(QObject *parent, const QVariantList &)
0030     : MicroBlog(QLatin1String("choqok_ocs"), parent)
0031     , mProviderManager(new Attica::ProviderManager)
0032     , mIsOperational(false)
0033 {
0034     connect(mProviderManager, &Attica::ProviderManager::defaultProvidersLoaded,
0035             this, &OCSMicroblog::slotDefaultProvidersLoaded);
0036     mProviderManager->loadDefaultProviders();
0037     setServiceName(QLatin1String("Social Desktop Activities"));
0038 }
0039 
0040 OCSMicroblog::~OCSMicroblog()
0041 {
0042     delete mProviderManager;
0043 }
0044 
0045 void OCSMicroblog::saveTimeline(Choqok::Account *account, const QString &timelineName,
0046                                 const QList< Choqok::UI::PostWidget * > &timeline)
0047 {
0048     qCDebug(CHOQOK);
0049     QString fileName = Choqok::AccountManager::generatePostBackupFileName(account->alias(), timelineName);
0050     KConfig postsBackup(fileName, KConfig::NoGlobals, QStandardPaths::DataLocation);
0051 
0052     ///Clear previous data:
0053     for (const QString &group: postsBackup.groupList()) {
0054         postsBackup.deleteGroup(group);
0055     }
0056 
0057     for (Choqok::UI::PostWidget *wd: timeline) {
0058         const Choqok::Post *post = wd->currentPost();
0059         KConfigGroup grp(&postsBackup, post->creationDateTime.toString());
0060         grp.writeEntry("creationDateTime", post->creationDateTime);
0061         grp.writeEntry("postId", post->postId);
0062         grp.writeEntry("text", post->content);
0063         grp.writeEntry("authorId", post->author.userId);
0064         grp.writeEntry("authorUserName", post->author.userName);
0065         grp.writeEntry("authorRealName", post->author.realName);
0066         grp.writeEntry("authorProfileImageUrl", post->author.profileImageUrl);
0067         grp.writeEntry("authorDescription" , post->author.description);
0068         grp.writeEntry("authorLocation" , post->author.location);
0069         grp.writeEntry("authorUrl" , post->author.homePageUrl);
0070         grp.writeEntry("link", post->link);
0071         grp.writeEntry("isRead" , post->isRead);
0072     }
0073     postsBackup.sync();
0074     if (Choqok::Application::isShuttingDown()) {
0075         Q_EMIT readyForUnload();
0076     }
0077 }
0078 
0079 QList< Choqok::Post * > OCSMicroblog::loadTimeline(Choqok::Account *account, const QString &timelineName)
0080 {
0081     qCDebug(CHOQOK) << timelineName;
0082     QList< Choqok::Post * > list;
0083     QString fileName = Choqok::AccountManager::generatePostBackupFileName(account->alias(), timelineName);
0084     KConfig postsBackup(fileName, KConfig::NoGlobals, QStandardPaths::DataLocation);
0085     QStringList tmpList = postsBackup.groupList();
0086 
0087     QList<QDateTime> groupList;
0088     for (const QString &str: tmpList) {
0089         groupList.append(QDateTime::fromString(str));
0090     }
0091     std::sort(groupList.begin(), groupList.end());
0092     int count = groupList.count();
0093     if (count) {
0094         Choqok::Post *st = nullptr;
0095         for (int i = 0; i < count; ++i) {
0096             st = new Choqok::Post;
0097             KConfigGroup grp(&postsBackup, groupList[i].toString());
0098             st->creationDateTime = grp.readEntry("creationDateTime", QDateTime::currentDateTime());
0099             st->postId = grp.readEntry("postId", QString());
0100             st->content = grp.readEntry("text", QString());
0101             st->author.userId = grp.readEntry("authorId", QString());
0102             st->author.userName = grp.readEntry("authorUserName", QString());
0103             st->author.realName = grp.readEntry("authorRealName", QString());
0104             st->author.profileImageUrl = grp.readEntry("authorProfileImageUrl", QUrl());
0105             st->author.description = grp.readEntry("authorDescription" , QString());
0106             st->author.location = grp.readEntry("authorLocation", QString());
0107             st->author.homePageUrl = grp.readEntry("authorUrl", QUrl());
0108             st->link = grp.readEntry("link", QUrl());
0109             st->isRead = grp.readEntry("isRead", true);
0110 
0111             list.append(st);
0112         }
0113     }
0114     return list;
0115 }
0116 
0117 Choqok::Account *OCSMicroblog::createNewAccount(const QString &alias)
0118 {
0119     OCSAccount *acc = qobject_cast<OCSAccount *>(Choqok::AccountManager::self()->findAccount(alias));
0120     if (!acc) {
0121         return new OCSAccount(this, alias);
0122     } else {
0123         return nullptr;//If there's an account with this alias, So We can't create a new one
0124     }
0125 }
0126 
0127 ChoqokEditAccountWidget *OCSMicroblog::createEditAccountWidget(Choqok::Account *account, QWidget *parent)
0128 {
0129     qCDebug(CHOQOK);
0130     OCSAccount *acc = qobject_cast<OCSAccount *>(account);
0131     if (acc || !account) {
0132         return new OCSConfigureWidget(this, acc, parent);
0133     } else {
0134         qCDebug(CHOQOK) << "Account passed here was not a valid OCSAccount!";
0135         return nullptr;
0136     }
0137 }
0138 
0139 void OCSMicroblog::createPost(Choqok::Account *theAccount, Choqok::Post *post)
0140 {
0141     if (!mIsOperational) {
0142         Q_EMIT errorPost(theAccount, post, OtherError, i18n("OCS plugin is not initialized yet. Try again later."));
0143         return;
0144     }
0145     qCDebug(CHOQOK);
0146     OCSAccount *acc = qobject_cast<OCSAccount *>(theAccount);
0147     Attica::PostJob *job = acc->provider().postActivity(post->content);
0148     mJobsAccount.insert(job, acc);
0149     mJobsPost.insert(job, post);
0150     connect(job, &Attica::PostJob::finished, this,
0151             &OCSMicroblog::slotCreatePost);
0152     job->start();
0153 }
0154 
0155 void OCSMicroblog::slotCreatePost(Attica::BaseJob *job)
0156 {
0157     OCSAccount *acc = mJobsAccount.take(job);
0158     Choqok::Post *post = mJobsPost.take(job);
0159     Q_EMIT postCreated(acc, post);
0160 }
0161 
0162 void OCSMicroblog::abortCreatePost(Choqok::Account *theAccount, Choqok::Post *post)
0163 {
0164     qCDebug(CHOQOK);
0165     Q_UNUSED(post);
0166     OCSAccount *acc = qobject_cast<OCSAccount *>(theAccount);
0167     Attica::BaseJob *job = mJobsAccount.key(acc);
0168     if (job) {
0169         job->abort();
0170     }
0171 }
0172 
0173 void OCSMicroblog::fetchPost(Choqok::Account *theAccount, Choqok::Post *post)
0174 {
0175     Q_UNUSED(theAccount);
0176     Q_UNUSED(post);
0177     KMessageBox::error(choqokMainWindow, i18n("Not Supported"));
0178 }
0179 
0180 void OCSMicroblog::removePost(Choqok::Account *theAccount, Choqok::Post *post)
0181 {
0182     Q_UNUSED(theAccount);
0183     Q_UNUSED(post);
0184     KMessageBox::error(choqokMainWindow, i18n("Not Supported"));
0185 }
0186 
0187 Attica::ProviderManager *OCSMicroblog::providerManager()
0188 {
0189     return mProviderManager;
0190 }
0191 
0192 void OCSMicroblog::updateTimelines(Choqok::Account *theAccount)
0193 {
0194     if (!mIsOperational) {
0195         scheduledTasks.insertMulti(theAccount, Update);
0196         return;
0197     }
0198     qCDebug(CHOQOK);
0199     OCSAccount *acc = qobject_cast<OCSAccount *>(theAccount);
0200     if (!acc) {
0201         qCCritical(CHOQOK) << "OCSMicroblog::updateTimelines: acc is not an OCSAccount";
0202         return;
0203     }
0204     Attica::ListJob <Attica::Activity> *job = acc->provider().requestActivities();
0205     mJobsAccount.insert(job, acc);
0206     connect(job, &Attica::BaseJob::finished, this, &OCSMicroblog::slotTimelineLoaded);
0207     job->start();
0208 }
0209 
0210 void OCSMicroblog::slotTimelineLoaded(Attica::BaseJob *job)
0211 {
0212     qCDebug(CHOQOK);
0213     OCSAccount *acc = mJobsAccount.take(job);
0214     if (job->metadata().error() == Attica::Metadata::NoError) {
0215         Attica::Activity::List actList = static_cast< Attica::ListJob<Attica::Activity> * >(job)->itemList();
0216         Q_EMIT timelineDataReceived(acc, QLatin1String("Activity"), parseActivityList(actList));
0217     } else {
0218         Q_EMIT error(acc, ServerError, job->metadata().message(), Low);
0219     }
0220 }
0221 
0222 QList< Choqok::Post * > OCSMicroblog::parseActivityList(const Attica::Activity::List &list)
0223 {
0224     qCDebug(CHOQOK) << list.count();
0225     QList< Choqok::Post * > resultList;
0226     for (const Attica::Activity &act: list) {
0227         Choqok::Post *pst = new Choqok::Post;
0228         pst->postId = act.id();
0229         pst->content = act.message();
0230         pst->creationDateTime = act.timestamp();
0231         pst->link = act.link();
0232         pst->isError = !act.isValid();
0233         pst->author.userId = act.associatedPerson().id();
0234         pst->author.userName = act.associatedPerson().id();
0235         pst->author.homePageUrl = QUrl::fromUserInput(act.associatedPerson().homepage());
0236         pst->author.location = QStringLiteral("%1(%2)").arg(act.associatedPerson().country())
0237                                .arg(act.associatedPerson().city());
0238         pst->author.profileImageUrl = act.associatedPerson().avatarUrl();
0239         pst->author.realName = QStringLiteral("%1 %2").arg(act.associatedPerson().firstName())
0240                                .arg(act.associatedPerson().lastName());
0241         resultList.insert(0, pst);
0242     }
0243     return resultList;
0244 }
0245 
0246 Choqok::TimelineInfo *OCSMicroblog::timelineInfo(const QString &timelineName)
0247 {
0248     if (timelineName == QLatin1String("Activity")) {
0249         Choqok::TimelineInfo *info = new Choqok::TimelineInfo;
0250         info->name = i18nc("Timeline Name", "Activity");
0251         info->description = i18n("Social activities");
0252         info->icon = QLatin1String("user-home");
0253         return info;
0254     } else {
0255         qCCritical(CHOQOK) << "timelineName is not valid!";
0256         return nullptr;
0257     }
0258 }
0259 
0260 bool OCSMicroblog::isOperational()
0261 {
0262     return mIsOperational;
0263 }
0264 
0265 void OCSMicroblog::slotDefaultProvidersLoaded()
0266 {
0267     qCDebug(CHOQOK);
0268     mIsOperational = true;
0269     Q_EMIT initialized();
0270 
0271     for (Choqok::Account *acc: scheduledTasks.keys()) {
0272         switch (scheduledTasks.value(acc)) {
0273         case Update:
0274             updateTimelines(acc);
0275             break;
0276         default:
0277             break;
0278         };
0279     }
0280 }
0281 
0282 QUrl OCSMicroblog::profileUrl(Choqok::Account *account, const QString &username) const
0283 {
0284     OCSAccount *acc = qobject_cast<OCSAccount *>(account);
0285     if (acc->providerUrl().host().contains(QLatin1String("opendesktop.org"))) {
0286         return QUrl::fromUserInput(QStringLiteral("https://opendesktop.org/usermanager/search.php?username=%1").arg(username));
0287     }
0288     return QUrl();
0289 }
0290 
0291 void OCSMicroblog::aboutToUnload()
0292 {
0293     Q_EMIT saveTimelines();
0294 }
0295 
0296 #include "moc_ocsmicroblog.cpp"
0297 #include "ocsmicroblog.moc"