From eaa9d7f3bd430558c1999473dd37dab4c07b251a Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 18 Mar 2011 13:47:50 +0100 Subject: [PATCH] AbstractBuddy and SpectrumBuddy --- include/transport/abstractbuddy.h | 98 +++++++++++++++++++++++ spectrum/src/main.cpp | 32 +++++++- spectrum/src/spectrumbuddy.cpp | 127 ++++++++++++++++++++++++++++++ spectrum/src/spectrumbuddy.h | 52 ++++++++++++ src/abstractbuddy.cpp | 109 +++++++++++++++++++++++++ 5 files changed, 417 insertions(+), 1 deletion(-) create mode 100644 include/transport/abstractbuddy.h create mode 100644 spectrum/src/spectrumbuddy.cpp create mode 100644 spectrum/src/spectrumbuddy.h create mode 100644 src/abstractbuddy.cpp diff --git a/include/transport/abstractbuddy.h b/include/transport/abstractbuddy.h new file mode 100644 index 00000000..0e3fdb64 --- /dev/null +++ b/include/transport/abstractbuddy.h @@ -0,0 +1,98 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, 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 General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include +#include "transport/transport.h" + +#include "Swiften/Swiften.h" + +typedef enum { SPECTRUM_BUDDY_NO_FLAG = 0, + SPECTRUM_BUDDY_JID_ESCAPING = 2, + SPECTRUM_BUDDY_IGNORE = 4 + } SpectrumBuddyFlag; + +using namespace Transport; + +// Wrapper for PurpleBuddy. +class AbstractBuddy { + public: + AbstractBuddy(long id); + virtual ~AbstractBuddy(); + + // Sets/gets ID used to identify this buddy for example by storage backend. + void setId(long id); + long getId(); + + // Returns full JID. + Swift::JID getJID(const std::string &hostname); + + // Generates whole stanza without "to" attribute. That attribute + // has to be added manually. + // only_new - if the stanza is the same as previous generated one, returns NULL. + Swift::Presence::ref generatePresenceStanza(int features, bool only_new = false); + + // Sets online/offline state information. + void setOnline(); + void setOffline(); + + // Returns true if online. + bool isOnline(); + + // Sets/gets current subscription. + // TODO: rewrite me to use SpectrumSubscriptionType! + void setSubscription(const std::string &subscription); + const std::string &getSubscription(); + + // Sets SpectrumBuddyFlags. + void setFlags(int flags); + + // Returns flags. + int getFlags(); + + // Returns buddy's name (so for example UIN for ICQ, JID for XMPP...). + virtual std::string getName() = 0; + + // Returns buddy's alias (nickname). + virtual std::string getAlias() = 0; + + // Returns buddy's group name. + virtual std::vector getGroups() = 0; + + // Returns name which doesn't contain unsafe characters, so it can be used. + // in JIDs. + virtual std::string getSafeName() = 0; + + // Stores current status in `status` and current status message in `statusMessage`. + // Returns true if data can be stored. + virtual bool getStatus(Swift::StatusShow &status, std::string &statusMessage) = 0; + + // Returns SHA-1 hash of buddy icon (avatar) or empty string if there is no avatar. + virtual std::string getIconHash() = 0; + + private: + long m_id; + bool m_online; + std::string m_subscription; + Swift::Presence::ref m_lastPresence; + int m_flags; +}; diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 10a500cd..84c360c3 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -37,9 +37,39 @@ static GOptionEntry options_entries[] = { { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, "", NULL } }; +static void buddyListNewNode(PurpleBlistNode *node) { + if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) + return; + PurpleBuddy *buddy = (PurpleBuddy *) node; + PurpleAccount *account = purple_buddy_get_account(buddy); + User *user = (User *) account->ui_data; + + if (!user) + return; + +} + +static PurpleBlistUiOps blistUiOps = +{ + NULL, + buddyListNewNode, + NULL, + NULL, // buddyListUpdate, + NULL, //NodeRemoved, + NULL, + NULL, + NULL, // buddyListAddBuddy, + NULL, + NULL, + NULL, //buddyListSaveNode, + NULL, //buddyListRemoveNode, + NULL, //buddyListSaveAccount, + NULL +}; + static void transport_core_ui_init(void) { -// purple_blist_set_ui_ops(&blistUiOps); + purple_blist_set_ui_ops(&blistUiOps); // purple_accounts_set_ui_ops(&accountUiOps); // purple_notify_set_ui_ops(¬ifyUiOps); // purple_request_set_ui_ops(&requestUiOps); diff --git a/spectrum/src/spectrumbuddy.cpp b/spectrum/src/spectrumbuddy.cpp new file mode 100644 index 00000000..25636670 --- /dev/null +++ b/spectrum/src/spectrumbuddy.cpp @@ -0,0 +1,127 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, 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 General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "spectrumbuddy.h" +#include "transport/user.h" + +#define Log(X, STRING) std::cout << "[SPECTRUM] " << X << " " << STRING << "\n"; + +SpectrumBuddy::SpectrumBuddy(long id, PurpleBuddy *buddy) : AbstractBuddy(id), m_buddy(buddy) { +} + +SpectrumBuddy::~SpectrumBuddy() { +} + + +std::string SpectrumBuddy::getAlias() { + std::string alias; + if (purple_buddy_get_server_alias(m_buddy)) + alias = (std::string) purple_buddy_get_server_alias(m_buddy); + else + alias = (std::string) purple_buddy_get_alias(m_buddy); + return alias; +} + +std::string SpectrumBuddy::getName() { + std::string name(purple_buddy_get_name(m_buddy)); + if (name.empty()) { + Log("SpectrumBuddy::getName", "Name is EMPTY!"); + } + return name; +} + +bool SpectrumBuddy::getStatus(Swift::StatusShow &status, std::string &statusMessage) { + PurplePresence *pres = purple_buddy_get_presence(m_buddy); + if (pres == NULL) + return false; + PurpleStatus *stat = purple_presence_get_active_status(pres); + if (stat == NULL) + return false; + int st = purple_status_type_get_primitive(purple_status_get_type(stat)); + // TODO: populate status + const char *message = purple_status_get_attr_string(stat, "message"); + + if (message != NULL) { + char *stripped = purple_markup_strip_html(message); + statusMessage = std::string(stripped); + g_free(stripped); + } + else + statusMessage = ""; + return true; +} + +std::string SpectrumBuddy::getIconHash() { + char *avatarHash = NULL; + PurpleBuddyIcon *icon = purple_buddy_icons_find(purple_buddy_get_account(m_buddy), purple_buddy_get_name(m_buddy)); + if (icon) { + avatarHash = purple_buddy_icon_get_full_path(icon); + Log(getName(), "avatarHash"); + } + + if (avatarHash) { + Log(getName(), "Got avatar hash"); + // Check if it's patched libpurple which saves icons to directories + char *hash = strrchr(avatarHash,'/'); + std::string h; + if (hash) { + char *dot; + hash++; + dot = strchr(hash, '.'); + if (dot) + *dot = '\0'; + + std::string ret(hash); + g_free(avatarHash); + return ret; + } + else { + std::string ret(avatarHash); + g_free(avatarHash); + return ret; + } + } + + return ""; +} + +std::vector SpectrumBuddy::getGroups() { + std::vector groups; + groups.push_back(purple_group_get_name(purple_buddy_get_group(m_buddy)) ? std::string(purple_group_get_name(purple_buddy_get_group(m_buddy))) : std::string("Buddies")); + return groups; +} + +std::string SpectrumBuddy::getSafeName() { + std::string name = getName(); +// Transport::instance()->protocol()->prepareUsername(name, purple_buddy_get_account(m_buddy)); + if (getFlags() & SPECTRUM_BUDDY_JID_ESCAPING) { +// name = JID::escapeNode(name); + } + else { + if (name.find_last_of("@") != std::string::npos) { + name.replace(name.find_last_of("@"), 1, "%"); + } + } + if (name.empty()) { + Log("SpectrumBuddy::getSafeName", "Name is EMPTY! Previous was " << getName() << "."); + } + return name; +} + diff --git a/spectrum/src/spectrumbuddy.h b/spectrum/src/spectrumbuddy.h new file mode 100644 index 00000000..0725b9c6 --- /dev/null +++ b/spectrum/src/spectrumbuddy.h @@ -0,0 +1,52 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, 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 General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#ifndef SPECTRUM_BUDDY_H +#define SPECTRUM_BUDDY_H + +#include +#include "purple.h" +#include "account.h" +#include "glib.h" +#include +#include "transport/abstractbuddy.h" + +using namespace Transport; + +// Wrapper for PurpleBuddy +class SpectrumBuddy : public AbstractBuddy { + public: + SpectrumBuddy(long id, PurpleBuddy *buddy); + virtual ~SpectrumBuddy(); + + std::string getAlias(); + std::string getName(); + bool getStatus(Swift::StatusShow &status, std::string &statusMessage); + std::string getIconHash(); + std::vector getGroups(); + std::string getSafeName(); + + PurpleBuddy *getBuddy() { return m_buddy; } + + private: + PurpleBuddy *m_buddy; +}; + +#endif diff --git a/src/abstractbuddy.cpp b/src/abstractbuddy.cpp new file mode 100644 index 00000000..c0b947fb --- /dev/null +++ b/src/abstractbuddy.cpp @@ -0,0 +1,109 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, 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 General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "transport/abstractbuddy.h" + +AbstractBuddy::AbstractBuddy(long id) : m_id(id), m_online(false), m_subscription("ask"), m_flags(0) { +} + +AbstractBuddy::~AbstractBuddy() { +} + +void AbstractBuddy::setId(long id) { + m_id = id; +} + +long AbstractBuddy::getId() { + return m_id; +} + +void AbstractBuddy::setFlags(int flags) { + m_flags = flags; +} + +int AbstractBuddy::getFlags() { + return m_flags; +} + +Swift::JID AbstractBuddy::getJID(const std::string &hostname) { + return Swift::JID(getSafeName(), hostname, "bot"); +} + +void AbstractBuddy::setOnline() { + m_online = true; +} + +void AbstractBuddy::setOffline() { + m_online = false; + m_lastPresence = Swift::Presence::ref(); +} + +bool AbstractBuddy::isOnline() { + return m_online; +} + +void AbstractBuddy::setSubscription(const std::string &subscription) { + m_subscription = subscription; +} + +const std::string &AbstractBuddy::getSubscription() { + return m_subscription; +} + +Swift::Presence::ref AbstractBuddy::generatePresenceStanza(int features, bool only_new) { + std::string alias = getAlias(); + std::string name = getSafeName(); + + Swift::StatusShow s; + std::string statusMessage; + if (!getStatus(s, statusMessage)) + return Swift::Presence::ref(); + + Swift::Presence::ref presence = Swift::Presence::create(); +// presence->setFrom(getJID()); + presence->setType(Swift::Presence::Available); + + if (!statusMessage.empty()) + presence->setStatus(statusMessage); + + if (s.getType() == Swift::StatusShow::None) + presence->setType(Swift::Presence::Unavailable); + presence->setShow(s.getType()); + + if (presence->getType() != Swift::Presence::Unavailable) { + // caps +// presence->addPayload(boost::shared_ptr(new Swift::CapsInfo (CONFIG().caps))); + + if (features & 0/*TRANSPORT_FEATURE_AVATARS*/) { + presence->addPayload(boost::shared_ptr(new Swift::VCardUpdate (getIconHash()))); + } + } + + if (only_new) { + if (m_lastPresence) + m_lastPresence->setTo(Swift::JID("")); + if (m_lastPresence == presence) { + return Swift::Presence::ref(); + } + m_lastPresence = presence; + } + + return presence; +}