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

James Geboski <[email protected]>
Newsgroups gmane.comp.gnome.gaim.cvs
Message-ID <[email protected]>
Changeset: 313fc6c8f4153ce6c9388aa029da565949136711
Author:	 James Geboski <[email protected]>
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

_______________________________________________
Commits mailing list
[email protected]
https://pidgin.im/cgi-bin/mailman/listinfo/commits
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.