diff options
-rw-r--r-- | src/facebook-connection.c | 179 |
1 files changed, 169 insertions, 10 deletions
diff --git a/src/facebook-connection.c b/src/facebook-connection.c index d0fc959..5a02929 100644 --- a/src/facebook-connection.c +++ b/src/facebook-connection.c @@ -28,6 +28,7 @@ #include <rtcom-telepathy-glib/extensions.h> #include <telepathy-glib/dbus.h> +#include <telepathy-glib/gtypes.h> #include <telepathy-glib/handle-repo-dynamic.h> #include <telepathy-glib/handle-repo-static.h> #include <telepathy-glib/interfaces.h> @@ -62,6 +63,7 @@ struct _GruschlerFacebookConnectionPrivate { GHashTable *group_channels; GHashTable *list_channels; + GHashTable *profiles; char *email; char *password; @@ -69,7 +71,10 @@ struct _GruschlerFacebookConnectionPrivate { }; static void -_channel_manager_iface_init (TpChannelManagerIface *iface); +_channel_manager_iface_init (TpChannelManagerIface *iface); + +static void +_aliasing_iface_init (TpSvcConnectionInterfaceAliasingClass *iface); G_DEFINE_TYPE_WITH_CODE (GruschlerFacebookConnection, gruschler_facebook_connection, @@ -77,6 +82,9 @@ G_DEFINE_TYPE_WITH_CODE (GruschlerFacebookConnection, G_IMPLEMENT_INTERFACE (TP_TYPE_CHANNEL_MANAGER, _channel_manager_iface_init); + + G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CONNECTION_INTERFACE_ALIASING, + _aliasing_iface_init); ); static void @@ -151,10 +159,10 @@ _finalize (GObject *object) g_object_unref (self->priv->groups); if (self->priv->lists) g_object_unref (self->priv->lists); - if (self->priv->list_channels) - g_hash_table_unref (self->priv->list_channels); - if (self->priv->group_channels) - g_hash_table_unref (self->priv->group_channels); + + g_hash_table_unref (self->priv->list_channels); + g_hash_table_unref (self->priv->group_channels); + g_hash_table_unref (self->priv->profiles); g_free (self->priv->email); g_free (self->priv->password); @@ -336,12 +344,31 @@ _get_unique_connection_name (TpBaseConnection *connection) } const char * -_get_uid (GruschlerFacebookConnection *self) +_get_self_uid (GruschlerFacebookConnection *self) { return tp_handle_inspect (self->priv->contacts, TP_BASE_CONNECTION (self)->self_handle); } +const char * +_get_contact_alias (GruschlerFacebookConnection *self, + TpHandle handle) +{ + RestXmlNode *profile, *node = NULL; + + profile = g_hash_table_lookup (self->priv->profiles, + GUINT_TO_POINTER (handle)); + + if (!profile) + return NULL; + + if (NULL != (node = rest_xml_node_find (profile, "name")) || + NULL != (node = rest_xml_node_find (profile, "uid"))) + return node->content; + + return NULL; +} + static void _report_network_error (GruschlerFacebookConnection *self) { @@ -443,7 +470,50 @@ static void _update_profiles (GruschlerFacebookConnection *self, RestXmlNode *result) { - /* TODO: read profiles to make aliasing interface work */ + RestXmlNode *user, *uid, *name; + GValue entry = { 0, }; + GPtrArray *aliases; + TpHandle handle; + int i; + + g_value_init (&entry, TP_STRUCT_TYPE_ALIAS_PAIR); + g_value_take_boxed (&entry, dbus_g_type_specialized_construct + (TP_STRUCT_TYPE_ALIAS_PAIR)); + + aliases = g_ptr_array_new (); + + for (user = rest_xml_node_find (result, "user"); user; user = user->next) + { + if (g_strcmp0 (user->name, "user")) + continue; + + uid = rest_xml_node_find (user, "uid"); + name = rest_xml_node_find (user, "name"); + + if (!uid) + continue; + + handle = tp_handle_ensure (self->priv->contacts, + uid->content, NULL, NULL); + + g_hash_table_insert (self->priv->profiles, + GUINT_TO_POINTER (handle), + rest_xml_node_ref (user)); + + dbus_g_type_struct_set (&entry, 0, handle, + 1, name ? name->content + : uid->content, G_MAXUINT); + + g_ptr_array_add (aliases, g_value_dup_boxed (&entry)); + } + + tp_svc_connection_interface_aliasing_emit_aliases_changed (aliases, aliases); + + for (i = 0; aliases->len; ++i) + g_boxed_free (TP_STRUCT_TYPE_ALIAS_PAIR, aliases->pdata[i]); + + g_ptr_array_free (aliases, TRUE); + g_value_unset (&entry); } static void @@ -502,7 +572,7 @@ _update_friends (GruschlerFacebookConnection *self) g_string_append_printf (queries, "\"uids\":" "\"SELECT uid2 FROM friend WHERE uid1=%s\"", - _get_uid (self)); + _get_self_uid (self)); g_string_append_c (queries, ','); @@ -510,7 +580,7 @@ _update_friends (GruschlerFacebookConnection *self) "\"profiles\":" "\"SELECT uid,name,profile_update_time " "FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1=%s)\"", - _get_uid (self)); + _get_self_uid (self)); /* TODO: "AND profile_update_time > 0" */ g_string_append_c (queries, '}'); @@ -845,8 +915,8 @@ static void gruschler_facebook_connection_class_init (GruschlerFacebookConnectionClass *class) { static const char *interfaces[] = { -#if 0 TP_IFACE_CONNECTION_INTERFACE_ALIASING, +#if 0 TP_IFACE_CONNECTION_INTERFACE_AVATARS, TP_IFACE_CONNECTION_INTERFACE_SIMPLE_PRESENCE, TP_IFACE_CONNECTION_INTERFACE_CONTACTS, @@ -1041,6 +1111,93 @@ _channel_manager_iface_init (TpChannelManagerIface *iface) } static void +_aliasing_get_alias_flags (TpSvcConnectionInterfaceAliasing *aliasing, + DBusGMethodInvocation *context) +{ + tp_svc_connection_interface_aliasing_return_from_get_alias_flags (context, 0); +} + +static void +_aliasing_request_aliases (TpSvcConnectionInterfaceAliasing *aliasing, + const GArray *contacts, + DBusGMethodInvocation *context) +{ + GruschlerFacebookConnection *self; + const char **aliases; + TpHandle handle; + int i; + + self = GRUSCHLER_FACEBOOK_CONNECTION (aliasing); + aliases = g_new0 (const char *, contacts->len + 1); + + for (i = 0; i < contacts->len; ++i) + { + handle = g_array_index (contacts, TpHandle, i); + aliases[i] = _get_contact_alias (self, handle); + } + + tp_svc_connection_interface_aliasing_return_from_request_aliases (context, aliases); + + g_free (aliases); +} + +static void +_aliasing_get_aliases (TpSvcConnectionInterfaceAliasing *aliasing, + const GArray *contacts, + DBusGMethodInvocation *context) +{ + GruschlerFacebookConnection *self; + GHashTable *aliases; + TpHandle handle; + const char *name; + int i; + + self = GRUSCHLER_FACEBOOK_CONNECTION (aliasing); + aliases = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + + for (i = 0; i < contacts->len; ++i) + { + handle = g_array_index (contacts, TpHandle, i); + name = _get_contact_alias (self, handle); + + if (!name) + continue; + + g_hash_table_insert (aliases, + GUINT_TO_POINTER (handle), + g_strdup (name)); + } + + tp_svc_connection_interface_aliasing_return_from_get_aliases (context, aliases); + g_hash_table_unref (aliases); +} + +static void +_aliasing_set_aliases (TpSvcConnectionInterfaceAliasing *aliasing, + GHashTable *aliases, + DBusGMethodInvocation *context) +{ + GError error = { + TP_ERRORS, TP_ERROR_NOT_IMPLEMENTED, + "you cannot modify Facebook aliases" + }; + + dbus_g_method_return_error (context, &error); +} + +static void +_aliasing_iface_init (TpSvcConnectionInterfaceAliasingClass *iface) +{ +#define IMPLEMENT(x) \ + tp_svc_connection_interface_aliasing_implement_##x (iface, _aliasing_##x) + IMPLEMENT (get_alias_flags); + IMPLEMENT (request_aliases); + IMPLEMENT (get_aliases); + IMPLEMENT (set_aliases); +#undef IMPLEMENT +} + +static void gruschler_facebook_connection_init (GruschlerFacebookConnection *self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, @@ -1051,6 +1208,8 @@ gruschler_facebook_connection_init (GruschlerFacebookConnection *self) (g_direct_hash, g_direct_equal, NULL, g_object_unref); self->priv->group_channels = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); + self->priv->profiles = g_hash_table_new_full + (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) rest_xml_node_unref); } TpBaseConnection * |