/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
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.