libpurple/protocols/facebook/facebook.c

Sat, 04 Jul 2015 13:26:42 -0400

author
James Geboski <jgeboski@gmail.com>
date
Sat, 04 Jul 2015 13:26:42 -0400
branch
facebook
changeset 37283
38fdbcc84bcd
parent 37282
0bd9b2c3f5b7
child 37284
53cb588d8760
permissions
-rw-r--r--

facebook: use PURPLE_IS_BUDDY() over manual check

/* purple
 *
 * Purple is the legal property of its developers, whose names are too numerous
 * to list here.  Please refer to the COPYRIGHT file distributed with this
 * source distribution.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 */

#include "internal.h"

#include "account.h"
#include "connection.h"
#include "plugins.h"
#include "protocol.h"
#include "protocols.h"
#include "roomlist.h"
#include "version.h"

#include "api.h"
#include "data.h"
#include "facebook.h"
#include "util.h"

static PurpleProtocol *my_protocol = NULL;

static void
fb_cb_api_error(FbApi *api, GError *error, gpointer data);

static void
fb_cb_api_auth(FbApi *api, gpointer data)
{
	FbData *fata = data;
	PurpleConnection *gc;

	gc = fb_data_get_connection(fata);

	purple_connection_update_progress(gc, _("Fetching contacts"), 2, 4);
	fb_data_save(fata);
	fb_api_contacts(api);
}

static void
fb_cb_api_connect(FbApi *api, gpointer data)
{
	FbData *fata = data;
	PurpleConnection *gc;

	gc = fb_data_get_connection(fata);

	fb_data_save(fata);
	purple_connection_set_state(gc, PURPLE_CONNECTION_CONNECTED);
}

static void
fb_cb_data_icon(PurpleHttpConnection *con, PurpleHttpResponse *res,
                gpointer data)
{
	const gchar *csum;
	const gchar *name;
	const gchar *str;
	FbDataIcon *icon = data;
	FbHttpParams *params;
	GError *err = NULL;
	gsize size;
	guchar *idata;
	PurpleAccount *acct;
	PurpleHttpRequest *req;

	acct = purple_buddy_get_account(icon->buddy);
	name = purple_buddy_get_name(icon->buddy);

	if (!fb_http_error_chk(res, &err)) {
		fb_util_debug_warning("Failed to retrieve icon for %s: %s",
		                      name, err->message);
		g_error_free(err);
		return;
	}

	req = purple_http_conn_get_request(con);
	str = purple_http_request_get_url(req);
	params = fb_http_params_new_parse(str, TRUE);
	csum = fb_http_params_get_str(params, "oh", &err);
	str = purple_http_response_get_data(res, &size);

	idata = g_memdup(str, size);
	purple_buddy_icons_set_for_user(acct, name, idata, size, csum);
	fb_http_params_free(params);
}

static void
fb_cb_api_contacts(FbApi *api, GSList *users, gpointer data)
{
	const gchar *alias;
	const gchar *csum;
	FbApiUser *user;
	FbData *fata = data;
	FbId muid;
	gchar uid[FB_ID_STRMAX];
	GSList *l;
	GValue val = G_VALUE_INIT;
	PurpleAccount *acct;
	PurpleBuddy *bdy;
	PurpleConnection *gc;
	PurpleGroup *grp;

	gc = fb_data_get_connection(fata);
	acct = purple_connection_get_account(gc);
	grp = purple_blist_get_default_group();
	alias = purple_account_get_private_alias(acct);

	g_value_init(&val, FB_TYPE_ID);
	g_object_get_property(G_OBJECT(api), "uid", &val);
	muid = g_value_get_int64(&val);
	g_value_unset(&val);

	for (l = users; l != NULL; l = l->next) {
		user = l->data;
		FB_ID_TO_STR(user->uid, uid);

		if (G_UNLIKELY(user->uid == muid)) {
			if (G_UNLIKELY(alias != NULL)) {
				continue;
			}

			purple_account_set_private_alias(acct, user->name);
			continue;
		}

		bdy = purple_blist_find_buddy(acct, uid);

		if (bdy == NULL) {
			bdy = purple_buddy_new(acct, uid, user->name);
			purple_blist_add_buddy(bdy, NULL, grp, NULL);
			fb_data_icon_add(fata, bdy, user->icon,
			                 fb_cb_data_icon);
			continue;
		}

		csum = purple_buddy_icons_get_checksum_for_user(bdy);

		if (!purple_strequal(csum, user->csum)) {
			fb_data_icon_add(fata, bdy, user->icon,
			                 fb_cb_data_icon);
		}
	}

	fb_data_icon_queue(fata);
	purple_connection_update_progress(gc, _("Connecting"), 3, 4);
	fb_api_connect(api);
}

static void
fb_cb_api_error(FbApi *api, GError *error, gpointer data)
{
	FbData *fata = data;
	PurpleConnection *gc;

	gc = fb_data_get_connection(fata);
	purple_connection_error(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
	                        error->message);
}

static void
fb_cb_api_message(FbApi *api, GSList *msgs, gpointer data)
{
	FbApiMessage *msg;
	FbData *fata = data;
	gchar tid[FB_ID_STRMAX];
	gchar uid[FB_ID_STRMAX];
	gint id;
	GSList *l;
	PurpleAccount *acct;
	PurpleChatConversation *chat;
	PurpleConnection *gc;

	gc = fb_data_get_connection(fata);
	acct = purple_connection_get_account(gc);

	for (l = msgs; l != NULL; l = l->next) {
		msg = l->data;
		chat = NULL;
		FB_ID_TO_STR(msg->uid, uid);

		if (msg->tid == 0) {
			purple_serv_got_im(gc, uid, msg->text,
		                           PURPLE_MESSAGE_RECV,
			                   time(NULL));
			continue;
		}

		FB_ID_TO_STR(msg->tid, tid);
		chat = purple_conversations_find_chat_with_account(tid, acct);

		if (chat != NULL) {
			id = purple_chat_conversation_get_id(chat);
			purple_serv_got_chat_in(gc, id, uid,
			                        PURPLE_MESSAGE_RECV,
		                                msg->text, time(NULL));
		}
	}
}

static void
fb_cb_api_presence(FbApi *api, GSList *press, gpointer data)
{
	const gchar *statid;
	FbApiPresence *pres;
	FbData *fata = data;
	gchar uid[FB_ID_STRMAX];
	GSList *l;
	PurpleAccount *acct;
	PurpleConnection *gc;
	PurpleStatusPrimitive pstat;

	gc = fb_data_get_connection(fata);
	acct = purple_connection_get_account(gc);

	for (l = press; l != NULL; l = l->next) {
		pres = l->data;

		if (pres->active) {
			pstat = PURPLE_STATUS_AVAILABLE;
		} else {
			pstat = PURPLE_STATUS_OFFLINE;
		}

		FB_ID_TO_STR(pres->uid, uid);
		statid = purple_primitive_get_id_from_type(pstat);
		purple_protocol_got_user_status(acct, uid, statid, NULL);
	}
}

static void
fb_cb_api_thread_create(FbApi *api, FbId tid, gpointer data)
{
	FbData *fata = data;
	gchar sid[FB_ID_STRMAX];
	GHashTable *table;
	PurpleConnection *gc;

	gc = fb_data_get_connection(fata);
	FB_ID_TO_STR(tid, sid);

	table = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
	g_hash_table_insert(table, "name", g_strdup(sid));
	purple_serv_join_chat(gc, table);
	g_hash_table_destroy(table);
}

static void
fb_cb_api_thread_info(FbApi *api, FbApiThread *thrd, gpointer data)
{
	FbApiUser *user;
	FbData *fata = data;
	gchar tid[FB_ID_STRMAX];
	gchar uid[FB_ID_STRMAX];
	gint id;
	GSList *l;
	PurpleChatConversation *chat;
	PurpleConnection *gc;

	gc = fb_data_get_connection(fata);
	id = fb_data_get_chatid(fata);
	FB_ID_TO_STR(thrd->tid, tid);

	chat = purple_serv_got_joined_chat(gc, id, tid);
	purple_chat_conversation_set_topic(chat, NULL, thrd->topic);

	for (l = thrd->users; l != NULL; l = l->next) {
		user = l->data;
		FB_ID_TO_STR(user->uid, uid);
		purple_chat_conversation_add_user(chat, uid, NULL, 0, FALSE);
	}
}

static void
fb_cb_api_thread_list(FbApi *api, GSList *thrds, gpointer data)
{
	FbApiUser *user;
	FbData *fata = data;
	gchar tid[FB_ID_STRMAX];
	GSList *l;
	GSList *m;
	GString *gstr;
	FbApiThread *thrd;
	PurpleRoomlist *list;
	PurpleRoomlistRoom *room;

	list = fb_data_get_roomlist(fata);
	gstr = g_string_new(NULL);

	for (l = thrds; l != NULL; l = l->next) {
		thrd = l->data;
		FB_ID_TO_STR(thrd->tid, tid);
		g_string_truncate(gstr, 0);

		for (m = thrd->users; m != NULL; m = m->next) {
			user = m->data;

			if (gstr->len > 0) {
				g_string_append(gstr, ", ");
			}

			g_string_append(gstr, user->name);
		}

		room = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM,
		                                tid, NULL);
		purple_roomlist_room_add_field(list, room, thrd->topic);
		purple_roomlist_room_add_field(list, room, gstr->str);
		purple_roomlist_room_add(list, room);
	}

	purple_roomlist_set_in_progress(list, FALSE);
	g_string_free(gstr, TRUE);
}

static void
fb_cb_api_typing(FbApi *api, FbApiTyping *typg, gpointer data)
{
	FbData *fata = data;
	gchar uid[FB_ID_STRMAX];
	PurpleConnection *gc;

	gc = fb_data_get_connection(fata);
	FB_ID_TO_STR(typg->uid, uid);

	if (typg->state) {
		purple_serv_got_typing(gc, uid, 0, PURPLE_IM_TYPING);
	} else {
		purple_serv_got_typing_stopped(gc, uid);
	}
}

static void
fb_blist_chat_create(GSList *buddies, gpointer data)
{
	const gchar *name;
	FbApi *api;
	FbData *fata = data;
	FbId uid;
	gpointer mptr;
	GSList *l;
	GSList *uids = NULL;
	PurpleConnection *gc;
	PurpleRequestCommonParameters *cpar;

	gc = fb_data_get_connection(fata);
	api = fb_data_get_api(fata);

	if (g_slist_length(buddies) < 2) {
		cpar = purple_request_cpar_from_connection(gc);
		purple_notify_error(gc,
		                    _("Initiate Chat"),
		                    _("Failed to Initiate Chat"),
		                    _("At least two initial chat participants"
		                      " are required."),
				    cpar);
		return;
	}

	for (l = buddies; l != NULL; l = l->next) {
		name = purple_buddy_get_name(l->data);
		uid = FB_ID_FROM_STR(name);
		mptr = g_memdup(&uid, sizeof uid);
		uids = g_slist_prepend(uids, mptr);
	}

	fb_api_thread_create(api, uids);
	g_slist_free_full(uids, g_free);
}

static void
fb_blist_chat_init(PurpleBlistNode *node, gpointer data)
{
	FbData *fata = data;
	GSList *select = NULL;
	PurpleConnection *gc;

	if (!PURPLE_IS_BUDDY(node)) {
		return;
	}

	gc = fb_data_get_connection(fata);
	select = g_slist_prepend(select, PURPLE_BUDDY(node));

	fb_util_request_buddy(gc,
	                      _("Initiate Chat"),
	                      _("Initial Chat Participants"),
	                      _("Select at least two initial participants."),
	                      select, TRUE,
			      G_CALLBACK(fb_blist_chat_create), NULL,
			      fata);
	g_slist_free(select);
}

static void
fb_login(PurpleAccount *acct)
{
	const gchar *pass;
	const gchar *user;
	FbApi *api;
	FbData *fata;
	PurpleConnection *gc;

	gc = purple_account_get_connection(acct);
	//purple_connection_set_flags(gc, );

	if (!purple_ssl_is_supported()) {
		purple_connection_error(gc,
			PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
			_("SSL support unavailable"));
		return;
	}

	fata = fb_data_new(gc);
	api = fb_data_get_api(fata);
	purple_connection_set_protocol_data(gc, fata);

	g_signal_connect(api,
	                 "auth",
	                 G_CALLBACK(fb_cb_api_auth),
	                 fata);
	g_signal_connect(api,
	                 "connect",
	                 G_CALLBACK(fb_cb_api_connect),
	                 fata);
	g_signal_connect(api,
	                 "contacts",
	                 G_CALLBACK(fb_cb_api_contacts),
	                 fata);
	g_signal_connect(api,
	                 "error",
	                 G_CALLBACK(fb_cb_api_error),
	                 fata);
	g_signal_connect(api,
	                 "message",
	                 G_CALLBACK(fb_cb_api_message),
	                 fata);
	g_signal_connect(api,
	                 "presence",
	                 G_CALLBACK(fb_cb_api_presence),
	                 fata);
	g_signal_connect(api,
	                 "thread-create",
	                 G_CALLBACK(fb_cb_api_thread_create),
	                 fata);
	g_signal_connect(api,
	                 "thread-info",
	                 G_CALLBACK(fb_cb_api_thread_info),
	                 fata);
	g_signal_connect(api,
	                 "thread-list",
	                 G_CALLBACK(fb_cb_api_thread_list),
	                 fata);
	g_signal_connect(api,
	                 "typing",
	                 G_CALLBACK(fb_cb_api_typing),
	                 fata);

	if (!fb_data_load(fata)) {
		user = purple_account_get_username(acct);
		pass = purple_connection_get_password(gc);
		purple_connection_update_progress(gc, _("Authenticating"),
		                                  1, 4);
		fb_api_auth(api, user, pass);
		return;
	}

	purple_connection_update_progress(gc, _("Fetching contacts"), 2, 4);
	fb_api_contacts(api);
}

static void
fb_close(PurpleConnection *gc)
{
	FbApi *api;
	FbData *fata;

	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);

	fb_api_disconnect(api);
	g_object_unref(fata);
	purple_connection_set_protocol_data(gc, NULL);
}

static GList *
fb_status_types(PurpleAccount *acct)
{
	PurpleStatusType *type;
	GList *types = NULL;

	type = purple_status_type_new(PURPLE_STATUS_AVAILABLE,
	                              NULL, NULL, TRUE);
	types = g_list_prepend(types, type);

	type = purple_status_type_new(PURPLE_STATUS_OFFLINE,
	                              NULL, NULL, TRUE);
	types = g_list_prepend(types, type);

	return types;
}

static const char *
fb_list_icon(PurpleAccount *account, PurpleBuddy *buddy)
{
	return "facebook";
}

static GList *
fb_client_blist_node_menu(PurpleBlistNode *node)
{
	FbData *fata;
	GList *acts = NULL;
	PurpleAccount *acct;
	PurpleConnection *gc;
	PurpleMenuAction *act;

	if (!PURPLE_IS_BUDDY(node)) {
		return NULL;
	}

	acct = purple_buddy_get_account(PURPLE_BUDDY(node));
	gc = purple_account_get_connection(acct);
	fata = purple_connection_get_protocol_data(gc);

	act = purple_menu_action_new(_("Initiate _Chat"),
	                             PURPLE_CALLBACK(fb_blist_chat_init),
	                             fata, NULL);
	acts = g_list_prepend(acts, act);

	return g_list_reverse(acts);
}

static gint
fb_im_send(PurpleConnection *gc, PurpleMessage *msg)
{
	const gchar *name;
	const gchar *text;
	FbApi *api;
	FbData *fata;
	FbId uid;

	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);

	name = purple_message_get_recipient(msg);
	uid = FB_ID_FROM_STR(name);

	text = purple_message_get_contents(msg);
	fb_api_message(api, uid, FALSE, text);
	return 1;
}

static guint
fb_im_send_typing(PurpleConnection *gc, const gchar *name,
                  PurpleIMTypingState state)
{
	FbApi *api;
	FbData *fata;
	FbId uid;

	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);
	uid = FB_ID_FROM_STR(name);

	fb_api_typing(api, uid, state != PURPLE_IM_NOT_TYPING);
	return 0;
}

static void
fb_chat_join(PurpleConnection *gc, GHashTable *data)
{
	const gchar *name;
	FbApi *api;
	FbData *fata;
	FbId tid;

	name = g_hash_table_lookup(data, "name");
	g_return_if_fail(name != NULL);

	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);
	tid = FB_ID_FROM_STR(name);

	fb_api_thread_info(api, tid);
}

static void
fb_chat_invite(PurpleConnection *gc, gint id, const gchar *msg,
               const gchar *who)
{
	const gchar *name;
	FbApi *api;
	FbData *fata;
	FbId tid;
	FbId uid;
	PurpleChatConversation *chat;
	PurpleRequestCommonParameters *cpar;

	if (!FB_ID_IS_STR(who)) {
		cpar = purple_request_cpar_from_connection(gc);
		purple_notify_error(gc,
		                    _("Invite Buddy Into Chat Room"),
		                    _("Failed to Invite User"),
		                    _("Invalid Facebook identifier."),
				    cpar);
		return;
	}

	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);
	chat = purple_conversations_find_chat(gc, id);

	name = purple_conversation_get_name(PURPLE_CONVERSATION(chat));
	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);
}

static gint
fb_chat_send(PurpleConnection *gc, gint id, PurpleMessage *msg)
{
	const gchar *name;
	const gchar *text;
	FbApi *api;
	FbData *fata;
	FbId tid;
	PurpleAccount *acct;
	PurpleChatConversation *chat;

	acct = purple_connection_get_account(gc);
	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);
	chat = purple_conversations_find_chat(gc, id);

	name = purple_conversation_get_name(PURPLE_CONVERSATION(chat));
	tid = FB_ID_FROM_STR(name);

	text = purple_message_get_contents(msg);
	fb_api_message(api, tid, TRUE, text);

	name = purple_account_get_username(acct);
	purple_serv_got_chat_in(gc, id, name,
				purple_message_get_flags(msg),
	                        purple_message_get_contents(msg),
	                        time(NULL));
	return 0;
}

static void
fb_chat_set_topic(PurpleConnection *gc, gint id, const gchar *topic)
{
	const gchar *name;
	FbApi *api;
	FbData *fata;
	FbId tid;
	PurpleAccount *acct;
	PurpleChatConversation *chat;

	acct = purple_connection_get_account(gc);
	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);
	chat = purple_conversations_find_chat(gc, id);

	name = purple_conversation_get_name(PURPLE_CONVERSATION(chat));
	tid = FB_ID_FROM_STR(name);

	name = purple_account_get_username(acct);
	purple_chat_conversation_set_topic(chat, name, topic);
	fb_api_thread_topic(api, tid, topic);
}

static PurpleRoomlist *
fb_roomlist_get_list(PurpleConnection *gc)
{
	FbApi *api;
	FbData *fata;
	GList *flds = NULL;
	PurpleAccount *acct;
	PurpleRoomlist *list;
	PurpleRoomlistField *fld;

	fata = purple_connection_get_protocol_data(gc);
	api = fb_data_get_api(fata);
	acct = purple_connection_get_account(gc);
	list = purple_roomlist_new(acct);
	fb_data_set_roomlist(fata, list);

	fld = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING,
	                                _("Topic"), "topic", FALSE);
	flds = g_list_prepend(flds, fld);

	fld = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING,
	                                _("Users"), "users", FALSE);
	flds = g_list_prepend(flds, fld);

	flds = g_list_reverse(flds);
	purple_roomlist_set_fields(list, flds);

	fb_api_thread_list(api);
	return list;
}

static void
fb_roomlist_cancel(PurpleRoomlist *list)
{
	FbData *fata;
	PurpleAccount *acct;
	PurpleConnection *gc;
	PurpleRoomlist *cist;

	acct = purple_roomlist_get_account(list);
	gc = purple_account_get_connection(acct);
	fata = purple_connection_get_protocol_data(gc);
	cist = fb_data_get_roomlist(fata);

	if (G_LIKELY(cist == list)) {
		fb_data_set_roomlist(fata, NULL);
	}

	purple_roomlist_set_in_progress(list, FALSE);
	g_object_unref(list);
}

static void
facebook_protocol_init(PurpleProtocol *protocol)
{
	protocol->id      = "prpl-facebook";
	protocol->name    = "Facebook";
	protocol->options = OPT_PROTO_CHAT_TOPIC;
}

static void
facebook_protocol_class_init(PurpleProtocolClass *klass)
{
	klass->login        = fb_login;
	klass->close        = fb_close;
	klass->status_types = fb_status_types;
	klass->list_icon    = fb_list_icon;
}

static void
facebook_protocol_client_iface_init(PurpleProtocolClientIface *iface)
{
	iface->blist_node_menu = fb_client_blist_node_menu;
}

static void
facebook_protocol_server_iface_init(PurpleProtocolServerIface *iface)
{

}

static void
facebook_protocol_im_iface_init(PurpleProtocolIMIface *iface)
{
	iface->send        = fb_im_send;
	iface->send_typing = fb_im_send_typing;
}

static void
facebook_protocol_chat_iface_init(PurpleProtocolChatIface *iface)
{
	iface->join      = fb_chat_join;
	iface->invite    = fb_chat_invite;
	iface->send      = fb_chat_send;
	iface->set_topic = fb_chat_set_topic;
}

static void
facebook_protocol_privacy_iface_init(PurpleProtocolPrivacyIface *iface)
{

}

static void
facebook_protocol_roomlist_iface_init(PurpleProtocolRoomlistIface *iface)
{
	iface->get_list = fb_roomlist_get_list;
	iface->cancel   = fb_roomlist_cancel;
}

PURPLE_DEFINE_TYPE_EXTENDED(
	FacebookProtocol, facebook_protocol, PURPLE_TYPE_PROTOCOL, 0,

	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CLIENT_IFACE,
	                                  facebook_protocol_client_iface_init)
	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_SERVER_IFACE,
	                                  facebook_protocol_server_iface_init)
	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_IM_IFACE,
	                                  facebook_protocol_im_iface_init)
	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CHAT_IFACE,
	                                  facebook_protocol_chat_iface_init)
	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_PRIVACY_IFACE,
	                                  facebook_protocol_privacy_iface_init)
	PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_ROOMLIST_IFACE,
	                                  facebook_protocol_roomlist_iface_init)
);

static PurplePluginInfo *
plugin_query(GError **error)
{
	return purple_plugin_info_new(
		"id",          "prpl-facebook",
		"name",        "Facebook Protocol",
		"version",     DISPLAY_VERSION,
		"category",    N_("Protocol"),
		"summary",     N_("Facebook Protocol Plugin"),
		"description", N_("Facebook Protocol Plugin"),
		"website",     PURPLE_WEBSITE,
		"abi-version", PURPLE_ABI_VERSION,
		"flags",       PURPLE_PLUGIN_INFO_FLAGS_INTERNAL |
		               PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD,
		NULL
	);
}

static gboolean
plugin_load(PurplePlugin *plugin, GError **error)
{
	facebook_protocol_register_type(plugin);
	my_protocol = purple_protocols_add(FACEBOOK_TYPE_PROTOCOL, error);
	return my_protocol != NULL;
}

static gboolean
plugin_unload(PurplePlugin *plugin, GError **error)
{
	return purple_protocols_remove(my_protocol, error);
}

PURPLE_PLUGIN_INIT(facebook, plugin_query, plugin_load, plugin_unload);

mercurial