/soc/2015/jgeboski/facebook: aecff282de76: facebook: handle grou...
James Geboski <[email protected]>
| Newsgroups | gmane.comp.gnome.gaim.cvs |
|---|---|
| Message-ID | <[email protected]> |
Changeset: aecff282de76da325dc736f5facedaa20b3a2218 Author: James Geboski <[email protected]> Date: 2015-08-10 16:57 -0400 Branch: facebook URL: https://hg.pidgin.im/soc/2015/jgeboski/facebook/rev/aecff282de76 Description: facebook: handle group chat events diffstat: libpurple/protocols/facebook/api.c | 123 ++++++++++++++++++++++++++++++++ libpurple/protocols/facebook/api.h | 24 ++++++ libpurple/protocols/facebook/facebook.c | 46 +++++++++++- 3 files changed, 191 insertions(+), 2 deletions(-) diffs (289 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 @@ -240,6 +240,14 @@ fb_api_class_init(FbApiClass *klass) fb_marshal_VOID__OBJECT, G_TYPE_NONE, 1, G_TYPE_ERROR); + g_signal_new("events", + 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("messages", G_TYPE_FROM_CLASS(klass), G_SIGNAL_ACTION, @@ -865,6 +873,98 @@ fb_api_cb_publish_mark(FbApi *api, GByte json_node_free(root); } +static GSList * +fb_api_event_parse(FbApi *api, FbApiEvent *event, GSList *events, + JsonNode *root, GError **error) +{ + const gchar *str; + FbJsonValues *values; + GError *err = NULL; + gpointer mptr; + guint i; + + static const struct { + FbApiEventType type; + const gchar *expr; + } evtypes[] = { + { + FB_API_EVENT_TYPE_THREAD_USER_ADDED, + "$.log_message_data.added_participants" + }, { + FB_API_EVENT_TYPE_THREAD_USER_REMOVED, + "$.log_message_data.removed_participants" + } + }; + + for (i = 0; i < G_N_ELEMENTS(evtypes); i++) { + event->type = evtypes[i].type; + values = fb_json_values_new(root); + fb_json_values_add(values, FB_JSON_TYPE_STR, TRUE, "$"); + fb_json_values_set_array(values, FALSE, evtypes[i].expr); + + while (fb_json_values_update(values, &err)) { + str = fb_json_values_next_str(values, ""); + str = strrchr(str, ':'); + + if (str != NULL) { + event->uid = FB_ID_FROM_STR(str + 1); + mptr = fb_api_event_dup(event); + events = g_slist_prepend(events, mptr); + } + } + + fb_json_values_free(values); + + if (G_UNLIKELY(err != NULL)) { + g_propagate_error(error, err); + break; + } + } + + return events; +} + +static void +fb_api_cb_mercury(FbApi *api, GByteArray *pload) +{ + const gchar *str; + FbApiEvent event; + FbJsonValues *values; + GError *err = NULL; + GSList *events = NULL; + JsonNode *root; + JsonNode *node; + + 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_STR, TRUE, "$.thread_fbid"); + fb_json_values_set_array(values, FALSE, "$.actions"); + + while (fb_json_values_update(values, &err)) { + fb_api_event_reset(&event); + str = fb_json_values_next_str(values, "0"); + event.tid = FB_ID_FROM_STR(str); + + node = fb_json_values_get_root(values); + events = fb_api_event_parse(api, &event, events, node, &err); + } + + if (G_LIKELY(err == NULL)) { + events = g_slist_reverse(events); + g_signal_emit_by_name(api, "events", events); + } else { + fb_api_error_emit(api, err); + } + + g_slist_free_full(events, (GDestroyNotify) fb_api_event_free); + fb_json_values_free(values); + json_node_free(root); + +} + static void fb_api_cb_publish_typing(FbApi *api, GByteArray *pload) { @@ -1273,6 +1373,7 @@ fb_api_cb_mqtt_publish(FbMqtt *mqtt, con void (*func) (FbApi *api, GByteArray *pload); } parsers[] = { {"/mark_thread_response", fb_api_cb_publish_mark}, + {"/mercury", fb_api_cb_mercury}, {"/orca_typing_notifications", fb_api_cb_publish_typing}, {"/t_ms", fb_api_cb_publish_ms}, {"/t_p", fb_api_cb_publish_p} @@ -2333,6 +2434,28 @@ fb_api_typing(FbApi *api, FbId uid, gboo g_free(json); } +FbApiEvent * +fb_api_event_dup(FbApiEvent *event) +{ + g_return_val_if_fail(event != NULL, NULL); + return g_memdup(event, sizeof *event); +} + +void +fb_api_event_reset(FbApiEvent *event) +{ + g_return_if_fail(event != NULL); + memset(event, 0, sizeof *event); +} + +void +fb_api_event_free(FbApiEvent *event) +{ + if (G_LIKELY(event != NULL)) { + g_free(event); + } +} + FbApiMessage * fb_api_message_dup(FbApiMessage *msg, gboolean deep) { 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 @@ -79,9 +79,11 @@ #define FB_API_ERROR fb_api_error_quark() typedef enum _FbApiError FbApiError; +typedef enum _FbApiEventType FbApiEventType; typedef struct _FbApi FbApi; typedef struct _FbApiClass FbApiClass; typedef struct _FbApiPrivate FbApiPrivate; +typedef struct _FbApiEvent FbApiEvent; typedef struct _FbApiMessage FbApiMessage; typedef struct _FbApiPresence FbApiPresence; typedef struct _FbApiThread FbApiThread; @@ -95,6 +97,12 @@ enum _FbApiError FB_API_ERROR_AUTH }; +enum _FbApiEventType +{ + FB_API_EVENT_TYPE_THREAD_USER_ADDED, + FB_API_EVENT_TYPE_THREAD_USER_REMOVED +}; + struct _FbApi { GObject parent; @@ -106,6 +114,13 @@ struct _FbApiClass GObjectClass parent_class; }; +struct _FbApiEvent +{ + FbApiEventType type; + FbId uid; + FbId tid; +}; + struct _FbApiMessage { FbId uid; @@ -210,6 +225,15 @@ fb_api_threads(FbApi *api); void fb_api_typing(FbApi *api, FbId uid, gboolean state); +FbApiEvent * +fb_api_event_dup(FbApiEvent *event); + +void +fb_api_event_reset(FbApiEvent *event); + +void +fb_api_event_free(FbApiEvent *event); + FbApiMessage * fb_api_message_dup(FbApiMessage *msg, gboolean deep); diff --git a/libpurple/protocols/facebook/facebook.c b/libpurple/protocols/facebook/facebook.c --- a/libpurple/protocols/facebook/facebook.c +++ b/libpurple/protocols/facebook/facebook.c @@ -224,6 +224,46 @@ fb_cb_api_error(FbApi *api, GError *erro } static void +fb_cb_api_events(FbApi *api, GSList *events, gpointer data) +{ + FbData *fata = data; + FbApiEvent *event; + gchar uid[FB_ID_STRMAX]; + gchar tid[FB_ID_STRMAX]; + GSList *l; + PurpleAccount *acct; + PurpleChatConversation *chat; + PurpleConnection *gc; + + gc = fb_data_get_connection(fata); + acct = purple_connection_get_account(gc); + + for (l = events; l != NULL; l = l->next) { + event = l->data; + + FB_ID_TO_STR(event->tid, tid); + chat = purple_conversations_find_chat_with_account(tid, acct); + + if (chat == NULL) { + continue; + } + + FB_ID_TO_STR(event->uid, uid); + + switch (event->type) { + case FB_API_EVENT_TYPE_THREAD_USER_ADDED: + purple_chat_conversation_add_user(chat, uid, NULL, 0, + TRUE); + break; + + case FB_API_EVENT_TYPE_THREAD_USER_REMOVED: + purple_chat_conversation_remove_user(chat, uid, NULL); + break; + } + } +} + +static void fb_cb_api_messages(FbApi *api, GSList *msgs, gpointer data) { FbApiMessage *msg; @@ -535,6 +575,10 @@ fb_login(PurpleAccount *acct) G_CALLBACK(fb_cb_api_error), fata); g_signal_connect(api, + "events", + G_CALLBACK(fb_cb_api_events), + fata); + g_signal_connect(api, "messages", G_CALLBACK(fb_cb_api_messages), fata); @@ -829,7 +873,6 @@ fb_chat_invite(PurpleConnection *gc, gin tid = FB_ID_FROM_STR(name); uid = FB_ID_FROM_STR(who); - purple_chat_conversation_add_user(chat, who, NULL, 0, TRUE); fb_api_thread_invite(api, tid, uid); } @@ -983,7 +1026,6 @@ fb_cmd_kick(PurpleConversation *conv, co name = purple_buddy_get_name(bdy); uid = FB_ID_FROM_STR(name); - purple_chat_conversation_remove_user(chat, name, NULL); fb_api_thread_remove(api, tid, uid); return PURPLE_CMD_RET_OK; } _______________________________________________ Commits mailing list [email protected] https://pidgin.im/cgi-bin/mailman/listinfo/commits