facebook: implemented kicking/leaving group chats facebook

Sun, 05 Jul 2015 14:44:14 -0400

author
James Geboski <jgeboski@gmail.com>
date
Sun, 05 Jul 2015 14:44:14 -0400
branch
facebook
changeset 37284
53cb588d8760
parent 37283
38fdbcc84bcd
child 37285
2a5decfdeb7b

facebook: implemented kicking/leaving group chats

libpurple/protocols/facebook/api.c file | annotate | diff | comparison | revisions
libpurple/protocols/facebook/api.h file | annotate | diff | comparison | revisions
libpurple/protocols/facebook/facebook.c file | annotate | diff | comparison | revisions
libpurple/protocols/facebook/json.c file | annotate | diff | comparison | revisions
libpurple/protocols/facebook/util.c file | annotate | diff | comparison | revisions
libpurple/protocols/facebook/util.h file | annotate | diff | comparison | revisions
--- a/libpurple/protocols/facebook/api.c	Sat Jul 04 13:26:42 2015 -0400
+++ b/libpurple/protocols/facebook/api.c	Sun Jul 05 14:44:14 2015 -0400
@@ -1219,6 +1219,7 @@
 	FbApiPrivate *priv = api->priv;
 	FbApiThread thrd;
 	FbApiUser user;
+	gboolean haself;
 	gchar *str;
 	GError *err = NULL;
 	GList *elms = NULL;
@@ -1258,7 +1259,7 @@
 		FB_API_ERROR_CHK(api, err, goto finish);
 		elms2 = json_array_get_elements(arr2);
 
-		for (m = elms2; m != NULL; m = m->next) {
+		for (haself = FALSE, m = elms2; m != NULL; m = m->next) {
 			node2 = m->data;
 			fb_api_user_reset(&user, FALSE);
 
@@ -1268,6 +1269,7 @@
 			g_free(str);
 
 			if (user.uid == priv->uid) {
+				haself = TRUE;
 				continue;
 			}
 
@@ -1289,8 +1291,12 @@
 			continue;
 		}
 
-		mptr = fb_api_thread_dup(&thrd, FALSE);
-		thrds = g_slist_prepend(thrds, mptr);
+		if (haself) {
+			mptr = fb_api_thread_dup(&thrd, FALSE);
+			thrds = g_slist_prepend(thrds, mptr);
+		} else {
+			fb_api_thread_reset(&thrd, TRUE);
+		}
 	}
 
 	ret = g_slist_reverse(thrds);
@@ -1428,6 +1434,42 @@
 }
 
 void
+fb_api_thread_remove(FbApi *api, FbId tid, FbId uid)
+{
+	FbApiPrivate *priv;
+	FbHttpParams *prms;
+	gchar *json;
+	JsonBuilder *bldr;
+
+	static const FbApiHttpInfo info = {
+		fb_api_cb_http_bool,
+		"com.facebook.orca.protocol.a",
+		"removeMembers",
+		"DELETE"
+	};
+
+	g_return_if_fail(api != NULL);
+	priv = api->priv;
+
+	prms = fb_http_params_new();
+	fb_http_params_set_strf(prms, "id", "t_id.%" FB_ID_FORMAT, tid);
+
+	if (uid == 0) {
+		uid = priv->uid;
+	}
+
+	if (uid != priv->uid) {
+		bldr = fb_json_bldr_new(JSON_NODE_ARRAY);
+		fb_json_bldr_add_strf(bldr, NULL, "%" FB_ID_FORMAT, uid);
+		json = fb_json_bldr_close(bldr, JSON_NODE_ARRAY, NULL);
+		fb_http_params_set_str(prms, "to", json);
+		g_free(json);
+	}
+
+	fb_api_http_req(api, &info, prms, FB_API_URL_PARTS);
+}
+
+void
 fb_api_thread_topic(FbApi *api, FbId tid, const gchar *topic)
 {
 	FbHttpParams *prms;
--- a/libpurple/protocols/facebook/api.h	Sat Jul 04 13:26:42 2015 -0400
+++ b/libpurple/protocols/facebook/api.h	Sun Jul 05 14:44:14 2015 -0400
@@ -191,6 +191,9 @@
 fb_api_thread_list(FbApi *api);
 
 void
+fb_api_thread_remove(FbApi *api, FbId tid, FbId uid);
+
+void
 fb_api_thread_topic(FbApi *api, FbId tid, const gchar *topic);
 
 void
--- a/libpurple/protocols/facebook/facebook.c	Sat Jul 04 13:26:42 2015 -0400
+++ b/libpurple/protocols/facebook/facebook.c	Sun Jul 05 14:44:14 2015 -0400
@@ -30,11 +30,13 @@
 #include "version.h"
 
 #include "api.h"
+#include "cmds.h"
 #include "data.h"
 #include "facebook.h"
 #include "util.h"
 
-static PurpleProtocol *my_protocol = NULL;
+static GSList *fb_cmds = NULL;
+static PurpleProtocol *fb_protocol = NULL;
 
 static void
 fb_cb_api_error(FbApi *api, GError *error, gpointer data);
@@ -739,6 +741,79 @@
 	g_object_unref(list);
 }
 
+static PurpleCmdRet
+fb_cmd_kick(PurpleConversation *conv, const gchar *cmd, gchar **args,
+            gchar **error, gpointer data)
+{
+	const gchar *name;
+	FbApi *api;
+	FbData *fata;
+	FbId tid;
+	FbId uid;
+	GError *err = NULL;
+	PurpleAccount *acct;
+	PurpleBuddy *bdy;
+	PurpleConnection *gc;
+	PurpleChatConversation *chat;
+
+	g_return_val_if_fail(PURPLE_IS_CHAT_CONVERSATION(conv),
+	                     PURPLE_CMD_RET_FAILED);
+
+	gc = purple_conversation_get_connection(conv);
+	acct = purple_connection_get_account(gc);
+	chat = PURPLE_CHAT_CONVERSATION(conv);
+	bdy = fb_util_account_find_buddy(acct, chat, args[0], &err);
+
+	if (err != NULL) {
+		*error = g_strdup_printf(_("%s."), err->message);
+		g_error_free(err);
+		return PURPLE_CMD_RET_FAILED;
+	}
+
+	fata = purple_connection_get_protocol_data(gc);
+	api = fb_data_get_api(fata);
+
+	name = purple_conversation_get_name(conv);
+	tid = FB_ID_FROM_STR(name);
+
+	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;
+}
+
+static PurpleCmdRet
+fb_cmd_leave(PurpleConversation *conv, const gchar *cmd, gchar **args,
+             gchar **error, gpointer data)
+{
+	const gchar *name;
+	FbApi *api;
+	FbData *fata;
+	FbId tid;
+	gint id;
+	PurpleConnection *gc;
+	PurpleChatConversation *chat;
+
+	g_return_val_if_fail(PURPLE_IS_CHAT_CONVERSATION(conv),
+	                     PURPLE_CMD_RET_FAILED);
+
+	gc = purple_conversation_get_connection(conv);
+	fata = purple_connection_get_protocol_data(gc);
+	api = fb_data_get_api(fata);
+
+	chat = PURPLE_CHAT_CONVERSATION(conv);
+	id = purple_chat_conversation_get_id(chat);
+
+	name = purple_conversation_get_name(conv);
+	tid = FB_ID_FROM_STR(name);
+
+	purple_serv_got_chat_left(gc, id);
+	fb_api_thread_remove(api, tid, 0);
+	return PURPLE_CMD_RET_OK;
+}
+
 static void
 facebook_protocol_init(PurpleProtocol *protocol)
 {
@@ -814,6 +889,43 @@
 	                                  facebook_protocol_roomlist_iface_init)
 );
 
+static void
+fb_cmds_register(void)
+{
+	PurpleCmdId id;
+
+	static PurpleCmdFlag cflags =
+		PURPLE_CMD_FLAG_CHAT |
+		PURPLE_CMD_FLAG_PROTOCOL_ONLY;
+
+	g_return_if_fail(fb_cmds == NULL);
+
+	id = purple_cmd_register("kick", "s", PURPLE_CMD_P_PROTOCOL, cflags,
+				 fb_protocol->id, fb_cmd_kick,
+				 _("kick: Kick someone from the chat"),
+				 NULL);
+	fb_cmds = g_slist_prepend(fb_cmds, GUINT_TO_POINTER(id));
+
+	id = purple_cmd_register("leave", "", PURPLE_CMD_P_PROTOCOL, cflags,
+				 fb_protocol->id, fb_cmd_leave,
+				 _("leave: Leave the chat"),
+				 NULL);
+	fb_cmds = g_slist_prepend(fb_cmds, GUINT_TO_POINTER(id));
+}
+
+static void
+fb_cmds_unregister_free(gpointer data)
+{
+	PurpleCmdId id = GPOINTER_TO_UINT(data);
+	purple_cmd_unregister(id);
+}
+
+static void
+fb_cmds_unregister(void)
+{
+	g_slist_free_full(fb_cmds, fb_cmds_unregister_free);
+}
+
 static PurplePluginInfo *
 plugin_query(GError **error)
 {
@@ -836,14 +948,21 @@
 plugin_load(PurplePlugin *plugin, GError **error)
 {
 	facebook_protocol_register_type(plugin);
-	my_protocol = purple_protocols_add(FACEBOOK_TYPE_PROTOCOL, error);
-	return my_protocol != NULL;
+	fb_protocol = purple_protocols_add(FACEBOOK_TYPE_PROTOCOL, error);
+
+	if (fb_protocol == NULL) {
+		return FALSE;
+	}
+
+	fb_cmds_register();
+	return TRUE;
 }
 
 static gboolean
 plugin_unload(PurplePlugin *plugin, GError **error)
 {
-	return purple_protocols_remove(my_protocol, error);
+	fb_cmds_unregister();
+	return purple_protocols_remove(fb_protocol, error);
 }
 
 PURPLE_PLUGIN_INIT(facebook, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/facebook/json.c	Sat Jul 04 13:26:42 2015 -0400
+++ b/libpurple/protocols/facebook/json.c	Sun Jul 05 14:44:14 2015 -0400
@@ -128,28 +128,40 @@
 void
 fb_json_bldr_add_bool(JsonBuilder *bldr, const gchar *name, gboolean value)
 {
-	json_builder_set_member_name(bldr, name);
+	if (name != NULL) {
+		json_builder_set_member_name(bldr, name);
+	}
+
 	json_builder_add_boolean_value(bldr, value);
 }
 
 void
 fb_json_bldr_add_dbl(JsonBuilder *bldr, const gchar *name, gdouble value)
 {
-	json_builder_set_member_name(bldr, name);
+	if (name != NULL) {
+		json_builder_set_member_name(bldr, name);
+	}
+
 	json_builder_add_double_value(bldr, value);
 }
 
 void
 fb_json_bldr_add_int(JsonBuilder *bldr, const gchar *name, gint64 value)
 {
-	json_builder_set_member_name(bldr, name);
+	if (name != NULL) {
+		json_builder_set_member_name(bldr, name);
+	}
+
 	json_builder_add_int_value(bldr, value);
 }
 
 void
 fb_json_bldr_add_str(JsonBuilder *bldr, const gchar *name, const gchar *value)
 {
-	json_builder_set_member_name(bldr, name);
+	if (name != NULL) {
+		json_builder_set_member_name(bldr, name);
+	}
+
 	json_builder_add_string_value(bldr, value);
 }
 
@@ -164,9 +176,7 @@
 	value = g_strdup_vprintf(format, ap);
 	va_end(ap);
 
-	json_builder_set_member_name(bldr, name);
-	json_builder_add_string_value(bldr, value);
-
+	fb_json_bldr_add_str(bldr, name, value);
 	g_free(value);
 }
 
--- a/libpurple/protocols/facebook/util.c	Sat Jul 04 13:26:42 2015 -0400
+++ b/libpurple/protocols/facebook/util.c	Sun Jul 05 14:44:14 2015 -0400
@@ -27,6 +27,68 @@
 
 #include "util.h"
 
+GQuark
+fb_util_error_quark(void)
+{
+	static GQuark q = 0;
+
+	if (G_UNLIKELY(q == 0)) {
+		q = g_quark_from_static_string("fb-util-error-quark");
+	}
+
+	return q;
+}
+
+PurpleBuddy *
+fb_util_account_find_buddy(PurpleAccount *acct, PurpleChatConversation *chat,
+                           const gchar *search, GError **error)
+{
+	const gchar *alias;
+	const gchar *name;
+	GSList *buddies;
+	GSList *l;
+	guint retc;
+	PurpleBuddy *ret = NULL;
+
+	g_return_val_if_fail(acct != NULL, NULL);
+	g_return_val_if_fail(search != NULL, NULL);
+
+	buddies = purple_blist_find_buddies(acct, NULL);
+
+	for (retc = 0, l = buddies; l != NULL; l = l->next) {
+		name = purple_buddy_get_name(l->data);
+		alias = purple_buddy_get_alias(l->data);
+
+		if ((chat != NULL) &&
+		    !purple_chat_conversation_has_user(chat, name))
+		{
+			continue;
+		}
+
+		if (g_ascii_strcasecmp(name, search) == 0) {
+			ret = l->data;
+			retc++;
+		}
+
+		if (g_ascii_strcasecmp(alias, search) == 0) {
+			ret = l->data;
+			retc++;
+		}
+	}
+
+	if (retc == 0) {
+		g_set_error(error, FB_UTIL_ERROR, FB_UTIL_ERROR_GENERAL,
+		            _("Buddy %s not found"), search);
+	} else if (retc > 1) {
+		g_set_error(error, FB_UTIL_ERROR, FB_UTIL_ERROR_GENERAL,
+		            _("Buddy name %s is ambiguous"), search);
+		ret = NULL;
+	}
+
+	g_slist_free(buddies);
+	return ret;
+}
+
 void
 fb_util_debug(PurpleDebugLevel level, const gchar *format, ...)
 {
--- a/libpurple/protocols/facebook/util.h	Sat Jul 04 13:26:42 2015 -0400
+++ b/libpurple/protocols/facebook/util.h	Sun Jul 05 14:44:14 2015 -0400
@@ -31,7 +31,10 @@
 		FB_UTIL_DEBUG_FLAG_VERBOSE  \
 	)
 
+#define FB_UTIL_ERROR fb_util_error_quark()
+
 typedef enum _FbUtilDebugFlags FbUtilDebugFlags;
+typedef enum _FbUtilError FbUtilError;
 
 typedef void (*FbUtilRequestBuddyFunc) (GSList *buddies, gpointer data);
 
@@ -41,6 +44,19 @@
 	FB_UTIL_DEBUG_FLAG_VERBOSE = 1 << 26
 };
 
+enum _FbUtilError
+{
+	FB_UTIL_ERROR_GENERAL
+};
+
+
+GQuark
+fb_util_error_quark(void);
+
+PurpleBuddy *
+fb_util_account_find_buddy(PurpleAccount *acct, PurpleChatConversation *chat,
+                           const gchar *name, GError **error);
+
 void
 fb_util_debug(PurpleDebugLevel level, const gchar *format, ...)
               G_GNUC_PRINTF(2, 3);

mercurial