Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

buddy list and presence #45

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
312 changes: 286 additions & 26 deletions apps/telepathy/Connection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ using namespace std;

#define RESIPROCATE_SUBSYSTEM ReconSubsystem::RECON

static const QString c_fileWithContacts = QLatin1String("data.txt");

tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString &cmName, const QString &protocolName, const QVariantMap &parameters)
: Tp::BaseConnection(dbusConnection, cmName, protocolName, parameters),
mUAProfile(new TelepathyMasterProfile(parameters)),
Expand Down Expand Up @@ -80,7 +82,7 @@ tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString
<< TP_QT_IFACE_CONNECTION
<< TP_QT_IFACE_CONNECTION_INTERFACE_CONTACT_LIST
<< TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE
//<< TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING
<< TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING
<< TP_QT_IFACE_CONNECTION_INTERFACE_REQUESTS
//<< TP_QT_IFACE_CONNECTION_INTERFACE_AVATARS
);
Expand All @@ -92,19 +94,25 @@ tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString
mSimplePresenceInterface->setSetPresenceCallback(Tp::memFun(this, &Connection::setPresence));
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mSimplePresenceInterface));

/* Connection.Interface.ContactList */
mContactListInterface = Tp::BaseConnectionContactListInterface::create();
mContactListInterface->setContactListPersists(true);
mContactListInterface->setCanChangeContactList(true);
mContactListInterface->setDownloadAtConnection(true);
//mContactListInterface->setGetContactListAttributesCallback(Tp::memFun(this, &Connection::getContactListAttributes));
//mContactListInterface->setRequestSubscriptionCallback(Tp::memFun(this, &Connection::requestSubscription));
//mContactListInterface->setAuthorizePublicationCallback(Tp::memFun(this, &Connection::authorizePublication));
//mContactListInterface->setRemoveContactsCallback(Tp::memFun(this, &Connection::removeContacts));
//mContactListInterface->setUnsubscribeCallback(Tp::memFun(this, &Connection::unsubscribe));
//mContactListInterface->setUnpublishCallback(Tp::memFun(this, &Connection::unpublish));
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mContactListInterface));

/* Connection.Interface.ContactList */
mContactListInterface = Tp::BaseConnectionContactListInterface::create();
mContactListInterface->setContactListPersists(true);
mContactListInterface->setCanChangeContactList(true);
mContactListInterface->setDownloadAtConnection(true);
mContactListInterface->setGetContactListAttributesCallback(Tp::memFun(this, &Connection::getContactListAttributes));
mContactListInterface->setRequestSubscriptionCallback(Tp::memFun(this, &Connection::requestSubscription));
// mContactListInterface->setAuthorizePublicationCallback(Tp::memFun(this, &Connection::authorizePublication));
mContactListInterface->setRemoveContactsCallback(Tp::memFun(this, &Connection::removeContacts));
//mContactListInterface->setUnsubscribeCallback(Tp::memFun(this, &Connection::unsubscribe));
//mContactListInterface->setUnpublishCallback(Tp::memFun(this, &Connection::unpublish));
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mContactListInterface));

/* Connection.Interface.Aliasing */
mAliasingInterface = Tp::BaseConnectionAliasingInterface::create();
mAliasingInterface->setGetAliasesCallback(Tp::memFun(this, &Connection::getAliases));
mAliasingInterface->setSetAliasesCallback(Tp::memFun(this, &Connection::setAliases));
plugInterface(Tp::AbstractConnectionInterfacePtr::dynamicCast(mAliasingInterface));

/* Connection.Interface.Requests */
mRequestsInterface = Tp::BaseConnectionRequestsInterface::create(this);
/* Fill requestableChannelClasses */
Expand Down Expand Up @@ -143,6 +151,165 @@ tr::Connection::Connection(const QDBusConnection &dbusConnection, const QString
setRequestHandlesCallback(Tp::memFun(this, &Connection::requestHandles));
connect(this, SIGNAL(disconnected()), SLOT(doDisconnect()));
}

void
tr::Connection::getContactsFromFile(Tp::DBusError *error)
{
if (error->isValid()) {
return;
}

QFile file(c_fileWithContacts);

if(file.open(QFile::ReadOnly)){
QTextStream in(&file);
QString line = in.readLine();
Tp::AliasMap aliases;
while(!line.isNull()){
uint handle = ensureHandle(line.split(" ").at(0));
aliases[handle] = line.split(" ").at(1);
line = in.readLine();
}
setAliases(aliases, error);
} else{
file.open(QFile::WriteOnly);
}

mContactListInterface->setContactListState(Tp::ContactListStateSuccess);
}

void
tr::Connection::setContactsInFile()
{
QFile file(c_fileWithContacts);

if(file.open(QIODevice::ReadWrite | QIODevice::Truncate)){
QTextStream stream(&file);
QMap<uint, QString>::iterator it;
for(it = mHandles.begin(); it != mHandles.end(); it++){
if(it.key() == selfHandle()) continue;

stream << it.value() << " " << mAliases[it.key()] << endl;
}
file.close();
} else{
ErrLog(<<"couldn't write contacts to file" << endl);
}
}

Tp::AliasMap
tr::Connection::getAliases(const Tp::UIntList& handles, Tp::DBusError *error)
{
if (error->isValid()) {
return Tp::AliasMap();
}

qDebug() << Q_FUNC_INFO << handles;

Tp::AliasMap aliases;
Q_FOREACH(uint handle, handles) {
if (mAliases.find(handle) == mAliases.end()) {
error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Invalid handle(s)"));
}
aliases[handle] = mAliases[handle];
}

return aliases;
}

void
tr::Connection::setAliases(const Tp::AliasMap &aliases, Tp::DBusError *error)
{
if (error->isValid()) {
return;
}

qDebug() << Q_FUNC_INFO << aliases;

for(Tp::AliasMap::const_iterator it = aliases.begin(); it != aliases.end(); it++){
mAliases[it.key()] = it.value();
}

}

void
tr::Connection::deleteContacts(const QStringList& contacts)
{

Tp::ContactSubscriptionMap changes;
Tp::HandleIdentifierMap identifiers;
Tp::HandleIdentifierMap removals;
Q_FOREACH(const QString &contact, contacts) {
uint id = mIdentifiers[contact];
removals[id] = contact;
}
mContactListInterface->contactsChangedWithID(changes, identifiers, removals);

setContactsInFile();
}


Tp::ContactAttributesMap
tr::Connection::getContactListAttributes(const QStringList &interfaces, bool hold, Tp::DBusError *error)
{
Tp::UIntList handles = mHandles.keys();
handles.removeOne(selfHandle());

StackLog(<<"getContactListAttributes()");
qDebug() << handles;

return getContactAttributes(handles, interfaces, error);
}

void
tr::Connection::requestSubscription(const Tp::UIntList &handles, const QString &message, Tp::DBusError *error)
{

QStringList contacts = inspectHandles(Tp::HandleTypeContact, handles, error);

if (error->isValid()) {
return;
}

if (contacts.isEmpty()) {
error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Invalid handle(s)"));
}

Tp::ContactSubscriptionMap changes;
Tp::HandleIdentifierMap identifiers;
Tp::HandleIdentifierMap removals;
Q_FOREACH(const QString &contact, contacts) {
uint handle = ensureHandle(contact);

Tp::ContactSubscriptions change;
change.publish = Tp::SubscriptionStateYes;
change.publishRequest = QString();
change.subscribe = Tp::SubscriptionStateUnknown;

changes[handle] = change;
identifiers[handle] = contact;
}
mContactListInterface->contactsChangedWithID(changes, identifiers, removals);

setContactsInFile();
}

void
tr::Connection::removeContacts(const Tp::UIntList &handles, Tp::DBusError *error)
{
QStringList contacts = inspectHandles(Tp::HandleTypeContact, handles, error);

if (error->isValid()) {
return;
}

if (contacts.isEmpty()) {
error->set(TP_QT_ERROR_INVALID_HANDLE, QLatin1String("Invalid handle(s)"));
}

deleteContacts(contacts);
}


void
tr::Connection::doConnect(Tp::DBusError *error)
Expand All @@ -153,8 +320,11 @@ tr::Connection::doConnect(Tp::DBusError *error)
ua->startup();
myConversationManager->startup();
ua->run();

statusMap = getSimpleStatusSpecMap();

mContactListInterface->setContactListState(Tp::ContactListStateWaiting);

getContactsFromFile(error);
}

void
Expand All @@ -163,19 +333,103 @@ tr::Connection::onConnected()
setStatus(Tp::ConnectionStatusConnected, Tp::ConnectionStatusReasonRequested);

Tp::SimpleContactPresences presences;
mSelfPresence.type = Tp::ConnectionPresenceTypeAvailable;
mSelfPresence.status = QLatin1String("available");
Tp::DBusError error;
setPresence(QLatin1String("available"), QLatin1String(""), &error);

presences[selfHandle()] = mSelfPresence;
// TODO: get presence from contacts
mSimplePresenceInterface->setPresences(presences);
}


// got this method from https://github.com/TelepathyQt/telepathy-morse/blob/master/connection.cpp
Tp::SimpleStatusSpecMap
tr::Connection::getSimpleStatusSpecMap()
{

Tp::SimpleStatusSpec spAvailable;
spAvailable.type = Tp::ConnectionPresenceTypeAvailable;
spAvailable.maySetOnSelf = true;
spAvailable.canHaveMessage = true;

Tp::SimpleStatusSpec spBusy;
spBusy.type = Tp::ConnectionPresenceTypeBusy;
spBusy.maySetOnSelf = true;
spBusy.canHaveMessage = true;

Tp::SimpleStatusSpec spAway;
spAway.type = Tp::ConnectionPresenceTypeAway;
spAway.maySetOnSelf = true;
spAway.canHaveMessage = true;

Tp::SimpleStatusSpec spOffline;
spOffline.type = Tp::ConnectionPresenceTypeOffline;
spOffline.maySetOnSelf = true;
spOffline.canHaveMessage = true;


Tp::SimpleStatusSpec spHidden;
spHidden.type = Tp::ConnectionPresenceTypeHidden;
spHidden.maySetOnSelf = true;
spHidden.canHaveMessage = true;

Tp::SimpleStatusSpec spUnknown;
spUnknown.type = Tp::ConnectionPresenceTypeUnknown;
spUnknown.maySetOnSelf = false;
spUnknown.canHaveMessage = true;

Tp::SimpleStatusSpecMap specs;
specs.insert(QLatin1String("available"), spAvailable);
specs.insert(QLatin1String("dnd"), spBusy);
specs.insert(QLatin1String("away"), spAway);
specs.insert(QLatin1String("offline"), spOffline);
specs.insert(QLatin1String("hidden"), spHidden);
specs.insert(QLatin1String("unknown"), spUnknown);
return specs;
}

uint
tr::Connection::setPresence(const QString &status, const QString &message, Tp::DBusError *error)
{
//FIXME
// TODO: find out why message is always getting here empty

StackLog(<<"setPresence()");

mSelfPresence.type = statusMap[status].type;
mSelfPresence.status = status;
if (statusMap[status].canHaveMessage) {
mSelfPresence.statusMessage = message;
}

qDebug() << "status = " << mSelfPresence.status << " type = " << mSelfPresence.type << " message = " << message;

return selfHandle();
}

Tp::SimpleContactPresences
tr::Connection::getPresences(const Tp::UIntList &handles)
{
StackLog(<<"getPresences()");

Tp::SimpleContactPresences presences;
Q_FOREACH(uint handle, handles) {
presences[handle] = getPresence(handle);
}

return presences;
}

Tp::SimplePresence
tr::Connection::getPresence(uint handle)
{
StackLog(<<"getPresence()");
if (!mPresences.contains(handle)) {
return Tp::SimplePresence();
}
qDebug() << "presence = " << mPresences.value(handle).status;

return mPresences.value(handle);
}

void
tr::Connection::doDisconnect()
Expand Down Expand Up @@ -241,7 +495,7 @@ tr::Connection::inspectHandles(uint handleType, const Tp::UIntList &handles, Tp:

QStringList result;

foreach (uint handle, handles) {
Q_FOREACH(uint handle, handles) {
if(!mHandles.contains(handle)) {
return QStringList();
}
Expand All @@ -264,8 +518,7 @@ tr::Connection::requestHandles(uint handleType, const QStringList &identifiers,
}

Q_FOREACH(const QString &identifier, identifiers) {
ensureHandle(identifier);
result.append(mIdentifiers[identifier]);
result.append(ensureHandle(identifier));
}

return result;
Expand Down Expand Up @@ -347,21 +600,28 @@ Tp::ContactAttributesMap
tr::Connection::getContactAttributes(const Tp::UIntList &handles, const QStringList &ifaces, Tp::DBusError *error)
{
StackLog(<<"getContactAttributes");
qDebug() << "getContactAttributes" << handles << ifaces;
Tp::ContactAttributesMap attributesMap;
Q_FOREACH(uint handle, handles) {
QVariantMap attributes;
QStringList inspectedHandles = inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error);
if (inspectedHandles.size() > 0) {
attributes[TP_QT_IFACE_CONNECTION+"/contact-id"] = inspectedHandles.at(0);
QStringList inspectedHandle = inspectHandles(Tp::HandleTypeContact, Tp::UIntList() << handle, error);
if (inspectedHandle.size() > 0) {
attributes[TP_QT_IFACE_CONNECTION+"/contact-id"] = inspectedHandle.at(0);
} else {
continue;
}
qDebug() << "handle = " << handle << " inspectedHandle = " << inspectedHandle;

if (ifaces.contains(TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE)) {
attributes[TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE+"/presence"] = QVariant::fromValue(mSelfPresence);
attributes[TP_QT_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE+"/presence"] = QVariant::fromValue(getPresence(handle));
}

if (ifaces.contains(TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING)) {
attributes[TP_QT_IFACE_CONNECTION_INTERFACE_ALIASING + QLatin1String("/alias")] = QVariant::fromValue(mAliases[handle]);
}

attributesMap[handle] = attributes;
}

return attributesMap;
}

Expand Down