diff options
author | jgeboski <jgeboski@gmail.com> | 2016-01-04 17:17:32 -0500 |
---|---|---|
committer | jgeboski <jgeboski@gmail.com> | 2016-01-04 18:59:36 -0500 |
commit | 074cfd563cf75f37b9fafbd9dfc1ed8f130dd343 (patch) | |
tree | 4013ad7acd21c145d3577dfded4e5e2271716b0d | |
parent | 56d729851a1a431cbdd28b9c5626fd7e1c86d9e0 (diff) | |
download | bitlbee-facebook-074cfd563cf75f37b9fafbd9dfc1ed8f130dd343.tar.gz bitlbee-facebook-074cfd563cf75f37b9fafbd9dfc1ed8f130dd343.tar.bz2 bitlbee-facebook-074cfd563cf75f37b9fafbd9dfc1ed8f130dd343.tar.xz |
facebook-api: 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.
-rw-r--r-- | facebook/facebook-api.c | 118 |
1 files changed, 93 insertions, 25 deletions
diff --git a/facebook/facebook-api.c b/facebook/facebook-api.c index 6b30bcd..e552e3a 100644 --- a/facebook/facebook-api.c +++ b/facebook/facebook-api.c @@ -56,7 +56,7 @@ struct _FbApiPrivate gchar *stoken; gchar *token; - GHashTable *mids; + GQueue *msgs; gboolean invisible; guint unread; @@ -75,6 +75,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); @@ -163,9 +166,8 @@ fb_api_dispose(GObject *obj) g_object_unref(priv->http); g_object_unref(priv->mqtt); - 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); @@ -476,10 +478,9 @@ fb_api_init(FbApi *api) priv->http = fb_http_new(NULL); priv->mqtt = fb_mqtt_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 @@ -891,6 +892,7 @@ fb_api_cb_mqtt_open(FbMqtt *mqtt, gpointer data) static void fb_api_connect_queue(FbApi *api) { + FbApiMessage *msg; FbApiPrivate *priv = api->priv; gchar *json; JsonBuilder *bldr; @@ -935,6 +937,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 @@ -1210,6 +1216,47 @@ fb_api_cb_publish_typing(FbApi *api, GByteArray *pload) 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) { @@ -1379,8 +1426,6 @@ fb_api_cb_publish_ms(FbApi *api, GByteArray *pload) 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" @@ -1399,12 +1444,6 @@ fb_api_cb_publish_ms(FbApi *api, GByteArray *pload) 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); @@ -1592,6 +1631,7 @@ fb_api_cb_mqtt_publish(FbMqtt *mqtt, const gchar *topic, GByteArray *pload, {"/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} }; @@ -2060,28 +2100,28 @@ fb_api_disconnect(FbApi *api) fb_mqtt_disconnect(priv->mqtt); } -void -fb_api_message(FbApi *api, FbId id, gboolean thread, const gchar *text) +static void +fb_api_message_send(FbApi *api, FbApiMessage *msg) { const gchar *tpfx; - FbApiPrivate *priv; - FbId *dmid; + FbApiPrivate *priv = api->priv; + FbId id; FbId mid; gchar *json; JsonBuilder *bldr; - 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); + 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", text); + 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); @@ -2092,6 +2132,34 @@ fb_api_message(FbApi *api, FbId id, gboolean thread, const gchar *text) } void +fb_api_message(FbApi *api, FbId id, gboolean thread, const gchar *text) +{ + FbApiMessage *msg; + FbApiPrivate *priv; + gboolean empty; + + g_return_if_fail(FB_IS_API(api)); + g_return_if_fail(text != NULL); + priv = api->priv; + + 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 fb_api_publish(FbApi *api, const gchar *topic, const gchar *format, ...) { FbApiPrivate *priv; |