/soc/2015/jgeboski/facebook: aecff282de76: facebook: handle grou...
James Geboski
jgeboski at gmail.com
Mon Aug 10 23:24:04 EDT 2015
Changeset: aecff282de76da325dc736f5facedaa20b3a2218
Author: James Geboski <jgeboski at gmail.com>
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;
}
More information about the Commits
mailing list