facebook: fetch URLs for all messages attachments facebook

Fri, 21 Aug 2015 00:41:38 -0400

author
James Geboski <jgeboski@gmail.com>
date
Fri, 21 Aug 2015 00:41:38 -0400
branch
facebook
changeset 37370
2d832af0f400
parent 37369
ebcd09a1a124
child 37371
5727ffb502c7

facebook: fetch URLs for all messages attachments

libpurple/protocols/facebook/api.c file | annotate | diff | comparison | revisions
libpurple/protocols/facebook/api.h file | annotate | diff | comparison | revisions
--- a/libpurple/protocols/facebook/api.c	Thu Aug 20 21:45:58 2015 -0400
+++ b/libpurple/protocols/facebook/api.c	Fri Aug 21 00:41:38 2015 -0400
@@ -62,7 +62,7 @@
 	gchar *stoken;
 	gchar *token;
 
-	GHashTable *msgids;
+	GHashTable *mids;
 	gboolean invisible;
 	guint unread;
 
@@ -75,6 +75,9 @@
 };
 
 static void
+fb_api_attach(FbApi *api, FbId aid, const gchar *msgid, FbApiMessage *msg);
+
+static void
 fb_api_contacts_after(FbApi *api, const gchar *writeid);
 
 static void
@@ -173,7 +176,7 @@
 	}
 
 	g_hash_table_destroy(priv->data);
-	g_hash_table_destroy(priv->msgids);
+	g_hash_table_destroy(priv->mids);
 
 	g_free(priv->cid);
 	g_free(priv->did);
@@ -484,8 +487,8 @@
 
 	priv->data = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 	                                   NULL, NULL);
-	priv->msgids = g_hash_table_new_full(g_int64_hash, g_int64_equal,
-	                                     g_free, NULL);
+	priv->mids = g_hash_table_new_full(g_int64_hash, g_int64_equal,
+	                                   g_free, NULL);
 }
 
 GQuark
@@ -943,18 +946,6 @@
 		fb_json_bldr_add_str(bldr, "device_id", priv->did);
 		fb_json_bldr_add_int(bldr, "entity_fbid", priv->uid);
 
-		fb_json_bldr_obj_begin(bldr, "device_params");
-		fb_json_bldr_add_str(bldr, "animated_image_format", "GIF");
-
-		fb_json_bldr_obj_begin(bldr, "animated_image_sizes");
-		fb_json_bldr_add_str(bldr, "0", "9001x9001");
-		fb_json_bldr_obj_end(bldr);
-
-		fb_json_bldr_obj_begin(bldr, "image_sizes");
-		fb_json_bldr_add_str(bldr, "0", "9001x9001");
-		fb_json_bldr_obj_end(bldr);
-		fb_json_bldr_obj_end(bldr);
-
 		fb_json_bldr_obj_begin(bldr, "queue_params");
 		fb_json_bldr_add_str(bldr, "buzz_on_deltas_enabled", "false");
 
@@ -966,8 +957,6 @@
 		fb_json_bldr_obj_begin(bldr, "graphql_query_params");
 		fb_json_bldr_obj_begin(bldr, G_STRINGIFY(FB_API_QUERY_XMA));
 		fb_json_bldr_add_str(bldr, "xma_id", "<ID>");
-		fb_json_bldr_add_str(bldr, "small_preview_size", "9001");
-		fb_json_bldr_add_str(bldr, "large_preview_size", "9001");
 		fb_json_bldr_obj_end(bldr);
 		fb_json_bldr_obj_end(bldr);
 		fb_json_bldr_obj_end(bldr);
@@ -1279,12 +1268,13 @@
 }
 
 static GSList *
-fb_api_message_parse_attach(FbApi *api, FbApiMessage *msg, GSList *msgs,
-                            const gchar *body, JsonNode *root, GError **error)
+fb_api_message_parse_attach(FbApi *api, const gchar *mid, FbApiMessage *msg,
+                            GSList *msgs, const gchar *body, JsonNode *root,
+                            GError **error)
 {
 	const gchar *str;
-	const gchar *url;
 	FbApiMessage *dmsg;
+	FbId id;
 	FbJsonValues *values;
 	gchar *xma;
 	GError *err = NULL;
@@ -1292,64 +1282,41 @@
 	JsonNode *xode;
 
 	values = fb_json_values_new(root);
-	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.mimeType");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
-	                   "$.imageMetadata.imageURIMap.0");
 	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.xmaGraphQL");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.filename");
+	fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE, "$.fbid");
 	fb_json_values_set_array(values, FALSE, "$.deltaNewMessage"
 	                                         ".attachments");
 
 	while (fb_json_values_update(values, &err)) {
 		str = fb_json_values_next_str(values, NULL);
-		url = fb_json_values_next_str(values, NULL);
-
-		if ((str != NULL) && g_str_has_prefix(str, "image/")) {
+
+		if (str == NULL) {
+			id = fb_json_values_next_int(values, 0);
 			dmsg = fb_api_message_dup(msg, FALSE);
-			dmsg->flags |= FB_API_MESSAGE_FLAG_IMAGE;
-			dmsg->text = g_strdup(url);
-			msgs = g_slist_prepend(msgs, dmsg);
+			fb_api_attach(api, id, mid, dmsg);
 			continue;
 		}
 
-		str = fb_json_values_next_str(values, NULL);
-
-		if (str != NULL) {
-			node = fb_json_node_new(str, -1, &err);
-
-			if (G_UNLIKELY(err != NULL)) {
-				break;
-			}
-
-			xode = fb_json_node_get_nth(node, 0);
-			xma = fb_api_xma_parse(api, body, xode, &err);
-
-			if (xma != NULL) {
-				dmsg = fb_api_message_dup(msg, FALSE);
-				dmsg->text = xma;
-				msgs = g_slist_prepend(msgs, dmsg);
-			}
-
-			json_node_free(node);
-
-			if (G_UNLIKELY(err != NULL)) {
-				break;
-			}
-
-			continue;
+		node = fb_json_node_new(str, -1, &err);
+
+		if (G_UNLIKELY(err != NULL)) {
+			break;
 		}
 
-		str = fb_json_values_next_str(values, NULL);
-
-		if (G_UNLIKELY(str == NULL)) {
-			str = _("unknown attachment");
+		xode = fb_json_node_get_nth(node, 0);
+		xma = fb_api_xma_parse(api, body, xode, &err);
+
+		if (xma != NULL) {
+			dmsg = fb_api_message_dup(msg, FALSE);
+			dmsg->text = xma;
+			msgs = g_slist_prepend(msgs, dmsg);
 		}
 
-		dmsg = fb_api_message_dup(msg, FALSE);
-		dmsg->text = g_strdup_printf("%s/%" FB_ID_FORMAT " [%s]",
-		                             FB_API_URL_MESSAGES,
-		                             msg->uid, str);
-		msgs = g_slist_prepend(msgs, dmsg);
+		json_node_free(node);
+
+		if (G_UNLIKELY(err != NULL)) {
+			break;
+		}
 	}
 
 	if (G_UNLIKELY(err != NULL)) {
@@ -1365,6 +1332,7 @@
 {
 	const gchar *body;
 	const gchar *data;
+	const gchar *str;
 	FbApiMessage *dmsg;
 	FbApiMessage msg;
 	FbApiPrivate *priv = api->priv;
@@ -1373,10 +1341,8 @@
 	FbId uid;
 	FbJsonValues *values;
 	FbThrift *thft;
-	gchar *json;
 	gchar *stoken;
 	GError *err = NULL;
-	GRegex *regex;
 	GSList *msgs = NULL;
 	guint size;
 	JsonNode *root;
@@ -1388,22 +1354,13 @@
 	g_object_unref(thft);
 
 	g_return_if_fail(size < pload->len);
-
 	data = (gchar *) pload->data + size;
 	size = pload->len - size;
 
-	/* Ugly hack to fix broken JSON from Facebook */
-	regex = g_regex_new("(\\d+)(:\")", 0, 0, &err);
-	json = g_regex_replace(regex, data, size, 0, "\"\\1\"\\2", 0, &err);
-	g_regex_unref(regex);
-	FB_API_ERROR_EMIT(api, err, return);
-
-	if (!fb_api_json_chk(api, json, -1, &root)) {
-		g_free(json);
+	if (!fb_api_json_chk(api, data, size, &root)) {
 		return;
 	}
 
-	g_free(json);
 	values = fb_json_values_new(root);
 	fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
 	                   "$.lastIssuedSeqId");
@@ -1444,12 +1401,14 @@
 	                   "$.deltaNewMessage.body");
 	fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
 	                   "$.deltaNewMessage.stickerId");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
+	                   "$.deltaNewMessage.messageMetadata.messageId");
 	fb_json_values_set_array(values, TRUE, "$.deltas");
 
 	while (fb_json_values_update(values, &err)) {
 		id = fb_json_values_next_int(values, 0);
 
-		if (g_hash_table_remove(priv->msgids, &id)) {
+		if (g_hash_table_remove(priv->mids, &id)) {
 			continue;
 		}
 
@@ -1484,8 +1443,14 @@
 			fb_api_sticker(api, id, dmsg);
 		}
 
+		str = fb_json_values_next_str(values, NULL);
+
+		if (str == NULL) {
+			continue;
+		}
+
 		node = fb_json_values_get_root(values);
-		msgs = fb_api_message_parse_attach(api, &msg, msgs, body,
+		msgs = fb_api_message_parse_attach(api, str, &msg, msgs, body,
 		                                   node, &err);
 
 		if (G_UNLIKELY(err != NULL)) {
@@ -1735,6 +1700,75 @@
 }
 
 static void
+fb_api_cb_attach(PurpleHttpConnection *con, PurpleHttpResponse *res,
+                 gpointer data)
+{
+	const gchar *str;
+	FbApi *api = data;
+	FbApiMessage *msg;
+	FbJsonValues *values;
+	gchar *name;
+	GError *err = NULL;
+	GSList *msgs = NULL;
+	guint i;
+	JsonNode *root;
+
+	static const gchar *imgexts[] = {".jpg", ".png", ".gif"};
+
+	if (!fb_api_http_chk(api, con, res, &root)) {
+		return;
+	}
+
+	values = fb_json_values_new(root);
+	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.filename");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.redirect_uri");
+	fb_json_values_update(values, &err);
+
+	FB_API_ERROR_EMIT(api, err,
+		g_object_unref(values);
+		json_node_free(root);
+		return;
+	);
+
+	msg = fb_api_data_take(api, con);
+	str = fb_json_values_next_str(values, NULL);
+	name = g_ascii_strdown(str, -1);
+
+	for (i = 0; i < G_N_ELEMENTS(imgexts); i++) {
+		if (g_str_has_suffix(name, imgexts[i])) {
+			msg->flags |= FB_API_MESSAGE_FLAG_IMAGE;
+			break;
+		}
+	}
+
+	g_free(name);
+	msg->text = fb_json_values_next_str_dup(values, NULL);
+	msgs = g_slist_prepend(msgs, msg);
+
+	g_signal_emit_by_name(api, "messages", msgs);
+	g_slist_free_full(msgs, (GDestroyNotify) fb_api_message_free);
+	g_object_unref(values);
+	json_node_free(root);
+
+}
+
+static void
+fb_api_attach(FbApi *api, FbId aid, const gchar *msgid, FbApiMessage *msg)
+{
+	FbHttpParams *prms;
+	PurpleHttpConnection *http;
+
+	prms = fb_http_params_new();
+	fb_http_params_set_str(prms, "mid", msgid);
+	fb_http_params_set_strf(prms, "aid", "%" FB_ID_FORMAT, aid);
+
+	http = fb_api_http_req(api, FB_API_URL_ATTACH, "getAttachment",
+	                       "messaging.getAttachment", prms,
+			       fb_api_cb_attach);
+	fb_api_data_set(api, http, msg, (GDestroyNotify) fb_api_message_free);
+}
+
+static void
 fb_api_cb_auth(PurpleHttpConnection *con, PurpleHttpResponse *res,
                gpointer data)
 {
@@ -2046,24 +2080,24 @@
 {
 	const gchar *tpfx;
 	FbApiPrivate *priv;
+	FbId *dmid;
+	FbId mid;
 	gchar *json;
-	guint64 *dmsgid;
-	guint64 msgid;
 	JsonBuilder *bldr;
 
 	g_return_if_fail(FB_IS_API(api));
 	g_return_if_fail(text != NULL);
 	priv = api->priv;
 
-	msgid = FB_API_MSGID(g_get_real_time() / 1000, g_random_int());
+	mid = FB_API_MSGID(g_get_real_time() / 1000, g_random_int());
 	tpfx = thread ? "tfbid_" : "";
 
-	dmsgid = g_memdup(&msgid, sizeof msgid);
-	g_hash_table_replace(priv->msgids, dmsgid, dmsgid);
+	dmid = g_memdup(&mid, sizeof mid);
+	g_hash_table_replace(priv->mids, dmid, dmid);
 
 	bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
-	fb_json_bldr_add_int(bldr, "msgid", msgid);
 	fb_json_bldr_add_str(bldr, "body", text);
+	fb_json_bldr_add_strf(bldr, "msgid", "%" FB_ID_FORMAT, mid);
 	fb_json_bldr_add_strf(bldr, "sender_fbid", "%" FB_ID_FORMAT, priv->uid);
 	fb_json_bldr_add_strf(bldr, "to", "%s%" FB_ID_FORMAT, tpfx, id);
 
@@ -2127,45 +2161,25 @@
 }
 
 static GSList *
-fb_api_cb_unread_parse_attach(FbApi *api, FbApiMessage *msg, GSList *msgs,
-                              JsonNode *root, GError **error)
+fb_api_cb_unread_parse_attach(FbApi *api, const gchar *mid, FbApiMessage *msg,
+                              GSList *msgs, JsonNode *root, GError **error)
 {
 	const gchar *str;
-	const gchar *url;
 	FbApiMessage *dmsg;
+	FbId id;
 	FbJsonValues *values;
 	GError *err = NULL;
 
 	values = fb_json_values_new(root);
-	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.mimetype");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE,
-	                   "$.image_full_screen.uri");
-	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.filename");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE,
+	                   "$.attachment_fbid");
 	fb_json_values_set_array(values, FALSE, "$.blob_attachments");
 
 	while (fb_json_values_update(values, &err)) {
 		str = fb_json_values_next_str(values, NULL);
-		url = fb_json_values_next_str(values, NULL);
-
-		if ((str != NULL) && g_str_has_prefix(str, "image/")) {
-			dmsg = fb_api_message_dup(msg, FALSE);
-			dmsg->flags |= FB_API_MESSAGE_FLAG_IMAGE;
-			dmsg->text = g_strdup(url);
-			msgs = g_slist_prepend(msgs, dmsg);
-			continue;
-		}
-
-		str = fb_json_values_next_str(values, NULL);
-
-		if (G_UNLIKELY(str == NULL)) {
-			str = _("unknown attachment");
-		}
-
+		id = FB_ID_FROM_STR(str);
 		dmsg = fb_api_message_dup(msg, FALSE);
-		dmsg->text = g_strdup_printf("%s/%" FB_ID_FORMAT " [%s]",
-		                             FB_API_URL_MESSAGES,
-		                             msg->uid, str);
-		msgs = g_slist_prepend(msgs, dmsg);
+		fb_api_attach(api, id, mid, dmsg);
 	}
 
 	if (G_UNLIKELY(err != NULL)) {
@@ -2229,6 +2243,7 @@
 	                   "$.message_sender.messaging_actor.id");
 	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.message.text");
 	fb_json_values_add(values, FB_JSON_TYPE_STR, FALSE, "$.sticker.id");
+	fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$.message_id");
 	fb_json_values_set_array(values, FALSE, "$.messages.nodes");
 
 	while (fb_json_values_update(values, &err)) {
@@ -2276,8 +2291,14 @@
 			}
 		}
 
-		msgs = fb_api_cb_unread_parse_attach(api, &msg, msgs, node,
-		                                     &err);
+		str = fb_json_values_next_str(values, NULL);
+
+		if (str == NULL) {
+			continue;
+		}
+
+		msgs = fb_api_cb_unread_parse_attach(api, str, &msg, msgs,
+		                                     node, &err);
 
 		if (G_UNLIKELY(err != NULL)) {
 			break;
--- a/libpurple/protocols/facebook/api.h	Thu Aug 20 21:45:58 2015 -0400
+++ b/libpurple/protocols/facebook/api.h	Fri Aug 21 00:41:38 2015 -0400
@@ -91,6 +91,14 @@
 #define FB_API_SECRET  "374e60f8b9bb6b8cbb30f78030438895"
 
 /**
+ * FB_API_URL_ATTACH:
+ *
+ * The URL for attachment URL requests.
+ */
+#define FB_API_URL_ATTACH  FB_API_AHOST "/method/messaging.getAttachment"
+//#define FB_API_URL_ATTACH  FB_API_AHOST "/method/messaging.attachmentRedirect"
+
+/**
  * FB_API_URL_AUTH:
  *
  * The URL for authentication requests.

mercurial