kde-extraapps/kdeplasma-addons/libs/rtm/session.cpp
2015-01-15 17:07:43 +00:00

301 lines
8 KiB
C++

/*
* Copyright 2009 Andrew Stromme <astromme@chatonka.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the
* Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "session.h"
#include "session_p.h"
#include "xmlreaders.h"
#include "request.h"
#include "auth.h"
#include "task.h"
#include <QUrl>
#include <QStringList>
#include <QByteArray>
#include <QCryptographicHash>
#include <QBuffer>
#include <QCoreApplication>
#include <QDomDocument>
#include <QDomNode>
#include <QDomElement>
#include <QDomNodeList>
#include <QtDebug>
RTM::Session::Session(QString apiKey, QString sharedSecret, RTM::Permissions permissions, QString token, QObject* parent)
: QObject(parent),
d(new SessionPrivate(this))
{
d->apiKey = apiKey;
d->sharedSecret = sharedSecret;
d->permissions = permissions;
connect(this, SIGNAL(tokenCheck(bool)), SLOT(handleValidToken(bool)));
connect(this, SIGNAL(settingsUpdated()), SLOT(createTimeline()));
setToken(token);
}
RTM::Session::~Session()
{
delete d;
}
bool RTM::Session::currentlyOnline() const {
return d->online;
}
QString RTM::Session::getAuthUrl() const {
return d->authUrl;
}
bool RTM::Session::authenticated() const {
return !d->token.isEmpty();
}
QString RTM::Session::apiKey() const {
return d->apiKey;
}
QHash< RTM::ListId, RTM::List* > RTM::Session::cachedLists() const {
return d->lists;
}
QHash< RTM::TaskId, RTM::Task* > RTM::Session::cachedTasks() const {
return d->tasks;
}
QStringList RTM::Session::allTags() const {
return d->tags.toList();
}
RTM::Permissions RTM::Session::permissions() const {
return d->permissions;
}
QString RTM::Session::dateFormat() const {
return d->dateFormat;
}
QString RTM::Session::timeFormat() const {
return d->timeFormat;
}
QString RTM::Session::sharedSecret() const {
return d->sharedSecret;
}
RTM::Timeline RTM::Session::getTimeline() const {
return d->timeline;
}
QString RTM::Session::token() const {
return d->token;
}
void RTM::Session::setToken(const QString& token)
{
d->token = token;
d->tasks.clear(); //FIXME: Leak? Tasks/Lists are pointers.
d->lists.clear();
checkToken();
}
void RTM::Session::handleValidToken(bool valid)
{
if (d->auth) {
d->auth->deleteLater();
d->auth = 0;
}
if (!valid) {
d->token.clear();
d->auth = new RTM::Auth(d->permissions, d->apiKey, d->sharedSecret);
d->authUrl = d->auth->getAuthUrl();
connect(d->auth, SIGNAL(tokenReceived(QString)), this, SLOT(setToken(QString)));
connect(d->auth, SIGNAL(tokenReceived(QString)), this, SIGNAL(tokenReceived(QString)));
}
else {
d->refreshSettings();
}
}
void RTM::Session::setTimeline(const RTM::Timeline& timeline) {
d->timeline = timeline;
}
void RTM::Session::continueAuthForToken()
{
d->auth->continueAuthForToken();
}
void RTM::Session::checkToken() {
if (d->token.isEmpty() || !currentlyOnline()) {
emit tokenCheck(false);
return;
}
RTM::Request *tokenRequest = new RTM::Request("rtm.auth.checkToken", d->apiKey, d->sharedSecret);
d->connectOfflineSignal(tokenRequest);
tokenRequest->addArgument("auth_token", d->token);
connect(tokenRequest, SIGNAL(replyReceived(RTM::Request*)), SLOT(tokenCheckReply(RTM::Request*)));
connect(tokenRequest, SIGNAL(replyReceived(RTM::Request*)), tokenRequest, SLOT(deleteLater()));
tokenRequest->sendRequest();
}
void RTM::Session::tokenCheckReply(RTM::Request* response)
{
QString reply = response->data();
if (!reply.contains(d->token)) {
qDebug() << "Failed Token Check: " << reply;
emit tokenCheck(false);
} else {
qDebug() << "Successful Token Check: " << reply;
emit tokenCheck(true);
}
}
void RTM::Session::createTimeline() {
RTM::Request *request = new RTM::Request("rtm.timelines.create", d->apiKey, d->sharedSecret);
request->addArgument("auth_token", d->token);
connect(request, SIGNAL(replyReceived(RTM::Request*)), SLOT(timelineReply(RTM::Request*)));
connect(request, SIGNAL(replyReceived(RTM::Request*)), request, SLOT(deleteLater()));
request->sendRequest();
}
void RTM::Session::timelineReply(RTM::Request* response)
{
QString reply = response->data();
QString timeline = reply.remove(0, reply.indexOf("<timeline>")+10);
timeline.truncate(timeline.indexOf("</timeline>"));
qDebug() << "Timeline: " << timeline;
d->timeline = timeline.toLong();
d->lastRefresh = QDateTime();
emit timelineCreated(getTimeline());
}
void RTM::Session::handleResponse()
{
//TODO: Move data from buffer to response, then clear buffer.
}
void RTM::Session::refreshTasksFromServer() {
if (!currentlyOnline())
return;
RTM::Request *allTasks = request("rtm.tasks.getList");
if (d->lastRefresh.isValid())
allTasks->addArgument("last_sync", d->lastRefresh.toUTC().toString(Qt::ISODate));
allTasks->setReadOnly(false);
allTasks->sendRequest();
}
void RTM::Session::refreshListsFromServer() {
if (!currentlyOnline())
return;
RTM::Request *allLists = new RTM::Request("rtm.lists.getList", d->apiKey, d->sharedSecret);
allLists->addArgument("auth_token", d->token);
connectListRequest(allLists);
allLists->sendRequest();
}
RTM::Task* RTM::Session::taskFromId(RTM::TaskId id) const {
if (cachedTasks().contains(id))
return cachedTasks().value(id);
return 0;
}
RTM::Task* RTM::Session::newBlankTask(RTM::TaskId id) const {
RTM::Task *newTask = Task::uninitializedTask(d->q); //HACK d->q == this but not const
d->tasks.insert(id, newTask);
return newTask;
}
RTM::List* RTM::Session::listFromId(RTM::ListId id) const {
if (cachedLists().contains(id))
return cachedLists().value(id);
return 0;
}
RTM::List* RTM::Session::newBlankList(RTM::ListId id) const {
RTM::List *newList = List::uninitializedList(d->q); //HACK d->q == this but not const
d->lists.insert(id, newList);
return newList;
}
void RTM::Session::connectTaskRequest(RTM::Request* request) {
connect(request, SIGNAL(replyReceived(RTM::Request*)), this, SLOT(taskUpdate(RTM::Request*)));
}
void RTM::Session::connectListRequest(RTM::Request* request) {
connect(request, SIGNAL(replyReceived(RTM::Request*)), this, SLOT(listUpdate(RTM::Request*)));
}
RTM::Request* RTM::Session::request(const QString& method) {
RTM::Request *request = new RTM::Request(method, apiKey(), sharedSecret());
d->connectOfflineSignal(request);
request->addArgument("auth_token", token());
connectTaskRequest(request);
return request;
}
void RTM::Session::addTask(const QString& task, RTM::ListId listId)
{
if (!currentlyOnline())
return;
RTM::List* list = listFromId(listId);
qDebug() << "Adding Task: " << task << "to list with id: " << listId;
RTM::Request *newTask = request("rtm.tasks.add"); // auth token is done for us
newTask->addArgument("name", task);
newTask->addArgument("parse", "1");
if (list && !list->isSmart())
newTask->addArgument("list_id", QString::number(listId));
newTask->addArgument("timeline", QString::number(getTimeline()));
newTask->setReadOnly(false);
newTask->sendRequest();
}
void RTM::Session::addList(const QString &list, const QString &filter)
{
if (!currentlyOnline())
return;
qDebug() << "Adding List: " << list << " to lists";
RTM::Request *newList = request("rtm.lists.add");
newList->addArgument("name", list);
newList->addArgument("timeline", QString::number(getTimeline()));
if (!filter.isEmpty())
newList->addArgument("filter", filter);
newList->setReadOnly(false);
newList->sendRequest();
}
#include "moc_session.cpp"