/soc/2015/jgeboski/facebook: e4d77bc25235: facebook: add and ali...

James Geboski jgeboski at gmail.com
Tue Aug 11 00:37:25 EDT 2015


Changeset: e4d77bc252352415fee25f467a2532410c4e085e
Author:	 James Geboski <jgeboski at gmail.com>
Date:	 2015-08-11 00:37 -0400
Branch:	 facebook
URL: https://hg.pidgin.im/soc/2015/jgeboski/facebook/rev/e4d77bc25235

Description:

facebook: add and alias non-friend buddies

diffstat:

 libpurple/glibcompat.h                  |    6 +
 libpurple/protocols/facebook/api.c      |  176 ++++++++++++++++++++++++++------
 libpurple/protocols/facebook/api.h      |    4 +
 libpurple/protocols/facebook/data.c     |   42 +++++++
 libpurple/protocols/facebook/data.h     |    7 +
 libpurple/protocols/facebook/facebook.c |  103 ++++++++++++++++++-
 6 files changed, 304 insertions(+), 34 deletions(-)

diffs (truncated from 538 to 300 lines):

diff --git a/libpurple/glibcompat.h b/libpurple/glibcompat.h
--- a/libpurple/glibcompat.h
+++ b/libpurple/glibcompat.h
@@ -105,6 +105,12 @@ static inline GByteArray * g_byte_array_
 	return array;
 }
 
+static inline void g_queue_free_full(GQueue *queue, GDestroyNotify free_func)
+{
+	g_queue_foreach(queue, (GFunc)free_func, NULL);
+	g_queue_free(queue);
+}
+
 static inline GThread * g_thread_try_new(const gchar *name, GThreadFunc func,
 	gpointer data, GError **error)
 {
diff --git a/libpurple/protocols/facebook/api.c b/libpurple/protocols/facebook/api.c
--- a/libpurple/protocols/facebook/api.c
+++ b/libpurple/protocols/facebook/api.c
@@ -224,6 +224,14 @@ fb_api_class_init(FbApiClass *klass)
 	             fb_marshal_VOID__VOID,
 	             G_TYPE_NONE,
 	             0);
+	g_signal_new("contact",
+	             G_TYPE_FROM_CLASS(klass),
+	             G_SIGNAL_ACTION,
+	             0,
+	             NULL, NULL,
+	             fb_marshal_VOID__POINTER,
+	             G_TYPE_NONE,
+	             1, G_TYPE_POINTER);
 	g_signal_new("contacts",
 	             G_TYPE_FROM_CLASS(klass),
 	             G_SIGNAL_ACTION,
@@ -352,6 +360,8 @@ fb_api_json_chk(FbApi *api, gconstpointe
 		return FALSE;
 	}
 
+	g_print("JSON: %.*s\n", (gint) size, (gchar*) data);
+
 	root = fb_json_node_new(data, size, &err);
 	FB_API_ERROR_EMIT(api, err, return FALSE);
 
@@ -549,6 +559,9 @@ fb_api_http_query(FbApi *api, gint64 que
 	gchar *json;
 
 	switch (query) {
+	case FB_API_QUERY_CONTACT:
+		name = "FetchContactQuery";
+		break;
 	case FB_API_QUERY_CONTACTS:
 		name = "FetchContactsFullQuery";
 		break;
@@ -1549,15 +1562,129 @@ fb_api_auth(FbApi *api, const gchar *use
 	                prms, fb_api_cb_auth);
 }
 
+static gboolean
+fb_api_contact_parse(FbApi *api, FbApiUser *user, JsonNode *root,
+                     GError **error)
+{
+	const gchar *str;
+	FbApiPrivate *priv = api->priv;
+	FbHttpParams *params;
+	FbJsonValues *values;
+	GError *err = NULL;
+
+	values = fb_json_values_new(root);
+	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
+	                   "$.represented_profile.id");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
+	                   "$.id");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
+	                   "$.represented_profile.friendship_status");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
+	                   "$.structured_name.text");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
+	                   "$.hugePictureUrl.uri");
+	fb_json_values_update(values, &err);
+
+	if (G_UNLIKELY(err != NULL)) {
+		g_propagate_error(error, err);
+		fb_json_values_free(values);
+		return FALSE;
+	}
+
+	str = fb_json_values_next_str(values, NULL);
+
+	if (str == NULL) {
+		str = fb_json_values_next_str(values, "0");
+	} else {
+		fb_json_values_next_str(values, NULL);
+	}
+
+	user->uid = FB_ID_FROM_STR(str);
+	str = fb_json_values_next_str(values, NULL);
+
+	if ((str != NULL) &&
+	    !purple_strequal(str, "ARE_FRIENDS") &&
+	    (user->uid != priv->uid))
+	{
+		return FALSE;
+	}
+
+	user->name = fb_json_values_next_str_dup(values, NULL);
+	user->icon = fb_json_values_next_str_dup(values, NULL);
+
+	params = fb_http_params_new_parse(user->icon, TRUE);
+	user->csum = fb_http_params_dup_str(params, "oh", &err);
+	fb_http_params_free(params);
+
+	fb_json_values_free(values);
+	return TRUE;
+}
+
+static void
+fb_api_cb_contact(PurpleHttpConnection *con, PurpleHttpResponse *res,
+                  gpointer data)
+{
+	FbApi *api = data;
+	FbApiUser user;
+	GError *err = NULL;
+	JsonNode *node;
+	JsonNode *root;
+
+	if (!fb_api_http_chk(api, con, res, &root)) {
+		return;
+	}
+
+	node = fb_json_node_get_nth(root, 0);
+
+	if (node == NULL) {
+		fb_api_error(api, FB_API_ERROR_GENERAL,
+		             _("Failed to obtain contact information"));
+		json_node_free(root);
+		return;
+	}
+
+	fb_api_user_reset(&user, FALSE);
+
+	if (!fb_api_contact_parse(api, &user, node, &err)) {
+		if (G_LIKELY(err == NULL)) {
+			fb_api_error(api, FB_API_ERROR_GENERAL,
+			             _("Failed to parse contact information"));
+		} else {
+			fb_api_error_emit(api, err);
+		}
+	} else {
+		g_signal_emit_by_name(api, "contact", &user);
+	}
+
+	fb_api_user_reset(&user, TRUE);
+	json_node_free(root);
+}
+
+void
+fb_api_contact(FbApi *api, FbId uid)
+{
+	JsonBuilder *bldr;
+
+	/* Object key mapping:
+	 *   0: contact_id
+	 *   1: big_img_size
+	 *   2: huge_img_size
+	 *   3: small_img_size
+	 *   4: low_res_cover_size
+	 *   6: media_type
+	 */
+
+	bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
+	fb_json_bldr_add_strf(bldr, "0", "%" FB_ID_FORMAT, uid);
+	fb_api_http_query(api, FB_API_QUERY_CONTACT, bldr, fb_api_cb_contact);
+}
+
 static void
 fb_api_cb_contacts(PurpleHttpConnection *con, PurpleHttpResponse *res,
                    gpointer data)
 {
-	const gchar *str;
 	FbApi *api = data;
-	FbApiPrivate *priv = api->priv;
 	FbApiUser user;
-	FbHttpParams *params;
 	FbJsonValues *values;
 	gboolean complete;
 	gchar *writeid = NULL;
@@ -1565,6 +1692,7 @@ fb_api_cb_contacts(PurpleHttpConnection 
 	gpointer mptr;
 	GSList *users = NULL;
 	guint count = 0;
+	JsonNode *node;
 	JsonNode *root;
 
 	if (!fb_api_http_chk(api, con, res, &root)) {
@@ -1573,44 +1701,26 @@ fb_api_cb_contacts(PurpleHttpConnection 
 
 	values = fb_json_values_new(root);
 	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
-	                   "$.represented_profile.id");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
 	                   "$.graph_api_write_id");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
-	                   "$.represented_profile.friendship_status");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
-	                   "$.structured_name.text");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
-	                   "$.hugePictureUrl.uri");
 	fb_json_values_set_array(values, FALSE, "$.viewer.messenger_contacts"
 	                                         ".nodes");
 
 	while (fb_json_values_update(values, &err)) {
+		g_free(writeid);
+		count++;
+
+		writeid = fb_json_values_next_str_dup(values, NULL);
+		node = fb_json_values_get_root(values);
 		fb_api_user_reset(&user, FALSE);
-		str = fb_json_values_next_str(values, NULL);
-		user.uid = FB_ID_FROM_STR(str);
-		count++;
-
-		g_free(writeid);
-		writeid = fb_json_values_next_str_dup(values, NULL);
-		str = fb_json_values_next_str(values, NULL);
-
-		if (!purple_strequal(str, "ARE_FRIENDS") &&
-		    (user.uid != priv->uid))
-		{
-			continue;
+
+		if (fb_api_contact_parse(api, &user, node, &err)) {
+			mptr = fb_api_user_dup(&user, FALSE);
+			users = g_slist_prepend(users, mptr);
 		}
 
-		user.name = fb_json_values_next_str_dup(values, NULL);
-		user.icon = fb_json_values_next_str_dup(values, NULL);
-
-		params = fb_http_params_new_parse(user.icon, TRUE);
-		str = fb_http_params_get_str(params, "oh", &err);
-		user.csum = g_strdup(str);
-		fb_http_params_free(params);
-
-		mptr = fb_api_user_dup(&user, FALSE);
-		users = g_slist_prepend(users, mptr);
+		if (G_UNLIKELY(err != NULL)) {
+			break;
+		}
 	}
 
 	complete = (writeid == NULL) || (count < FB_API_CONTACTS_COUNT);
diff --git a/libpurple/protocols/facebook/api.h b/libpurple/protocols/facebook/api.h
--- a/libpurple/protocols/facebook/api.h
+++ b/libpurple/protocols/facebook/api.h
@@ -49,6 +49,7 @@
 #define FB_API_URL_THREADS  FB_API_GHOST "/me/threads"
 #define FB_API_URL_TOPIC    FB_API_AHOST "/method/messaging.setthreadname"
 
+#define FB_API_QUERY_CONTACT        10153746900701729
 #define FB_API_QUERY_CONTACTS       10153856456271729
 #define FB_API_QUERY_CONTACTS_AFTER 10153856456281729
 #define FB_API_QUERY_THREAD         10153919752036729
@@ -183,6 +184,9 @@ void
 fb_api_auth(FbApi *api, const gchar *user, const gchar *pass);
 
 void
+fb_api_contact(FbApi *api, FbId uid);
+
+void
 fb_api_contacts(FbApi *api);
 
 void
diff --git a/libpurple/protocols/facebook/data.c b/libpurple/protocols/facebook/data.c
--- a/libpurple/protocols/facebook/data.c
+++ b/libpurple/protocols/facebook/data.c
@@ -32,6 +32,7 @@ struct _FbDataPrivate
 	FbApi *api;
 	PurpleConnection *gc;
 	PurpleRoomlist *roomlist;
+	GQueue *msgs;
 	GHashTable *icons;
 	GHashTable *icona;
 };
@@ -57,6 +58,7 @@ fb_data_dispose(GObject *obj)
 		g_object_unref(priv->api);
 	}
 
+	g_queue_free_full(priv->msgs, (GDestroyNotify) fb_api_message_free);
 	g_hash_table_destroy(priv->icons);
 	g_hash_table_destroy(priv->icona);
 }
@@ -78,6 +80,7 @@ fb_data_init(FbData *fata)
 	priv = G_TYPE_INSTANCE_GET_PRIVATE(fata, FB_TYPE_DATA, FbDataPrivate);
 	fata->priv = priv;
 
+	priv->msgs = g_queue_new();
 	priv->icons = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 	                                    (GDestroyNotify) fb_data_icon_free,
 					    NULL);
@@ -246,6 +249,45 @@ fb_data_set_roomlist(FbData *fata, Purpl



More information about the Commits mailing list