Skip to content

Commit

Permalink
[sociald] Add VK notifications sync adaptor. Contributes to JB#19271
Browse files Browse the repository at this point in the history
This commit adds a VK notifications sync adaptor.

Contributes to JB#19271
  • Loading branch information
Bea Lam authored and Antti Seppälä committed Oct 12, 2015
1 parent 63031f8 commit db201ab
Show file tree
Hide file tree
Showing 12 changed files with 372 additions and 1 deletion.
28 changes: 28 additions & 0 deletions rpm/sociald.spec
Expand Up @@ -474,6 +474,34 @@ systemctl-user try-restart msyncd.service || :



%package vk-notifications
Summary: Provides notification synchronisation with VK
License: TBD
Group: System/Libraries
BuildRequires: nemo-qml-plugin-notifications-qt5-devel
BuildRequires: qt5-qttools-linguist
Requires: %{name} = %{version}-%{release}

%description vk-notifications
Provides notification synchronisation with VK

%files vk-notifications
#out-of-process-plugin form:
/usr/lib/buteo-plugins-qt5/oopp/vk-notifications-client
#in-process-plugin form:
#/usr/lib/buteo-plugins-qt5/libvk-notifications-client.so
%config %{_sysconfdir}/buteo/profiles/client/vk-notifications.xml
%config %{_sysconfdir}/buteo/profiles/sync/vk.Notifications.xml
%{_datadir}/lipstick/notificationcategories/x-nemo.social.vk.notification.conf

%pre vk-notifications
rm -f /home/nemo/.cache/msyncd/sync/client/vk-notifications.xml
rm -f /home/nemo/.cache/msyncd/sync/vk.Notifications.xml

%post vk-notifications
systemctl-user restart msyncd.service || :


%package ts-devel
Summary: Translation source for sociald
License: LGPLv2.1
Expand Down
1 change: 1 addition & 0 deletions src/sociald/socialdplugin.cpp
Expand Up @@ -100,6 +100,7 @@ bool SocialdPlugin::startSync()
startSyncParams << "twitter.Notifications";
startSyncParams << "twitter.Posts";
startSyncParams << "vk.Posts";
startSyncParams << "vk.Notifications";
}

foreach (const QString &param, startSyncParams) {
Expand Down
6 changes: 6 additions & 0 deletions src/vk/vk-notifications/vk-notifications.pri
@@ -0,0 +1,6 @@
CONFIG += link_pkgconfig meegotouchevents-qt5
PKGCONFIG += nemonotifications-qt5
SOURCES += $$PWD/vknotificationsyncadaptor.cpp
HEADERS += $$PWD/vknotificationsyncadaptor.h
INCLUDEPATH += $$PWD

29 changes: 29 additions & 0 deletions src/vk/vk-notifications/vk-notifications.pro
@@ -0,0 +1,29 @@
TARGET = vk-notifications-client
VERSION = 0.0.1

DEFINES += "CLASSNAME=VKNotificationsPlugin"
DEFINES += CLASSNAME_H=\\\"vknotificationsplugin.h\\\"
include($$PWD/../../common.pri)
include($$PWD/../vk-common.pri)
include($$PWD/vk-notifications.pri)

vk_notifications_sync_profile.path = /etc/buteo/profiles/sync
vk_notifications_sync_profile.files = $$PWD/vk.Notifications.xml
vk_notifications_client_plugin_xml.path = /etc/buteo/profiles/client
vk_notifications_client_plugin_xml.files = $$PWD/vk-notifications.xml
vk_notifications_notification_xml.path = /usr/share/lipstick/notificationcategories/
vk_notifications_notification_xml.files = $$PWD/x-nemo.social.vk.notification.conf

HEADERS += vknotificationsplugin.h
SOURCES += vknotificationsplugin.cpp

OTHER_FILES += \
vk.Notifications.xml \
vk-notifications.xml \
x-nemo.social.vk.notification.conf

INSTALLS += \
target \
vk_notifications_sync_profile \
vk_notifications_client_plugin_xml \
vk_notifications_notification_xml
4 changes: 4 additions & 0 deletions src/vk/vk-notifications/vk-notifications.xml
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<profile name="vk-notifications" type="client" >
<field name="Sync Direction" />
</profile>
15 changes: 15 additions & 0 deletions src/vk/vk-notifications/vk.Notifications.xml
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<profile name="vk.Notifications" type="sync" >
<key name="category" value="eventfeed" />
<key name="enabled" value="false" />
<key name="use_accounts" value="false" />
<key name="destinationtype" value="online" />
<key name="hidden" value="true" />
<key name="displayname" value="VK Notifications"/>

<schedule enabled="false" interval="30" days="1,2,3,4,5,6,7" syncconfiguredtime="" time="" />

<profile name="vk-notifications" type="client" >
<key name="Sync Direction" value="from-remote" />
</profile>
</profile>
40 changes: 40 additions & 0 deletions src/vk/vk-notifications/vknotificationsplugin.cpp
@@ -0,0 +1,40 @@
/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd.
** Contact: Chris Adams <chris.adams@jolla.com>
**
****************************************************************************/

#include "vknotificationsplugin.h"
#include "vknotificationsyncadaptor.h"
#include "socialnetworksyncadaptor.h"

extern "C" VKNotificationsPlugin* createPlugin(const QString& pluginName,
const Buteo::SyncProfile& profile,
Buteo::PluginCbInterface *callbackInterface)
{
return new VKNotificationsPlugin(pluginName, profile, callbackInterface);
}

extern "C" void destroyPlugin(VKNotificationsPlugin* plugin)
{
delete plugin;
}

VKNotificationsPlugin::VKNotificationsPlugin(const QString& pluginName,
const Buteo::SyncProfile& profile,
Buteo::PluginCbInterface *callbackInterface)
: SocialdButeoPlugin(pluginName, profile, callbackInterface,
QStringLiteral("vk"),
SocialNetworkSyncAdaptor::dataTypeName(SocialNetworkSyncAdaptor::Notifications))
{
}

VKNotificationsPlugin::~VKNotificationsPlugin()
{
}

SocialNetworkSyncAdaptor *VKNotificationsPlugin::createSocialNetworkSyncAdaptor()
{
return new VKNotificationSyncAdaptor(this);
}
33 changes: 33 additions & 0 deletions src/vk/vk-notifications/vknotificationsplugin.h
@@ -0,0 +1,33 @@
/****************************************************************************
**
** Copyright (C) 2014 Jolla Ltd.
** Contact: Chris Adams <chris.adams@jolla.com>
**
****************************************************************************/

#ifndef VKNOTIFICATIONSPLUGIN_H
#define VKNOTIFICATIONSPLUGIN_H

#include "socialdbuteoplugin.h"

class VKNotificationsPlugin : public SocialdButeoPlugin
{
Q_OBJECT

public:
VKNotificationsPlugin(const QString& pluginName,
const Buteo::SyncProfile& profile,
Buteo::PluginCbInterface *cbInterface);
~VKNotificationsPlugin();

protected:
SocialNetworkSyncAdaptor *createSocialNetworkSyncAdaptor();
};

extern "C" VKNotificationsPlugin* createPlugin(const QString& pluginName,
const Buteo::SyncProfile& profile,
Buteo::PluginCbInterface *cbInterface);

extern "C" void destroyPlugin(VKNotificationsPlugin* client);

#endif // VKNOTIFICATIONSPLUGIN_H
150 changes: 150 additions & 0 deletions src/vk/vk-notifications/vknotificationsyncadaptor.cpp
@@ -0,0 +1,150 @@
/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Chris Adams <chris.adams@jollamobile.com>
**
****************************************************************************/

#include "vknotificationsyncadaptor.h"
#include "trace.h"

#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QUrlQuery>
#include <QDebug>

//static const int OLD_NOTIFICATION_LIMIT_IN_DAYS = 21; // TODO

VKNotificationSyncAdaptor::VKNotificationSyncAdaptor(QObject *parent)
: VKDataTypeSyncAdaptor(SocialNetworkSyncAdaptor::Notifications, parent)
{
setInitialActive(true);
}

VKNotificationSyncAdaptor::~VKNotificationSyncAdaptor()
{
}

QString VKNotificationSyncAdaptor::syncServiceName() const
{
return QStringLiteral("vk-microblog");
}

void VKNotificationSyncAdaptor::purgeDataForOldAccount(int oldId, SocialNetworkSyncAdaptor::PurgeMode)
{
m_db.removeNotifications(oldId);
m_db.sync();
m_db.wait();
}

void VKNotificationSyncAdaptor::beginSync(int accountId, const QString &accessToken)
{
requestNotifications(accountId, accessToken);
}

void VKNotificationSyncAdaptor::finalize(int accountId)
{
Q_UNUSED(accountId);
if (syncAborted()) {
SOCIALD_LOG_DEBUG("sync aborted, skipping finalize of VK Notifications from account:" << accountId);
} else {
SOCIALD_LOG_DEBUG("finalizing VK Notifications sync with account:" << accountId);
//m_db.purgeOldNotifications(OLD_NOTIFICATION_LIMIT_IN_DAYS); // TODO
Q_FOREACH (const NotificationData &notification, m_notificationsToAdd) {
QList<UserProfile> userProfiles;
foreach (const QJsonValue &entry, notification.profiles) {
userProfiles << UserProfile::fromJsonObject(entry.toObject());
}
saveVKNotificationFromObject(notification.accountId, notification.notification, userProfiles);
}
m_db.sync();
m_db.wait();
}
}

void VKNotificationSyncAdaptor::requestNotifications(int accountId, const QString &accessToken, const QString &until, const QString &pagingToken)
{
// TODO: result paging
Q_UNUSED(until);
Q_UNUSED(pagingToken);

QList<QPair<QString, QString> > queryItems;
queryItems.append(QPair<QString, QString>(QString(QLatin1String("access_token")), accessToken));
queryItems.append(QPair<QString, QString>(QString(QLatin1String("v")), QStringLiteral("5.21"))); // version

QUrl url(QStringLiteral("https://api.vk.com/method/notifications.get"));
QUrlQuery query(url);
query.setQueryItems(queryItems);
url.setQuery(query);
QNetworkReply *reply = m_networkAccessManager->get(QNetworkRequest(url));

if (reply) {
reply->setProperty("accountId", accountId);
reply->setProperty("accessToken", accessToken);
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(errorHandler(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsHandler(QList<QSslError>)));
connect(reply, SIGNAL(finished()), this, SLOT(finishedHandler()));

// we're requesting data. Increment the semaphore so that we know we're still busy.
incrementSemaphore(accountId);
setupReplyTimeout(accountId, reply);
} else {
SOCIALD_LOG_ERROR("error: unable to request home posts from VK account with id:" << accountId);
}
}

void VKNotificationSyncAdaptor::finishedHandler()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
bool isError = reply->property("isError").toBool();
int accountId = reply->property("accountId").toInt();
QByteArray replyData = reply->readAll();
disconnect(reply);
reply->deleteLater();
removeReplyTimeout(accountId, reply);

bool ok = false;
QJsonObject parsed = parseJsonObjectReplyData(replyData, &ok);

if (!isError && ok && parsed.contains(QLatin1String("response"))) {
QJsonObject responseObj = parsed.value(QStringLiteral("response")).toObject();

QJsonArray profileValues = responseObj.value(QStringLiteral("profiles")).toArray();
QJsonArray items = responseObj.value(QLatin1String("items")).toArray();
foreach (const QJsonValue &entry, items) {
QJsonObject object = entry.toObject();
if (!object.isEmpty()) {
m_notificationsToAdd.append(NotificationData(accountId, object, profileValues));
} else {
SOCIALD_LOG_DEBUG("notification object empty; skipping");
}
}
} else {
// error occurred during request.
SOCIALD_LOG_ERROR("error: unable to parse notification data from request with account:" << accountId <<
"got:" << QString::fromUtf8(replyData));
}

// we're finished this request. Decrement our busy semaphore.
decrementSemaphore(accountId);
}

void VKNotificationSyncAdaptor::saveVKNotificationFromObject(int accountId, const QJsonObject &notif, const QList<UserProfile> &userProfiles)
{
QString type = notif.value("type").toString();
QDateTime timestamp = parseVKDateTime(notif.value(QStringLiteral("date")));
QJsonObject feedback = notif.value(QStringLiteral("feedback")).toObject();
Q_FOREACH (const QJsonValue &feedbackItem, feedback.value(QStringLiteral("items")).toArray()) {
QJsonObject feedbackItemObj = feedbackItem.toObject();
int fromId = int(feedbackItemObj.value(QStringLiteral("from_id")).toDouble());
int toId = int(feedbackItemObj.value(QStringLiteral("to_id")).toDouble());
UserProfile profile = findUserProfile(userProfiles, fromId);
if (profile.uid != 0) {
SOCIALD_LOG_TRACE("adding VK notification:" << type);
m_db.addVKNotification(accountId, type, QString::number(fromId), profile.name(), profile.icon, QString::number(toId), timestamp);
} else {
SOCIALD_LOG_DEBUG("no user profile found for owner" << fromId << "of notification from account" << accountId);
}
}
}
56 changes: 56 additions & 0 deletions src/vk/vk-notifications/vknotificationsyncadaptor.h
@@ -0,0 +1,56 @@
/****************************************************************************
**
** Copyright (C) 2013 Jolla Ltd.
** Contact: Chris Adams <chris.adams@jollamobile.com>
**
****************************************************************************/

#ifndef VKNOTIFICATIONSYNCADAPTOR_H
#define VKNOTIFICATIONSYNCADAPTOR_H

#include "vkdatatypesyncadaptor.h"
#include <socialcache/vknotificationsdatabase.h>

#include <QList>
#include <QJsonObject>

class Notification;

class VKNotificationSyncAdaptor : public VKDataTypeSyncAdaptor
{
Q_OBJECT

public:
VKNotificationSyncAdaptor(QObject *parent);
~VKNotificationSyncAdaptor();

QString syncServiceName() const;

protected: // implementing VKDataTypeSyncAdaptor interface
void purgeDataForOldAccount(int oldId, SocialNetworkSyncAdaptor::PurgeMode mode);
void beginSync(int accountId, const QString &accessToken);
void finalize(int accountId);

private:
void requestNotifications(int accountId, const QString &accessToken,
const QString &until = QString(),
const QString &pagingToken = QString());

private Q_SLOTS:
void finishedHandler();

private:
void saveVKNotificationFromObject(int accountId, const QJsonObject &notif, const QList<UserProfile> &userProfiles);
struct NotificationData {
NotificationData() : accountId(0) {}
NotificationData(int accountId, const QJsonObject &notification, const QJsonArray &profiles)
: accountId(accountId), notification(notification), profiles(profiles) {}
int accountId;
QJsonObject notification;
QJsonArray profiles;
};
QList<NotificationData> m_notificationsToAdd;
VKNotificationsDatabase m_db;
};

#endif // VKNOTIFICATIONSYNCADAPTOR_H
8 changes: 8 additions & 0 deletions src/vk/vk-notifications/x-nemo.social.vk.notification.conf
@@ -0,0 +1,8 @@
x-nemo-icon=icon-lock-vk
x-nemo-preview-icon=icon-lock-vk
x-nemo-feedback=social
genericTextId=qtn_social_notifications_new_vk
genericTextCatalogue=sociald
priority=60
lowPowerModeIconId=icon-lock-vk
statusAreaIconId=icon-lock-vk
3 changes: 2 additions & 1 deletion src/vk/vk.pro
@@ -1,3 +1,4 @@
TEMPLATE = subdirs
SUBDIRS = \
$$PWD/vk-posts
$$PWD/vk-posts \
$$PWD/vk-notifications

0 comments on commit db201ab

Please sign in to comment.