/pidgin/main: 313fc6c8f415: facebook: implemented queued message...

James Geboski jgeboski at gmail.com
Thu Jan 7 15:34:25 EST 2016


Changeset: 313fc6c8f4153ce6c9388aa029da565949136711
Author:	 James Geboski <jgeboski at gmail.com>
Date:	 2016-01-04 17:17 -0500
Branch:	 default
URL: https://hg.pidgin.im/pidgin/main/rev/313fc6c8f415

Description:

facebook: implemented queued message sending

This ensures a message is sent successfully before attempting to send
another message. As a result, messages are sent in their proper order,
instead of the order in which they arrive. This also introduces a check
for the successful sending of a message, rather than silently failing.

The queued sending also ensures messages are not lost when the state of
visibility is being switched. This also allows the plugin to silently
reconnect when a connection failure occurs.

diffstat:

 libpurple/protocols/facebook/api.c |  134 +++++++++++++++++++++++++++---------
 1 files changed, 101 insertions(+), 33 deletions(-)

diffs (225 lines):

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
@@ -63,7 +63,7 @@ struct _FbApiPrivate
 	gchar *stoken;
 	gchar *token;
 
-	GHashTable *mids;
+	GQueue *msgs;
 	gboolean invisible;
 	guint unread;
 
@@ -82,6 +82,9 @@ static void
 fb_api_contacts_after(FbApi *api, const gchar *writeid);
 
 static void
+fb_api_message_send(FbApi *api, FbApiMessage *msg);
+
+static void
 fb_api_sticker(FbApi *api, FbId sid, FbApiMessage *msg);
 
 G_DEFINE_TYPE(FbApi, fb_api, G_TYPE_OBJECT);
@@ -175,7 +178,7 @@ fb_api_dispose(GObject *obj)
 
 	fb_http_conns_free(priv->cons);
 	g_hash_table_destroy(priv->data);
-	g_hash_table_destroy(priv->mids);
+	g_queue_free_full(priv->msgs, (GDestroyNotify) fb_api_message_free);
 
 	g_free(priv->cid);
 	g_free(priv->did);
@@ -485,10 +488,9 @@ fb_api_init(FbApi *api)
 	api->priv = priv;
 
 	priv->cons = fb_http_conns_new();
+	priv->msgs = g_queue_new();
 	priv->data = g_hash_table_new_full(g_direct_hash, g_direct_equal,
 	                                   NULL, NULL);
-	priv->mids = g_hash_table_new_full(g_int64_hash, g_int64_equal,
-	                                   g_free, NULL);
 }
 
 GQuark
@@ -938,6 +940,7 @@ fb_api_cb_mqtt_open(FbMqtt *mqtt, gpoint
 static void
 fb_api_connect_queue(FbApi *api)
 {
+	FbApiMessage *msg;
 	FbApiPrivate *priv = api->priv;
 	gchar *json;
 	JsonBuilder *bldr;
@@ -984,6 +987,10 @@ fb_api_connect_queue(FbApi *api)
 	g_signal_emit_by_name(api, "connect");
 	g_free(json);
 
+	if (!g_queue_is_empty(priv->msgs)) {
+		msg = g_queue_peek_head(priv->msgs);
+		fb_api_message_send(api, msg);
+	}
 }
 
 static void
@@ -1262,6 +1269,47 @@ fb_api_cb_publish_typing(FbApi *api, GBy
 	json_node_free(root);
 }
 
+static void
+fb_api_cb_publish_ms_r(FbApi *api, GByteArray *pload)
+{
+	FbApiMessage *msg;
+	FbApiPrivate *priv = api->priv;
+	FbJsonValues *values;
+	GError *err = NULL;
+	JsonNode *root;
+
+	if (!fb_api_json_chk(api, pload->data, pload->len, &root)) {
+		return;
+	}
+
+	values = fb_json_values_new(root);
+	fb_json_values_add(values, FB_JSON_TYPE_BOOL, TRUE, "$.succeeded");
+	fb_json_values_update(values, &err);
+
+	FB_API_ERROR_EMIT(api, err,
+		g_object_unref(values);
+		json_node_free(root);
+		return;
+	);
+
+	if (fb_json_values_next_bool(values, TRUE)) {
+		/* Pop and free the successful message */
+		msg = g_queue_pop_head(priv->msgs);
+		fb_api_message_free(msg);
+
+		if (!g_queue_is_empty(priv->msgs)) {
+			msg = g_queue_peek_head(priv->msgs);
+			fb_api_message_send(api, msg);
+		}
+	} else {
+		fb_api_error(api, FB_API_ERROR_GENERAL,
+					 "Failed to send message");
+	}
+
+	g_object_unref(values);
+	json_node_free(root);
+}
+
 static gchar *
 fb_api_xma_parse(FbApi *api, const gchar *body, JsonNode *root, GError **error)
 {
@@ -1432,9 +1480,6 @@ fb_api_cb_publish_ms(FbApi *api, GByteAr
 
 	values = fb_json_values_new(root);
 	fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
-	                   "$.deltaNewMessage.messageMetadata"
-			    ".offlineThreadingId");
-	fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
 	                   "$.deltaNewMessage.messageMetadata.actorFbId");
 	fb_json_values_add(values, FB_JSON_TYPE_INT, FALSE,
 	                   "$.deltaNewMessage.messageMetadata"
@@ -1453,12 +1498,6 @@ fb_api_cb_publish_ms(FbApi *api, GByteAr
 	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->mids, &id)) {
-			continue;
-		}
-
 		fb_api_message_reset(&msg, FALSE);
 		msg.uid = fb_json_values_next_int(values, 0);
 		oid = fb_json_values_next_int(values, 0);
@@ -1646,6 +1685,7 @@ fb_api_cb_mqtt_publish(FbMqtt *mqtt, con
 		{"/mark_thread_response", fb_api_cb_publish_mark},
 		{"/mercury", fb_api_cb_publish_mercury},
 		{"/orca_typing_notifications", fb_api_cb_publish_typing},
+		{"/send_message_response", fb_api_cb_publish_ms_r},
 		{"/t_ms", fb_api_cb_publish_ms},
 		{"/t_p", fb_api_cb_publish_p}
 	};
@@ -2119,35 +2159,63 @@ fb_api_disconnect(FbApi *api)
 	fb_mqtt_disconnect(priv->mqtt);
 }
 
+static void
+fb_api_message_send(FbApi *api, FbApiMessage *msg)
+{
+	const gchar *tpfx;
+	FbApiPrivate *priv = api->priv;
+	FbId id;
+	FbId mid;
+	gchar *json;
+	JsonBuilder *bldr;
+
+	mid = FB_API_MSGID(g_get_real_time() / 1000, g_random_int());
+
+	if (msg->tid != 0) {
+		tpfx = "tfbid_";
+		id = msg->tid;
+	} else {
+		tpfx = "";
+		id = msg->uid;
+	}
+
+	bldr = fb_json_bldr_new(JSON_NODE_OBJECT);
+	fb_json_bldr_add_str(bldr, "body", msg->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);
+
+	json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
+	fb_api_publish(api, "/send_message2", "%s", json);
+	g_free(json);
+}
+
 void
 fb_api_message(FbApi *api, FbId id, gboolean thread, const gchar *text)
 {
-	const gchar *tpfx;
+	FbApiMessage *msg;
 	FbApiPrivate *priv;
-	FbId *dmid;
-	FbId mid;
-	gchar *json;
-	JsonBuilder *bldr;
+	gboolean empty;
 
 	g_return_if_fail(FB_IS_API(api));
 	g_return_if_fail(text != NULL);
 	priv = api->priv;
 
-	mid = FB_API_MSGID(g_get_real_time() / 1000, g_random_int());
-	tpfx = thread ? "tfbid_" : "";
-
-	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_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);
-
-	json = fb_json_bldr_close(bldr, JSON_NODE_OBJECT, NULL);
-	fb_api_publish(api, "/send_message2", "%s", json);
-	g_free(json);
+	msg = fb_api_message_dup(NULL, FALSE);
+	msg->text = g_strdup(text);
+
+	if (thread) {
+		msg->tid = id;
+	} else {
+		msg->uid = id;
+	}
+
+	empty = g_queue_is_empty(priv->msgs);
+	g_queue_push_tail(priv->msgs, msg);
+
+	if (empty && fb_mqtt_connected(priv->mqtt, FALSE)) {
+		fb_api_message_send(api, msg);
+	}
 }
 
 void



More information about the Commits mailing list